mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-02 12:26:42 +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 = {
|
||||
name: `table_column_name_to_exist_in_id_${uuid()}`,
|
||||
label: 'Table Column Name To Exist',
|
||||
type: 'tableColumnNameToExist',
|
||||
field: 'testCase',
|
||||
description: 'New table test case for TableColumnNameToExist',
|
||||
name: `table_row_count_to_equal_in_id_${uuid()}`,
|
||||
label: 'Table Row Count To Equal',
|
||||
type: 'tableRowCountToEqual',
|
||||
value: '100000',
|
||||
description: 'New table test case for TableRowCountToEqual',
|
||||
};
|
||||
|
@ -31,6 +31,10 @@ import {
|
||||
redirectToHomePage,
|
||||
toastNotification,
|
||||
} from '../../utils/common';
|
||||
import {
|
||||
saveAndTriggerDataContractValidation,
|
||||
validateDataContractInsideBundleTestSuites,
|
||||
} from '../../utils/dataContracts';
|
||||
import { addOwner } from '../../utils/entity';
|
||||
|
||||
test.use({ storageState: 'playwright/.auth/admin.json' });
|
||||
@ -230,90 +234,9 @@ test.describe('Data Contracts', () => {
|
||||
).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Fill Contract Quality form', async () => {
|
||||
await page.getByRole('button', { name: 'Quality' }).click();
|
||||
|
||||
// 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 test.step('Save contract and validate for semantics', async () => {
|
||||
// save and trigger contract validation
|
||||
await saveAndTriggerDataContractValidation(page);
|
||||
|
||||
await expect(
|
||||
page.getByTestId('contract-card-title-container').filter({
|
||||
@ -335,6 +258,10 @@ test.describe('Data Contracts', () => {
|
||||
dataTestId: 'data-assets-header',
|
||||
});
|
||||
|
||||
const runNowResponse = page.waitForResponse(
|
||||
'/api/v1/dataContracts/*/validate'
|
||||
);
|
||||
|
||||
await page.getByTestId('contract-run-now-button').click();
|
||||
await runNowResponse;
|
||||
|
||||
@ -350,11 +277,85 @@ test.describe('Data Contracts', () => {
|
||||
).toContainText('Passed');
|
||||
});
|
||||
|
||||
await test.step('Edit contract and validate', async () => {
|
||||
await test.step(
|
||||
'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.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.locator('#testCaseFormV1_testTypeId').click();
|
||||
|
||||
const dropdown = page.locator('.rc-virtual-list-holder-inner');
|
||||
|
||||
await expect(dropdown).toBeVisible();
|
||||
|
||||
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();
|
||||
@ -363,25 +364,66 @@ test.describe('Data Contracts', () => {
|
||||
page.getByRole('checkbox', { name: 'Select all' })
|
||||
).toBeChecked();
|
||||
|
||||
await page.getByTestId('save-contract-btn').click();
|
||||
// save and trigger contract validation
|
||||
await saveAndTriggerDataContractValidation(page);
|
||||
|
||||
await toastNotification(page, 'Data contract saved successfully');
|
||||
|
||||
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 expect(page.getByTestId('alert-bar')).toBeVisible();
|
||||
await expect(
|
||||
page.locator('.anticon-exclamation-circle[role="img"]')
|
||||
).toBeVisible();
|
||||
}
|
||||
);
|
||||
|
||||
await page.reload();
|
||||
});
|
||||
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 table.visitEntityPage(page);
|
||||
|
||||
await page.getByTestId('contract').click();
|
||||
|
||||
await page.getByTestId('contract-view-switch-tab-yaml').click();
|
||||
|
||||
await expect(page.getByTestId('code-mirror-container')).toBeVisible();
|
||||
@ -403,7 +445,7 @@ test.describe('Data Contracts', () => {
|
||||
|
||||
await test.step('Delete contract', async () => {
|
||||
const deleteContractResponse = page.waitForResponse(
|
||||
'api/v1/dataContracts/*?hardDelete=true'
|
||||
'api/v1/dataContracts/*?hardDelete=true&recursive=true'
|
||||
);
|
||||
|
||||
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) => {
|
||||
const response = await APIClient.delete<void>(
|
||||
`/dataContracts/${contractId}?hardDelete=true`
|
||||
`/dataContracts/${contractId}?hardDelete=true&recursive=true`
|
||||
);
|
||||
|
||||
return response.data;
|
||||
|
Loading…
x
Reference in New Issue
Block a user