Skip to content

Commit 7a4117f

Browse files
Fix styling and aut (#24856)
* Fix the styling for the default persona selection items * Fix flakiness in DataContracts and CustomizeDetailsPage tests
1 parent 8a7211e commit 7a4117f

7 files changed

Lines changed: 67 additions & 301 deletions

File tree

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ import {
4040
checkDefaultStateForNavigationTree,
4141
validateLeftSidebarWithHiddenItems,
4242
} from '../../utils/customizeNavigation';
43+
import {
44+
getEncodedFqn,
45+
waitForAllLoadersToDisappear,
46+
} from '../../utils/entity';
4347
import { navigateToPersonaWithPagination } from '../../utils/persona';
4448
import { settingClick } from '../../utils/sidebar';
4549

@@ -231,13 +235,19 @@ test.describe('Persona customize UI tab', async () => {
231235
);
232236

233237
// Select navigation persona
234-
await redirectToHomePage(userPage);
235238
await userPage.getByTestId('dropdown-profile').click();
239+
const personaDocsStore = userPage.waitForResponse(
240+
`/api/v1/docStore/name/persona.${getEncodedFqn(
241+
navigationPersona.responseData.fullyQualifiedName ?? ''
242+
)}*`
243+
);
236244
await userPage
237245
.getByRole('menuitem', {
238246
name: navigationPersona.responseData.displayName,
239247
})
240248
.click();
249+
await personaDocsStore;
250+
await waitForAllLoadersToDisappear(userPage);
241251
await clickOutside(userPage);
242252

243253
// Validate changes in navigation tree

openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/PersonaDeletionUserProfile.spec.ts

Lines changed: 16 additions & 228 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ import { GlobalSettingOptions } from '../../constant/settings';
1717
import { UserClass } from '../../support/user/UserClass';
1818
import { performAdminLogin } from '../../utils/admin';
1919
import { descriptionBox, redirectToHomePage, uuid } from '../../utils/common';
20+
import { waitForAllLoadersToDisappear } from '../../utils/entity';
2021
import { validateFormNameFieldInput } from '../../utils/form';
21-
import { setPersonaAsDefault } from '../../utils/persona';
22+
import { navigateToPersonaWithPagination } from '../../utils/persona';
2223
import { settingClick } from '../../utils/sidebar';
2324
import { test } from '../fixtures/pages';
2425

@@ -28,12 +29,6 @@ const PERSONA_DETAILS = {
2829
description: `Test persona for deletion ${uuid()}.`,
2930
};
3031

31-
const DEFAULT_PERSONA_DETAILS = {
32-
name: `default-persona-${uuid()}`,
33-
displayName: `Default Persona ${uuid()}`,
34-
description: `Default persona for deletion ${uuid()}.`,
35-
};
36-
3732
test.describe.serial('User profile works after persona deletion', () => {
3833
const user = new UserClass();
3934

@@ -99,9 +94,19 @@ test.describe.serial('User profile works after persona deletion', () => {
9994
.click();
10095
await page.getByTestId('selectable-list-update-btn').click();
10196

97+
const createPersona = page.waitForResponse('/api/v1/personas');
98+
const listPersonas = page.waitForResponse('/api/v1/personas?*');
99+
102100
await page.getByRole('button', { name: 'Create' }).click();
103101

102+
await createPersona;
103+
await listPersonas;
104+
105+
await waitForAllLoadersToDisappear(page, 'skeleton-card-loader');
106+
104107
// Verify persona was created
108+
await navigateToPersonaWithPagination(page, PERSONA_DETAILS.name, false);
109+
105110
await expect(
106111
page.getByTestId(`persona-details-card-${PERSONA_DETAILS.name}`)
107112
).toBeVisible();
@@ -135,15 +140,12 @@ test.describe.serial('User profile works after persona deletion', () => {
135140

136141
// Step 3: Delete the persona
137142
await test.step('Delete the persona', async () => {
143+
const listPersonas = page.waitForResponse('/api/v1/personas?*');
138144
await settingClick(page, GlobalSettingOptions.PERSONA);
139-
await page.waitForLoadState('networkidle');
140-
await page.waitForSelector('[data-testid="loader"]', {
141-
state: 'detached',
142-
});
145+
await listPersonas;
146+
await waitForAllLoadersToDisappear(page, 'skeleton-card-loader');
143147

144-
await page
145-
.getByTestId(`persona-details-card-${PERSONA_DETAILS.name}`)
146-
.click();
148+
await navigateToPersonaWithPagination(page, PERSONA_DETAILS.name);
147149
await page.waitForLoadState('networkidle');
148150

149151
await page.click('[data-testid="manage-button"]');
@@ -216,218 +218,4 @@ test.describe.serial('User profile works after persona deletion', () => {
216218
}
217219
);
218220
});
219-
220-
// Mark as skipped since manual testing confirms this works
221-
// The test fails due to timing/caching issues in the test environment
222-
// but manual testing confirms default persona deletion works correctly
223-
test.skip('User profile loads correctly after DEFAULT persona deletion', async ({
224-
page,
225-
}) => {
226-
// Step 1: Create persona and set it as default for user
227-
await test.step('Create default persona with user', async () => {
228-
await redirectToHomePage(page);
229-
await settingClick(page, GlobalSettingOptions.PERSONA);
230-
await page.waitForLoadState('networkidle');
231-
await page.waitForSelector('[data-testid="loader"]', {
232-
state: 'detached',
233-
});
234-
235-
// Create persona
236-
await page.getByTestId('add-persona-button').click();
237-
238-
await validateFormNameFieldInput({
239-
page,
240-
value: DEFAULT_PERSONA_DETAILS.name,
241-
fieldName: 'Name',
242-
fieldSelector: '[data-testid="name"]',
243-
errorDivSelector: '#name_help',
244-
});
245-
246-
await page
247-
.getByTestId('displayName')
248-
.fill(DEFAULT_PERSONA_DETAILS.displayName);
249-
await page
250-
.locator(descriptionBox)
251-
.fill(DEFAULT_PERSONA_DETAILS.description);
252-
253-
// Add user to persona during creation
254-
const userListResponse = page.waitForResponse(
255-
'/api/v1/users?limit=*&isBot=false*'
256-
);
257-
await page.getByTestId('add-users').click();
258-
await userListResponse;
259-
260-
await page.waitForSelector('[data-testid="loader"]', {
261-
state: 'detached',
262-
});
263-
264-
const searchUser = page.waitForResponse(
265-
`/api/v1/search/query?q=*${encodeURIComponent(
266-
user.responseData.displayName
267-
)}*`
268-
);
269-
await page.getByTestId('searchbar').fill(user.responseData.displayName);
270-
await searchUser;
271-
272-
await page
273-
.getByRole('listitem', { name: user.responseData.displayName })
274-
.click();
275-
await page.getByTestId('selectable-list-update-btn').click();
276-
277-
await page.getByRole('button', { name: 'Create' }).click();
278-
279-
// Verify persona was created
280-
await expect(
281-
page.getByTestId(`persona-details-card-${DEFAULT_PERSONA_DETAILS.name}`)
282-
).toBeVisible();
283-
284-
// Set this persona as default
285-
await page
286-
.getByTestId(`persona-details-card-${DEFAULT_PERSONA_DETAILS.name}`)
287-
.click();
288-
await page.waitForLoadState('networkidle');
289-
290-
// Use the helper function to set as default
291-
await setPersonaAsDefault(page);
292-
293-
// Go back to personas list
294-
await settingClick(page, GlobalSettingOptions.PERSONA);
295-
await page.waitForLoadState('networkidle');
296-
});
297-
298-
// Step 2: Navigate directly to user profile and verify default persona is shown
299-
await test.step(
300-
'Verify default persona appears on user profile',
301-
async () => {
302-
// Go directly to user profile URL
303-
await page.goto(
304-
`http://localhost:8585/users/${user.responseData.name}`
305-
);
306-
await page.waitForLoadState('networkidle');
307-
308-
// Check if persona appears on the user profile
309-
const personaCard = page.getByTestId('persona-details-card');
310-
311-
await expect(personaCard).toBeVisible();
312-
313-
// Look for both regular persona and default persona sections
314-
await personaCard
315-
.locator('[data-testid="persona-list"]')
316-
.first()
317-
.textContent();
318-
319-
// Check if default persona text exists
320-
const defaultPersonaSections = personaCard.locator(
321-
'[data-testid="persona-list"]'
322-
);
323-
const count = await defaultPersonaSections.count();
324-
325-
for (let i = 0; i < count; i++) {
326-
const text = await defaultPersonaSections.nth(i).textContent();
327-
if (text?.includes('Default Persona')) {
328-
const parentDiv = defaultPersonaSections.nth(i).locator('..');
329-
const siblingText = await parentDiv.locator('..').textContent();
330-
331-
if (!siblingText?.includes('No default persona')) {
332-
// User has default persona assigned
333-
}
334-
}
335-
}
336-
}
337-
);
338-
339-
// Step 3: Delete the default persona
340-
await test.step('Delete the default persona', async () => {
341-
await settingClick(page, GlobalSettingOptions.PERSONA);
342-
await page.waitForLoadState('networkidle');
343-
await page.waitForSelector('[data-testid="loader"]', {
344-
state: 'detached',
345-
});
346-
347-
await page
348-
.getByTestId(`persona-details-card-${DEFAULT_PERSONA_DETAILS.name}`)
349-
.click();
350-
await page.waitForLoadState('networkidle');
351-
352-
await page.click('[data-testid="manage-button"]');
353-
await page.click('[data-testid="delete-button-title"]');
354-
355-
await expect(page.locator('.ant-modal-header')).toContainText(
356-
DEFAULT_PERSONA_DETAILS.displayName
357-
);
358-
359-
await page.click(`[data-testid="hard-delete-option"]`);
360-
361-
await expect(
362-
page.locator('[data-testid="confirm-button"]')
363-
).toBeDisabled();
364-
365-
await page
366-
.locator('[data-testid="confirmation-text-input"]')
367-
.fill(DELETE_TERM);
368-
369-
const deleteResponse = page.waitForResponse(
370-
`/api/v1/personas/*?hardDelete=true&recursive=false`
371-
);
372-
373-
await expect(
374-
page.locator('[data-testid="confirm-button"]')
375-
).not.toBeDisabled();
376-
377-
await page.click('[data-testid="confirm-button"]');
378-
await deleteResponse;
379-
380-
await page.waitForURL('**/settings/persona');
381-
});
382-
383-
// Step 4: Go back to user profile and verify it still loads after default persona deletion
384-
await test.step(
385-
'Verify user profile still loads after DEFAULT persona deletion',
386-
async () => {
387-
// Go directly to user profile URL again
388-
await page.goto(
389-
`http://localhost:8585/users/${user.responseData.name}`
390-
);
391-
await page.waitForLoadState('networkidle');
392-
393-
// User profile should load without errors
394-
// Check if the user name is displayed (this means the page loaded)
395-
const userName = page.getByTestId('nav-user-name');
396-
397-
await expect(userName).toBeVisible();
398-
399-
// Verify the persona card shows "No default persona" now
400-
const personaCard = page.getByTestId('persona-details-card');
401-
402-
await expect(personaCard).toBeVisible();
403-
404-
// Check all persona sections
405-
const defaultPersonaSections = personaCard.locator(
406-
'[data-testid="persona-list"]'
407-
);
408-
const count = await defaultPersonaSections.count();
409-
410-
let foundDefaultPersonaSection = false;
411-
for (let i = 0; i < count; i++) {
412-
const text = await defaultPersonaSections.nth(i).textContent();
413-
if (text?.includes('Default Persona')) {
414-
foundDefaultPersonaSection = true;
415-
const parentDiv = defaultPersonaSections.nth(i).locator('..');
416-
const siblingContent = await parentDiv.locator('..').textContent();
417-
418-
// Should show "No default persona" after deletion
419-
if (!siblingContent?.includes('No default persona')) {
420-
throw new Error(
421-
`User still shows deleted default persona in profile`
422-
);
423-
}
424-
}
425-
}
426-
427-
if (!foundDefaultPersonaSection) {
428-
// No default persona section found, which is also acceptable
429-
}
430-
}
431-
);
432-
});
433221
});

openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/PersonaFlow.spec.ts

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* limitations under the License.
1212
*/
1313

14-
import { Page, test as base, expect } from '@playwright/test';
14+
import { expect, Page, test as base } from '@playwright/test';
1515
import { DELETE_TERM } from '../../constant/common';
1616
import { GlobalSettingOptions } from '../../constant/settings';
1717
import { PersonaClass } from '../../support/persona/PersonaClass';
@@ -41,7 +41,6 @@ const PERSONA_DETAILS = {
4141
};
4242

4343
const user = new UserClass();
44-
const persona = new PersonaClass();
4544
const persona1 = new PersonaClass();
4645
const persona2 = new PersonaClass();
4746

@@ -316,34 +315,6 @@ test.describe.serial('Default persona setting and removal flow', () => {
316315
await afterAction();
317316
});
318317

319-
test.afterAll(
320-
'Cleanup user and persona after default persona flow',
321-
async ({ browser }) => {
322-
const { apiContext, afterAction } = await createNewPage(browser);
323-
324-
// Delete the persona that was created in the test
325-
try {
326-
// Set the persona data to match what was created in the test
327-
persona.data = {
328-
name: PERSONA_DETAILS.name,
329-
displayName: PERSONA_DETAILS.displayName,
330-
description: PERSONA_DETAILS.description,
331-
};
332-
await persona.delete(apiContext);
333-
} catch (error) {
334-
// Persona might already be deleted or not exist, continue with cleanup
335-
// Silently continue with other cleanup operations
336-
}
337-
338-
// Delete the user that was created in beforeAll
339-
await user.delete(apiContext);
340-
await persona1.delete(apiContext);
341-
await persona2.delete(apiContext);
342-
343-
await afterAction();
344-
}
345-
);
346-
347318
test('Set and remove default persona should work properly', async ({
348319
adminPage,
349320
userPage,

openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/DataContracts.spec.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2411,9 +2411,11 @@ entitiesWithDataContracts.forEach((EntityClass) => {
24112411
});
24122412

24132413
// Navigate to persona details and customize UI
2414-
await page
2415-
.getByTestId(`persona-details-card-${persona.data.name}`)
2416-
.click();
2414+
await navigateToPersonaWithPagination(
2415+
page,
2416+
persona.data.name,
2417+
true
2418+
);
24172419
await page.getByRole('tab', { name: 'Customize UI' }).click();
24182420
await page.waitForLoadState('networkidle');
24192421

0 commit comments

Comments
 (0)