mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-11 16:58:38 +00:00
test(ui): e2e tests for data contracts (#22737)
* add test for create data contract * add test * add test * fix tests * add test for data contract export and delete * refactor test
This commit is contained in:
parent
12808a9a1f
commit
d4f643bd10
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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 { uuid } from '../utils/common';
|
||||||
|
|
||||||
|
export const DATA_CONTRACT_DETAILS = {
|
||||||
|
name: `data_contract_${uuid()}`,
|
||||||
|
description: 'new data contract description',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DATA_CONTRACT_SEMANTICS1 = {
|
||||||
|
name: `data_contract_semantic_1_${uuid()}`,
|
||||||
|
description: 'new data contract semantic description 1',
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
field: 'Owners',
|
||||||
|
operator: 'Is',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'Description',
|
||||||
|
operator: 'Is Set',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DATA_CONTRACT_SEMANTICS2 = {
|
||||||
|
name: `data_contract_semantic_2_${uuid()}`,
|
||||||
|
description: 'new data contract semantic description 2',
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
field: 'Name',
|
||||||
|
operator: 'Is Set',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
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',
|
||||||
|
};
|
@ -112,19 +112,13 @@ test.describe('Curated Assets', () => {
|
|||||||
await selectOption(
|
await selectOption(
|
||||||
page,
|
page,
|
||||||
ruleLocator2.locator('.rule--field .ant-select'),
|
ruleLocator2.locator('.rule--field .ant-select'),
|
||||||
'Description'
|
'Deleted'
|
||||||
);
|
);
|
||||||
|
|
||||||
await selectOption(
|
await selectOption(
|
||||||
page,
|
page,
|
||||||
ruleLocator2.locator('.rule--operator .ant-select'),
|
ruleLocator2.locator('.rule--operator .ant-select'),
|
||||||
'=='
|
'Is not null'
|
||||||
);
|
|
||||||
|
|
||||||
await selectOption(
|
|
||||||
page,
|
|
||||||
ruleLocator2.locator('.rule--value .ant-select'),
|
|
||||||
'Complete'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect(page.locator('[data-testid="saveButton"]')).toBeEnabled();
|
await expect(page.locator('[data-testid="saveButton"]')).toBeEnabled();
|
||||||
|
@ -157,9 +157,7 @@ test.describe('Description Suggestions Table Entity', () => {
|
|||||||
state: 'detached',
|
state: 'detached',
|
||||||
});
|
});
|
||||||
|
|
||||||
await expect(page.locator('.ant-badge .ant-badge-count')).toContainText(
|
await expect(page.locator('.ant-badge [title="6"]')).toBeVisible();
|
||||||
'6'
|
|
||||||
);
|
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.locator(
|
page.locator(
|
||||||
|
@ -0,0 +1,425 @@
|
|||||||
|
/*
|
||||||
|
* 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, test } from '@playwright/test';
|
||||||
|
import {
|
||||||
|
DATA_CONTRACT_DETAILS,
|
||||||
|
DATA_CONTRACT_SEMANTICS1,
|
||||||
|
DATA_CONTRACT_SEMANTICS2,
|
||||||
|
NEW_TABLE_TEST_CASE,
|
||||||
|
} from '../../constant/dataContracts';
|
||||||
|
import { EntityTypeEndpoint } from '../../support/entity/Entity.interface';
|
||||||
|
import { TableClass } from '../../support/entity/TableClass';
|
||||||
|
import { Glossary } from '../../support/glossary/Glossary';
|
||||||
|
import { GlossaryTerm } from '../../support/glossary/GlossaryTerm';
|
||||||
|
import { ClassificationClass } from '../../support/tag/ClassificationClass';
|
||||||
|
import { TagClass } from '../../support/tag/TagClass';
|
||||||
|
import { UserClass } from '../../support/user/UserClass';
|
||||||
|
import { selectOption } from '../../utils/advancedSearch';
|
||||||
|
import {
|
||||||
|
clickOutside,
|
||||||
|
createNewPage,
|
||||||
|
redirectToHomePage,
|
||||||
|
toastNotification,
|
||||||
|
} from '../../utils/common';
|
||||||
|
import { addOwner } from '../../utils/entity';
|
||||||
|
|
||||||
|
test.use({ storageState: 'playwright/.auth/admin.json' });
|
||||||
|
|
||||||
|
test.describe('Data Contracts', () => {
|
||||||
|
const table = new TableClass();
|
||||||
|
const user = new UserClass();
|
||||||
|
const testClassification = new ClassificationClass();
|
||||||
|
const testTag = new TagClass({
|
||||||
|
classification: testClassification.data.name,
|
||||||
|
});
|
||||||
|
const testGlossary = new Glossary();
|
||||||
|
const testGlossaryTerm = new GlossaryTerm(testGlossary);
|
||||||
|
|
||||||
|
test.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||||
|
test.slow(true);
|
||||||
|
|
||||||
|
const { apiContext, afterAction } = await createNewPage(browser);
|
||||||
|
await table.create(apiContext);
|
||||||
|
await user.create(apiContext);
|
||||||
|
await testClassification.create(apiContext);
|
||||||
|
await testTag.create(apiContext);
|
||||||
|
await testGlossary.create(apiContext);
|
||||||
|
await testGlossaryTerm.create(apiContext);
|
||||||
|
await afterAction();
|
||||||
|
});
|
||||||
|
|
||||||
|
test.afterAll('Cleanup', async ({ browser }) => {
|
||||||
|
test.slow(true);
|
||||||
|
|
||||||
|
const { apiContext, afterAction } = await createNewPage(browser);
|
||||||
|
await table.delete(apiContext);
|
||||||
|
await user.delete(apiContext);
|
||||||
|
await testClassification.delete(apiContext);
|
||||||
|
await testTag.delete(apiContext);
|
||||||
|
await testGlossary.delete(apiContext);
|
||||||
|
await testGlossaryTerm.delete(apiContext);
|
||||||
|
await afterAction();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Create Data Contract and validate', async ({ page }) => {
|
||||||
|
test.slow(true);
|
||||||
|
|
||||||
|
await test.step('Redirect to Home Page and visit entity', async () => {
|
||||||
|
await redirectToHomePage(page);
|
||||||
|
await table.visitEntityPage(page);
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'Open contract section and start adding contract',
|
||||||
|
async () => {
|
||||||
|
await page.click('[data-testid="contract"]');
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await test.step('Fill Contract Details form', async () => {
|
||||||
|
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('add-owner').click();
|
||||||
|
await page.getByRole('tab', { name: 'Users' }).click();
|
||||||
|
await page
|
||||||
|
.getByTestId('owner-select-users-search-bar')
|
||||||
|
.fill(user.responseData.displayName);
|
||||||
|
await page
|
||||||
|
.getByRole('listitem', {
|
||||||
|
name: user.responseData.displayName,
|
||||||
|
exact: true,
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
await page.getByTestId('selectable-list-update-btn').click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByTestId('owner-link')
|
||||||
|
.getByTestId(user.responseData.displayName)
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Fill Contract Schema form', async () => {
|
||||||
|
await page.getByRole('button', { name: 'Schema' }).click();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator('input[type="checkbox"][aria-label="Select all"]')
|
||||||
|
.check();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole('checkbox', { name: 'Select all' })
|
||||||
|
).toBeChecked();
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Fill first Contract Semantics form', async () => {
|
||||||
|
await page.getByRole('button', { 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
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(page.locator('#semantics_0_enabled')).toHaveAttribute(
|
||||||
|
'aria-checked',
|
||||||
|
'true'
|
||||||
|
);
|
||||||
|
|
||||||
|
const ruleLocator = page.locator('.group').nth(0);
|
||||||
|
await selectOption(
|
||||||
|
page,
|
||||||
|
ruleLocator.locator('.group--field .ant-select'),
|
||||||
|
DATA_CONTRACT_SEMANTICS1.rules[0].field
|
||||||
|
);
|
||||||
|
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'
|
||||||
|
);
|
||||||
|
await page.getByRole('button', { name: 'Add New Rule' }).click();
|
||||||
|
|
||||||
|
await expect(page.locator('.group--conjunctions')).toBeVisible();
|
||||||
|
|
||||||
|
const ruleLocator2 = page.locator('.rule').nth(1);
|
||||||
|
await selectOption(
|
||||||
|
page,
|
||||||
|
ruleLocator2.locator('.rule--field .ant-select'),
|
||||||
|
DATA_CONTRACT_SEMANTICS1.rules[1].field
|
||||||
|
);
|
||||||
|
await selectOption(
|
||||||
|
page,
|
||||||
|
ruleLocator2.locator('.rule--operator .ant-select'),
|
||||||
|
DATA_CONTRACT_SEMANTICS1.rules[1].operator
|
||||||
|
);
|
||||||
|
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);
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByTestId('contract-semantics-card-0')
|
||||||
|
.locator('.semantic-form-item-description')
|
||||||
|
).toContainText(DATA_CONTRACT_SEMANTICS1.description);
|
||||||
|
|
||||||
|
await page.locator('.expand-collapse-icon').click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator('.semantic-rule-editor-view-only')
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Add second semantic and delete it', async () => {
|
||||||
|
await page.getByTestId('add-semantic-button').click();
|
||||||
|
await page.fill('#semantics_1_name', DATA_CONTRACT_SEMANTICS2.name);
|
||||||
|
await page.fill(
|
||||||
|
'#semantics_1_description',
|
||||||
|
DATA_CONTRACT_SEMANTICS2.description
|
||||||
|
);
|
||||||
|
const ruleLocator3 = page.locator('.group').nth(2);
|
||||||
|
await selectOption(
|
||||||
|
page,
|
||||||
|
ruleLocator3.locator('.group--field .ant-select'),
|
||||||
|
DATA_CONTRACT_SEMANTICS2.rules[0].field
|
||||||
|
);
|
||||||
|
await selectOption(
|
||||||
|
page,
|
||||||
|
ruleLocator3.locator('.rule--operator .ant-select'),
|
||||||
|
DATA_CONTRACT_SEMANTICS2.rules[0].operator
|
||||||
|
);
|
||||||
|
await page.getByTestId('save-semantic-button').click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByTestId('contract-semantics-card-1')
|
||||||
|
.locator('.semantic-form-item-title')
|
||||||
|
).toContainText(DATA_CONTRACT_SEMANTICS2.name);
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByTestId('contract-semantics-card-1')
|
||||||
|
.locator('.semantic-form-item-description')
|
||||||
|
).toContainText(DATA_CONTRACT_SEMANTICS2.description);
|
||||||
|
|
||||||
|
await page.getByTestId('delete-semantic-1').click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByTestId('contract-semantics-card-1')
|
||||||
|
).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 expect(
|
||||||
|
page.getByTestId('contract-card-title-container').filter({
|
||||||
|
hasText: 'Contract Status',
|
||||||
|
})
|
||||||
|
).toBeVisible();
|
||||||
|
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 addOwner({
|
||||||
|
page,
|
||||||
|
owner: 'admin',
|
||||||
|
type: 'Users',
|
||||||
|
endpoint: EntityTypeEndpoint.Table,
|
||||||
|
dataTestId: 'data-assets-header',
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.getByTestId('contract-run-now-button').click();
|
||||||
|
await runNowResponse;
|
||||||
|
|
||||||
|
await toastNotification(
|
||||||
|
page,
|
||||||
|
'Contract validation trigger successfully.'
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.reload();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByTestId('contract-status-card-item-Semantics-status')
|
||||||
|
).toContainText('Passed');
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Edit contract and validate', async () => {
|
||||||
|
await page.getByTestId('contract-edit-button').click();
|
||||||
|
|
||||||
|
await page.getByRole('tab', { name: 'Quality' }).click();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator('input[type="checkbox"][aria-label="Select all"]')
|
||||||
|
.check();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole('checkbox', { name: 'Select all' })
|
||||||
|
).toBeChecked();
|
||||||
|
|
||||||
|
await page.getByTestId('save-contract-btn').click();
|
||||||
|
|
||||||
|
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 page.reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Verify YAML view', async () => {
|
||||||
|
await page.getByTestId('contract-view-switch-tab-yaml').click();
|
||||||
|
|
||||||
|
await expect(page.getByTestId('code-mirror-container')).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByTestId('code-mirror-container')
|
||||||
|
.getByTestId('query-copy-button')
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Export YAML', async () => {
|
||||||
|
const downloadPromise = page.waitForEvent('download');
|
||||||
|
|
||||||
|
await page.getByTestId('export-contract-button').click();
|
||||||
|
const download = await downloadPromise;
|
||||||
|
// Wait for the download process to complete and save the downloaded file somewhere.
|
||||||
|
await download.saveAs('downloads/' + download.suggestedFilename());
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Delete contract', async () => {
|
||||||
|
const deleteContractResponse = page.waitForResponse(
|
||||||
|
'api/v1/dataContracts/*?hardDelete=true'
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.getByTestId('delete-contract-button').click();
|
||||||
|
await deleteContractResponse;
|
||||||
|
|
||||||
|
await toastNotification(page, '"Contract" deleted successfully!');
|
||||||
|
|
||||||
|
await expect(page.getByTestId('no-data-placeholder')).toBeVisible();
|
||||||
|
await expect(page.getByTestId('add-contract-button')).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -432,6 +432,7 @@ export const DataAssetsHeader = ({
|
|||||||
`data-contract-latest-result-button
|
`data-contract-latest-result-button
|
||||||
${dataContract?.latestResult?.status}`
|
${dataContract?.latestResult?.status}`
|
||||||
)}
|
)}
|
||||||
|
data-testid="data-contract-latest-result-btn"
|
||||||
icon={getDataContractStatusIcon(dataContract?.latestResult?.status)}
|
icon={getDataContractStatusIcon(dataContract?.latestResult?.status)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(
|
navigate(
|
||||||
|
@ -224,7 +224,8 @@ const AddDataContract: React.FC<{
|
|||||||
{t('label.cancel')}
|
{t('label.cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
className="m-l-sm"
|
className="add-contract-save-button"
|
||||||
|
data-testid="save-contract-btn"
|
||||||
loading={isSubmitting}
|
loading={isSubmitting}
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={handleSave}>
|
onClick={handleSave}>
|
||||||
@ -260,7 +261,10 @@ const AddDataContract: React.FC<{
|
|||||||
}, [mode, items, handleTabChange, activeTab, yaml]);
|
}, [mode, items, handleTabChange, activeTab, yaml]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="add-contract-card" title={cardTitle}>
|
<Card
|
||||||
|
className="add-contract-card"
|
||||||
|
data-testid="add-contract-card"
|
||||||
|
title={cardTitle}>
|
||||||
{cardContent}
|
{cardContent}
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
@ -42,6 +42,9 @@ export const ContractDetailFormTab: React.FC<{
|
|||||||
name: 'name',
|
name: 'name',
|
||||||
type: FieldTypes.TEXT,
|
type: FieldTypes.TEXT,
|
||||||
required: true,
|
required: true,
|
||||||
|
props: {
|
||||||
|
'data-testid': 'contract-name',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('label.description'),
|
label: t('label.description'),
|
||||||
@ -50,7 +53,7 @@ export const ContractDetailFormTab: React.FC<{
|
|||||||
type: FieldTypes.DESCRIPTION,
|
type: FieldTypes.DESCRIPTION,
|
||||||
required: false,
|
required: false,
|
||||||
props: {
|
props: {
|
||||||
'data-testid': 'description',
|
'data-testid': 'contract-description',
|
||||||
initialValue: initialValues?.description ?? '',
|
initialValue: initialValues?.description ?? '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -330,6 +330,7 @@ const ContractDetail: React.FC<{
|
|||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="contract-run-now-button"
|
className="contract-run-now-button"
|
||||||
|
data-testid="contract-run-now-button"
|
||||||
icon={<PlayCircleOutlined />}
|
icon={<PlayCircleOutlined />}
|
||||||
loading={validateLoading}
|
loading={validateLoading}
|
||||||
size="middle"
|
size="middle"
|
||||||
@ -347,12 +348,14 @@ const ContractDetail: React.FC<{
|
|||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
className="delete-button"
|
className="delete-button"
|
||||||
|
data-testid="delete-contract-button"
|
||||||
icon={<DeleteIcon />}
|
icon={<DeleteIcon />}
|
||||||
size="small"
|
size="small"
|
||||||
onClick={onDelete}
|
onClick={onDelete}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
className="contract-edit-button"
|
className="contract-edit-button"
|
||||||
|
data-testid="contract-edit-button"
|
||||||
icon={
|
icon={
|
||||||
<EditIcon
|
<EditIcon
|
||||||
className="anticon"
|
className="anticon"
|
||||||
@ -401,6 +404,7 @@ const ContractDetail: React.FC<{
|
|||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="m-t-md"
|
className="m-t-md"
|
||||||
|
data-testid="add-contract-button"
|
||||||
icon={<PlusOutlined />}
|
icon={<PlusOutlined />}
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={onEdit}>
|
onClick={onEdit}>
|
||||||
@ -488,7 +492,9 @@ const ContractDetail: React.FC<{
|
|||||||
cardProps={{
|
cardProps={{
|
||||||
className: 'expandable-card-contract',
|
className: 'expandable-card-contract',
|
||||||
title: (
|
title: (
|
||||||
<div className="contract-card-title-container">
|
<div
|
||||||
|
className="contract-card-title-container"
|
||||||
|
data-testid="contract-card-title-container">
|
||||||
<Typography.Text className="contract-card-title">
|
<Typography.Text className="contract-card-title">
|
||||||
{t('label.contract-status')}
|
{t('label.contract-status')}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
@ -514,6 +520,7 @@ const ContractDetail: React.FC<{
|
|||||||
{constraintStatus.map((item) => (
|
{constraintStatus.map((item) => (
|
||||||
<div
|
<div
|
||||||
className="contract-status-card-item d-flex justify-between items-center"
|
className="contract-status-card-item d-flex justify-between items-center"
|
||||||
|
data-testid={`contract-status-card-item-${item.label}`}
|
||||||
key={item.label}>
|
key={item.label}>
|
||||||
<div className="d-flex items-center">
|
<div className="d-flex items-center">
|
||||||
<Icon
|
<Icon
|
||||||
@ -538,6 +545,7 @@ const ContractDetail: React.FC<{
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StatusBadgeV2
|
<StatusBadgeV2
|
||||||
|
dataTestId={`contract-status-card-item-${item.label}-status`}
|
||||||
label={item.status}
|
label={item.status}
|
||||||
status={getContractStatusType(item.status)}
|
status={getContractStatusType(item.status)}
|
||||||
/>
|
/>
|
||||||
|
@ -120,6 +120,7 @@ export const ContractSemanticFormTab: React.FC<{
|
|||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="add-semantic-button"
|
className="add-semantic-button"
|
||||||
|
data-testid="add-semantic-button"
|
||||||
disabled={!isNull(editingKey) || !addFunctionRef.current}
|
disabled={!isNull(editingKey) || !addFunctionRef.current}
|
||||||
icon={<Icon className="anticon" component={PlusIcon} />}
|
icon={<Icon className="anticon" component={PlusIcon} />}
|
||||||
type="link"
|
type="link"
|
||||||
@ -192,6 +193,7 @@ export const ContractSemanticFormTab: React.FC<{
|
|||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
className="delete-expand-button"
|
className="delete-expand-button"
|
||||||
|
data-testid={`delete-semantic-${field.key}`}
|
||||||
icon={<DeleteIcon />}
|
icon={<DeleteIcon />}
|
||||||
size="middle"
|
size="middle"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -204,6 +206,7 @@ export const ContractSemanticFormTab: React.FC<{
|
|||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
|
dataTestId={`contract-semantics-card-${field.key}`}
|
||||||
defaultExpanded={editingKey === field.key}
|
defaultExpanded={editingKey === field.key}
|
||||||
key={field.key}>
|
key={field.key}>
|
||||||
{editingKey === field.key ? (
|
{editingKey === field.key ? (
|
||||||
@ -283,6 +286,7 @@ export const ContractSemanticFormTab: React.FC<{
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
className="m-l-md"
|
className="m-l-md"
|
||||||
|
data-testid="save-semantic-button"
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={() => setEditingKey(null)}>
|
onClick={() => setEditingKey(null)}>
|
||||||
{t('label.save')}
|
{t('label.save')}
|
||||||
|
@ -34,6 +34,7 @@ const ContractViewSwitchTab = ({
|
|||||||
<CodeOutline
|
<CodeOutline
|
||||||
className="align-middle"
|
className="align-middle"
|
||||||
color={DE_ACTIVE_COLOR}
|
color={DE_ACTIVE_COLOR}
|
||||||
|
data-testid="contract-view-switch-tab-yaml"
|
||||||
height={20}
|
height={20}
|
||||||
width={20}
|
width={20}
|
||||||
/>
|
/>
|
||||||
@ -45,6 +46,7 @@ const ContractViewSwitchTab = ({
|
|||||||
<BookOutline
|
<BookOutline
|
||||||
className="align-middle"
|
className="align-middle"
|
||||||
color={DE_ACTIVE_COLOR}
|
color={DE_ACTIVE_COLOR}
|
||||||
|
data-testid="contract-view-switch-tab-ui"
|
||||||
height={20}
|
height={20}
|
||||||
width={20}
|
width={20}
|
||||||
/>
|
/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user