Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ import {
triggerContractValidation,
validateDataContractInsideBundleTestSuites,
validateSecurityAndSLADetails,
waitForDataContractExecution,
waitForContractExecutionWithFallback,
} from '../../utils/dataContracts';
import {
addOwner,
Expand Down Expand Up @@ -143,7 +143,7 @@ test.describe('Data Contracts', () => {
page,
}) => {
// 12-min timeout so waitForDataContractExecution completes first.
test.setTimeout(720_000);
test.setTimeout(900_000);

const testClassification = new ClassificationClass();
const testTag = new TagClass({
Expand Down Expand Up @@ -259,7 +259,7 @@ test.describe('Data Contracts', () => {
await selectOption(
page,
ruleLocator.locator('.rule--value .ant-select'),
user.responseData.displayName,
user.getUserDisplayName(),
true
);
await page.getByRole('button', { name: 'Add New Rule' }).click();
Expand Down Expand Up @@ -353,7 +353,7 @@ test.describe('Data Contracts', () => {

await addOwner({
page,
owner: user.responseData.displayName,
owner: user.getUserDisplayName(),
type: 'Users',
endpoint: entity.endpoint,
dataTestId: 'data-assets-header',
Expand Down Expand Up @@ -473,6 +473,9 @@ test.describe('Data Contracts', () => {
// save and trigger contract validation
const response = await saveAndTriggerDataContractValidation(page);

// The test suite results may be available before the contract's latestResult is
// updated. If waitForDataContractExecution times out, fall back to the DataQuality
// page to verify the test suite ran successfully.
if (
typeof response === 'object' &&
response !== null &&
Expand All @@ -481,13 +484,20 @@ test.describe('Data Contracts', () => {
const { id: contractId } = response as { id: string };

if (contractId) {
await waitForDataContractExecution(page, contractId);
const contractResultVisible =
await waitForContractExecutionWithFallback(
page,
contractId,
DATA_CONTRACT_DETAILS.name
);

if (contractResultVisible) {
await expect(
page.getByTestId('data-contract-latest-result-btn')
).toBeVisible();
}
}
}

await expect(
page.getByTestId('data-contract-latest-result-btn')
).toBeVisible();
});

await test.step('Validate inside the Observability, bundle test suites, that data contract test suite is present', async () => {
Expand Down Expand Up @@ -2383,17 +2393,17 @@ entitiesWithDataContracts.forEach((EntityClass) => {

const searchUser = page.waitForResponse(
`/api/v1/search/query?q=*${encodeURIComponent(
adminUser.responseData.displayName
adminUser.getUserDisplayName()
)}*`
);
await page
.getByTestId('searchbar')
.fill(adminUser.responseData.displayName);
.fill(adminUser.getUserDisplayName());
await searchUser;

await page
.getByRole('listitem', {
name: adminUser.responseData.displayName,
name: adminUser.getUserDisplayName(),
})
.click();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ test.describe('Data Contracts Semantics Rule Owner', () => {

await addOwner({
page,
owner: user2.responseData.displayName,
owner: user2.getUserDisplayName(),
type: 'Users',
endpoint: EntityTypeEndpoint.Table,
dataTestId: 'data-assets-header',
Expand Down Expand Up @@ -210,7 +210,7 @@ test.describe('Data Contracts Semantics Rule Owner', () => {
await selectOption(
page,
ruleLocator.locator('.rule--value .ant-select'),
user.responseData.displayName,
user.getUserDisplayName(),
true
);

Expand All @@ -235,7 +235,7 @@ test.describe('Data Contracts Semantics Rule Owner', () => {

await updateOwner({
page,
owner: user.responseData.displayName,
owner: user.getUserDisplayName(),
type: 'Users',
endpoint: EntityTypeEndpoint.Table,
dataTestId: 'data-assets-header',
Expand Down Expand Up @@ -281,7 +281,7 @@ test.describe('Data Contracts Semantics Rule Owner', () => {

await addOwner({
page,
owner: user2.responseData.displayName,
owner: user2.getUserDisplayName(),
type: 'Users',
endpoint: EntityTypeEndpoint.Table,
dataTestId: 'data-assets-header',
Expand Down Expand Up @@ -314,7 +314,7 @@ test.describe('Data Contracts Semantics Rule Owner', () => {
await selectOption(
page,
ruleLocator.locator('.rule--value .ant-select'),
user.responseData.displayName,
user.getUserDisplayName(),
true
);

Expand All @@ -340,7 +340,7 @@ test.describe('Data Contracts Semantics Rule Owner', () => {

await updateOwner({
page,
owner: user.responseData.displayName,
owner: user.getUserDisplayName(),
type: 'Users',
endpoint: EntityTypeEndpoint.Table,
dataTestId: 'data-assets-header',
Expand Down Expand Up @@ -385,7 +385,7 @@ test.describe('Data Contracts Semantics Rule Owner', () => {

await addOwner({
page,
owner: user2.responseData.displayName,
owner: user2.getUserDisplayName(),
type: 'Users',
endpoint: EntityTypeEndpoint.Table,
dataTestId: 'data-assets-header',
Expand Down Expand Up @@ -418,7 +418,7 @@ test.describe('Data Contracts Semantics Rule Owner', () => {
await selectOption(
page,
ruleLocator.locator('.rule--value .ant-select'),
user.responseData.displayName,
user.getUserDisplayName(),
true
);

Expand All @@ -443,7 +443,7 @@ test.describe('Data Contracts Semantics Rule Owner', () => {

await updateOwner({
page,
owner: user.responseData.displayName,
owner: user.getUserDisplayName(),
type: 'Users',
endpoint: EntityTypeEndpoint.Table,
dataTestId: 'data-assets-header',
Expand Down Expand Up @@ -527,7 +527,7 @@ test.describe('Data Contracts Semantics Rule Owner', () => {
await test.step('Should Passed since entity has owner', async () => {
await addOwner({
page,
owner: user2.responseData.displayName,
owner: user2.getUserDisplayName(),
type: 'Users',
endpoint: EntityTypeEndpoint.Table,
dataTestId: 'data-assets-header',
Expand Down Expand Up @@ -609,7 +609,7 @@ test.describe('Data Contracts Semantics Rule Owner', () => {
await test.step('Should Failed since entity has owner', async () => {
await addOwner({
page,
owner: user2.responseData.displayName,
owner: user2.getUserDisplayName(),
type: 'Users',
endpoint: EntityTypeEndpoint.Table,
dataTestId: 'data-assets-header',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,76 @@ export const waitForDataContractExecution = async (
.toEqual(expect.stringMatching(terminalStatusPattern));
};

/**
* Waits for the data contract execution to complete. If the contract's latestResult
* is not updated in time (the test suite takes significant time and the contract result
* propagation lags), falls back to the DataQuality page to verify the test suite results
* directly from the Bundle Suites list.
*
* Returns true if the contract's own result was available, false if the DQ fallback was used.
*/
export const waitForContractExecutionWithFallback = async (
page: Page,
contractId: string,
contractName: string
): Promise<boolean> => {
try {
await waitForDataContractExecution(page, contractId);

return true;
} catch {
// The test suite has results but the contract's latestResult was not updated in time.
// Verify execution status directly from the DataQuality Bundle Suites page.
await validateDataContractInsideBundleTestSuites(page);
Comment thread
shrabantipaul-collate marked this conversation as resolved.

const suiteNameCell = page
.getByTestId('test-suite-table')
.locator('.ant-table-cell')
.filter({ hasText: `Data Contract - ${contractName}` });

await expect(suiteNameCell).toBeVisible();

const testCaseListResponse = page.waitForResponse(
'/api/v1/dataQuality/testCases/search/list*'
);
await suiteNameCell.locator('a').first().click();
const testCasesJson = await (await testCaseListResponse).json();
await waitForAllLoadersToDisappear(page);

await expect(page.getByTestId('manage-button')).toBeVisible();

type TestCaseEntry = { testCaseResult?: { testCaseStatus?: string } };

const testCases = testCasesJson?.data ?? [];
const hasFailure = testCases.some(
(tc: TestCaseEntry) => tc.testCaseResult?.testCaseStatus === 'Failed'
);
const hasAborted = testCases.some(
(tc: TestCaseEntry) => tc.testCaseResult?.testCaseStatus === 'Aborted'
);
const hasSuccess = testCases.some(
(tc: TestCaseEntry) => tc.testCaseResult?.testCaseStatus === 'Success'
);
Comment thread
gitar-bot[bot] marked this conversation as resolved.

let suiteStatus = 'Running';

if (hasFailure) {
suiteStatus = 'Failed';
} else if (hasAborted) {
suiteStatus = 'Aborted';
} else if (hasSuccess) {
suiteStatus = 'Success';
}

const terminalStatusPattern =
/(Aborted|Success|Failed|PartialSuccess|Queued)/;

expect(suiteStatus).toEqual(expect.stringMatching(terminalStatusPattern));
Comment thread
shrabantipaul-collate marked this conversation as resolved.

return false;
}
};

export const saveSecurityAndSLADetails = async (
page: Page,
data: DataContractSecuritySlaData,
Expand Down
Loading