mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-02 03:29:03 +00:00
chore(ui): refactor data contract spec test (#23741)
* chore(ui): fix data contract flaky test around contract tab not found * modify the test to have their own table to run to avoid flakiness * fix contract failing * revert unwanted commit * change the contract test admin page way * fix the blank page issue after redirect
This commit is contained in:
parent
8ccd879655
commit
9286933d5c
@ -36,6 +36,7 @@ import { selectOption } from '../../utils/advancedSearch';
|
||||
import { resetTokenFromBotPage } from '../../utils/bot';
|
||||
import {
|
||||
clickOutside,
|
||||
getApiContext,
|
||||
redirectToHomePage,
|
||||
toastNotification,
|
||||
} from '../../utils/common';
|
||||
@ -54,10 +55,10 @@ import {
|
||||
assignTier,
|
||||
} from '../../utils/entity';
|
||||
import { settingClick } from '../../utils/sidebar';
|
||||
import { test } from '../fixtures/pages';
|
||||
|
||||
const adminUser = new UserClass();
|
||||
|
||||
const test = base.extend<{ page: Page }>({
|
||||
const testPersona = base.extend<{ page: Page }>({
|
||||
page: async ({ browser }, use) => {
|
||||
const adminPage = await browser.newPage();
|
||||
await adminUser.login(adminPage);
|
||||
@ -67,57 +68,8 @@ const test = base.extend<{ page: Page }>({
|
||||
});
|
||||
|
||||
test.describe('Data Contracts', () => {
|
||||
const table = new TableClass();
|
||||
const table2 = new TableClass();
|
||||
const testClassification = new ClassificationClass();
|
||||
const testTag = new TagClass({
|
||||
classification: testClassification.data.name,
|
||||
});
|
||||
const testGlossary = new Glossary();
|
||||
const testGlossaryTerm = new GlossaryTerm(testGlossary);
|
||||
const testPersona = new PersonaClass();
|
||||
|
||||
test.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||
test.slow(true);
|
||||
|
||||
const { apiContext, afterAction, page } = await performAdminLogin(browser);
|
||||
await table.create(apiContext);
|
||||
await table2.create(apiContext);
|
||||
await testClassification.create(apiContext);
|
||||
await testTag.create(apiContext);
|
||||
await testGlossary.create(apiContext);
|
||||
await testGlossaryTerm.create(apiContext);
|
||||
await testPersona.create(apiContext);
|
||||
await adminUser.create(apiContext);
|
||||
await adminUser.setAdminRole(apiContext);
|
||||
await adminUser.patch({
|
||||
apiContext,
|
||||
patchData: [
|
||||
{
|
||||
op: 'add',
|
||||
path: '/personas/0',
|
||||
value: {
|
||||
id: testPersona.responseData.id,
|
||||
name: testPersona.responseData.name,
|
||||
displayName: testPersona.responseData.displayName,
|
||||
fullyQualifiedName: testPersona.responseData.fullyQualifiedName,
|
||||
type: 'persona',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/defaultPersona',
|
||||
value: {
|
||||
id: testPersona.responseData.id,
|
||||
name: testPersona.responseData.name,
|
||||
displayName: testPersona.responseData.displayName,
|
||||
fullyQualifiedName: testPersona.responseData.fullyQualifiedName,
|
||||
type: 'persona',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const { afterAction, page } = await performAdminLogin(browser);
|
||||
if (!process.env.PLAYWRIGHT_IS_OSS) {
|
||||
// Todo: Remove this patch once the issue is fixed #19140
|
||||
await resetTokenFromBotPage(page, 'testsuite-bot');
|
||||
@ -126,9 +78,28 @@ test.describe('Data Contracts', () => {
|
||||
await afterAction();
|
||||
});
|
||||
|
||||
test.beforeEach('Redirect to Home Page', async ({ page }) => {
|
||||
await redirectToHomePage(page);
|
||||
});
|
||||
|
||||
test('Create Data Contract and validate', async ({ page }) => {
|
||||
test.setTimeout(360000);
|
||||
|
||||
const table = new TableClass();
|
||||
const testClassification = new ClassificationClass();
|
||||
const testTag = new TagClass({
|
||||
classification: testClassification.data.name,
|
||||
});
|
||||
const testGlossary = new Glossary();
|
||||
const testGlossaryTerm = new GlossaryTerm(testGlossary);
|
||||
|
||||
const { apiContext } = await getApiContext(page);
|
||||
await table.create(apiContext);
|
||||
await testClassification.create(apiContext);
|
||||
await testTag.create(apiContext);
|
||||
await testGlossary.create(apiContext);
|
||||
await testGlossaryTerm.create(apiContext);
|
||||
|
||||
await test.step('Redirect to Home Page and visit entity', async () => {
|
||||
await redirectToHomePage(page);
|
||||
await table.visitEntityPage(page);
|
||||
@ -421,11 +392,18 @@ test.describe('Data Contracts', () => {
|
||||
'Pipeline will only be triggered manually.'
|
||||
);
|
||||
|
||||
const pipelineResponse = page.waitForResponse(
|
||||
'/api/v1/services/ingestionPipelines'
|
||||
);
|
||||
|
||||
const testCaseResponse = page.waitForResponse(
|
||||
'/api/v1/dataQuality/testCases'
|
||||
);
|
||||
await page.click('[data-testid="create-btn"]');
|
||||
await testCaseResponse;
|
||||
await pipelineResponse;
|
||||
|
||||
await expect(page.getByRole('dialog')).not.toBeVisible();
|
||||
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
@ -681,246 +659,6 @@ test.describe('Data Contracts', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona', async ({
|
||||
page,
|
||||
}) => {
|
||||
test.slow(true);
|
||||
|
||||
await test.step(
|
||||
'Create Data Contract in Table and validate it fails',
|
||||
async () => {
|
||||
await table2.visitEntityPage(page);
|
||||
|
||||
// Open contract section and start adding contract
|
||||
await page.click('[data-testid="contract"]');
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
await expect(page.getByTestId('no-data-placeholder')).toBeVisible();
|
||||
await expect(page.getByTestId('add-contract-button')).toBeVisible();
|
||||
|
||||
await page.getByTestId('add-contract-button').click();
|
||||
|
||||
await expect(page.getByTestId('add-contract-card')).toBeVisible();
|
||||
|
||||
// Fill Contract Details form
|
||||
await page
|
||||
.getByTestId('contract-name')
|
||||
.fill(DATA_CONTRACT_DETAILS.name);
|
||||
await page.fill(
|
||||
'.om-block-editor[contenteditable="true"]',
|
||||
DATA_CONTRACT_DETAILS.description
|
||||
);
|
||||
|
||||
await page.getByTestId('select-owners').click();
|
||||
await page.locator('.rc-virtual-list-holder-inner li').first().click();
|
||||
|
||||
await expect(page.getByTestId('user-tag')).toBeVisible();
|
||||
|
||||
// Fill Contract Schema form
|
||||
await page
|
||||
.getByTestId('add-contract-card')
|
||||
.getByRole('tab', { name: 'Schema' })
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('input[type="checkbox"][aria-label="Select all"]')
|
||||
.check();
|
||||
|
||||
await expect(
|
||||
page.getByRole('checkbox', { name: 'Select all' })
|
||||
).toBeChecked();
|
||||
|
||||
// Fill Contract Semantics form
|
||||
await page.getByRole('tab', { name: 'Semantics' }).click();
|
||||
|
||||
await expect(page.getByTestId('add-semantic-button')).toBeDisabled();
|
||||
|
||||
await page.fill('#semantics_0_name', DATA_CONTRACT_SEMANTICS1.name);
|
||||
await page.fill(
|
||||
'#semantics_0_description',
|
||||
DATA_CONTRACT_SEMANTICS1.description
|
||||
);
|
||||
|
||||
const ruleLocator = page.locator('.group').nth(0);
|
||||
await selectOption(
|
||||
page,
|
||||
ruleLocator.locator('.group--field .ant-select'),
|
||||
DATA_CONTRACT_SEMANTICS1.rules[0].field,
|
||||
true
|
||||
);
|
||||
await selectOption(
|
||||
page,
|
||||
ruleLocator.locator('.rule--operator .ant-select'),
|
||||
DATA_CONTRACT_SEMANTICS1.rules[0].operator
|
||||
);
|
||||
await selectOption(
|
||||
page,
|
||||
ruleLocator.locator('.rule--value .ant-select'),
|
||||
'admin',
|
||||
true
|
||||
);
|
||||
await page.getByTestId('save-semantic-button').click();
|
||||
|
||||
await expect(
|
||||
page
|
||||
.getByTestId('contract-semantics-card-0')
|
||||
.locator('.semantic-form-item-title')
|
||||
).toContainText(DATA_CONTRACT_SEMANTICS1.name);
|
||||
|
||||
// Save contract and validate for semantics - should fail initially
|
||||
await saveAndTriggerDataContractValidation(page, true);
|
||||
|
||||
await expect(
|
||||
page.getByTestId('contract-status-card-item-semantics-status')
|
||||
).toContainText('Failed');
|
||||
await expect(
|
||||
page.getByTestId('data-contract-latest-result-btn')
|
||||
).toContainText('Contract Failed');
|
||||
}
|
||||
);
|
||||
|
||||
await test.step('Create Persona and assign user to it', async () => {
|
||||
await redirectToHomePage(page);
|
||||
|
||||
const personaGetResponse = page.waitForResponse('/api/v1/personas**');
|
||||
await settingClick(page, GlobalSettingOptions.PERSONA);
|
||||
await personaGetResponse;
|
||||
|
||||
await page.waitForSelector('.ant-skeleton-content', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
// Navigate to persona details
|
||||
await page
|
||||
.getByTestId(`persona-details-card-${testPersona.data.name}`)
|
||||
.click();
|
||||
await page.getByRole('tab', { name: 'Users' }).click();
|
||||
|
||||
// Add user to persona
|
||||
await page.getByTestId('add-persona-button').click();
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
const searchUser = page.waitForResponse(
|
||||
`/api/v1/search/query?q=*${encodeURIComponent(
|
||||
adminUser.responseData.displayName
|
||||
)}*`
|
||||
);
|
||||
await page
|
||||
.getByTestId('searchbar')
|
||||
.fill(adminUser.responseData.displayName);
|
||||
await searchUser;
|
||||
|
||||
await page
|
||||
.getByRole('listitem', { name: adminUser.responseData.displayName })
|
||||
.click();
|
||||
|
||||
const personaResponse = page.waitForResponse('/api/v1/personas/*');
|
||||
|
||||
await page.getByTestId('selectable-list-update-btn').click();
|
||||
await personaResponse;
|
||||
});
|
||||
|
||||
await test.step(
|
||||
'Verify Contract tab and status badge are visible if persona is set',
|
||||
async () => {
|
||||
await redirectToHomePage(page);
|
||||
await table2.visitEntityPage(page);
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
// Verify Contract tab is not visible (should be hidden by persona customization)
|
||||
await expect(page.getByTestId('contract')).toBeVisible();
|
||||
|
||||
// Verify Contract status badge is not visible in header
|
||||
await expect(
|
||||
page.getByTestId('data-contract-latest-result-btn')
|
||||
).toBeVisible();
|
||||
|
||||
// Additional verification: Check that other tabs are still visible
|
||||
await expect(page.getByTestId('schema')).toBeVisible();
|
||||
await expect(page.getByTestId('activity_feed')).toBeVisible();
|
||||
await expect(page.getByTestId('sample_data')).toBeVisible();
|
||||
await expect(page.getByTestId('table_queries')).toBeVisible();
|
||||
await expect(page.getByTestId('profiler')).toBeVisible();
|
||||
await expect(page.getByTestId('lineage')).toBeVisible();
|
||||
await expect(page.getByTestId('custom_properties')).toBeVisible();
|
||||
}
|
||||
);
|
||||
|
||||
await test.step('Customize Table page to hide Contract tab', async () => {
|
||||
await settingClick(page, GlobalSettingOptions.PERSONA);
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
// Navigate to persona details and customize UI
|
||||
await page
|
||||
.getByTestId(`persona-details-card-${testPersona.data.name}`)
|
||||
.click();
|
||||
await page.getByRole('tab', { name: 'Customize UI' }).click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Navigate to Table customization
|
||||
await page.getByTestId('data-assets').getByText('Data Assets').click();
|
||||
await page.getByText('Table', { exact: true }).click();
|
||||
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
// Hide the Contract tab
|
||||
await page.getByTestId('tab-contract').click();
|
||||
await page.getByText('Hide', { exact: true }).click();
|
||||
|
||||
// Save the customization
|
||||
await page.getByTestId('save-button').click();
|
||||
await toastNotification(
|
||||
page,
|
||||
/^Page layout (created|updated) successfully\.$/
|
||||
);
|
||||
});
|
||||
|
||||
await test.step(
|
||||
'Verify Contract tab and status badge are hidden after persona customization',
|
||||
async () => {
|
||||
// After applying persona customization to hide the contract tab,
|
||||
// we need to verify that the contract tab and status badge are not visible
|
||||
// when viewing the table page with the customized persona.
|
||||
|
||||
await redirectToHomePage(page);
|
||||
await table2.visitEntityPage(page);
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
// Verify Contract tab is not visible (should be hidden by persona customization)
|
||||
await expect(page.getByTestId('contract')).not.toBeVisible();
|
||||
|
||||
// Verify Contract status badge is not visible in header
|
||||
await expect(
|
||||
page.getByTestId('data-contract-latest-result-btn')
|
||||
).not.toBeVisible();
|
||||
|
||||
// Additional verification: Check that other tabs are still visible
|
||||
await expect(page.getByTestId('schema')).toBeVisible();
|
||||
await expect(page.getByTestId('activity_feed')).toBeVisible();
|
||||
await expect(page.getByTestId('sample_data')).toBeVisible();
|
||||
await expect(page.getByTestId('table_queries')).toBeVisible();
|
||||
await expect(page.getByTestId('profiler')).toBeVisible();
|
||||
await expect(page.getByTestId('lineage')).toBeVisible();
|
||||
await expect(page.getByTestId('custom_properties')).toBeVisible();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('Pagination in Schema Tab with Selection Persistent', async ({
|
||||
page,
|
||||
}) => {
|
||||
@ -1232,6 +970,21 @@ test.describe('Data Contracts', () => {
|
||||
}) => {
|
||||
test.slow(true);
|
||||
|
||||
const table = new TableClass();
|
||||
const testClassification = new ClassificationClass();
|
||||
const testTag = new TagClass({
|
||||
classification: testClassification.data.name,
|
||||
});
|
||||
const testGlossary = new Glossary();
|
||||
const testGlossaryTerm = new GlossaryTerm(testGlossary);
|
||||
|
||||
const { apiContext } = await getApiContext(page);
|
||||
await table.create(apiContext);
|
||||
await testClassification.create(apiContext);
|
||||
await testTag.create(apiContext);
|
||||
await testGlossary.create(apiContext);
|
||||
await testGlossaryTerm.create(apiContext);
|
||||
|
||||
await redirectToHomePage(page);
|
||||
await table.visitEntityPage(page);
|
||||
await page.click('[data-testid="contract"]');
|
||||
@ -1402,6 +1155,21 @@ test.describe('Data Contracts', () => {
|
||||
test('Semantic with Not_Contains Operator should work for Tier, Tag and Glossary', async ({
|
||||
page,
|
||||
}) => {
|
||||
const table = new TableClass();
|
||||
const testClassification = new ClassificationClass();
|
||||
const testTag = new TagClass({
|
||||
classification: testClassification.data.name,
|
||||
});
|
||||
const testGlossary = new Glossary();
|
||||
const testGlossaryTerm = new GlossaryTerm(testGlossary);
|
||||
|
||||
const { apiContext } = await getApiContext(page);
|
||||
await table.create(apiContext);
|
||||
await testClassification.create(apiContext);
|
||||
await testTag.create(apiContext);
|
||||
await testGlossary.create(apiContext);
|
||||
await testGlossaryTerm.create(apiContext);
|
||||
|
||||
await redirectToHomePage(page);
|
||||
await table.visitEntityPage(page);
|
||||
await page.click('[data-testid="contract"]');
|
||||
@ -1574,6 +1342,10 @@ test.describe('Data Contracts', () => {
|
||||
});
|
||||
|
||||
test('Nested Column should not be selectable', async ({ page }) => {
|
||||
const { apiContext } = await getApiContext(page);
|
||||
const table = new TableClass();
|
||||
await table.create(apiContext);
|
||||
|
||||
const entityFQN = table.entityResponseData.fullyQualifiedName;
|
||||
await redirectToHomePage(page);
|
||||
await table.visitEntityPage(page);
|
||||
@ -1642,6 +1414,10 @@ test.describe('Data Contracts', () => {
|
||||
test('should allow adding a semantic with multiple rules', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { apiContext } = await getApiContext(page);
|
||||
const table = new TableClass();
|
||||
await table.create(apiContext);
|
||||
|
||||
await redirectToHomePage(page);
|
||||
await table.visitEntityPage(page);
|
||||
await page.click('[data-testid="contract"]');
|
||||
@ -1717,6 +1493,10 @@ test.describe('Data Contracts', () => {
|
||||
test('should allow adding a second semantic and verify its rule', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { apiContext } = await getApiContext(page);
|
||||
const table = new TableClass();
|
||||
await table.create(apiContext);
|
||||
|
||||
await redirectToHomePage(page);
|
||||
await table.visitEntityPage(page);
|
||||
await page.click('[data-testid="contract"]');
|
||||
@ -1806,6 +1586,10 @@ test.describe('Data Contracts', () => {
|
||||
test('should allow editing a semantic and reflect changes', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { apiContext } = await getApiContext(page);
|
||||
const table = new TableClass();
|
||||
await table.create(apiContext);
|
||||
|
||||
await redirectToHomePage(page);
|
||||
await table.visitEntityPage(page);
|
||||
await page.click('[data-testid="contract"]');
|
||||
@ -1860,6 +1644,10 @@ test.describe('Data Contracts', () => {
|
||||
test('should allow deleting a semantic and remove it from the list', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { apiContext } = await getApiContext(page);
|
||||
const table = new TableClass();
|
||||
await table.create(apiContext);
|
||||
|
||||
await redirectToHomePage(page);
|
||||
await table.visitEntityPage(page);
|
||||
await page.click('[data-testid="contract"]');
|
||||
@ -1925,10 +1713,14 @@ test.describe('Data Contracts', () => {
|
||||
});
|
||||
|
||||
test('Add and update Security and SLA tabs', async ({ page }) => {
|
||||
await redirectToHomePage(page);
|
||||
await table.visitEntityPage(page);
|
||||
const { apiContext } = await getApiContext(page);
|
||||
const table = new TableClass();
|
||||
await table.create(apiContext);
|
||||
|
||||
await test.step('Add Security and SLA Details', async () => {
|
||||
await redirectToHomePage(page);
|
||||
await table.visitEntityPage(page);
|
||||
|
||||
await page.click('[data-testid="contract"]');
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
@ -2148,3 +1940,297 @@ test.describe('Data Contracts', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
testPersona.describe('Data Contracts With Persona', () => {
|
||||
test.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||
const { apiContext, afterAction } = await performAdminLogin(browser);
|
||||
await adminUser.create(apiContext);
|
||||
await adminUser.setAdminRole(apiContext);
|
||||
await afterAction();
|
||||
});
|
||||
|
||||
testPersona(
|
||||
'Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona',
|
||||
async ({ page }) => {
|
||||
testPersona.slow(true);
|
||||
const { apiContext } = await getApiContext(page);
|
||||
const table = new TableClass();
|
||||
const persona = new PersonaClass();
|
||||
await table.create(apiContext);
|
||||
await persona.create(apiContext);
|
||||
await adminUser.patch({
|
||||
apiContext,
|
||||
patchData: [
|
||||
{
|
||||
op: 'add',
|
||||
path: '/personas/0',
|
||||
value: {
|
||||
id: persona.responseData.id,
|
||||
name: persona.responseData.name,
|
||||
displayName: persona.responseData.displayName,
|
||||
fullyQualifiedName: persona.responseData.fullyQualifiedName,
|
||||
type: 'persona',
|
||||
},
|
||||
},
|
||||
{
|
||||
op: 'add',
|
||||
path: '/defaultPersona',
|
||||
value: {
|
||||
id: persona.responseData.id,
|
||||
name: persona.responseData.name,
|
||||
displayName: persona.responseData.displayName,
|
||||
fullyQualifiedName: persona.responseData.fullyQualifiedName,
|
||||
type: 'persona',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await testPersona.step(
|
||||
'Create Data Contract in Table and validate it fails',
|
||||
async () => {
|
||||
await table.visitEntityPage(page);
|
||||
|
||||
// Open contract section and start adding contract
|
||||
await page.click('[data-testid="contract"]');
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
await expect(page.getByTestId('no-data-placeholder')).toBeVisible();
|
||||
await expect(page.getByTestId('add-contract-button')).toBeVisible();
|
||||
|
||||
await page.getByTestId('add-contract-button').click();
|
||||
|
||||
await expect(page.getByTestId('add-contract-card')).toBeVisible();
|
||||
|
||||
// Fill Contract Details form
|
||||
await page
|
||||
.getByTestId('contract-name')
|
||||
.fill(DATA_CONTRACT_DETAILS.name);
|
||||
await page.fill(
|
||||
'.om-block-editor[contenteditable="true"]',
|
||||
DATA_CONTRACT_DETAILS.description
|
||||
);
|
||||
|
||||
await page.getByTestId('select-owners').click();
|
||||
await page
|
||||
.locator('.rc-virtual-list-holder-inner li')
|
||||
.first()
|
||||
.click();
|
||||
|
||||
await expect(page.getByTestId('user-tag')).toBeVisible();
|
||||
|
||||
// Fill Contract Schema form
|
||||
await page
|
||||
.getByTestId('add-contract-card')
|
||||
.getByRole('tab', { name: 'Schema' })
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('input[type="checkbox"][aria-label="Select all"]')
|
||||
.check();
|
||||
|
||||
await expect(
|
||||
page.getByRole('checkbox', { name: 'Select all' })
|
||||
).toBeChecked();
|
||||
|
||||
// Fill Contract Semantics form
|
||||
await page.getByRole('tab', { name: 'Semantics' }).click();
|
||||
|
||||
await expect(page.getByTestId('add-semantic-button')).toBeDisabled();
|
||||
|
||||
await page.fill('#semantics_0_name', DATA_CONTRACT_SEMANTICS1.name);
|
||||
await page.fill(
|
||||
'#semantics_0_description',
|
||||
DATA_CONTRACT_SEMANTICS1.description
|
||||
);
|
||||
|
||||
const ruleLocator = page.locator('.group').nth(0);
|
||||
await selectOption(
|
||||
page,
|
||||
ruleLocator.locator('.group--field .ant-select'),
|
||||
DATA_CONTRACT_SEMANTICS1.rules[0].field,
|
||||
true
|
||||
);
|
||||
await selectOption(
|
||||
page,
|
||||
ruleLocator.locator('.rule--operator .ant-select'),
|
||||
DATA_CONTRACT_SEMANTICS1.rules[0].operator
|
||||
);
|
||||
await selectOption(
|
||||
page,
|
||||
ruleLocator.locator('.rule--value .ant-select'),
|
||||
'admin',
|
||||
true
|
||||
);
|
||||
await page.getByTestId('save-semantic-button').click();
|
||||
|
||||
await expect(
|
||||
page
|
||||
.getByTestId('contract-semantics-card-0')
|
||||
.locator('.semantic-form-item-title')
|
||||
).toContainText(DATA_CONTRACT_SEMANTICS1.name);
|
||||
|
||||
// Save contract and validate for semantics - should fail initially
|
||||
await saveAndTriggerDataContractValidation(page, true);
|
||||
|
||||
await expect(
|
||||
page.getByTestId('contract-status-card-item-semantics-status')
|
||||
).toContainText('Failed');
|
||||
await expect(
|
||||
page.getByTestId('data-contract-latest-result-btn')
|
||||
).toContainText('Contract Failed');
|
||||
}
|
||||
);
|
||||
|
||||
await testPersona.step(
|
||||
'Create Persona and assign user to it',
|
||||
async () => {
|
||||
await redirectToHomePage(page);
|
||||
|
||||
const personaGetResponse = page.waitForResponse('/api/v1/personas**');
|
||||
await settingClick(page, GlobalSettingOptions.PERSONA);
|
||||
await personaGetResponse;
|
||||
|
||||
await page.waitForSelector('.ant-skeleton-content', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
// Navigate to persona details
|
||||
await page
|
||||
.getByTestId(`persona-details-card-${persona.data.name}`)
|
||||
.click();
|
||||
await page.getByRole('tab', { name: 'Users' }).click();
|
||||
|
||||
// Add user to persona
|
||||
await page.getByTestId('add-persona-button').click();
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
const searchUser = page.waitForResponse(
|
||||
`/api/v1/search/query?q=*${encodeURIComponent(
|
||||
adminUser.responseData.displayName
|
||||
)}*`
|
||||
);
|
||||
await page
|
||||
.getByTestId('searchbar')
|
||||
.fill(adminUser.responseData.displayName);
|
||||
await searchUser;
|
||||
|
||||
await page
|
||||
.getByRole('listitem', { name: adminUser.responseData.displayName })
|
||||
.click();
|
||||
|
||||
const personaResponse = page.waitForResponse('/api/v1/personas/*');
|
||||
|
||||
await page.getByTestId('selectable-list-update-btn').click();
|
||||
await personaResponse;
|
||||
}
|
||||
);
|
||||
|
||||
await testPersona.step(
|
||||
'Verify Contract tab and status badge are visible if persona is set',
|
||||
async () => {
|
||||
await redirectToHomePage(page);
|
||||
await table.visitEntityPage(page);
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
// Verify Contract tab is not visible (should be hidden by persona customization)
|
||||
await expect(page.getByTestId('contract')).toBeVisible();
|
||||
|
||||
// Verify Contract status badge is not visible in header
|
||||
await expect(
|
||||
page.getByTestId('data-contract-latest-result-btn')
|
||||
).toBeVisible();
|
||||
|
||||
// Additional verification: Check that other tabs are still visible
|
||||
await expect(page.getByTestId('schema')).toBeVisible();
|
||||
await expect(page.getByTestId('activity_feed')).toBeVisible();
|
||||
await expect(page.getByTestId('sample_data')).toBeVisible();
|
||||
await expect(page.getByTestId('table_queries')).toBeVisible();
|
||||
await expect(page.getByTestId('profiler')).toBeVisible();
|
||||
await expect(page.getByTestId('lineage')).toBeVisible();
|
||||
await expect(page.getByTestId('custom_properties')).toBeVisible();
|
||||
}
|
||||
);
|
||||
|
||||
await testPersona.step(
|
||||
'Customize Table page to hide Contract tab',
|
||||
async () => {
|
||||
await settingClick(page, GlobalSettingOptions.PERSONA);
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
// Navigate to persona details and customize UI
|
||||
await page
|
||||
.getByTestId(`persona-details-card-${persona.data.name}`)
|
||||
.click();
|
||||
await page.getByRole('tab', { name: 'Customize UI' }).click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Navigate to Table customization
|
||||
await page
|
||||
.getByTestId('data-assets')
|
||||
.getByText('Data Assets')
|
||||
.click();
|
||||
await page.getByText('Table', { exact: true }).click();
|
||||
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
// Hide the Contract tab
|
||||
await page.getByTestId('tab-contract').click();
|
||||
await page.getByText('Hide', { exact: true }).click();
|
||||
|
||||
// Save the customization
|
||||
await page.getByTestId('save-button').click();
|
||||
await toastNotification(
|
||||
page,
|
||||
/^Page layout (created|updated) successfully\.$/
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
await testPersona.step(
|
||||
'Verify Contract tab and status badge are hidden after persona customization',
|
||||
async () => {
|
||||
// After applying persona customization to hide the contract tab,
|
||||
// we need to verify that the contract tab and status badge are not visible
|
||||
// when viewing the table page with the customized persona.
|
||||
|
||||
await redirectToHomePage(page);
|
||||
await table.visitEntityPage(page);
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
// Verify Contract tab is not visible (should be hidden by persona customization)
|
||||
await expect(page.getByTestId('contract')).not.toBeVisible();
|
||||
|
||||
// Verify Contract status badge is not visible in header
|
||||
await expect(
|
||||
page.getByTestId('data-contract-latest-result-btn')
|
||||
).not.toBeVisible();
|
||||
|
||||
// Additional verification: Check that other tabs are still visible
|
||||
await expect(page.getByTestId('schema')).toBeVisible();
|
||||
await expect(page.getByTestId('activity_feed')).toBeVisible();
|
||||
await expect(page.getByTestId('sample_data')).toBeVisible();
|
||||
await expect(page.getByTestId('table_queries')).toBeVisible();
|
||||
await expect(page.getByTestId('profiler')).toBeVisible();
|
||||
await expect(page.getByTestId('lineage')).toBeVisible();
|
||||
await expect(page.getByTestId('custom_properties')).toBeVisible();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@ -187,10 +187,18 @@ export const selectOption = async (
|
||||
.locator('.ant-select-selector')
|
||||
.click({ force: true });
|
||||
|
||||
await page.waitForSelector('.ant-select-item-empty', {
|
||||
state: 'detached',
|
||||
});
|
||||
|
||||
// Clear any existing input and type the new value
|
||||
const combobox = dropdownLocator.getByRole('combobox');
|
||||
await combobox.clear();
|
||||
await combobox.fill(optionTitle);
|
||||
|
||||
await page.waitForSelector('.ant-select-item-empty', {
|
||||
state: 'detached',
|
||||
});
|
||||
} else {
|
||||
await dropdownLocator.click();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user