diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityFeed.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityFeed.spec.ts index ec4f15752488..e73437509887 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityFeed.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityFeed.spec.ts @@ -30,7 +30,6 @@ import { REACTION_EMOJIS, reactOnFeedCard } from '../../utils/activityFeed'; import { performAdminLogin } from '../../utils/admin'; import { redirectToHomePage, - removeLandingBanner, uuid, visitOwnProfilePage, } from '../../utils/common'; @@ -168,7 +167,6 @@ test.describe('FeedWidget on landing page', () => { try { // Set persona as default await redirectToHomePage(adminPage); - await removeLandingBanner(adminPage); await waitForAllLoadersToDisappear(adminPage); await setUserDefaultPersona(adminPage, testPersona.data.displayName); @@ -199,7 +197,6 @@ test.describe('FeedWidget on landing page', () => { } await redirectToHomePage(adminPage); - await removeLandingBanner(adminPage); await waitForAllLoadersToDisappear(adminPage); } finally { await adminPage.close(); @@ -224,7 +221,6 @@ test.describe('FeedWidget on landing page', () => { test.beforeEach(async ({ page }) => { await adminUser.login(page); await redirectToHomePage(page); - await removeLandingBanner(page); await waitForAllLoadersToDisappear(page); }); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/CuratedAssets.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/CuratedAssets.spec.ts index eb460b91acbe..b03d3f2d2822 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/CuratedAssets.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/CuratedAssets.spec.ts @@ -16,7 +16,7 @@ import { PersonaClass } from '../../support/persona/PersonaClass'; import { UserClass } from '../../support/user/UserClass'; import { performAdminLogin } from '../../utils/admin'; import { selectOption } from '../../utils/advancedSearch'; -import { redirectToHomePage, removeLandingBanner } from '../../utils/common'; +import { redirectToHomePage } from '../../utils/common'; import { addCuratedAssetPlaceholder, CURATED_ASSETS_WIDGET_KEY, @@ -101,7 +101,6 @@ test.describe('Curated Assets Widget', () => { await setUserDefaultPersona(page, persona.responseData.displayName); await redirectToHomePage(page); - await removeLandingBanner(page); await page.getByTestId('sidebar-toggle').click(); }); @@ -188,7 +187,6 @@ test.describe('Curated Assets Widget', () => { ).toBeVisible(); await redirectToHomePage(page); - await removeLandingBanner(page); await waitForAllLoadersToDisappear(page, 'entity-list-skeleton'); @@ -387,7 +385,6 @@ test.describe('Curated Assets Widget', () => { // Wait for auto-save to complete before navigating await redirectToHomePage(page); - await removeLandingBanner(page); await waitForAllLoadersToDisappear(page, 'entity-list-skeleton'); @@ -503,7 +500,6 @@ test.describe('Curated Assets Widget', () => { // Navigate to landing page to verify widget await redirectToHomePage(page); - await removeLandingBanner(page); await waitForAllLoadersToDisappear(page, 'entity-list-skeleton'); @@ -646,7 +642,6 @@ test.describe('Curated Assets Widget', () => { // Navigate to landing page to verify widget await redirectToHomePage(page); - await removeLandingBanner(page); await waitForAllLoadersToDisappear(page, 'entity-list-skeleton'); @@ -685,7 +680,6 @@ test.describe('Curated Assets Widget', () => { await page.locator('[data-testid="save-button"]').click(); await redirectToHomePage(page); - await removeLandingBanner(page); // Verify placeholder is not visible when no widget is configured await expect( diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts index 1e0f0064fbc2..b194f55c9402 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts @@ -20,7 +20,7 @@ import { TopicClass } from '../../../support/entity/TopicClass'; import { PersonaClass } from '../../../support/persona/PersonaClass'; import { UserClass } from '../../../support/user/UserClass'; import { performAdminLogin } from '../../../utils/admin'; -import { redirectToHomePage, removeLandingBanner } from '../../../utils/common'; +import { redirectToHomePage } from '../../../utils/common'; import { addAndVerifyWidget, setUserDefaultPersona, @@ -95,7 +95,6 @@ test.describe.serial('Domain and Data Product Asset Counts', () => { test.slow(); // Slow Test test.beforeEach(async ({ page }, testInfo) => { await redirectToHomePage(page, false); - await removeLandingBanner(page); await waitForAllLoadersToDisappear(page).catch(() => undefined); if (testInfo.title !== 'Assign Widgets') { @@ -112,7 +111,6 @@ test.describe.serial('Domain and Data Product Asset Counts', () => { dataProduct.responseData.id ?? '' ); await redirectToHomePage(page, false); - await removeLandingBanner(page); await waitForAllLoadersToDisappear(page).catch(() => undefined); } }); @@ -134,7 +132,6 @@ test.describe.serial('Domain and Data Product Asset Counts', () => { test('Verify Widgets are having 0 count initially', async ({ page }) => { await redirectToHomePage(page, false); - await removeLandingBanner(page); await waitForAllLoadersToDisappear(page).catch(() => undefined); await verifyWidgetCountOnCurrentPage( diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/CustomizeLandingPage.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/CustomizeLandingPage.spec.ts index d633b89ec41b..660665af5581 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/CustomizeLandingPage.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/CustomizeLandingPage.spec.ts @@ -15,11 +15,7 @@ import { PLAYWRIGHT_BASIC_TEST_TAG_OBJ } from '../../constant/config'; import { PersonaClass } from '../../support/persona/PersonaClass'; import { UserClass } from '../../support/user/UserClass'; import { performAdminLogin } from '../../utils/admin'; -import { - redirectToHomePage, - removeLandingBanner, - toastNotification, -} from '../../utils/common'; +import { redirectToHomePage, toastNotification } from '../../utils/common'; import { checkAllDefaultWidgets, navigateToCustomizeLandingPage, @@ -339,7 +335,6 @@ test.describe( await saveCustomizeLayoutPage(adminPage); await redirectToHomePage(adminPage, false); - await removeLandingBanner(adminPage); await waitForAllLoadersToDisappear(adminPage).catch(() => undefined); await waitForLandingPageWidget(adminPage, 'KnowledgePanel.MyData'); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/CustomizeWidgets.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/CustomizeWidgets.spec.ts index a89ae28378c9..55b1e028c530 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/CustomizeWidgets.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/CustomizeWidgets.spec.ts @@ -22,11 +22,7 @@ import { PersonaClass } from '../../support/persona/PersonaClass'; import { UserClass } from '../../support/user/UserClass'; import { insertActivityEventForTest } from '../../utils/activityAPI'; import { performAdminLogin } from '../../utils/admin'; -import { - getApiContext, - redirectToHomePage, - removeLandingBanner, -} from '../../utils/common'; +import { getApiContext, redirectToHomePage } from '../../utils/common'; import { addAndVerifyWidget, removeAndVerifyWidget, @@ -238,7 +234,6 @@ test.afterAll( test.beforeEach(async ({ page }) => { await redirectToHomePage(page); - await removeLandingBanner(page); await waitForAllLoadersToDisappear(page); await waitForAllLoadersToDisappear(page, 'entity-list-skeleton'); }); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/Tour.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/Tour.spec.ts index 5a794c1efd95..9fab6e2c956a 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/Tour.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/Tour.spec.ts @@ -173,7 +173,11 @@ test.describe( }); test.beforeEach('Visit entity details page', async ({ page }) => { - await user.login(page); + // Tour is entered from the welcome banner, so this suite must NOT suppress + // it. The other tour tests already guard against the banner if present. + await user.login(page, undefined, undefined, { + suppressWelcomeScreen: false, + }); }); test('Tour should work from help section', async ({ page }) => { diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts index bf4d2a7c2b24..a87d8587188c 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts @@ -11,6 +11,7 @@ * limitations under the License. */ +import { Page } from '@playwright/test'; import { KnowledgeCenterClass } from '../../support/entity/KnowledgeCenterClass'; import { expect, test as baseTest } from '../../support/fixtures/userPages'; import { Glossary } from '../../support/glossary/Glossary'; @@ -68,6 +69,31 @@ export const test = baseTest.extend<{ }, }); +/** + * Assert the owner chip is in the summary panel, re-opening the entity if it is + * not. The panel renders owners from the Explore search document, which is + * refreshed asynchronously after the owner PATCH — a panel that rendered before + * that refresh will never show the chip, so waiting on it is waiting on the + * wrong thing. Re-navigating re-reads it. + */ +async function expectOwnerInPanel( + page: Page, + entityName: string, + ownerName: string +) { + const ownerChip = page + .locator('[data-testid="entity-summary-panel-container"]') + .getByTestId(ownerName); + + await expect(async () => { + if (!(await ownerChip.isVisible())) { + await navigateToKCEntity(page, entityName); + } + + await expect(ownerChip).toBeVisible({ timeout: 10_000 }); + }).toPass({ timeout: 60_000, intervals: [2_000, 5_000] }); +} + test.describe('Knowledge Center Right Panel Test Suite', () => { test.beforeAll(async ({ browser }) => { test.slow(true); @@ -163,7 +189,6 @@ test.describe('Knowledge Center Right Panel Test Suite', () => { test('Should update owners for knowledgeCenter', async ({ adminPage, rightPanel, - overview, }) => { await navigateToKCEntity( adminPage, @@ -174,7 +199,11 @@ test.describe('Knowledge Center Right Panel Test Suite', () => { rightPanel.setEntityConfigByType('knowledgeCenter'); await addOwnerInKCPanel(adminPage, user1.getUserDisplayName()); - await overview.shouldShowOwner(user1.getUserDisplayName()); + await expectOwnerInPanel( + adminPage, + getEntityDisplayName(knowledgeCenter.responseData), + user1.getUserDisplayName() + ); }); }); @@ -277,7 +306,11 @@ test.describe('Knowledge Center Right Panel Test Suite', () => { rightPanel.setEntityConfigByType('knowledgeCenter'); await addOwnerInKCPanel(adminPage, user1.getUserDisplayName()); - await overview.shouldShowOwner(user1.getUserDisplayName()); + await expectOwnerInPanel( + adminPage, + getEntityDisplayName(knowledgeCenter.responseData), + user1.getUserDisplayName() + ); await overview.removeOwner([user1.getUserDisplayName()], 'Users'); await waitForAllLoadersToDisappear(adminPage); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts index 81a5fde38ba9..42dff396e9c9 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts @@ -44,6 +44,7 @@ import { redirectToHomePage, uuid, visitGlossaryPage, + waitForAntdPopupToSettle, } from '../../utils/common'; import { addMultiOwner, @@ -2194,10 +2195,12 @@ test.describe('Glossary tests', () => { .filter({ hasText: 'EN' }) .first(); await languageDropdown.click(); + await waitForAntdPopupToSettle(page); const germanOption = page.getByRole('menuitem', { name: 'Deutsch - DE', }); + await expect(germanOption).toBeVisible(); await germanOption.click(); await waitForAllLoadersToDisappear(page); @@ -2230,10 +2233,12 @@ test.describe('Glossary tests', () => { .filter({ hasText: 'DE' }) .first(); await languageDropdown.click(); + await waitForAntdPopupToSettle(page); const englishOption = page.getByRole('menuitem', { name: 'English - EN', }); + await expect(englishOption).toBeVisible(); await englishOption.click(); }); } finally { diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/ingestion/ServiceBaseClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/ingestion/ServiceBaseClass.ts index 4a8603cae938..bb823e56e09d 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/ingestion/ServiceBaseClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/ingestion/ServiceBaseClass.ts @@ -218,7 +218,19 @@ class ServiceBaseClass { await waitForIngestionWorkflowForm(page); await this.fillIngestionDetails(page); - await page.click('[data-testid="next-button"]'); + // Creating the service triggers AutoPilot, whose success toast renders + // bottom-center — directly over the wizard footer — and auto-closes after 5s + // (showSuccessToast(..., 5000) in AddServicePage). A click landing inside + // that window is intercepted by the toast, and with no per-action timeout + // the retry loop runs to the end of the test instead. + // + // Bounding the click is what fixes it, not waiting the toast out: the toast + // is fired by the create call several steps earlier, so whether it is on + // screen when we get here depends on how fast those steps ran. Gating on it + // being gone is a no-op when it has not rendered yet and when it has already + // closed. A bounded click covers every ordering — Playwright retries the + // intercepted click for the whole timeout, which outlasts the toast. + await page.click('[data-testid="next-button"]', { timeout: 30_000 }); // Go back and data should persist await page.click('[data-testid="previous-button"]'); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/user/AdminClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/user/AdminClass.ts index 2295aeae00b3..9df2acaf5338 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/user/AdminClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/user/AdminClass.ts @@ -22,8 +22,9 @@ export class AdminClass extends UserClass { async login( page: Page, userName = DEFAULT_ADMIN_USER.userName, - password = DEFAULT_ADMIN_USER.password + password = DEFAULT_ADMIN_USER.password, + options: { suppressWelcomeScreen?: boolean } = {} ) { - await super.login(page, userName, password); + await super.login(page, userName, password, options); } } diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/user/UserClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/user/UserClass.ts index f999c23dad78..c8b780476725 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/user/UserClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/user/UserClass.ts @@ -21,6 +21,7 @@ import { okJson, withNotFoundRetry } from '../../utils/apiResponse'; import { disableEtagConditionalReads, generateRandomUsername, + suppressWelcomeScreen, uuid, } from '../../utils/common'; import { PolicyClass, PolicyRulesType } from '../access-control/PoliciesClass'; @@ -257,8 +258,22 @@ export class UserClass { async login( page: Page, userName = this.data.email, - password = this.data.password + password = this.data.password, + options: { suppressWelcomeScreen?: boolean } = {} ) { + const { suppressWelcomeScreen: shouldSuppressWelcomeScreen = true } = + options; + + // Seed `loggedInUsers` before the first navigation so the landing-page + // welcome banner never renders for this session. Prefer the authoritative + // entity name from create(); fall back to the login email's local-part + // (the server-assigned username) for a pure login such as admin. Tests that + // exercise the welcome banner itself (e.g. Tour) opt out with + // `suppressWelcomeScreen: false`. + if (shouldSuppressWelcomeScreen) { + await suppressWelcomeScreen(page, this.responseData?.name ?? userName); + } + await page.goto('/signin'); try { await page.waitForURL('**/signin', { timeout: 5000 }); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/activityFeed.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/activityFeed.ts index 0501f0210e4f..1f5c9498792a 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/activityFeed.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/activityFeed.ts @@ -11,7 +11,7 @@ * limitations under the License. */ import { expect, Locator, Page } from '@playwright/test'; -import { descriptionBox, removeLandingBanner } from './common'; +import { descriptionBox } from './common'; import { waitForAllLoadersToDisappear } from './entity'; import { waitForPageLoaded } from './polling'; import { TaskDetails } from './task'; @@ -149,7 +149,6 @@ export const addMentionCommentInFeed = async ( const fetchFeedResponse = page.waitForResponse( '/api/v1/feed?type=Conversation*' ); - await removeLandingBanner(page); await fetchFeedResponse; } diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/common.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/common.ts index dc152265ed00..9bccfc5df978 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/common.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/common.ts @@ -105,6 +105,38 @@ export const disableEtagConditionalReads = async (page: Page) => { } }; +const LOGGED_IN_USERS_KEY = 'loggedInUsers'; + +/** + * Suppress the landing-page welcome banner at the source. + * + * MyDataPage renders the welcome banner only when the logged-in user's `name` + * is absent from the `loggedInUsers` localStorage list (see + * MyDataPage.component.tsx). Seeding that list with the user's name before the + * first navigation means the banner never renders for the session, so no test + * has to dismiss it. `userName` must equal the app's `currentUser.name` — for a + * created UserClass that is `responseData.name`; the email local-part is the + * server-assigned fallback for a pure login (e.g. admin). + */ +export const suppressWelcomeScreen = async (page: Page, userName: string) => { + const name = userName.includes('@') ? userName.split('@')[0] : userName; + const seed = ({ key, value }: { key: string; value: string }) => { + const existing = (localStorage.getItem(key) ?? '') + .split(',') + .filter(Boolean); + if (!existing.includes(value)) { + localStorage.setItem(key, [...existing, value].join(',')); + } + }; + const arg = { key: LOGGED_IN_USERS_KEY, value: name }; + + await page.addInitScript(seed, arg); + + if (/^https?:/.test(page.url())) { + await page.evaluate(seed, arg); + } +}; + export const redirectToHomePage = async ( page: Page, _waitForLoaders = true @@ -128,29 +160,6 @@ export const redirectToExplorePage = async (page: Page) => { await waitForAllLoadersToDisappear(page); }; -export const removeLandingBanner = async (page: Page) => { - try { - const welcomePageCloseButton = page.getByTestId('welcome-screen-close-btn'); - await welcomePageCloseButton - .waitFor({ - state: 'visible', - timeout: 5000, - }) - .catch(() => { - // Do nothing if the welcome banner does not exist - return; - }); - - // Close the welcome banner if it exists - if (await welcomePageCloseButton.isVisible()) { - await welcomePageCloseButton.click(); - } - } catch { - // Do nothing if the welcome banner does not exist - return; - } -}; - type CreateNewPageResult = { afterAction: () => Promise; apiContext: APIRequestContext; diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/customizeLandingPage.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/customizeLandingPage.ts index 0db748a1c445..0e006e408b49 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/customizeLandingPage.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/customizeLandingPage.ts @@ -13,7 +13,6 @@ import { expect, type Locator, type Page } from '@playwright/test'; import { redirectToHomePage, - removeLandingBanner, toastNotification, visitOwnProfilePage, } from './common'; @@ -287,7 +286,6 @@ export const toNameableEntity = ( }; export const checkAllDefaultWidgets = async (page: Page) => { - await removeLandingBanner(page); await waitForAllLoadersToDisappear(page); await waitForAllLoadersToDisappear(page, 'entity-list-skeleton'); @@ -417,7 +415,6 @@ export const addAndVerifyWidget = async ( await redirectToHomePage(page, false); await waitForAllLoadersToDisappear(page).catch(() => undefined); - await removeLandingBanner(page); // The save response is awaited and its toast asserted above, and `redirectToHomePage` // disables ETag conditional reads, so the first read-back is authoritative — the widget @@ -737,7 +734,6 @@ export const verifyWidgetHeaderNavigation = async ( // Home keeps background requests alive on some persona routes; use the lighter // redirect path and wait on rendered state instead of networkidle. await redirectToHomePage(page, false); - await removeLandingBanner(page); await waitForAllLoadersToDisappear(page).catch(() => undefined); await waitForAllLoadersToDisappear(page, 'entity-list-skeleton').catch( () => undefined @@ -755,7 +751,6 @@ export const verifyDomainCountInDomainWidget = async ( ].join(', '); await redirectToHomePage(page, false); - await removeLandingBanner(page); await expect .poll( @@ -795,7 +790,6 @@ export const verifyDataProductCountInDataProductWidget = async ( const widgetCardSelector = `[data-testid="data-product-card-${dataProductId}"] [data-testid="data-product-asset-count"]`; await redirectToHomePage(page, false); - await removeLandingBanner(page); await expect .poll( diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts index 8dc4b4b8396c..893019eb0096 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts @@ -36,7 +36,6 @@ import { getEntityTypeSearchIndexMapping, readElementInListWithScroll, redirectToHomePage, - removeLandingBanner, toastNotification, uuid, } from './common'; @@ -94,15 +93,6 @@ export const visitEntityPage = async (data: { await waitForAllLoadersToDisappear(page); - // Dismiss welcome screen if visible - const isWelcomeScreenVisible = await page - .getByTestId('welcome-screen') - .isVisible(); - - if (isWelcomeScreenVisible) { - await page.getByTestId('welcome-screen-close-btn').click(); - } - const searchResponse = page.waitForResponse( (response) => response.url().includes('/api/v1/search/query') && @@ -141,7 +131,6 @@ export const visitEntityPageByFqn = async (data: { }) => { const { page, endpoint, fqn } = data; await waitForAllLoadersToDisappear(page); - await removeLandingBanner(page); const routeSegment = ENTITY_PATH[endpoint as keyof typeof ENTITY_PATH]; if (!routeSegment) { @@ -1528,7 +1517,6 @@ const revealFollowingWidget = async (page: Page): Promise => { const loadFollowingWidget = async (page: Page): Promise => { await redirectToHomePage(page, false); - await removeLandingBanner(page); await waitForAllLoadersToDisappear(page).catch(() => undefined); const followingWidgetPanel = await revealFollowingWidget(page); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts index 7f5b25a80259..f0bab8cb0efc 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts @@ -1189,16 +1189,26 @@ export const changeTermHierarchyFromModal = async ( await page.getByTestId('manage-button').click(); await page.getByTestId('change-parent-button').click(); - await expect(page.locator('[role="dialog"]')).toBeVisible(); + const hierarchyModal = page.locator( + '[data-testid="change-parent-hierarchy-modal"]' + ); + await expect(hierarchyModal).toBeVisible(); + + // Scope to this modal: the page-level label also matches the control of a + // hierarchy modal left in the DOM by an earlier step, and the click then waits + // out the whole test on a hidden element. + const parentSelect = hierarchyModal.getByLabel('Select Parent'); + await expect(parentSelect).toBeVisible(); + await expect(parentSelect).toBeEnabled(); + await parentSelect.click(); - await page.getByLabel('Select Parent').click(); await page.locator('.async-tree-select-list-dropdown').waitFor({ state: 'visible', }); if (isGlossaryTerm) { const searchRes = page.waitForResponse(`/api/v1/search/query?q=*`); - await page.getByLabel('Select Parent').fill(entityDisplayName); + await parentSelect.fill(entityDisplayName); await searchRes; } diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/lineage.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/lineage.ts index f08225490254..1ce1f52e6c1c 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/lineage.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/lineage.ts @@ -1015,10 +1015,16 @@ export const toggleLineageFilters = async (page: Page, tableFqn: string) => { }; export const clickLineageNode = async (page: Page, nodeFqn: string) => { - await page + // React Flow mounts nodes after its own layout pass, which runs well after the + // getLineage response the caller waited on. Clicking straight away leaves the + // action auto-waiting with no timeout of its own, so a graph that is slow to + // lay out surfaces as a bare test timeout with nothing naming the node. + const nodeTitle = page .locator(`[data-testid="lineage-node-${nodeFqn}"]`) - .locator(`[data-testid="entity-header-display-name"]`) - .click(); + .locator(`[data-testid="entity-header-display-name"]`); + + await expect(nodeTitle).toBeVisible(); + await nodeTitle.click(); }; export const updateLineageConfigFromModal = async ( diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/searchRBAC.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/searchRBAC.ts index 593702f8eab8..5b79a5494b4e 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/searchRBAC.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/searchRBAC.ts @@ -16,16 +16,6 @@ import { redirectToHomePage } from './common'; import { waitForAllLoadersToDisappear } from './entity'; import { sidebarClick } from './sidebar'; -const closeWelcomeScreenIfVisible = async (page: Page) => { - const isWelcomeScreenVisible = await page - .getByTestId('welcome-screen') - .isVisible(); - - if (isWelcomeScreenVisible) { - await page.getByTestId('welcome-screen-close-btn').click(); - } -}; - /** * Navigate the given (already-logged-in) user to the Explore page, search for an * entity by FQN, and assert whether its result card is shown — used to verify @@ -37,7 +27,6 @@ export const exploreShouldShowEntity = async ( displayName: string, shouldSee: boolean ) => { - await closeWelcomeScreenIfVisible(page); await redirectToHomePage(page); const exploreRes = page.waitForResponse('/api/v1/search/query?*'); @@ -85,7 +74,6 @@ export const exploreTreeCategories = async ( page: Page, { visible, hidden }: { visible: string[]; hidden: string[] } ) => { - await closeWelcomeScreenIfVisible(page); await redirectToHomePage(page); const exploreRes = page.waitForResponse('/api/v1/search/query?*'); @@ -172,15 +160,6 @@ export const searchForEntityShouldWork = async ( page: Page, entityName: string ) => { - // Wait for welcome screen and close it if visible - const isWelcomeScreenVisible = await page - .getByTestId('welcome-screen') - .isVisible(); - - if (isWelcomeScreenVisible) { - await page.getByTestId('welcome-screen-close-btn').click(); - } - await page.getByTestId('searchBox').click(); await page.getByTestId('searchBox').fill(fqn); @@ -213,15 +192,6 @@ export const searchForEntityShouldWorkShowNoResult = async ( displayName: string, page: Page ) => { - // Wait for welcome screen and close it if visible - const isWelcomeScreenVisible = await page - .getByTestId('welcome-screen') - .isVisible(); - - if (isWelcomeScreenVisible) { - await page.getByTestId('welcome-screen-close-btn').click(); - } - await page.getByTestId('searchBox').click(); await page.getByTestId('searchBox').fill(fqn);