mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-02 20:35:25 +00:00
test(ui): enhance data contract playwright test (#22795)
* enhance data contract test * minor fix
This commit is contained in:
parent
1cc1abcd27
commit
6358446c0e
@ -44,9 +44,9 @@ export const DATA_CONTRACT_SEMANTICS2 = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const NEW_TABLE_TEST_CASE = {
|
export const NEW_TABLE_TEST_CASE = {
|
||||||
name: `table_column_name_to_exist_in_id_${uuid()}`,
|
name: `table_row_count_to_equal_in_id_${uuid()}`,
|
||||||
label: 'Table Column Name To Exist',
|
label: 'Table Row Count To Equal',
|
||||||
type: 'tableColumnNameToExist',
|
type: 'tableRowCountToEqual',
|
||||||
field: 'testCase',
|
value: '100000',
|
||||||
description: 'New table test case for TableColumnNameToExist',
|
description: 'New table test case for TableRowCountToEqual',
|
||||||
};
|
};
|
||||||
|
@ -31,6 +31,10 @@ import {
|
|||||||
redirectToHomePage,
|
redirectToHomePage,
|
||||||
toastNotification,
|
toastNotification,
|
||||||
} from '../../utils/common';
|
} from '../../utils/common';
|
||||||
|
import {
|
||||||
|
saveAndTriggerDataContractValidation,
|
||||||
|
validateDataContractInsideBundleTestSuites,
|
||||||
|
} from '../../utils/dataContracts';
|
||||||
import { addOwner } from '../../utils/entity';
|
import { addOwner } from '../../utils/entity';
|
||||||
|
|
||||||
test.use({ storageState: 'playwright/.auth/admin.json' });
|
test.use({ storageState: 'playwright/.auth/admin.json' });
|
||||||
@ -230,90 +234,9 @@ test.describe('Data Contracts', () => {
|
|||||||
).not.toBeVisible();
|
).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
await test.step('Fill Contract Quality form', async () => {
|
await test.step('Save contract and validate for semantics', async () => {
|
||||||
await page.getByRole('button', { name: 'Quality' }).click();
|
// save and trigger contract validation
|
||||||
|
await saveAndTriggerDataContractValidation(page);
|
||||||
// Fill Contract Quality form
|
|
||||||
|
|
||||||
await page.getByTestId('add-test-button').click();
|
|
||||||
|
|
||||||
await expect(page.getByRole('dialog')).toBeVisible();
|
|
||||||
|
|
||||||
await page.fill(
|
|
||||||
'[data-testid="test-case-name"]',
|
|
||||||
NEW_TABLE_TEST_CASE.name
|
|
||||||
);
|
|
||||||
|
|
||||||
await page.click('#testCaseFormV1_testTypeId');
|
|
||||||
await page.waitForSelector(`text=${NEW_TABLE_TEST_CASE.label}`);
|
|
||||||
await page.click(`text=${NEW_TABLE_TEST_CASE.label}`);
|
|
||||||
await page.fill(
|
|
||||||
'#testCaseFormV1_params_columnName',
|
|
||||||
NEW_TABLE_TEST_CASE.field
|
|
||||||
);
|
|
||||||
|
|
||||||
await page.click('[data-testid="tags-selector"] input');
|
|
||||||
await page.fill('[data-testid="tags-selector"] input', testTag.data.name);
|
|
||||||
await page
|
|
||||||
.getByTestId(`tag-${testTag.responseData.fullyQualifiedName}`)
|
|
||||||
.click();
|
|
||||||
|
|
||||||
await clickOutside(page);
|
|
||||||
|
|
||||||
await page.click('[data-testid="glossary-terms-selector"] input');
|
|
||||||
await page.fill(
|
|
||||||
'[data-testid="glossary-terms-selector"] input',
|
|
||||||
testGlossaryTerm.data.name
|
|
||||||
);
|
|
||||||
|
|
||||||
await page
|
|
||||||
.getByTestId(`tag-${testGlossaryTerm.responseData.fullyQualifiedName}`)
|
|
||||||
.click();
|
|
||||||
|
|
||||||
await clickOutside(page);
|
|
||||||
|
|
||||||
const testCaseResponse = page.waitForResponse(
|
|
||||||
'/api/v1/dataQuality/testCases'
|
|
||||||
);
|
|
||||||
await page.click('[data-testid="create-btn"]');
|
|
||||||
await testCaseResponse;
|
|
||||||
|
|
||||||
await page.waitForTimeout(100);
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page
|
|
||||||
.locator('.ant-table-cell')
|
|
||||||
.filter({ hasText: NEW_TABLE_TEST_CASE.name })
|
|
||||||
).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
await test.step('Save contract and validate', async () => {
|
|
||||||
const saveContractResponse = page.waitForResponse(
|
|
||||||
'/api/v1/dataContracts'
|
|
||||||
);
|
|
||||||
await page.getByTestId('save-contract-btn').click();
|
|
||||||
await saveContractResponse;
|
|
||||||
|
|
||||||
await toastNotification(page, 'Data contract saved successfully');
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page
|
|
||||||
.getByTestId('contract-card-title-container')
|
|
||||||
.filter({ hasText: 'Contract Status' })
|
|
||||||
).not.toBeVisible();
|
|
||||||
|
|
||||||
const runNowResponse = page.waitForResponse(
|
|
||||||
'/api/v1/dataContracts/*/validate'
|
|
||||||
);
|
|
||||||
await page.getByTestId('contract-run-now-button').click();
|
|
||||||
await runNowResponse;
|
|
||||||
|
|
||||||
await toastNotification(
|
|
||||||
page,
|
|
||||||
'Contract validation trigger successfully.'
|
|
||||||
);
|
|
||||||
|
|
||||||
await page.reload();
|
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('contract-card-title-container').filter({
|
page.getByTestId('contract-card-title-container').filter({
|
||||||
@ -335,6 +258,10 @@ test.describe('Data Contracts', () => {
|
|||||||
dataTestId: 'data-assets-header',
|
dataTestId: 'data-assets-header',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const runNowResponse = page.waitForResponse(
|
||||||
|
'/api/v1/dataContracts/*/validate'
|
||||||
|
);
|
||||||
|
|
||||||
await page.getByTestId('contract-run-now-button').click();
|
await page.getByTestId('contract-run-now-button').click();
|
||||||
await runNowResponse;
|
await runNowResponse;
|
||||||
|
|
||||||
@ -350,38 +277,153 @@ test.describe('Data Contracts', () => {
|
|||||||
).toContainText('Passed');
|
).toContainText('Passed');
|
||||||
});
|
});
|
||||||
|
|
||||||
await test.step('Edit contract and validate', async () => {
|
await test.step(
|
||||||
await page.getByTestId('contract-edit-button').click();
|
'Add table test case and validate for quality',
|
||||||
|
async () => {
|
||||||
|
await page.getByTestId('contract-edit-button').click();
|
||||||
|
|
||||||
await page.getByRole('tab', { name: 'Quality' }).click();
|
await page.getByRole('tab', { name: 'Quality' }).click();
|
||||||
|
|
||||||
await page
|
await page.getByTestId('add-test-button').click();
|
||||||
.locator('input[type="checkbox"][aria-label="Select all"]')
|
|
||||||
.check();
|
|
||||||
|
|
||||||
await expect(
|
await expect(page.getByRole('dialog')).toBeVisible();
|
||||||
page.getByRole('checkbox', { name: 'Select all' })
|
|
||||||
).toBeChecked();
|
|
||||||
|
|
||||||
await page.getByTestId('save-contract-btn').click();
|
await page.fill(
|
||||||
|
'[data-testid="test-case-name"]',
|
||||||
|
NEW_TABLE_TEST_CASE.name
|
||||||
|
);
|
||||||
|
|
||||||
await toastNotification(page, 'Data contract saved successfully');
|
await page.locator('#testCaseFormV1_testTypeId').click();
|
||||||
|
|
||||||
const runNowResponse = page.waitForResponse(
|
const dropdown = page.locator('.rc-virtual-list-holder-inner');
|
||||||
'/api/v1/dataContracts/*/validate'
|
|
||||||
);
|
|
||||||
await page.getByTestId('contract-run-now-button').click();
|
|
||||||
await runNowResponse;
|
|
||||||
|
|
||||||
await toastNotification(
|
await expect(dropdown).toBeVisible();
|
||||||
page,
|
|
||||||
'Contract validation trigger successfully.'
|
|
||||||
);
|
|
||||||
|
|
||||||
await page.reload();
|
for (let i = 0; i < 20; i++) {
|
||||||
});
|
const optionVisible = await dropdown
|
||||||
|
.getByText(NEW_TABLE_TEST_CASE.label)
|
||||||
|
.isVisible();
|
||||||
|
if (optionVisible) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
await dropdown.press('ArrowDown');
|
||||||
|
}
|
||||||
|
|
||||||
|
await dropdown.getByText(NEW_TABLE_TEST_CASE.label).click();
|
||||||
|
|
||||||
|
await page.click(`text=${NEW_TABLE_TEST_CASE.label}`);
|
||||||
|
await page.fill(
|
||||||
|
'#testCaseFormV1_params_value',
|
||||||
|
NEW_TABLE_TEST_CASE.value
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.click('[data-testid="tags-selector"] input');
|
||||||
|
await page.fill(
|
||||||
|
'[data-testid="tags-selector"] input',
|
||||||
|
testTag.data.name
|
||||||
|
);
|
||||||
|
await page
|
||||||
|
.getByTestId(`tag-${testTag.responseData.fullyQualifiedName}`)
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await clickOutside(page);
|
||||||
|
|
||||||
|
await page.click('[data-testid="glossary-terms-selector"] input');
|
||||||
|
await page.fill(
|
||||||
|
'[data-testid="glossary-terms-selector"] input',
|
||||||
|
testGlossaryTerm.data.name
|
||||||
|
);
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByTestId(
|
||||||
|
`tag-${testGlossaryTerm.responseData.fullyQualifiedName}`
|
||||||
|
)
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await clickOutside(page);
|
||||||
|
|
||||||
|
const testCaseResponse = page.waitForResponse(
|
||||||
|
'/api/v1/dataQuality/testCases'
|
||||||
|
);
|
||||||
|
await page.click('[data-testid="create-btn"]');
|
||||||
|
await testCaseResponse;
|
||||||
|
|
||||||
|
await page.waitForTimeout(100);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.locator('.ant-table-cell')
|
||||||
|
.filter({ hasText: NEW_TABLE_TEST_CASE.name })
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator('input[type="checkbox"][aria-label="Select all"]')
|
||||||
|
.check();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole('checkbox', { name: 'Select all' })
|
||||||
|
).toBeChecked();
|
||||||
|
|
||||||
|
// save and trigger contract validation
|
||||||
|
await saveAndTriggerDataContractValidation(page);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('alert-bar')).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.locator('.anticon-exclamation-circle[role="img"]')
|
||||||
|
).toBeVisible();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Validate inside the Observability, bundle test suites, that data contract test suite is present',
|
||||||
|
async () => {
|
||||||
|
await validateDataContractInsideBundleTestSuites(page);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByTestId('test-suite-table')
|
||||||
|
.locator('.ant-table-cell')
|
||||||
|
.filter({
|
||||||
|
hasText: `${DATA_CONTRACT_DETAILS.name} - Data Contract Expectations`,
|
||||||
|
})
|
||||||
|
).toBeVisible();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Edit quality expectations from the data contract and validate',
|
||||||
|
async () => {
|
||||||
|
await table.visitEntityPage(page);
|
||||||
|
|
||||||
|
await page.getByTestId('contract').click();
|
||||||
|
|
||||||
|
await page.getByTestId('contract-edit-button').click();
|
||||||
|
|
||||||
|
await page.getByRole('tab', { name: 'Quality' }).click();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator('input[type="checkbox"][aria-label="Select all"]')
|
||||||
|
.uncheck();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole('checkbox', { name: 'Select all' })
|
||||||
|
).not.toBeChecked();
|
||||||
|
|
||||||
|
await saveAndTriggerDataContractValidation(page);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByTestId('contract-status-card-item-Quality Status')
|
||||||
|
).not.toBeVisible();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: Add a step to validate the test suite is removed from observability -> bundle test suites
|
||||||
|
|
||||||
await test.step('Verify YAML view', async () => {
|
await test.step('Verify YAML view', async () => {
|
||||||
|
await table.visitEntityPage(page);
|
||||||
|
|
||||||
|
await page.getByTestId('contract').click();
|
||||||
|
|
||||||
await page.getByTestId('contract-view-switch-tab-yaml').click();
|
await page.getByTestId('contract-view-switch-tab-yaml').click();
|
||||||
|
|
||||||
await expect(page.getByTestId('code-mirror-container')).toBeVisible();
|
await expect(page.getByTestId('code-mirror-container')).toBeVisible();
|
||||||
@ -403,7 +445,7 @@ test.describe('Data Contracts', () => {
|
|||||||
|
|
||||||
await test.step('Delete contract', async () => {
|
await test.step('Delete contract', async () => {
|
||||||
const deleteContractResponse = page.waitForResponse(
|
const deleteContractResponse = page.waitForResponse(
|
||||||
'api/v1/dataContracts/*?hardDelete=true'
|
'api/v1/dataContracts/*?hardDelete=true&recursive=true'
|
||||||
);
|
);
|
||||||
|
|
||||||
await page.getByTestId('delete-contract-button').click();
|
await page.getByTestId('delete-contract-button').click();
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 Collate.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import { expect, Page } from '@playwright/test';
|
||||||
|
import { SidebarItem } from '../constant/sidebar';
|
||||||
|
import { toastNotification } from './common';
|
||||||
|
import { sidebarClick } from './sidebar';
|
||||||
|
|
||||||
|
export const saveAndTriggerDataContractValidation = async (page: Page) => {
|
||||||
|
const saveContractResponse = page.waitForResponse('/api/v1/dataContracts');
|
||||||
|
await page.getByTestId('save-contract-btn').click();
|
||||||
|
await saveContractResponse;
|
||||||
|
|
||||||
|
await toastNotification(page, 'Data contract saved successfully');
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByTestId('contract-card-title-container')
|
||||||
|
.filter({ hasText: 'Contract Status' })
|
||||||
|
).not.toBeVisible();
|
||||||
|
|
||||||
|
const runNowResponse = page.waitForResponse(
|
||||||
|
'/api/v1/dataContracts/*/validate'
|
||||||
|
);
|
||||||
|
await page.getByTestId('contract-run-now-button').click();
|
||||||
|
await runNowResponse;
|
||||||
|
|
||||||
|
await toastNotification(page, 'Contract validation trigger successfully.');
|
||||||
|
|
||||||
|
await page.reload();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const validateDataContractInsideBundleTestSuites = async (
|
||||||
|
page: Page
|
||||||
|
) => {
|
||||||
|
await sidebarClick(page, SidebarItem.DATA_QUALITY);
|
||||||
|
|
||||||
|
const testSuiteResponse = page.waitForResponse(
|
||||||
|
'/api/v1/dataQuality/testSuites/search/list?*'
|
||||||
|
);
|
||||||
|
await page.getByTestId('test-suites').click();
|
||||||
|
await testSuiteResponse;
|
||||||
|
|
||||||
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator('.ant-radio-button-wrapper')
|
||||||
|
.filter({ hasText: 'Bundle Suites' })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(page.getByTestId('test-suite-table')).toBeVisible();
|
||||||
|
};
|
@ -98,7 +98,7 @@ export const validateContractById = async (contractId: string) => {
|
|||||||
|
|
||||||
export const deleteContractById = async (contractId: string) => {
|
export const deleteContractById = async (contractId: string) => {
|
||||||
const response = await APIClient.delete<void>(
|
const response = await APIClient.delete<void>(
|
||||||
`/dataContracts/${contractId}?hardDelete=true`
|
`/dataContracts/${contractId}?hardDelete=true&recursive=true`
|
||||||
);
|
);
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user