PLAYWRIGHT: fix the flaky delete step failing in entity and serviceEntity around bar (#21671)

This commit is contained in:
Ashish Gupta 2025-06-12 15:10:49 +05:30 committed by Shailesh Parmar
parent 81469afd63
commit 5f60bc0b2e
11 changed files with 76 additions and 53 deletions

View File

@ -52,8 +52,11 @@ const entity = new TableClass();
const entity2 = new TableClass(); const entity2 = new TableClass();
const entity3 = new TableClass(); const entity3 = new TableClass();
const entity4 = new TableClass(); const entity4 = new TableClass();
const entity5 = new TableClass();
const user1 = new UserClass(); const user1 = new UserClass();
const user2 = new UserClass(); const user2 = new UserClass();
const user3 = new UserClass();
const user4 = new UserClass();
const adminUser = new UserClass(); const adminUser = new UserClass();
const test = base.extend<{ page: Page }>({ const test = base.extend<{ page: Page }>({
@ -76,8 +79,11 @@ test.describe('Activity feed', () => {
await entity2.create(apiContext); await entity2.create(apiContext);
await entity3.create(apiContext); await entity3.create(apiContext);
await entity4.create(apiContext); await entity4.create(apiContext);
await entity5.create(apiContext);
await user1.create(apiContext); await user1.create(apiContext);
await user2.create(apiContext); await user2.create(apiContext);
await user3.create(apiContext);
await user4.create(apiContext);
await afterAction(); await afterAction();
}); });
@ -88,8 +94,11 @@ test.describe('Activity feed', () => {
await entity2.delete(apiContext); await entity2.delete(apiContext);
await entity3.delete(apiContext); await entity3.delete(apiContext);
await entity4.delete(apiContext); await entity4.delete(apiContext);
await entity5.delete(apiContext);
await user1.delete(apiContext); await user1.delete(apiContext);
await user2.delete(apiContext); await user2.delete(apiContext);
await user3.delete(apiContext);
await user4.delete(apiContext);
await adminUser.delete(apiContext); await adminUser.delete(apiContext);
await afterAction(); await afterAction();
@ -504,18 +513,18 @@ test.describe('Activity feed', () => {
test('Check Task Filter in Landing Page Widget', async ({ browser }) => { test('Check Task Filter in Landing Page Widget', async ({ browser }) => {
const { page: page1, afterAction: afterActionUser1 } = const { page: page1, afterAction: afterActionUser1 } =
await performUserLogin(browser, user1); await performUserLogin(browser, user1);
const { page: page2, afterAction: afterActionUser2 } = const { page: page2, afterAction: afterActionUser3 } =
await performUserLogin(browser, user2); await performUserLogin(browser, user3);
await base.step('Create and Assign Task to User 2', async () => { await base.step('Create and Assign Task to User 3', async () => {
await redirectToHomePage(page1); await redirectToHomePage(page1);
await entity.visitEntityPage(page1); await entity.visitEntityPage(page1);
// Create task for the user 2 // Create task for the user 3
await page1.getByTestId('request-description').click(); await page1.getByTestId('request-description').click();
await createDescriptionTask(page1, { await createDescriptionTask(page1, {
term: entity.entity.displayName, term: entity.entity.displayName,
assignee: user2.responseData.name, assignee: user3.responseData.name,
}); });
await afterActionUser1(); await afterActionUser1();
@ -544,6 +553,7 @@ test.describe('Activity feed', () => {
.click(); .click();
await taskResponse; await taskResponse;
await page2.waitForLoadState('networkidle');
await expect( await expect(
page2.locator( page2.locator(
@ -571,7 +581,7 @@ test.describe('Activity feed', () => {
await page2.getByTestId('task-feed-card').locator('.ant-avatar').hover(); await page2.getByTestId('task-feed-card').locator('.ant-avatar').hover();
await expect( await expect(
page2.getByText(user2.responseData.displayName).first() page2.getByText(user3.responseData.displayName).first()
).toBeVisible(); ).toBeVisible();
// Check the Task based on Created by me task filter // Check the Task based on Created by me task filter
@ -592,21 +602,23 @@ test.describe('Activity feed', () => {
await page2.getByTestId('task-feed-card').locator('.ant-avatar').hover(); await page2.getByTestId('task-feed-card').locator('.ant-avatar').hover();
await expect( await expect(
page2.getByText(user2.responseData.displayName).first() page2.getByText(user3.responseData.displayName).first()
).toBeVisible(); ).toBeVisible();
await afterActionUser2(); await afterActionUser3();
}); });
}); });
test('Verify feed count', async ({ page }) => { test('Verify feed count', async ({ page }) => {
await redirectToHomePage(page); await redirectToHomePage(page);
await entity.visitEntityPage(page); await entity5.visitEntityPage(page);
await page.getByTestId('request-description').click(); await page.getByTestId('request-description').click();
await createDescriptionTask(page, { await createDescriptionTask(page, {
term: entity.entity.displayName, term: entity5.entity.displayName,
assignee: user1.responseData.name, assignee: user4.responseData.name,
}); });
await page.waitForSelector('[data-testid="loader"]', { state: 'detached' });
await page.waitForLoadState('networkidle');
await expect(page.getByTestId('left-panel-task-count')).toHaveText('1'); await expect(page.getByTestId('left-panel-task-count')).toHaveText('1');
}); });

View File

@ -122,9 +122,6 @@ test.describe('Bulk Edit Entity', () => {
); );
await page.click('[data-testid="bulk-edit-table"]'); await page.click('[data-testid="bulk-edit-table"]');
// Adding manual wait for the file to load
await page.waitForTimeout(500);
await page.waitForSelector('[data-testid="loader"]', { await page.waitForSelector('[data-testid="loader"]', {
state: 'detached', state: 'detached',
}); });
@ -138,6 +135,9 @@ test.describe('Bulk Edit Entity', () => {
page.getByRole('button', { name: 'Previous' }) page.getByRole('button', { name: 'Previous' })
).not.toBeVisible(); ).not.toBeVisible();
// Adding manual wait for the file to load
await page.waitForTimeout(500);
// Click on first cell and edit // Click on first cell and edit
await page.click( await page.click(
@ -260,9 +260,6 @@ test.describe('Bulk Edit Entity', () => {
await page.click('[data-testid="bulk-edit-table"]'); await page.click('[data-testid="bulk-edit-table"]');
// Adding manual wait for the file to load
await page.waitForTimeout(500);
await page.waitForSelector('[data-testid="loader"]', { await page.waitForSelector('[data-testid="loader"]', {
state: 'detached', state: 'detached',
}); });
@ -276,6 +273,9 @@ test.describe('Bulk Edit Entity', () => {
page.getByRole('button', { name: 'Previous' }) page.getByRole('button', { name: 'Previous' })
).not.toBeVisible(); ).not.toBeVisible();
// Adding manual wait for the file to load
await page.waitForTimeout(500);
// click on last row first cell // click on last row first cell
await page.click( await page.click(
'.InovuaReactDataGrid__row--first > .InovuaReactDataGrid__row-cell-wrap > .InovuaReactDataGrid__cell--first' '.InovuaReactDataGrid__row--first > .InovuaReactDataGrid__row-cell-wrap > .InovuaReactDataGrid__cell--first'
@ -410,9 +410,6 @@ test.describe('Bulk Edit Entity', () => {
await page.click('[data-testid="bulk-edit-table"]'); await page.click('[data-testid="bulk-edit-table"]');
// Adding manual wait for the file to load
await page.waitForTimeout(500);
// Adding some assertion to make sure that CSV loaded correctly // Adding some assertion to make sure that CSV loaded correctly
await expect( await expect(
page.locator('.InovuaReactDataGrid__header-layout') page.locator('.InovuaReactDataGrid__header-layout')
@ -422,6 +419,9 @@ test.describe('Bulk Edit Entity', () => {
page.getByRole('button', { name: 'Previous' }) page.getByRole('button', { name: 'Previous' })
).not.toBeVisible(); ).not.toBeVisible();
// Adding manual wait for the file to load
await page.waitForTimeout(500);
// Click on first cell and edit // Click on first cell and edit
await page.click( await page.click(
'.InovuaReactDataGrid__row--first > .InovuaReactDataGrid__row-cell-wrap > .InovuaReactDataGrid__cell--first' '.InovuaReactDataGrid__row--first > .InovuaReactDataGrid__row-cell-wrap > .InovuaReactDataGrid__cell--first'
@ -524,9 +524,6 @@ test.describe('Bulk Edit Entity', () => {
await page.click('[data-testid="bulk-edit-table"]'); await page.click('[data-testid="bulk-edit-table"]');
// Adding manual wait for the file to load
await page.waitForTimeout(500);
// Adding some assertion to make sure that CSV loaded correctly // Adding some assertion to make sure that CSV loaded correctly
await expect( await expect(
page.locator('.InovuaReactDataGrid__header-layout') page.locator('.InovuaReactDataGrid__header-layout')
@ -536,6 +533,9 @@ test.describe('Bulk Edit Entity', () => {
page.getByRole('button', { name: 'Previous' }) page.getByRole('button', { name: 'Previous' })
).not.toBeVisible(); ).not.toBeVisible();
// Adding manual wait for the file to load
await page.waitForTimeout(500);
// click on row first cell // click on row first cell
await page.click( await page.click(
'.InovuaReactDataGrid__row--first > .InovuaReactDataGrid__row-cell-wrap > .InovuaReactDataGrid__cell--first' '.InovuaReactDataGrid__row--first > .InovuaReactDataGrid__row-cell-wrap > .InovuaReactDataGrid__cell--first'
@ -623,9 +623,6 @@ test.describe('Bulk Edit Entity', () => {
await page.click('[data-testid="bulk-edit-table"]'); await page.click('[data-testid="bulk-edit-table"]');
// Adding manual wait for the file to load
await page.waitForTimeout(500);
// Adding some assertion to make sure that CSV loaded correctly // Adding some assertion to make sure that CSV loaded correctly
await expect( await expect(
page.locator('.InovuaReactDataGrid__header-layout') page.locator('.InovuaReactDataGrid__header-layout')
@ -635,6 +632,9 @@ test.describe('Bulk Edit Entity', () => {
page.getByRole('button', { name: 'Previous' }) page.getByRole('button', { name: 'Previous' })
).not.toBeVisible(); ).not.toBeVisible();
// Adding manual wait for the file to load
await page.waitForTimeout(500);
// Click on first cell and edit // Click on first cell and edit
await page.click( await page.click(
'.InovuaReactDataGrid__row--first > .InovuaReactDataGrid__row-cell-wrap > .InovuaReactDataGrid__cell--first' '.InovuaReactDataGrid__row--first > .InovuaReactDataGrid__row-cell-wrap > .InovuaReactDataGrid__cell--first'

View File

@ -137,9 +137,8 @@ test.describe('Tag Page with Admin Roles', () => {
test('Rename Tag name', async ({ adminPage }) => { test('Rename Tag name', async ({ adminPage }) => {
await redirectToHomePage(adminPage); await redirectToHomePage(adminPage);
const res = adminPage.waitForResponse(`/api/v1/tags/name/*`);
await tag.visitPage(adminPage); await tag.visitPage(adminPage);
await res;
await adminPage.getByTestId('manage-button').click(); await adminPage.getByTestId('manage-button').click();
await expect( await expect(
@ -163,9 +162,8 @@ test.describe('Tag Page with Admin Roles', () => {
test('Restyle Tag', async ({ adminPage }) => { test('Restyle Tag', async ({ adminPage }) => {
await redirectToHomePage(adminPage); await redirectToHomePage(adminPage);
const res = adminPage.waitForResponse(`/api/v1/tags/name/*`);
await tag.visitPage(adminPage); await tag.visitPage(adminPage);
await res;
await adminPage.getByTestId('manage-button').click(); await adminPage.getByTestId('manage-button').click();
await expect( await expect(
@ -189,9 +187,8 @@ test.describe('Tag Page with Admin Roles', () => {
test('Edit Tag Description', async ({ adminPage }) => { test('Edit Tag Description', async ({ adminPage }) => {
await redirectToHomePage(adminPage); await redirectToHomePage(adminPage);
const res = adminPage.waitForResponse(`/api/v1/tags/name/*`);
await tag.visitPage(adminPage); await tag.visitPage(adminPage);
await res;
await adminPage.getByTestId('edit-description').click(); await adminPage.getByTestId('edit-description').click();
await expect(adminPage.getByRole('dialog')).toBeVisible(); await expect(adminPage.getByRole('dialog')).toBeVisible();
@ -212,9 +209,7 @@ test.describe('Tag Page with Admin Roles', () => {
test('Delete a Tag', async ({ adminPage }) => { test('Delete a Tag', async ({ adminPage }) => {
await redirectToHomePage(adminPage); await redirectToHomePage(adminPage);
const res = adminPage.waitForResponse(`/api/v1/tags/name/*`);
await tag.visitPage(adminPage); await tag.visitPage(adminPage);
await res;
await adminPage.getByTestId('manage-button').click(); await adminPage.getByTestId('manage-button').click();
await expect( await expect(

View File

@ -98,6 +98,8 @@ const test = base.extend<{
}); });
base.beforeAll('Setup pre-requests', async ({ browser }) => { base.beforeAll('Setup pre-requests', async ({ browser }) => {
test.slow(true);
const { apiContext, afterAction } = await performAdminLogin(browser); const { apiContext, afterAction } = await performAdminLogin(browser);
await adminUser.create(apiContext); await adminUser.create(apiContext);
@ -116,6 +118,8 @@ base.beforeAll('Setup pre-requests', async ({ browser }) => {
}); });
base.afterAll('Cleanup', async ({ browser }) => { base.afterAll('Cleanup', async ({ browser }) => {
test.slow(true);
const { apiContext, afterAction } = await performAdminLogin(browser); const { apiContext, afterAction } = await performAdminLogin(browser);
await adminUser.delete(apiContext); await adminUser.delete(apiContext);
await dataConsumerUser.delete(apiContext); await dataConsumerUser.delete(apiContext);
@ -417,7 +421,7 @@ test.describe('User with Data Steward Roles', () => {
await addOwner({ await addOwner({
page: adminPage, page: adminPage,
owner: user.responseData.displayName, owner: user.responseData.displayName ?? user.responseData.name,
type: 'Users', type: 'Users',
endpoint: EntityTypeEndpoint.Table, endpoint: EntityTypeEndpoint.Table,
dataTestId: 'data-assets-header', dataTestId: 'data-assets-header',
@ -471,9 +475,10 @@ test.describe('User Profile Feed Interactions', () => {
); );
const avatar = adminPage const avatar = adminPage
.locator('[data-testid="message-container"]') .locator('#feedData [data-testid="message-container"]')
.first() .first()
.locator('[data-testid="profile-avatar"]'); .locator('[data-testid="profile-avatar"]')
.first();
await avatar.hover(); await avatar.hover();
await adminPage.waitForSelector('.ant-popover-card'); await adminPage.waitForSelector('.ant-popover-card');

View File

@ -187,6 +187,7 @@ test('GlossaryTerm', async ({ page }) => {
}); });
await page.reload(); await page.reload();
await page.waitForLoadState('networkidle');
const versionPageResponse = page.waitForResponse( const versionPageResponse = page.waitForResponse(
`/api/v1/glossaryTerms/${term2.responseData.id}/versions/0.2` `/api/v1/glossaryTerms/${term2.responseData.id}/versions/0.2`
); );
@ -199,14 +200,10 @@ test('GlossaryTerm', async ({ page }) => {
) )
).toBeVisible(); ).toBeVisible();
await page.waitForLoadState('networkidle');
const glossaryTermsRes = page.waitForResponse( const glossaryTermsRes = page.waitForResponse(
'/api/v1/glossaryTerms/name/**' '/api/v1/glossaryTerms/name/**'
); );
await page.getByRole('dialog').getByRole('img').click(); await page.getByRole('dialog').getByRole('img').click();
await page.waitForLoadState('networkidle');
await glossaryTermsRes; await glossaryTermsRes;
await addMultiOwner({ await addMultiOwner({
@ -219,11 +216,11 @@ test('GlossaryTerm', async ({ page }) => {
}); });
await page.reload(); await page.reload();
await page.waitForLoadState('networkidle');
await page.click('[data-testid="version-button"]'); await page.click('[data-testid="version-button"]');
await versionPageResponse; await versionPageResponse;
await page.waitForLoadState('networkidle');
const diffLocator = page.locator( const diffLocator = page.locator(
'[data-testid="glossary-reviewer"] [data-testid="diff-added"]' '[data-testid="glossary-reviewer"] [data-testid="diff-added"]'
); );

View File

@ -69,7 +69,10 @@ export class TagClass {
this.responseData.classification.name, this.responseData.classification.name,
this.responseData.classification.displayName this.responseData.classification.displayName
); );
const res = page.waitForResponse(`/api/v1/tags/name/*`);
await page.getByTestId(this.data.name).click(); await page.getByTestId(this.data.name).click();
await res;
await page.waitForLoadState('networkidle');
} }
async create(apiContext: APIRequestContext) { async create(apiContext: APIRequestContext) {

View File

@ -58,8 +58,8 @@ export const getAuthContext = async (token: string) => {
export const redirectToHomePage = async (page: Page) => { export const redirectToHomePage = async (page: Page) => {
await page.goto('/'); await page.goto('/');
await page.waitForLoadState('networkidle');
await page.waitForURL('**/my-data'); await page.waitForURL('**/my-data');
await page.waitForLoadState('networkidle');
}; };
export const removeLandingBanner = async (page: Page) => { export const removeLandingBanner = async (page: Page) => {

View File

@ -43,10 +43,10 @@ export const visitEntityPage = async (data: {
dataTestId: string; dataTestId: string;
}) => { }) => {
const { page, searchTerm, dataTestId } = data; const { page, searchTerm, dataTestId } = data;
await page.waitForLoadState('networkidle');
const waitForSearchResponse = page.waitForResponse( const waitForSearchResponse = page.waitForResponse(
'/api/v1/search/query?q=*index=dataAsset*' '/api/v1/search/query?q=*index=dataAsset*'
); );
await page.waitForLoadState('networkidle');
await page.getByTestId('searchBox').fill(searchTerm); await page.getByTestId('searchBox').fill(searchTerm);
await waitForSearchResponse; await waitForSearchResponse;
await page.getByTestId(dataTestId).getByTestId('data-name').click(); await page.getByTestId(dataTestId).getByTestId('data-name').click();
@ -1367,10 +1367,9 @@ export const hardDeleteEntity = async (
await page.click('[data-testid="confirm-button"]'); await page.click('[data-testid="confirm-button"]');
await deleteResponse; await deleteResponse;
await toastNotification( await expect(page.getByTestId('alert-bar')).toHaveText(
page, /(deleted successfully!|Delete operation initiated)/,
/deleted successfully!/, { timeout: BIG_ENTITY_DELETE_TIMEOUT }
BIG_ENTITY_DELETE_TIMEOUT
); );
}; };

View File

@ -46,9 +46,19 @@ export const createGlossaryTermRowDetails = () => {
export const fillTextInputDetails = async (page: Page, text: string) => { export const fillTextInputDetails = async (page: Page, text: string) => {
await page.keyboard.press('Enter', { delay: 100 }); await page.keyboard.press('Enter', { delay: 100 });
const isVisible = await page
.locator('.ant-layout-content')
.getByRole('textbox')
.isVisible();
if (!isVisible) {
await page.keyboard.press('Enter', { delay: 100 });
}
const textboxLocator = page const textboxLocator = page
.locator('.ant-layout-content') .locator('.ant-layout-content')
.getByRole('textbox'); .getByRole('textbox');
await textboxLocator.fill(text); await textboxLocator.fill(text);
await textboxLocator.press('Enter', { delay: 100 }); await textboxLocator.press('Enter', { delay: 100 });
}; };

View File

@ -91,9 +91,7 @@ export const addAssetsToTag = async (
tag: TagClass, tag: TagClass,
otherAsset?: EntityClass[] otherAsset?: EntityClass[]
) => { ) => {
const res = page.waitForResponse(`/api/v1/tags/name/*`);
await tag.visitPage(page); await tag.visitPage(page);
await res;
await page.waitForSelector( await page.waitForSelector(
'[data-testid="tags-container"] [data-testid="loader"]', '[data-testid="tags-container"] [data-testid="loader"]',
@ -334,9 +332,7 @@ export const verifyTagPageUI = async (
limitedAccess = false limitedAccess = false
) => { ) => {
await redirectToHomePage(page); await redirectToHomePage(page);
const res = page.waitForResponse(`/api/v1/tags/name/*`);
await tag.visitPage(page); await tag.visitPage(page);
await res;
await page.waitForSelector( await page.waitForSelector(
'[data-testid="tags-container"] [data-testid="loader"]', '[data-testid="tags-container"] [data-testid="loader"]',
@ -363,6 +359,7 @@ export const verifyTagPageUI = async (
await page.getByRole('link', { name: classificationName }).click(); await page.getByRole('link', { name: classificationName }).click();
classificationTable; classificationTable;
const res = page.waitForResponse(`/api/v1/tags/name/*`);
await page.getByTestId(tag.data.name).click(); await page.getByTestId(tag.data.name).click();
await res; await res;

View File

@ -578,6 +578,11 @@ export const checkStewardServicesPermissions = async (page: Page) => {
await queryResponse; await queryResponse;
// Perform search actions // Perform search actions
await page.click('[data-testid="search-dropdown-Data Assets"]'); await page.click('[data-testid="search-dropdown-Data Assets"]');
await page.getByTestId('drop-down-menu').getByTestId('loader').waitFor({
state: 'detached',
});
await page.locator('[data-testid="table-checkbox"]').scrollIntoViewIfNeeded(); await page.locator('[data-testid="table-checkbox"]').scrollIntoViewIfNeeded();
await page.click('[data-testid="table-checkbox"]'); await page.click('[data-testid="table-checkbox"]');