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 88d7bc10251..e30bdf8af3c 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 @@ -360,7 +360,9 @@ test.describe('Activity feed', () => { await checkDescriptionInEditModal(page, secondTaskValue); + const resolveTask = page.waitForResponse('/api/v1/feed/tasks/*/resolve'); await page.getByText('OK').click(); + await resolveTask; await toastNotification(page, /Task resolved successfully/); @@ -394,17 +396,15 @@ test.describe('Activity feed', () => { expect(descriptionTask).toContain('Request to update description'); // Check the editor send button is not visible and comment button is disabled when no text is added - expect(page.locator('[data-testid="send-button"]')).not.toBeVisible(); - expect( - await page.locator('[data-testid="comment-button"]').isDisabled() - ).toBeTruthy(); + await expect(page.locator('[data-testid="send-button"]')).not.toBeVisible(); + await expect(page.locator('[data-testid="comment-button"]')).toBeDisabled(); await page.fill( '[data-testid="editor-wrapper"] .ql-editor', 'Test comment added' ); const addComment = page.waitForResponse('/api/v1/feed/*/posts'); - await page.getByTestId('comment-button').click({ force: true }); + await page.getByTestId('comment-button').click(); await addComment; // Close the task from the Button.Group, should throw error when no comment is added. @@ -451,10 +451,12 @@ test.describe('Activity feed', () => { await page.getByTestId('request-description').click(); // create description task + const waitForCountFetch1 = page.waitForResponse('/api/v1/feed/count?**'); const openTaskAfterDescriptionResponse = page.waitForResponse(TASK_OPEN_FETCH_LINK); await createDescriptionTask(page, value); await openTaskAfterDescriptionResponse; + await waitForCountFetch1; // open task count after description const openTask1 = await page.getByTestId('open-task').textContent(); @@ -466,11 +468,11 @@ test.describe('Activity feed', () => { await page.getByTestId('request-entity-tags').click(); // create tag task - const waitForCountFetch = page.waitForResponse('/api/v1/feed/count?**'); + const waitForCountFetch2 = page.waitForResponse('/api/v1/feed/count?**'); const openTaskAfterTagResponse = page.waitForResponse(TASK_OPEN_FETCH_LINK); await createTagTask(page, { ...value, tag: 'PII.None' }); await openTaskAfterTagResponse; - await waitForCountFetch; + await waitForCountFetch2; // open task count after description await checkTaskCount(page, 2, 0); @@ -490,9 +492,9 @@ test.describe('Activity feed', () => { await page.getByRole('menuitem', { name: 'close' }).click(); await commentWithCloseTask; - const waitForCountFetch2 = page.waitForResponse('/api/v1/feed/count?**'); + const waitForCountFetch3 = page.waitForResponse('/api/v1/feed/count?**'); await toastNotification(page, 'Task closed successfully.'); - await waitForCountFetch2; + await waitForCountFetch3; // open task count after closing one task await checkTaskCount(page, 1, 1); @@ -601,10 +603,6 @@ base.describe('Activity feed with Data Consumer User', () => { resources: ['All'], }, ]; - const viewAllUser = new UserClass(); - const viewAllPolicy = new PolicyClass(); - const viewAllRoles = new RolesClass(); - let viewAllTeam: TeamClass; base.beforeAll('Setup pre-requests', async ({ browser }) => { const { afterAction, apiContext } = await performAdminLogin(browser); @@ -614,20 +612,6 @@ base.describe('Activity feed with Data Consumer User', () => { await entity3.create(apiContext); await user1.create(apiContext); await user2.create(apiContext); - await viewAllUser.create(apiContext); - await viewAllPolicy.create(apiContext, rules); - await viewAllRoles.create(apiContext, [viewAllPolicy.responseData.name]); - viewAllTeam = new TeamClass({ - name: `PW%team-${id}`, - displayName: `PW Team ${id}`, - description: 'playwright team description', - teamType: 'Group', - users: [viewAllUser.responseData.id], - defaultRoles: viewAllRoles.responseData.id - ? [viewAllRoles.responseData.id] - : [], - }); - await viewAllTeam.create(apiContext); await afterAction(); }); @@ -639,10 +623,6 @@ base.describe('Activity feed with Data Consumer User', () => { await entity3.delete(apiContext); await user1.delete(apiContext); await user2.delete(apiContext); - await viewAllUser.delete(apiContext); - await viewAllPolicy.delete(apiContext); - await viewAllRoles.delete(apiContext); - await viewAllTeam.delete(apiContext); await afterAction(); }); @@ -937,7 +917,29 @@ base.describe('Activity feed with Data Consumer User', () => { base( 'Accepting task should throw error for not having edit permission', + async ({ browser }) => { + const { afterAction, apiContext } = await performAdminLogin(browser); + + const viewAllUser = new UserClass(); + const viewAllPolicy = new PolicyClass(); + const viewAllRoles = new RolesClass(); + + await viewAllUser.create(apiContext); + await viewAllPolicy.create(apiContext, rules); + await viewAllRoles.create(apiContext, [viewAllPolicy.responseData.name]); + const viewAllTeam = new TeamClass({ + name: `PW%team-${id}`, + displayName: `PW Team ${id}`, + description: 'playwright team description', + teamType: 'Group', + users: [viewAllUser.responseData.id], + defaultRoles: viewAllRoles.responseData.id + ? [viewAllRoles.responseData.id] + : [], + }); + await viewAllTeam.create(apiContext); + const { page: page1, afterAction: afterActionUser1 } = await performUserLogin(browser, user1); const { page: page2, afterAction: afterActionUser2 } = @@ -948,39 +950,52 @@ base.describe('Activity feed with Data Consumer User', () => { assignee: viewAllUser.responseData.name, }; - await base.step('Create and Assign Task to user 3', async () => { - await redirectToHomePage(page1); - await entity3.visitEntityPage(page1); + try { + await base.step('Create and Assign Task to user 3', async () => { + await redirectToHomePage(page1); + await entity3.visitEntityPage(page1); - await page1.getByTestId('request-description').click(); + await page1.getByTestId('request-description').click(); - await createDescriptionTask(page1, value); + await createDescriptionTask(page1, value); - await afterActionUser1(); - }); + await afterActionUser1(); + }); - await base.step( - 'Accept Task By user 2 should throw error for since it has only viewAll permission', - async () => { - await redirectToHomePage(page2); + await base.step( + 'Accept Task By user 2 should throw error for since it has only viewAll permission', + async () => { + await redirectToHomePage(page2); - await entity3.visitEntityPage(page2); + await entity3.visitEntityPage(page2); - await page2.getByTestId('activity_feed').click(); + await page2.getByTestId('activity_feed').click(); - await page2.getByRole('menuitem', { name: 'Tasks' }).click(); + const taskResponse = page2.waitForResponse( + '/api/v1/feed?entityLink=**type=Task&taskStatus=Open' + ); + await page2.getByRole('menuitem', { name: 'Tasks' }).click(); + await taskResponse; - await page2.getByText('Accept Suggestion').click(); + await page2.getByText('Accept Suggestion').click(); - await toastNotification( - page2, - // eslint-disable-next-line max-len - `Principal: CatalogPrincipal{name='${viewAllUser.responseData.name}'} operation EditDescription denied by role ${viewAllRoles.responseData.name}, policy ${viewAllPolicy.responseData.name}, rule editNotAllowed` - ); + await toastNotification( + page2, + // eslint-disable-next-line max-len + `Principal: CatalogPrincipal{name='${viewAllUser.responseData.name}'} operation EditDescription denied by role ${viewAllRoles.responseData.name}, policy ${viewAllPolicy.responseData.name}, rule editNotAllowed` + ); - await afterActionUser2(); - } - ); + await afterActionUser2(); + } + ); + } finally { + await viewAllUser.delete(apiContext); + await viewAllPolicy.delete(apiContext); + await viewAllRoles.delete(apiContext); + await viewAllTeam.delete(apiContext); + + await afterAction(); + } } ); }); 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 59d4372e7b2..1ecdde8aefd 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/activityFeed.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/activityFeed.ts @@ -63,7 +63,12 @@ export const checkDescriptionInEditModal = async ( }; export const deleteFeedComments = async (page: Page, feed: Locator) => { - await feed.click(); + await feed.locator('.feed-reply-card-v2').click(); + + await page.waitForSelector('[data-testid="feed-actions"]', { + state: 'visible', + }); + await page.locator('[data-testid="delete-message"]').click(); await page.waitForSelector('[role="dialog"].ant-modal'); @@ -88,14 +93,21 @@ export const reactOnFeed = async (page: Page) => { await page .locator('.ant-popover-feed-reactions .ant-popover-inner-content') .waitFor({ state: 'visible' }); + + const waitForReactionResponse = page.waitForResponse('/api/v1/feed/*'); await page .locator(`[data-testid="reaction-button"][title="${reaction}"]`) .click(); + await waitForReactionResponse; } }; export const addMentionCommentInFeed = async (page: Page, user: string) => { + const fetchFeedResponse = page.waitForResponse( + '/api/v1/feed?type=Conversation*' + ); await removeLandingBanner(page); + await fetchFeedResponse; // Click on add reply const feedResponse = page.waitForResponse('/api/v1/feed/*'); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/customProperty.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/customProperty.ts index 9a46860eae3..3cb8491d568 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/customProperty.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/customProperty.ts @@ -21,7 +21,7 @@ import { ENTITY_PATH, } from '../support/entity/Entity.interface'; import { UserClass } from '../support/user/UserClass'; -import { descriptionBox, uuid } from './common'; +import { clickOutside, descriptionBox, uuid } from './common'; export enum CustomPropertyType { STRING = 'String', @@ -111,7 +111,7 @@ export const setValueForProperty = async (data: { await page.click('#enumValues'); await page.fill('#enumValues', value); await page.press('#enumValues', 'Enter'); - await page.mouse.click(0, 0); + await clickOutside(page); await page.click('[data-testid="inline-save-btn"]'); break; @@ -543,8 +543,8 @@ export const addCustomPropertiesForEntity = async ({ await page.click('#root\\/enumConfig'); await page.fill('#root\\/enumConfig', val); await page.press('#root\\/enumConfig', 'Enter'); - await page.mouse.click(0, 0); } + await clickOutside(page); if (enumConfig.multiSelect) { await page.click('#root\\/multiSelect'); @@ -621,14 +621,14 @@ export const editCreatedProperty = async ( await page.click('#root\\/customPropertyConfig'); await page.fill('#root\\/customPropertyConfig', 'updatedValue'); await page.press('#root\\/customPropertyConfig', 'Enter'); - await page.mouse.click(0, 0); + await clickOutside(page); } if (ENTITY_REFERENCE_PROPERTIES.includes(type ?? '')) { await page.click('#root\\/customPropertyConfig'); await page.fill('#root\\/customPropertyConfig', 'Table'); await page.press('#root\\/customPropertyConfig', 'Enter'); - await page.mouse.click(0, 0); + await clickOutside(page); } const patchRequest = page.waitForResponse('/api/v1/metadata/types/*'); 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 a21782b6f94..33ed3a4bf30 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts @@ -11,7 +11,7 @@ * limitations under the License. */ import { expect, Page } from '@playwright/test'; -import { lowerCase } from 'lodash'; +import { isEmpty, lowerCase } from 'lodash'; import { customFormatDateTime, getCurrentMillis, @@ -325,9 +325,13 @@ export const updateDescription = async (page: Page, description: string) => { await page.locator('.ProseMirror').first().fill(description); await page.getByTestId('save').click(); - await expect( - page.getByTestId('asset-description-container').getByRole('paragraph') - ).toContainText(description); + isEmpty(description) + ? await expect( + page.getByTestId('asset-description-container') + ).toContainText('No description') + : await expect( + page.getByTestId('asset-description-container').getByRole('paragraph') + ).toContainText(description); }; export const assignTag = async (