mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-27 10:26:09 +00:00
playwright: migrate announcement, rename, soft delete and hard delete test (#16542)
* playwright: migrate announcement, rename, soft delete and hard delete test * addressing comment * minor fix for hover
This commit is contained in:
parent
e9ec4367ee
commit
10cda1dac1
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
export const LIST_OF_FIELDS_TO_EDIT_NOT_TO_BE_PRESENT = [
|
||||
{
|
||||
containerSelector: '[data-testid="header-domain-container"]',
|
||||
elementSelector: '[data-testid="add-domain"]',
|
||||
},
|
||||
{
|
||||
containerSelector: '[data-testid="owner-label"]',
|
||||
elementSelector: '[data-testid="edit-owner"]',
|
||||
},
|
||||
{
|
||||
containerSelector: '[data-testid="header-tier-container"]',
|
||||
elementSelector: '[data-testid="edit-tier"]',
|
||||
},
|
||||
{
|
||||
containerSelector: '[data-testid="asset-description-container"]',
|
||||
elementSelector: '[data-testid="edit-description"]',
|
||||
},
|
||||
{
|
||||
containerSelector:
|
||||
'[data-testid="entity-right-panel"] [data-testid="tags-container"]',
|
||||
elementSelector: '[data-testid="add-tag"]',
|
||||
},
|
||||
{
|
||||
containerSelector:
|
||||
'[data-testid="entity-right-panel"] [data-testid="glossary-container"]',
|
||||
elementSelector: '[data-testid="add-tag"]',
|
||||
},
|
||||
];
|
||||
|
||||
export const LIST_OF_FIELDS_TO_EDIT_TO_BE_DISABLED = [
|
||||
{
|
||||
containerSelector: '[data-testid="asset-header-btn-group"]',
|
||||
elementSelector: '[data-testid="up-vote-btn"]',
|
||||
},
|
||||
{
|
||||
containerSelector: '[data-testid="asset-header-btn-group"]',
|
||||
elementSelector: '[data-testid="down-vote-btn"]',
|
||||
},
|
||||
{
|
||||
containerSelector: '[data-testid="asset-header-btn-group"]',
|
||||
elementSelector: '[data-testid="entity-follow-button"]',
|
||||
},
|
||||
];
|
||||
|
||||
export const ENTITIES_WITHOUT_FOLLOWING_BUTTON = [
|
||||
'databases',
|
||||
'databaseSchemas',
|
||||
'services/databaseServices',
|
||||
'services/messagingServices',
|
||||
'services/pipelineServices',
|
||||
'services/dashboardServices',
|
||||
'services/mlmodelServices',
|
||||
'services/storageServices',
|
||||
'services/metadataServices',
|
||||
'services/searchServices',
|
||||
];
|
@ -19,22 +19,30 @@ import { MlModelClass } from '../../support/entity/MlModelClass';
|
||||
import { PipelineClass } from '../../support/entity/PipelineClass';
|
||||
import { SearchIndexClass } from '../../support/entity/SearchIndexClass';
|
||||
import { TopicClass } from '../../support/entity/TopicClass';
|
||||
import { createNewPage, redirectToHomePage } from '../../utils/common';
|
||||
import {
|
||||
createNewPage,
|
||||
getAuthContext,
|
||||
getToken,
|
||||
redirectToHomePage,
|
||||
} from '../../utils/common';
|
||||
|
||||
const entities = [
|
||||
new DashboardClass(),
|
||||
new PipelineClass(),
|
||||
new TopicClass(),
|
||||
new MlModelClass(),
|
||||
new ContainerClass(),
|
||||
new SearchIndexClass(),
|
||||
new DashboardDataModelClass(),
|
||||
DashboardClass,
|
||||
PipelineClass,
|
||||
TopicClass,
|
||||
MlModelClass,
|
||||
ContainerClass,
|
||||
SearchIndexClass,
|
||||
DashboardDataModelClass,
|
||||
] as const;
|
||||
|
||||
// use the admin user to login
|
||||
test.use({ storageState: 'playwright/.auth/admin.json' });
|
||||
|
||||
entities.forEach((entity) => {
|
||||
entities.forEach((EntityClass) => {
|
||||
const entity = new EntityClass();
|
||||
const deleteEntity = new EntityClass();
|
||||
|
||||
test.describe(entity.getType(), () => {
|
||||
test.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||
const { apiContext, afterAction } = await createNewPage(browser);
|
||||
@ -89,6 +97,17 @@ entities.forEach((entity) => {
|
||||
);
|
||||
});
|
||||
|
||||
test(`Announcement create & delete`, async ({ page }) => {
|
||||
await entity.announcement(
|
||||
page,
|
||||
entity.entityResponseData?.['fullyQualifiedName']
|
||||
);
|
||||
});
|
||||
|
||||
test(`Inactive Announcement create & delete`, async ({ page }) => {
|
||||
await entity.inactiveAnnouncement(page);
|
||||
});
|
||||
|
||||
test(`UpVote & DownVote entity`, async ({ page }) => {
|
||||
await entity.upVote(page);
|
||||
await entity.downVote(page);
|
||||
@ -99,6 +118,10 @@ entities.forEach((entity) => {
|
||||
await entity.followUnfollowEntity(page, entityName);
|
||||
});
|
||||
|
||||
test(`Update displayName`, async ({ page }) => {
|
||||
await entity.renameEntity(page, entity.entity.name);
|
||||
});
|
||||
|
||||
test.afterAll('Cleanup', async ({ browser }) => {
|
||||
const { apiContext, afterAction } = await createNewPage(browser);
|
||||
await entity.delete(apiContext);
|
||||
@ -106,4 +129,32 @@ entities.forEach((entity) => {
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test(`Delete ${deleteEntity.getType()}`, async ({ page }) => {
|
||||
await redirectToHomePage(page);
|
||||
// get the token from localStorage
|
||||
const token = await getToken(page);
|
||||
|
||||
// create a new context with the token
|
||||
const apiContext = await getAuthContext(token);
|
||||
await deleteEntity.create(apiContext);
|
||||
await redirectToHomePage(page);
|
||||
await deleteEntity.visitEntityPage(page);
|
||||
|
||||
await test.step('Soft delete', async () => {
|
||||
await deleteEntity.softDeleteEntity(
|
||||
page,
|
||||
deleteEntity.entity.name,
|
||||
deleteEntity.entityResponseData?.['displayName']
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Hard delete', async () => {
|
||||
await deleteEntity.hardDeleteEntity(
|
||||
page,
|
||||
deleteEntity.entity.name,
|
||||
deleteEntity.entityResponseData?.['displayName']
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -21,14 +21,21 @@ import {
|
||||
assignGlossaryTerm,
|
||||
assignTag,
|
||||
assignTier,
|
||||
createAnnouncement,
|
||||
createInactiveAnnouncement,
|
||||
deleteAnnouncement,
|
||||
downVote,
|
||||
followEntity,
|
||||
hardDeleteEntity,
|
||||
removeGlossaryTerm,
|
||||
removeOwner,
|
||||
removeTag,
|
||||
removeTier,
|
||||
replyAnnouncement,
|
||||
softDeleteEntity,
|
||||
unFollowEntity,
|
||||
updateDescription,
|
||||
updateDisplayNameForEntity,
|
||||
updateOwner,
|
||||
upVote,
|
||||
validateFollowedEntityToWidget,
|
||||
@ -132,4 +139,42 @@ export class EntityClass {
|
||||
await unFollowEntity(page, this.endpoint);
|
||||
await validateFollowedEntityToWidget(page, entity, false);
|
||||
}
|
||||
|
||||
async announcement(page: Page, entityFqn: string) {
|
||||
await createAnnouncement(page, entityFqn, {
|
||||
title: 'Playwright Test Announcement',
|
||||
description: 'Playwright Test Announcement Description',
|
||||
});
|
||||
await replyAnnouncement(page);
|
||||
await deleteAnnouncement(page);
|
||||
}
|
||||
|
||||
async inactiveAnnouncement(page: Page) {
|
||||
await createInactiveAnnouncement(page, {
|
||||
title: 'Inactive Playwright announcement',
|
||||
description: 'Inactive Playwright announcement description',
|
||||
});
|
||||
await deleteAnnouncement(page);
|
||||
}
|
||||
|
||||
async renameEntity(page: Page, entityName: string) {
|
||||
await updateDisplayNameForEntity(
|
||||
page,
|
||||
`Cypress ${entityName} updated`,
|
||||
this.endpoint
|
||||
);
|
||||
}
|
||||
|
||||
async softDeleteEntity(page: Page, entityName: string, displayName?: string) {
|
||||
await softDeleteEntity(
|
||||
page,
|
||||
entityName,
|
||||
this.endpoint,
|
||||
displayName ?? entityName
|
||||
);
|
||||
}
|
||||
|
||||
async hardDeleteEntity(page: Page, entityName: string, displayName?: string) {
|
||||
await hardDeleteEntity(page, displayName ?? entityName, this.endpoint);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,20 @@
|
||||
*/
|
||||
import { expect, Page } from '@playwright/test';
|
||||
import { lowerCase } from 'lodash';
|
||||
import { EntityType } from '../support/entity/Entity.interface';
|
||||
import {
|
||||
customFormatDateTime,
|
||||
getCurrentMillis,
|
||||
getEpochMillisForFutureDays,
|
||||
} from '../../src/utils/date-time/DateTimeUtils';
|
||||
import {
|
||||
ENTITIES_WITHOUT_FOLLOWING_BUTTON,
|
||||
LIST_OF_FIELDS_TO_EDIT_NOT_TO_BE_PRESENT,
|
||||
LIST_OF_FIELDS_TO_EDIT_TO_BE_DISABLED,
|
||||
} from '../constant/delete.constant';
|
||||
import {
|
||||
EntityType,
|
||||
EntityTypeEndpoint,
|
||||
} from '../support/entity/Entity.interface';
|
||||
import { redirectToHomePage } from './common';
|
||||
|
||||
export const visitEntityPage = async (data: {
|
||||
@ -35,6 +48,10 @@ export const addOwner = async (
|
||||
) => {
|
||||
await page.getByTestId('edit-owner').click();
|
||||
await page.getByRole('tab', { name: type }).click();
|
||||
if (type === 'Users') {
|
||||
await page.waitForResponse('/api/v1/users?limit=*&isBot=false*');
|
||||
}
|
||||
await page.waitForSelector('[data-testid="loader"]', { state: 'detached' });
|
||||
|
||||
await page
|
||||
.getByTestId(`owner-select-${lowerCase(type)}-search-bar`)
|
||||
@ -57,7 +74,7 @@ export const updateOwner = async (
|
||||
) => {
|
||||
await page.getByTestId('edit-owner').click();
|
||||
await page.getByRole('tab', { name: type }).click();
|
||||
|
||||
await page.waitForSelector('[data-testid="loader"]', { state: 'detached' });
|
||||
await page
|
||||
.getByTestId(`owner-select-${lowerCase(type)}-search-bar`)
|
||||
.fill(owner);
|
||||
@ -282,3 +299,519 @@ export const validateFollowedEntityToWidget = async (
|
||||
await expect(page.getByTestId(`following-${entity}`)).not.toBeVisible();
|
||||
}
|
||||
};
|
||||
|
||||
const announcementForm = async (
|
||||
page: Page,
|
||||
data: {
|
||||
title: string;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
description: string;
|
||||
}
|
||||
) => {
|
||||
await page.fill('#title', data.title);
|
||||
|
||||
await page.click('#startTime');
|
||||
await page.fill('#startTime', `${data.startDate}`);
|
||||
await page.press('#startTime', 'Enter');
|
||||
|
||||
await page.click('#endTime');
|
||||
await page.fill('#endTime', `${data.endDate}`);
|
||||
await page.press('#startTime', 'Enter');
|
||||
|
||||
await page.fill(
|
||||
'.toastui-editor-md-container > .toastui-editor > .ProseMirror',
|
||||
data.description
|
||||
);
|
||||
|
||||
await page.locator('#announcement-submit').scrollIntoViewIfNeeded();
|
||||
await page.click('#announcement-submit');
|
||||
await page.waitForResponse('/api/v1/feed?entityLink=*type=Announcement*');
|
||||
await page.click('.Toastify__close-button');
|
||||
};
|
||||
|
||||
export const createAnnouncement = async (
|
||||
page: Page,
|
||||
entityFqn: string,
|
||||
data: { title: string; description: string }
|
||||
) => {
|
||||
await page.getByTestId('manage-button').click();
|
||||
await page.getByTestId('announcement-button').click();
|
||||
const startDate = customFormatDateTime(getCurrentMillis(), 'yyyy-MM-dd');
|
||||
const endDate = customFormatDateTime(
|
||||
getEpochMillisForFutureDays(5),
|
||||
'yyyy-MM-dd'
|
||||
);
|
||||
|
||||
await expect(page.getByTestId('announcement-error')).toContainText(
|
||||
'No Announcements, Click on add announcement to add one.'
|
||||
);
|
||||
|
||||
await page.getByTestId('add-announcement').click();
|
||||
|
||||
await expect(page.locator('.ant-modal-header')).toContainText(
|
||||
'Make an announcement'
|
||||
);
|
||||
|
||||
await announcementForm(page, { ...data, startDate, endDate });
|
||||
|
||||
await page.reload();
|
||||
await page.getByTestId('announcement-card').isVisible();
|
||||
|
||||
await expect(page.getByTestId('announcement-card')).toContainText(data.title);
|
||||
|
||||
await redirectToHomePage(page);
|
||||
|
||||
await page
|
||||
.getByTestId('announcement-container')
|
||||
.locator(`a[href*="${encodeURIComponent(entityFqn)}"]`)
|
||||
.click();
|
||||
await page.getByTestId('announcement-card').isVisible();
|
||||
|
||||
await expect(page.getByTestId('announcement-card')).toContainText(data.title);
|
||||
};
|
||||
|
||||
export const replyAnnouncement = async (page: Page) => {
|
||||
await page.click('[data-testid="announcement-card"]');
|
||||
|
||||
await page.hover(
|
||||
'[data-testid="announcement-card"] [data-testid="main-message"]'
|
||||
);
|
||||
|
||||
await page.waitForSelector('.ant-popover', { state: 'visible' });
|
||||
|
||||
await expect(page.getByTestId('add-reply').locator('svg')).toBeVisible();
|
||||
|
||||
await page.getByTestId('add-reply').locator('svg').click();
|
||||
|
||||
await expect(page.locator('.ql-editor')).toBeVisible();
|
||||
|
||||
const sendButtonIsDisabled = await page
|
||||
.locator('[data-testid="send-button"]')
|
||||
.isEnabled();
|
||||
|
||||
expect(sendButtonIsDisabled).toBe(false);
|
||||
|
||||
await page.fill('[data-testid="editor-wrapper"] .ql-editor', 'Reply message');
|
||||
await page.click('[data-testid="send-button"]');
|
||||
|
||||
await expect(
|
||||
page.locator('[data-testid="replies"] [data-testid="viewer-container"]')
|
||||
).toHaveText('Reply message');
|
||||
await expect(page.locator('[data-testid="show-reply-thread"]')).toHaveText(
|
||||
'1 replies'
|
||||
);
|
||||
|
||||
// Edit the reply message
|
||||
await page.hover('[data-testid="replies"] > [data-testid="main-message"]');
|
||||
await page.waitForSelector('.ant-popover', { state: 'visible' });
|
||||
await page.click('[data-testid="edit-message"]');
|
||||
|
||||
await page.fill(
|
||||
'[data-testid="editor-wrapper"] .ql-editor',
|
||||
'Reply message edited'
|
||||
);
|
||||
|
||||
await page.click('[data-testid="save-button"]');
|
||||
|
||||
await expect(
|
||||
page.locator('[data-testid="replies"] [data-testid="viewer-container"]')
|
||||
).toHaveText('Reply message edited');
|
||||
|
||||
await page.reload();
|
||||
};
|
||||
|
||||
export const deleteAnnouncement = async (page: Page) => {
|
||||
await page.getByTestId('manage-button').click();
|
||||
await page.getByTestId('announcement-button').click();
|
||||
|
||||
await page.hover(
|
||||
'[data-testid="announcement-card"] [data-testid="main-message"]'
|
||||
);
|
||||
|
||||
await page.waitForSelector('.ant-popover', { state: 'visible' });
|
||||
|
||||
await page.click('[data-testid="delete-message"]');
|
||||
const modalText = await page.textContent('.ant-modal-body');
|
||||
|
||||
expect(modalText).toContain(
|
||||
'Are you sure you want to permanently delete this message?'
|
||||
);
|
||||
|
||||
await page.click('[data-testid="save-button"]');
|
||||
await page.waitForResponse('/api/v1/feed/*');
|
||||
};
|
||||
|
||||
export const createInactiveAnnouncement = async (
|
||||
page: Page,
|
||||
data: { title: string; description: string }
|
||||
) => {
|
||||
await page.getByTestId('manage-button').click();
|
||||
await page.getByTestId('announcement-button').click();
|
||||
const startDate = customFormatDateTime(
|
||||
getEpochMillisForFutureDays(6),
|
||||
'yyyy-MM-dd'
|
||||
);
|
||||
const endDate = customFormatDateTime(
|
||||
getEpochMillisForFutureDays(11),
|
||||
'yyyy-MM-dd'
|
||||
);
|
||||
|
||||
await page.getByTestId('add-announcement').click();
|
||||
|
||||
await expect(page.locator('.ant-modal-header')).toContainText(
|
||||
'Make an announcement'
|
||||
);
|
||||
|
||||
await announcementForm(page, { ...data, startDate, endDate });
|
||||
await page.getByTestId('inActive-announcements').isVisible();
|
||||
await page.reload();
|
||||
};
|
||||
|
||||
export const updateDisplayNameForEntity = async (
|
||||
page: Page,
|
||||
displayName: string,
|
||||
endPoint: string
|
||||
) => {
|
||||
await page.click('[data-testid="manage-button"]');
|
||||
await page.click('[data-testid="rename-button"]');
|
||||
|
||||
const nameInputIsDisabled = await page.locator('#name').isEnabled();
|
||||
|
||||
expect(nameInputIsDisabled).toBe(false);
|
||||
|
||||
await expect(page.locator('#displayName')).toBeVisible();
|
||||
|
||||
await page.locator('#displayName').clear();
|
||||
|
||||
await page.fill('#displayName', displayName);
|
||||
await page.click('[data-testid="save-button"]');
|
||||
|
||||
// For the network request verification, you can use `page.waitForResponse`:
|
||||
await page.waitForResponse(`/api/v1/${endPoint}/*`);
|
||||
|
||||
await expect(
|
||||
page.locator('[data-testid="entity-header-display-name"]')
|
||||
).toHaveText(displayName);
|
||||
};
|
||||
|
||||
export const checkForEditActions = async ({ entityType, deleted, page }) => {
|
||||
for (const {
|
||||
containerSelector,
|
||||
elementSelector,
|
||||
} of LIST_OF_FIELDS_TO_EDIT_TO_BE_DISABLED) {
|
||||
if (
|
||||
elementSelector === '[data-testid="entity-follow-button"]' &&
|
||||
ENTITIES_WITHOUT_FOLLOWING_BUTTON.includes(entityType)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entityType.startsWith('services/')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const isDisabled = await page
|
||||
.locator(`${containerSelector} ${elementSelector}`)
|
||||
.isEnabled();
|
||||
|
||||
expect(isDisabled).toBe(!deleted);
|
||||
}
|
||||
|
||||
for (const {
|
||||
containerSelector,
|
||||
elementSelector,
|
||||
} of LIST_OF_FIELDS_TO_EDIT_NOT_TO_BE_PRESENT) {
|
||||
if (!deleted) {
|
||||
await expect(
|
||||
page.locator(`${containerSelector} ${elementSelector}`)
|
||||
).toBeVisible();
|
||||
} else {
|
||||
const exists = await page
|
||||
.locator(`${containerSelector} ${elementSelector}`)
|
||||
.isVisible();
|
||||
|
||||
expect(exists).toBe(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const checkLineageTabActions = async (page: Page, deleted?: boolean) => {
|
||||
// Click the lineage tab
|
||||
await page.click('[data-testid="lineage"]');
|
||||
|
||||
// Ensure the response has been received and check the status code
|
||||
await page.waitForResponse(
|
||||
'/api/v1/lineage/getLineage?fqn=*&upstreamDepth=3&downstreamDepth=3&query_filter=*&includeDeleted=false'
|
||||
);
|
||||
|
||||
// Check the presence or absence of the edit-lineage element based on the deleted flag
|
||||
if (deleted) {
|
||||
await expect(
|
||||
page.locator('[data-testid="edit-lineage"]')
|
||||
).not.toBeVisible();
|
||||
} else {
|
||||
await expect(page.locator('[data-testid="edit-lineage"]')).toBeVisible();
|
||||
}
|
||||
};
|
||||
|
||||
export const checkForTableSpecificFields = async (
|
||||
page: Page,
|
||||
deleted?: boolean
|
||||
) => {
|
||||
const queryDataUrl = `/api/v1/search/query?q=*&index=query_search_index*`;
|
||||
const systemProfileUrl = `/api/v1/tables/*/systemProfile*`;
|
||||
|
||||
// Click the table queries tab
|
||||
await page.click('[data-testid="table_queries"]');
|
||||
|
||||
if (!deleted) {
|
||||
await page.waitForResponse(queryDataUrl);
|
||||
|
||||
// Check if the add-query button is enabled
|
||||
const addQueryButton = page.locator('[data-testid="add-query-btn"]');
|
||||
|
||||
await expect(addQueryButton).toBeEnabled();
|
||||
} else {
|
||||
// Check for the no data placeholder message
|
||||
const noDataPlaceholder = page.locator(
|
||||
'[data-testid="no-data-placeholder"]'
|
||||
);
|
||||
|
||||
await expect(noDataPlaceholder).toContainText(
|
||||
'Queries data is not available for deleted entities.'
|
||||
);
|
||||
}
|
||||
|
||||
// Click the profiler tab
|
||||
await page.click('[data-testid="profiler"]');
|
||||
await page.waitForResponse(systemProfileUrl);
|
||||
|
||||
// Check the visibility of profiler buttons based on the deleted flag
|
||||
const addTableTestButton = page.locator(
|
||||
'[data-testid="profiler-add-table-test-btn"]'
|
||||
);
|
||||
const settingButton = page.locator('[data-testid="profiler-setting-btn"]');
|
||||
|
||||
if (!deleted) {
|
||||
await expect(addTableTestButton).toBeVisible();
|
||||
await expect(settingButton).toBeVisible();
|
||||
} else {
|
||||
await expect(addTableTestButton).not.toBeVisible();
|
||||
await expect(settingButton).not.toBeVisible();
|
||||
}
|
||||
};
|
||||
|
||||
export const deletedEntityCommonChecks = async ({
|
||||
page,
|
||||
endPoint,
|
||||
deleted,
|
||||
}: {
|
||||
page: Page;
|
||||
endPoint: EntityTypeEndpoint;
|
||||
deleted?: boolean;
|
||||
}) => {
|
||||
const isTableEntity = endPoint === EntityTypeEndpoint.Table;
|
||||
|
||||
// Go to first tab before starts validating
|
||||
await page.click('.ant-tabs-tab:nth-child(1)');
|
||||
|
||||
// Check if all the edit actions are available for the entity
|
||||
await checkForEditActions({
|
||||
page,
|
||||
entityType: endPoint,
|
||||
deleted,
|
||||
});
|
||||
|
||||
if (isTableEntity) {
|
||||
await checkLineageTabActions(page, deleted);
|
||||
}
|
||||
|
||||
if (isTableEntity) {
|
||||
await checkForTableSpecificFields(page, deleted);
|
||||
}
|
||||
|
||||
await page.click('[data-testid="manage-button"]');
|
||||
|
||||
if (deleted) {
|
||||
// only two menu options (restore and delete) should be present
|
||||
await expect(
|
||||
page.locator(
|
||||
'[data-testid="manage-dropdown-list-container"] [data-testid="announcement-button"]'
|
||||
)
|
||||
).toBeHidden();
|
||||
await expect(
|
||||
page.locator(
|
||||
'[data-testid="manage-dropdown-list-container"] [data-testid="rename-button"]'
|
||||
)
|
||||
).toBeHidden();
|
||||
await expect(
|
||||
page.locator(
|
||||
'[data-testid="manage-dropdown-list-container"] [data-testid="profiler-setting-button"]'
|
||||
)
|
||||
).toBeHidden();
|
||||
await expect(
|
||||
page.locator(
|
||||
'[data-testid="manage-dropdown-list-container"] [data-testid="restore-button"]'
|
||||
)
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.locator(
|
||||
'[data-testid="manage-dropdown-list-container"] [data-testid="delete-button"]'
|
||||
)
|
||||
).toBeVisible();
|
||||
} else {
|
||||
await expect(
|
||||
page.locator(
|
||||
'[data-testid="manage-dropdown-list-container"] [data-testid="announcement-button"]'
|
||||
)
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.locator(
|
||||
'[data-testid="manage-dropdown-list-container"] [data-testid="rename-button"]'
|
||||
)
|
||||
).toBeVisible();
|
||||
|
||||
if (
|
||||
[EntityTypeEndpoint.Database, EntityTypeEndpoint.DatabaseSchema].includes(
|
||||
endPoint
|
||||
)
|
||||
) {
|
||||
await expect(
|
||||
page.locator(
|
||||
'[data-testid="manage-dropdown-list-container"] [data-testid="profiler-setting-button"]'
|
||||
)
|
||||
).toBeVisible();
|
||||
}
|
||||
|
||||
await expect(
|
||||
page.locator(
|
||||
'[data-testid="manage-dropdown-list-container"] [data-testid="delete-button"]'
|
||||
)
|
||||
).toBeVisible();
|
||||
}
|
||||
|
||||
await page.click('body');
|
||||
};
|
||||
|
||||
export const restoreEntity = async (page: Page) => {
|
||||
await expect(page.locator('[data-testid="deleted-badge"]')).toBeVisible();
|
||||
|
||||
await page.click('[data-testid="manage-button"]');
|
||||
await page.click('[data-testid="restore-button"]');
|
||||
await page.click('button:has-text("Restore")');
|
||||
|
||||
await expect(page.locator('.Toastify__toast-body')).toHaveText(
|
||||
/restored successfully/
|
||||
);
|
||||
|
||||
await page.click('.Toastify__close-button');
|
||||
|
||||
const exists = await page
|
||||
.locator('[data-testid="deleted-badge"]')
|
||||
.isVisible();
|
||||
|
||||
expect(exists).toBe(false);
|
||||
};
|
||||
|
||||
export const softDeleteEntity = async (
|
||||
page: Page,
|
||||
entityName: string,
|
||||
endPoint: EntityTypeEndpoint,
|
||||
displayName: string
|
||||
) => {
|
||||
await deletedEntityCommonChecks({
|
||||
page,
|
||||
endPoint,
|
||||
deleted: false,
|
||||
});
|
||||
|
||||
await page.click('body'); // Equivalent to clicking outside
|
||||
|
||||
await page.click('[data-testid="manage-button"]');
|
||||
await page.click('[data-testid="delete-button"]');
|
||||
|
||||
await page.waitForSelector('[role="dialog"]');
|
||||
|
||||
await expect(page.locator('[role="dialog"]')).toBeVisible();
|
||||
await expect(page.locator('.ant-modal-title')).toContainText(displayName);
|
||||
|
||||
await page.fill('[data-testid="confirmation-text-input"]', 'DELETE');
|
||||
await page.click('[data-testid="confirm-button"]');
|
||||
|
||||
await page.waitForResponse(
|
||||
`/api/v1/${endPoint}/*?hardDelete=false&recursive=true`
|
||||
);
|
||||
|
||||
await expect(page.locator('.Toastify__toast-body')).toHaveText(
|
||||
/deleted successfully!/
|
||||
);
|
||||
|
||||
await page.click('.Toastify__close-button');
|
||||
|
||||
await page.reload();
|
||||
|
||||
const deletedBadge = await page.locator('[data-testid="deleted-badge"]');
|
||||
|
||||
await expect(deletedBadge).toHaveText('Deleted');
|
||||
|
||||
await deletedEntityCommonChecks({
|
||||
page,
|
||||
endPoint,
|
||||
deleted: true,
|
||||
});
|
||||
|
||||
await page.click('body'); // Equivalent to clicking outside
|
||||
|
||||
if (endPoint === EntityTypeEndpoint.Table) {
|
||||
await page.click('[data-testid="breadcrumb-link"]:last-child');
|
||||
await page.waitForResponse('/api/v1/databaseSchemas/name');
|
||||
await page.click('[data-testid="show-deleted"]');
|
||||
await page.waitForResponse('/api/v1/tables?databaseSchema=*');
|
||||
const tableCount = await page.locator(
|
||||
'[data-testid="table"] [data-testid="count"]'
|
||||
);
|
||||
|
||||
await expect(tableCount).toContainText('1');
|
||||
|
||||
await page.click(`[data-testid=${entityName}]`);
|
||||
}
|
||||
|
||||
await restoreEntity(page);
|
||||
await page.reload();
|
||||
|
||||
await deletedEntityCommonChecks({
|
||||
page,
|
||||
endPoint,
|
||||
deleted: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const hardDeleteEntity = async (
|
||||
page: Page,
|
||||
entityName: string,
|
||||
endPoint: EntityType
|
||||
) => {
|
||||
await page.click('[data-testid="manage-button"]');
|
||||
await page.click('[data-testid="delete-button"]');
|
||||
|
||||
await expect(page.locator('[role="dialog"]')).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.locator('[data-testid="delete-modal"] .ant-modal-title')
|
||||
).toHaveText(new RegExp(entityName));
|
||||
|
||||
await page.click('[data-testid="hard-delete-option"]');
|
||||
await page.check('[data-testid="hard-delete"]');
|
||||
await page.fill('[data-testid="confirmation-text-input"]', 'DELETE');
|
||||
await page.click('[data-testid="confirm-button"]');
|
||||
await page.waitForResponse(
|
||||
`**/api/v1/${endPoint}/*?hardDelete=true&recursive=true`
|
||||
);
|
||||
|
||||
await expect(page.locator('.Toastify__toast-body')).toHaveText(
|
||||
/deleted successfully!/
|
||||
);
|
||||
|
||||
await page.click('.Toastify__close-button');
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user