mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-23 16:03:16 +00:00

* fix the api version endpoint page breaking due to STRING changeDescription updated * change the logic and use same function which displayName use * added unit test for schemaVersionUtils * change function name to be generic * added support for dataDisplayType diff supported for other supporting entity as well * adde playwright test
314 lines
9.4 KiB
TypeScript
314 lines
9.4 KiB
TypeScript
/*
|
|
* Copyright 2024 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, test as base } from '@playwright/test';
|
|
import { BIG_ENTITY_DELETE_TIMEOUT } from '../../constant/delete';
|
|
import { EntityDataClass } from '../../support/entity/EntityDataClass';
|
|
import { EntityDataClassCreationConfig } from '../../support/entity/EntityDataClass.interface';
|
|
import { TableClass } from '../../support/entity/TableClass';
|
|
import { UserClass } from '../../support/user/UserClass';
|
|
import { performAdminLogin } from '../../utils/admin';
|
|
import {
|
|
descriptionBoxReadOnly,
|
|
redirectToHomePage,
|
|
toastNotification,
|
|
} from '../../utils/common';
|
|
import {
|
|
addMultiOwner,
|
|
assignTier,
|
|
getEntityDataTypeDisplayPatch,
|
|
} from '../../utils/entity';
|
|
|
|
const entityCreationConfig: EntityDataClassCreationConfig = {
|
|
apiEndpoint: true,
|
|
table: true,
|
|
storedProcedure: true,
|
|
dashboard: true,
|
|
pipeline: true,
|
|
topic: true,
|
|
mlModel: true,
|
|
container: true,
|
|
searchIndex: true,
|
|
dashboardDataModel: true,
|
|
entityDetails: true,
|
|
};
|
|
|
|
const entities = [
|
|
EntityDataClass.apiEndpoint1,
|
|
EntityDataClass.table1,
|
|
EntityDataClass.storedProcedure1,
|
|
EntityDataClass.dashboard1,
|
|
EntityDataClass.pipeline1,
|
|
EntityDataClass.topic1,
|
|
EntityDataClass.mlModel1,
|
|
EntityDataClass.container1,
|
|
EntityDataClass.searchIndex1,
|
|
EntityDataClass.dashboardDataModel1,
|
|
];
|
|
|
|
// use the admin user to login
|
|
const adminUser = new UserClass();
|
|
|
|
const test = base.extend<{ page: Page }>({
|
|
page: async ({ browser }, use) => {
|
|
const adminPage = await browser.newPage();
|
|
await adminUser.login(adminPage);
|
|
await use(adminPage);
|
|
await adminPage.close();
|
|
},
|
|
});
|
|
|
|
test.describe('Entity Version pages', () => {
|
|
test.beforeAll('Setup pre-requests', async ({ browser }) => {
|
|
test.slow();
|
|
|
|
const { apiContext, afterAction } = await performAdminLogin(browser);
|
|
await adminUser.create(apiContext);
|
|
await adminUser.setAdminRole(apiContext);
|
|
|
|
await EntityDataClass.preRequisitesForTests(
|
|
apiContext,
|
|
entityCreationConfig
|
|
);
|
|
const domain = EntityDataClass.domain1.responseData;
|
|
|
|
for (const entity of entities) {
|
|
const dataTypeDisplayPath = getEntityDataTypeDisplayPatch(entity);
|
|
await entity.patch({
|
|
apiContext,
|
|
patchData: [
|
|
{
|
|
op: 'add',
|
|
path: '/tags/0',
|
|
value: {
|
|
labelType: 'Manual',
|
|
state: 'Confirmed',
|
|
source: 'Classification',
|
|
tagFQN: 'PersonalData.SpecialCategory',
|
|
},
|
|
},
|
|
{
|
|
op: 'add',
|
|
path: '/tags/1',
|
|
value: {
|
|
labelType: 'Manual',
|
|
state: 'Confirmed',
|
|
source: 'Classification',
|
|
tagFQN: 'PII.Sensitive',
|
|
},
|
|
},
|
|
{
|
|
op: 'add',
|
|
path: '/description',
|
|
value: 'Description for newly added service',
|
|
},
|
|
{
|
|
op: 'add',
|
|
path: '/domain',
|
|
value: {
|
|
id: domain.id,
|
|
type: 'domain',
|
|
name: domain.name,
|
|
description: domain.description,
|
|
},
|
|
},
|
|
...(dataTypeDisplayPath
|
|
? [
|
|
{
|
|
op: 'add' as const,
|
|
path: dataTypeDisplayPath,
|
|
value: 'OBJECT',
|
|
},
|
|
]
|
|
: []),
|
|
],
|
|
});
|
|
}
|
|
|
|
await afterAction();
|
|
});
|
|
|
|
test.beforeEach('Visit entity details page', async ({ page }) => {
|
|
await redirectToHomePage(page);
|
|
});
|
|
|
|
test.afterAll('Cleanup', async ({ browser }) => {
|
|
test.slow();
|
|
|
|
const { apiContext, afterAction } = await performAdminLogin(browser);
|
|
await adminUser.delete(apiContext);
|
|
|
|
await EntityDataClass.postRequisitesForTests(
|
|
apiContext,
|
|
entityCreationConfig
|
|
);
|
|
await afterAction();
|
|
});
|
|
|
|
entities.forEach((entity) => {
|
|
test(`${entity.getType()}`, async ({ page }) => {
|
|
test.slow();
|
|
|
|
await entity.visitEntityPage(page);
|
|
const versionDetailResponse = page.waitForResponse(`**/versions/0.2`);
|
|
await page.locator('[data-testid="version-button"]').click();
|
|
await versionDetailResponse;
|
|
|
|
await test.step(
|
|
'should show edited tags and description changes',
|
|
async () => {
|
|
await expect(
|
|
page.locator(
|
|
'[data-testid="domain-link"] [data-testid="diff-added"]'
|
|
)
|
|
).toBeVisible();
|
|
|
|
await expect(
|
|
page.locator(
|
|
`[data-testid="asset-description-container"] ${descriptionBoxReadOnly} [data-testid="diff-added"]`
|
|
)
|
|
).toBeVisible();
|
|
|
|
await expect(
|
|
page.locator(
|
|
'[data-testid="entity-right-panel"] .diff-added [data-testid="tag-PersonalData.SpecialCategory"]'
|
|
)
|
|
).toBeVisible();
|
|
|
|
await expect(
|
|
page.locator(
|
|
'[data-testid="entity-right-panel"] .diff-added [data-testid="tag-PII.Sensitive"]'
|
|
)
|
|
).toBeVisible();
|
|
}
|
|
);
|
|
|
|
await test.step('should show owner changes', async () => {
|
|
await page.locator('[data-testid="version-button"]').click();
|
|
const OWNER1 = EntityDataClass.user1.getUserName();
|
|
|
|
await addMultiOwner({
|
|
page,
|
|
ownerNames: [OWNER1],
|
|
activatorBtnDataTestId: 'edit-owner',
|
|
resultTestId: 'data-assets-header',
|
|
endpoint: entity.endpoint,
|
|
type: 'Users',
|
|
});
|
|
|
|
const versionDetailResponse = page.waitForResponse(`**/versions/0.3`);
|
|
await page.locator('[data-testid="version-button"]').click();
|
|
await versionDetailResponse;
|
|
|
|
await expect(
|
|
page.locator('[data-testid="owner-link"] [data-testid="diff-added"]')
|
|
).toBeVisible();
|
|
});
|
|
|
|
if (entity.endpoint === 'tables') {
|
|
await test.step(
|
|
'should show column display name changes properly',
|
|
async () => {
|
|
await page.locator('[data-testid="version-button"]').click();
|
|
|
|
await page
|
|
.locator(
|
|
`[data-row-key$="${
|
|
(entity as TableClass).entity.columns[0].name
|
|
}"] [data-testid="edit-displayName-button"]`
|
|
)
|
|
.click();
|
|
|
|
await page.locator('#displayName').clear();
|
|
await page.locator('#displayName').fill('New Column Name');
|
|
|
|
await page
|
|
.locator('.ant-modal-footer [data-testid="save-button"]')
|
|
.click();
|
|
|
|
await page.waitForSelector('.ant-modal-body', {
|
|
state: 'detached',
|
|
});
|
|
|
|
await page.locator('[data-testid="version-button"]').click();
|
|
|
|
await expect(
|
|
page.locator(
|
|
`[data-row-key$="${
|
|
(entity as TableClass).entity.columns[0].name
|
|
}"] [data-testid="diff-added"]`
|
|
)
|
|
).toBeVisible();
|
|
}
|
|
);
|
|
}
|
|
|
|
await test.step('should show tier changes', async () => {
|
|
await page.locator('[data-testid="version-button"]').click();
|
|
|
|
await assignTier(page, 'Tier1', entity.endpoint);
|
|
|
|
const versionDetailResponse = page.waitForResponse(`**/versions/0.3`);
|
|
await page.locator('[data-testid="version-button"]').click();
|
|
await versionDetailResponse;
|
|
|
|
await expect(
|
|
page.locator('[data-testid="Tier"] > [data-testid="diff-added"]')
|
|
).toBeVisible();
|
|
});
|
|
|
|
await test.step(
|
|
'should show version details after soft deleted',
|
|
async () => {
|
|
await page.locator('[data-testid="version-button"]').click();
|
|
|
|
await page.click('[data-testid="manage-button"]');
|
|
await page.click('[data-testid="delete-button"]');
|
|
|
|
await page.waitForSelector('[role="dialog"].ant-modal');
|
|
|
|
await expect(page.locator('[role="dialog"].ant-modal')).toBeVisible();
|
|
|
|
await page.fill('[data-testid="confirmation-text-input"]', 'DELETE');
|
|
const deleteResponse = page.waitForResponse(
|
|
`/api/v1/${entity.endpoint}/async/*?hardDelete=false&recursive=true`
|
|
);
|
|
await page.click('[data-testid="confirm-button"]');
|
|
|
|
await deleteResponse;
|
|
|
|
await toastNotification(
|
|
page,
|
|
/deleted successfully!/,
|
|
BIG_ENTITY_DELETE_TIMEOUT
|
|
);
|
|
|
|
await page.reload();
|
|
|
|
const deletedBadge = page.locator('[data-testid="deleted-badge"]');
|
|
|
|
await expect(deletedBadge).toHaveText('Deleted');
|
|
|
|
const versionDetailResponse = page.waitForResponse(`**/versions/0.4`);
|
|
await page.locator('[data-testid="version-button"]').click();
|
|
await versionDetailResponse;
|
|
|
|
// Deleted badge should be visible
|
|
await expect(
|
|
page.locator('[data-testid="deleted-badge"]')
|
|
).toBeVisible();
|
|
}
|
|
);
|
|
});
|
|
});
|
|
});
|