From 1cde091b194f0b09ab7e429e2df7eabf1fb277f1 Mon Sep 17 00:00:00 2001 From: Dhruv Parmar <83108871+dhruvjsx@users.noreply.github.com> Date: Thu, 11 Sep 2025 20:05:32 +0530 Subject: [PATCH] Fix(ui): Flaky Table.spec Playwright (#23267) * fixed table.spec * fixed failing tests --------- Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com> --- .../ui/playwright/e2e/Features/Table.spec.ts | 169 ++++++++++++++---- 1 file changed, 131 insertions(+), 38 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/Table.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/Table.spec.ts index 7600920ba55..e3b48daaee1 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/Table.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/Table.spec.ts @@ -467,9 +467,8 @@ test.describe( test.afterAll(async ({ browser }) => { const { apiContext } = await performAdminLogin(browser); - - await glossary.delete(apiContext); await glossaryTerm.delete(apiContext); + await glossary.delete(apiContext); await testClassification.delete(apiContext); await testTag.delete(apiContext); }); @@ -477,13 +476,77 @@ test.describe( test('Glossary term should be consistent for search', async ({ dataConsumerPage: page, }) => { + // Go to tables page await page.goto('/table/sample_data.ecommerce_db.shopify.dim_customer'); + // Wait for page to be fully loaded + await page.waitForLoadState('networkidle'); + await page.waitForSelector('[data-testid="loader"]', { + state: 'detached', + }); + + // Check if add button exists and is visible + const rowSelector = + '[data-row-key="sample_data.ecommerce_db.shopify.dim_customer.customer_id"] [data-testid="glossary-tags-0"]'; + + const addButton = await page.$(`${rowSelector} [data-testid="add-tag"]`); + if (addButton && (await addButton.isVisible())) { + await addButton.click(); + } else { + await page + .locator(`${rowSelector} [data-testid="edit-button"]`) + .click(); + } + + await page.waitForSelector('.ant-select-dropdown', { state: 'visible' }); + await page.waitForSelector( + '.ant-select-dropdown [data-testid="loader"]', + { + state: 'detached', + } + ); + await page - .locator( - '[data-row-key="sample_data.ecommerce_db.shopify.dim_customer.customer_id"] [data-testid="glossary-tags-0"] [data-testid="entity-tags"] svg' - ) + .locator('[data-testid="tag-selector"] input') + .fill(glossaryTerm.data.name); + + await page + .getByTestId(`tag-${glossaryTerm.responseData.fullyQualifiedName}`) .click(); + const saveResponse = page.waitForResponse('api/v1/columns/name/*'); + await page.getByTestId('saveAssociatedTag').click(); + + await saveResponse; + + await expect( + page.getByTestId(`tag-${glossaryTerm.responseData.fullyQualifiedName}`) + ).toBeVisible(); + + const searchRequest = page.waitForResponse( + 'api/v1/tables/name/sample_data.ecommerce_db.shopify.dim_customer/columns/*' + ); + + await page + .getByTestId('search-bar-container') + .getByTestId('searchbar') + .fill('customer_id'); + + await searchRequest; + await page.waitForSelector( + '[data-testid="entity-table"] [data-testid="loader"]', + { + state: 'detached', + } + ); + + await expect( + page + .getByTestId('glossary-tags-0') + .getByTestId(`tag-${glossaryTerm.responseData.fullyQualifiedName}`) + ).toBeVisible(); + + await page.click(`${rowSelector} [data-testid="edit-button"]`); + await page.waitForSelector('.ant-select-dropdown', { state: 'visible' }); await page.waitForSelector( '.ant-select-dropdown [data-testid="loader"]', @@ -492,11 +555,11 @@ test.describe( } ); await page - .locator('.ant-select-dropdown') - .getByTestId(`tag-${glossary.responseData.fullyQualifiedName}`) - .getByTestId('expand-icon') - .click(); + .locator('[data-testid="tag-selector"] input') + .fill(glossaryTerm.data.name); + await page + .locator('.ant-select-dropdown') .getByTestId(`tag-${glossaryTerm.responseData.fullyQualifiedName}`) .click(); @@ -506,24 +569,7 @@ test.describe( await expect( page.getByTestId(`tag-${glossaryTerm.responseData.fullyQualifiedName}`) - ).toContainText(glossaryTerm.responseData.displayName); - - const getRequest = page.waitForResponse( - 'api/v1/tables/name/sample_data.ecommerce_db.shopify.dim_customer/columns/*' - ); - - await page - .getByTestId('search-bar-container') - .getByTestId('searchbar') - .fill('customer_id'); - - await getRequest; - - await expect( - page - .getByTestId('glossary-tags-0') - .getByTestId(`tag-${glossaryTerm.responseData.fullyQualifiedName}`) - ).toContainText(glossaryTerm.responseData.displayName); + ).not.toBeVisible(); }); test('Tags term should be consistent for search', async ({ @@ -531,11 +577,22 @@ test.describe( }) => { await page.goto('/table/sample_data.ecommerce_db.shopify.dim_customer'); - await page - .locator( - '[data-row-key="sample_data.ecommerce_db.shopify.dim_customer.customer_id"] [data-testid="classification-tags-0"] [data-testid="entity-tags"] svg' - ) - .click(); + // Wait for page to be fully loaded + await page.waitForLoadState('networkidle'); + await page.waitForSelector('[data-testid="loader"]', { + state: 'detached', + }); + + // Check if add button exists and is visible + const rowSelector = + '[data-row-key="sample_data.ecommerce_db.shopify.dim_customer.shop_id"] [data-testid="classification-tags-1"]'; + + const addButton = await page.$(`${rowSelector} [data-testid="add-tag"]`); + if (addButton && (await addButton.isVisible())) { + await addButton.click(); + } else { + await page.click(`${rowSelector} [data-testid="edit-button"]`); + } await page.waitForSelector('.ant-select-dropdown', { state: 'visible' }); await page.waitForSelector( @@ -558,22 +615,58 @@ test.describe( await expect( page.getByTestId(`tag-${testTag.responseData.fullyQualifiedName}`) - ).toContainText(testTag.responseData.displayName); + ).toBeVisible(); + page.reload(); + // Wait for page to be fully loaded + await page.waitForLoadState('networkidle'); + await page.waitForSelector('[data-testid="loader"]', { + state: 'detached', + }); + const getRequest = page.waitForResponse( + 'api/v1/tables/name/sample_data.ecommerce_db.shopify.dim_customer/columns/*' + ); await page .getByTestId('search-bar-container') .getByTestId('searchbar') - .fill('customer_id'); + .fill('shop_id'); - await page.waitForResponse( - 'api/v1/tables/name/sample_data.ecommerce_db.shopify.dim_customer/columns/*' - ); + await getRequest; await expect( page .getByTestId('classification-tags-0') .getByTestId(`tag-${testTag.responseData.fullyQualifiedName}`) - ).toContainText(testTag.responseData.displayName); + ).toBeVisible(); + + await page.click( + `[data-row-key="sample_data.ecommerce_db.shopify.dim_customer.shop_id"] [data-testid="classification-tags-0"] [data-testid="edit-button"]` + ); + + await page.waitForSelector('.ant-select-dropdown', { state: 'visible' }); + await page.waitForSelector( + '.ant-select-dropdown [data-testid="loader"]', + { + state: 'detached', + } + ); + await page + .locator('[data-testid="tag-selector"] input') + .fill(testTag.data.name); + await page + .locator('.ant-select-dropdown') + .getByTestId(`tag-${testTag.responseData.fullyQualifiedName}`) + .click(); + + await page.getByTestId('saveAssociatedTag').click(); + + await page.waitForResponse('api/v1/columns/name/*'); + + await expect( + page + .getByTestId('classification-tags-0') + .getByTestId(`tag-${testTag.responseData.fullyQualifiedName}`) + ).not.toBeVisible(); }); } );