Skip to content

Commit 6db2ba9

Browse files
anuj-kumaryclaude
authored andcommitted
fix(playwright): wait for add/edit-domain button to be visible before clicking (#31719)
* fix(playwright): wait for add/edit-domain button before checking which to click isVisible() is a snapshot call with no retry — it can return false for add-domain while edit-domain has not yet rendered, leaving both absent during a UI re-render after a domain PATCH. The subsequent .click() then waits the full 60 s timeout before failing. Add an explicit waitFor({ state: 'visible' }) on the or()-combined locator so either button is stable before the snapshot check. Fixes the flaky "should change domain on glossary" test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix overall add and edit test --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> (cherry picked from commit 7859d17)
1 parent 34ffe49 commit 6db2ba9

5 files changed

Lines changed: 33 additions & 38 deletions

File tree

openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/DataAssetRulesDisabled.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ test.describe(
799799
await assignDomainWidget(page, testDomain1.responseData, true);
800800

801801
// Assign second domain (should ADD to first, not replace)
802-
await assignDomainWidget(page, testDomain2.responseData, true);
802+
await assignDomainWidget(page, testDomain2.responseData, true, true);
803803

804804
// Verify both domains are visible (multi-select mode allows multiple)
805805
// Use filter to find specific domain links

openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/DataAssetRulesEnabled.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ test.describe(
284284
);
285285

286286
// Assign second domain (should REPLACE first, not add to it)
287-
await assignDomainWidget(page, testDomain2.responseData);
287+
await assignDomainWidget(page, testDomain2.responseData, false, true);
288288

289289
// Verify second domain is visible
290290
await expect(page.getByTestId('domain-link')).toContainText(

openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/DomainTierCertificationVoting.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ test.describe('Domain & DataProduct - Tier, Certification, and Voting', () => {
5656
test('Domain - Tier assign, update, and remove', async ({ page }) => {
5757
await domain.visitEntityPage(page);
5858
await addTierWidget(page, 'Tier1', domain.endpoint);
59-
await addTierWidget(page, 'Tier3', domain.endpoint);
59+
await addTierWidget(page, 'Tier3', domain.endpoint, true);
6060
await removeTierFromWidget(page, domain.endpoint);
6161
});
6262

@@ -65,7 +65,7 @@ test.describe('Domain & DataProduct - Tier, Certification, and Voting', () => {
6565
}) => {
6666
await domain.visitEntityPage(page);
6767
await addCertificationWidget(page, certTag1, domain.endpoint);
68-
await addCertificationWidget(page, certTag2, domain.endpoint);
68+
await addCertificationWidget(page, certTag2, domain.endpoint, true);
6969
await removeCertificationFromWidget(page, domain.endpoint);
7070
});
7171

@@ -78,7 +78,7 @@ test.describe('Domain & DataProduct - Tier, Certification, and Voting', () => {
7878
test('DataProduct - Tier assign, update, and remove', async ({ page }) => {
7979
await dataProduct.visitEntityPage(page);
8080
await addTierWidget(page, 'Tier1', dataProduct.endpoint);
81-
await addTierWidget(page, 'Tier3', dataProduct.endpoint);
81+
await addTierWidget(page, 'Tier3', dataProduct.endpoint, true);
8282
await removeTierFromWidget(page, dataProduct.endpoint);
8383
});
8484

@@ -87,7 +87,7 @@ test.describe('Domain & DataProduct - Tier, Certification, and Voting', () => {
8787
}) => {
8888
await dataProduct.visitEntityPage(page);
8989
await addCertificationWidget(page, certTag1, dataProduct.endpoint);
90-
await addCertificationWidget(page, certTag2, dataProduct.endpoint);
90+
await addCertificationWidget(page, certTag2, dataProduct.endpoint, true);
9191
await removeCertificationFromWidget(page, dataProduct.endpoint);
9292
});
9393

openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/Glossary/GlossaryAdvancedOperations.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ test.describe('Glossary Advanced Operations', () => {
362362
await selectActiveGlossary(page, glossary.data.displayName);
363363

364364
await assignDomainWidget(page, domain1.responseData);
365-
await assignDomainWidget(page, domain2.responseData);
365+
await assignDomainWidget(page, domain2.responseData, false, true);
366366
} finally {
367367
await glossary.delete(apiContext);
368368
await domain1.delete(apiContext);

openmetadata-ui/src/main/resources/ui/playwright/utils/domain.ts

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -63,29 +63,24 @@ const waitForSearchDebounce = async (page: Page) => {
6363
}
6464
};
6565

66-
const clickAvailableWidgetAction = async (
67-
addBtn: Locator,
68-
editBtn: Locator
69-
) => {
70-
await addBtn.or(editBtn).first().waitFor({ state: 'visible' });
71-
72-
if (await addBtn.isVisible()) {
73-
await addBtn.click();
74-
75-
return;
76-
}
77-
78-
await editBtn.click();
79-
};
66+
// A widget shows the add button when the value is unset and the edit button
67+
// once it is assigned. The caller knows which state the entity is in, so it
68+
// passes `isUpdate` and we open the exact button — click() auto-waits for it,
69+
// so there is no need to probe which of the two is currently rendered.
70+
const openWidgetEditor = (
71+
page: Page,
72+
addTestId: string,
73+
editTestId: string,
74+
isUpdate: boolean
75+
) => page.getByTestId(isUpdate ? editTestId : addTestId).click();
8076

8177
export const addTierWidget = async (
8278
page: Page,
8379
tier: string,
84-
endpoint: string
80+
endpoint: string,
81+
isUpdate = false
8582
) => {
86-
const addBtn = page.getByTestId('add-tier');
87-
const editBtn = page.getByTestId('edit-tier');
88-
await clickAvailableWidgetAction(addBtn, editBtn);
83+
await openWidgetEditor(page, 'add-tier', 'edit-tier', isUpdate);
8984

9085
await waitForAllLoadersToDisappear(page);
9186

@@ -116,11 +111,15 @@ export const addTierWidget = async (
116111
export const addCertificationWidget = async (
117112
page: Page,
118113
certification: TagClass,
119-
endpoint: string
114+
endpoint: string,
115+
isUpdate = false
120116
) => {
121-
const addBtn = page.getByTestId('add-certification');
122-
const editBtn = page.getByTestId('edit-certification');
123-
await clickAvailableWidgetAction(addBtn, editBtn);
117+
await openWidgetEditor(
118+
page,
119+
'add-certification',
120+
'edit-certification',
121+
isUpdate
122+
);
124123

125124
await page.locator('.certification-card-popover').waitFor({
126125
state: 'visible',
@@ -248,12 +247,10 @@ export const removeCertificationFromWidget = async (
248247
export const assignDomainWidget = async (
249248
page: Page,
250249
domain: { name: string; displayName: string; fullyQualifiedName?: string },
251-
multiSelect = false
250+
multiSelect = false,
251+
isUpdate = false
252252
) => {
253-
const addBtn = page.getByTestId('add-domain');
254-
const editBtn = page.getByTestId('edit-domain');
255-
const isAdd = await addBtn.isVisible();
256-
await (isAdd ? addBtn : editBtn).click();
253+
await openWidgetEditor(page, 'add-domain', 'edit-domain', isUpdate);
257254
await waitForAllLoadersToDisappear(page);
258255

259256
const searchDomain = page.waitForResponse(
@@ -296,10 +293,8 @@ export const removeDomainWidget = async (
296293
page: Page,
297294
domain: { name: string; displayName: string; fullyQualifiedName?: string }
298295
) => {
299-
const addBtn = page.getByTestId('add-domain');
300-
const editBtn = page.getByTestId('edit-domain');
301-
const isAdd = await addBtn.isVisible();
302-
await (isAdd ? addBtn : editBtn).click();
296+
// Removing implies a domain is already assigned, so the widget shows edit.
297+
await openWidgetEditor(page, 'add-domain', 'edit-domain', true);
303298
await waitForAllLoadersToDisappear(page);
304299

305300
await page

0 commit comments

Comments
 (0)