Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1059 lines
33 KiB
TypeScript
Raw Normal View History

/*
* Copyright 2024 Collate.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Feature: Allow Custom Property Update in Glossary Bulk Import/export (#17919) * fix import issue * Feat : Allow Custom Property Update in Bulk Upload * Feat : Allow Custom Property Update in Bulk Upload * supported editable imports in glossary page * added remaning localizaion keys * update logic of fieldToExtensionStrings to use csvparser * update json and partialStatus condition * fix tests for partialSuccess status change * supported customProperty editable field * fix error in custom property edit modal on new line empty custom property * added entity type from root to support other bulk import entity as well * fix the quote removing due to the regex in the string type * Add backend tests , and error msg improvements * GlossaryStatus header change * fix unit test and dry run in case of synonyms having quotes in it * Remove extension column in CSVs for all entities except glossaryTerm * added editor for reviewers * unit test around csv utils * added escape for string too, in case of semicolon comes * added playwright test without extension and supported relatedTerm as editable * added unit test around csv util logic * resolve conflicts * Backend - add support for enumWithDescriptions in bulk import * add tests and other error handling improvements related to enumWithDescriptions * fix the custom property modal header and render the layout as per right panel in entities * parese enumWithDescription for the customProperty modal while editable * fix description data in enumWithDescription one * fix: Handle NullPointerException when adding custom properties to ensure loop continues for other schemas of the same type for addToRegistry * added extension playwrigth test and fix enumWithDescription object failure * descrease the size of extension modal * remove additional comments * fix the escape in parent key * improve custom property layout * improve ui for inline properties * fix description, glossary and relatedTerm escape char issue * fix some customProperty ui changes * fix sonar issue * minor layout changes * minor label improvements for entity ref and list --------- Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com> Co-authored-by: Ashish Gupta <ashish@getcollate.io> Co-authored-by: mohitdeuex <mohit.y@deuexsolutions.com> Co-authored-by: Sachin Chaurasiya <sachinchaurasiyachotey87@gmail.com>
2024-10-01 00:12:43 +05:30
import { expect, Page, test as base } from '@playwright/test';
import {
PolicyClass,
PolicyRulesType,
} from '../../support/access-control/PoliciesClass';
import { RolesClass } from '../../support/access-control/RolesClass';
import { EntityTypeEndpoint } from '../../support/entity/Entity.interface';
import { TableClass } from '../../support/entity/TableClass';
import { TeamClass } from '../../support/team/TeamClass';
import { UserClass } from '../../support/user/UserClass';
import {
addMentionCommentInFeed,
checkDescriptionInEditModal,
FIRST_FEED_SELECTOR,
REACTION_EMOJIS,
reactOnFeed,
} from '../../utils/activityFeed';
import { performAdminLogin } from '../../utils/admin';
import {
clickOutside,
descriptionBox,
redirectToHomePage,
removeLandingBanner,
toastNotification,
uuid,
visitOwnProfilePage,
} from '../../utils/common';
import { addOwner, updateDescription } from '../../utils/entity';
import { clickOnLogo } from '../../utils/sidebar';
import {
checkTaskCountInActivityFeed,
createDescriptionTask,
createTagTask,
TaskDetails,
Feature: Allow Custom Property Update in Glossary Bulk Import/export (#17919) * fix import issue * Feat : Allow Custom Property Update in Bulk Upload * Feat : Allow Custom Property Update in Bulk Upload * supported editable imports in glossary page * added remaning localizaion keys * update logic of fieldToExtensionStrings to use csvparser * update json and partialStatus condition * fix tests for partialSuccess status change * supported customProperty editable field * fix error in custom property edit modal on new line empty custom property * added entity type from root to support other bulk import entity as well * fix the quote removing due to the regex in the string type * Add backend tests , and error msg improvements * GlossaryStatus header change * fix unit test and dry run in case of synonyms having quotes in it * Remove extension column in CSVs for all entities except glossaryTerm * added editor for reviewers * unit test around csv utils * added escape for string too, in case of semicolon comes * added playwright test without extension and supported relatedTerm as editable * added unit test around csv util logic * resolve conflicts * Backend - add support for enumWithDescriptions in bulk import * add tests and other error handling improvements related to enumWithDescriptions * fix the custom property modal header and render the layout as per right panel in entities * parese enumWithDescription for the customProperty modal while editable * fix description data in enumWithDescription one * fix: Handle NullPointerException when adding custom properties to ensure loop continues for other schemas of the same type for addToRegistry * added extension playwrigth test and fix enumWithDescription object failure * descrease the size of extension modal * remove additional comments * fix the escape in parent key * improve custom property layout * improve ui for inline properties * fix description, glossary and relatedTerm escape char issue * fix some customProperty ui changes * fix sonar issue * minor layout changes * minor label improvements for entity ref and list --------- Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com> Co-authored-by: Ashish Gupta <ashish@getcollate.io> Co-authored-by: mohitdeuex <mohit.y@deuexsolutions.com> Co-authored-by: Sachin Chaurasiya <sachinchaurasiyachotey87@gmail.com>
2024-10-01 00:12:43 +05:30
TASK_OPEN_FETCH_LINK,
} from '../../utils/task';
import { performUserLogin } from '../../utils/user';
const entity = new TableClass();
const entity2 = new TableClass();
const entity3 = new TableClass();
const entity4 = new TableClass();
const entity5 = new TableClass();
const user1 = new UserClass();
const user2 = new UserClass();
const user3 = new UserClass();
const user4 = new UserClass();
const adminUser = new UserClass();
const test = base.extend<{ page: Page }>({
page: async ({ browser }, use) => {
const adminPage = await browser.newPage();
await adminUser.login(adminPage);
await use(adminPage);
await adminPage.close();
},
});
test.describe('Activity feed', () => {
test.slow(true);
test.beforeAll('Setup pre-requests', async ({ browser }) => {
const { apiContext, afterAction } = await performAdminLogin(browser);
await adminUser.create(apiContext);
await adminUser.setAdminRole(apiContext);
await entity.create(apiContext);
await entity2.create(apiContext);
await entity3.create(apiContext);
await entity4.create(apiContext);
await entity5.create(apiContext);
await user1.create(apiContext);
await user2.create(apiContext);
await user3.create(apiContext);
await user4.create(apiContext);
await afterAction();
});
test.afterAll('Cleanup', async ({ browser }) => {
const { apiContext, afterAction } = await performAdminLogin(browser);
await entity.delete(apiContext);
await entity2.delete(apiContext);
await entity3.delete(apiContext);
await entity4.delete(apiContext);
await entity5.delete(apiContext);
await user1.delete(apiContext);
await user2.delete(apiContext);
await user3.delete(apiContext);
await user4.delete(apiContext);
await adminUser.delete(apiContext);
await afterAction();
});
test('Feed widget should be visible', async ({ page }) => {
await removeLandingBanner(page);
// Locate the feed widget
const feedWidget = page.locator('[data-testid="activity-feed-widget"]');
// Check if the feed widget is visible
await expect(feedWidget).toBeVisible();
// Check if the feed widget contains specific text
await expect(feedWidget).toContainText('All');
await expect(feedWidget).toContainText('@Mentions');
await expect(feedWidget).toContainText('Tasks');
});
test('Emoji reaction on feed should be working fine', async ({ page }) => {
await removeLandingBanner(page);
await test.step('Add Emoji reaction', async () => {
// Assign reaction for latest feed
await reactOnFeed(page);
// Verify if reaction is working or not
for (const emoji of REACTION_EMOJIS) {
await expect(
page.locator(
'[data-testid="activity-feed-widget"] [data-testid="message-container"]:first-child [data-testid="feed-reaction-container"]'
)
).toContainText(emoji);
}
});
await test.step('Remove Emoji reaction from feed', async () => {
// Remove reaction for latest feed
await reactOnFeed(page);
// Verify if reaction is removed or not
const feedReactionContainer = page
.locator('[data-testid="message-container"]')
.nth(1)
.locator('[data-testid="feed-reaction-container"]');
await expect(feedReactionContainer).toHaveCount(1);
});
});
test('Assigned task should appear to task tab', async ({ page }) => {
const value: TaskDetails = {
term: entity.entity.displayName,
assignee: user1.responseData.name,
};
await redirectToHomePage(page);
await entity.visitEntityPage(page);
await page.getByTestId('request-description').click();
// create description task
await createDescriptionTask(page, value);
await page.getByTestId('schema').click();
await page.getByTestId('request-entity-tags').click();
// create tag task
await createTagTask(page, { ...value, tag: 'PII.None' });
await clickOnLogo(page);
const taskResponse = page.waitForResponse(
'/api/v1/feed?type=Task&filterType=OWNER&taskStatus=Open&userId=*'
);
await page.getByTestId('activity-feed-widget').getByText('Tasks').click();
await taskResponse;
await expect(
page.locator(
'[data-testid="activity-feed-widget"] [data-testid="no-data-placeholder"]'
)
).not.toBeVisible();
const entityPageTaskTab = page.waitForResponse(TASK_OPEN_FETCH_LINK);
const tagsTask = page.getByTestId('redirect-task-button-link').first();
const tagsTaskContent = await tagsTask.innerText();
expect(tagsTaskContent).toContain('Request tags for');
await tagsTask.click();
await entityPageTaskTab;
// Task 1 - Request Tag right panel check
const firstTaskContent = await page.getByTestId('task-title').innerText();
expect(firstTaskContent).toContain('Request tags for');
// Task 2 - Update Description right panel check
await page.getByTestId('message-container').last().click();
const lastTaskContent = await page.getByTestId('task-title').innerText();
expect(lastTaskContent).toContain('Request to update description');
await page.getByText('Accept Suggestion').click();
await toastNotification(page, /Task resolved successfully/);
// Task 1 - Request to update tag to be resolved
const resolveSuggestion = page.waitForResponse(
'/api/v1/feed/tasks/*/resolve'
);
await page.getByText('Accept Suggestion').click();
await toastNotification(page, /Task resolved successfully/);
await resolveSuggestion;
await checkTaskCountInActivityFeed(page, 0, 2);
});
Feat: Revamp user profile Page (#19566) * new svg for user page * user page profile sidebar * sidebar fixes * activity feed left and right panel updates * activity feed editor and css fixes and profile edits * task tab initial feed * sidebar ht fix * task tab * task tab update * update task panel tab * update task and activity tab * update task and activity tab * update mydata and following * remove body font style * user profile manage * update profile section * update activity feed tab * update task tab * update task tab * update task tab * Improve border radius for preview panel * update styling * fix key issue * update edit profile * cleanup summary panels with re-usable code to make changes efficient * css fixes * fix missing case for common details * fix layout * update profile edit popovers * remove access spacing at bottom * popover placements * fix some styling * css fixes and bug fixes * full-width update * fix styling * minor fixes * minor fixes * edit popover fix * dropdown class update * domain edit fix * delete profile * reply card css fixes * task feed card btn changes * css changes * task tab refactor for inline edit * profile edit * fix update persona issue * minor fix * minor fixes * updated layout for activity feed tab on entity page and users page * Revert "updated layout for activity feed tab on entity page and users page" This reverts commit 37789e4eb344d59bca1ff008059ffb5b2d0b324e. * cleaned code for activity and task tab * cleaned code for task tab and incident manager * cleaned code for profile updates * cleaned code for diff view * cleaned code for profile edits * refactor code * fix card hover issue * minor fix * minor fixes * addtress pr comments * address pr comments * address pr comments * address pr comments * Revert "address pr comments" This reverts commit cc8cf74a59e13146f255216b7a4d59498f2fd74e. * address pr comments * address pr comments * address pr comments * minor fixes * minor fixes * fix failing test for teams and roles * fix failing unit tests * change icon file names * minor fix * minor fix * fix failing unit test cases * profile css fixes and team bug fix * fix default card render for activity feed * fix manage profile for delete and change pw * fix closed task input issue * fix richtextpreview editor issue * fix task count update on refresh * fix task approve issue for non admin users * task tab link issue fix * minor fix related to preview editor * fix activity feed playwright tests * playwright test fixes for roles and users * fix entitySummaryPanel title * playwright fix for user spec * fix customize landing page playwright test * fix domain rbac playwright failure * sonarCloud fix * fix user spec playwright failure * count issue for incident manager --------- Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com>
2025-02-24 23:08:21 +05:30
test('User should be able to reply in feeds in ActivityFeed', async ({
page,
}) => {
await redirectToHomePage(page);
await visitOwnProfilePage(page);
Feat: Revamp user profile Page (#19566) * new svg for user page * user page profile sidebar * sidebar fixes * activity feed left and right panel updates * activity feed editor and css fixes and profile edits * task tab initial feed * sidebar ht fix * task tab * task tab update * update task panel tab * update task and activity tab * update task and activity tab * update mydata and following * remove body font style * user profile manage * update profile section * update activity feed tab * update task tab * update task tab * update task tab * Improve border radius for preview panel * update styling * fix key issue * update edit profile * cleanup summary panels with re-usable code to make changes efficient * css fixes * fix missing case for common details * fix layout * update profile edit popovers * remove access spacing at bottom * popover placements * fix some styling * css fixes and bug fixes * full-width update * fix styling * minor fixes * minor fixes * edit popover fix * dropdown class update * domain edit fix * delete profile * reply card css fixes * task feed card btn changes * css changes * task tab refactor for inline edit * profile edit * fix update persona issue * minor fix * minor fixes * updated layout for activity feed tab on entity page and users page * Revert "updated layout for activity feed tab on entity page and users page" This reverts commit 37789e4eb344d59bca1ff008059ffb5b2d0b324e. * cleaned code for activity and task tab * cleaned code for task tab and incident manager * cleaned code for profile updates * cleaned code for diff view * cleaned code for profile edits * refactor code * fix card hover issue * minor fix * minor fixes * addtress pr comments * address pr comments * address pr comments * address pr comments * Revert "address pr comments" This reverts commit cc8cf74a59e13146f255216b7a4d59498f2fd74e. * address pr comments * address pr comments * address pr comments * minor fixes * minor fixes * fix failing test for teams and roles * fix failing unit tests * change icon file names * minor fix * minor fix * fix failing unit test cases * profile css fixes and team bug fix * fix default card render for activity feed * fix manage profile for delete and change pw * fix closed task input issue * fix richtextpreview editor issue * fix task count update on refresh * fix task approve issue for non admin users * task tab link issue fix * minor fix related to preview editor * fix activity feed playwright tests * playwright test fixes for roles and users * fix entitySummaryPanel title * playwright fix for user spec * fix customize landing page playwright test * fix domain rbac playwright failure * sonarCloud fix * fix user spec playwright failure * count issue for incident manager --------- Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com>
2025-02-24 23:08:21 +05:30
const commentInput = page.locator('[data-testid="comments-input-field"]');
commentInput.click();
Feat: Revamp user profile Page (#19566) * new svg for user page * user page profile sidebar * sidebar fixes * activity feed left and right panel updates * activity feed editor and css fixes and profile edits * task tab initial feed * sidebar ht fix * task tab * task tab update * update task panel tab * update task and activity tab * update task and activity tab * update mydata and following * remove body font style * user profile manage * update profile section * update activity feed tab * update task tab * update task tab * update task tab * Improve border radius for preview panel * update styling * fix key issue * update edit profile * cleanup summary panels with re-usable code to make changes efficient * css fixes * fix missing case for common details * fix layout * update profile edit popovers * remove access spacing at bottom * popover placements * fix some styling * css fixes and bug fixes * full-width update * fix styling * minor fixes * minor fixes * edit popover fix * dropdown class update * domain edit fix * delete profile * reply card css fixes * task feed card btn changes * css changes * task tab refactor for inline edit * profile edit * fix update persona issue * minor fix * minor fixes * updated layout for activity feed tab on entity page and users page * Revert "updated layout for activity feed tab on entity page and users page" This reverts commit 37789e4eb344d59bca1ff008059ffb5b2d0b324e. * cleaned code for activity and task tab * cleaned code for task tab and incident manager * cleaned code for profile updates * cleaned code for diff view * cleaned code for profile edits * refactor code * fix card hover issue * minor fix * minor fixes * addtress pr comments * address pr comments * address pr comments * address pr comments * Revert "address pr comments" This reverts commit cc8cf74a59e13146f255216b7a4d59498f2fd74e. * address pr comments * address pr comments * address pr comments * minor fixes * minor fixes * fix failing test for teams and roles * fix failing unit tests * change icon file names * minor fix * minor fix * fix failing unit test cases * profile css fixes and team bug fix * fix default card render for activity feed * fix manage profile for delete and change pw * fix closed task input issue * fix richtextpreview editor issue * fix task count update on refresh * fix task approve issue for non admin users * task tab link issue fix * minor fix related to preview editor * fix activity feed playwright tests * playwright test fixes for roles and users * fix entitySummaryPanel title * playwright fix for user spec * fix customize landing page playwright test * fix domain rbac playwright failure * sonarCloud fix * fix user spec playwright failure * count issue for incident manager --------- Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com>
2025-02-24 23:08:21 +05:30
await page.fill(
'[data-testid="editor-wrapper"] .ql-editor',
`Reply message`
);
Feat: Revamp user profile Page (#19566) * new svg for user page * user page profile sidebar * sidebar fixes * activity feed left and right panel updates * activity feed editor and css fixes and profile edits * task tab initial feed * sidebar ht fix * task tab * task tab update * update task panel tab * update task and activity tab * update task and activity tab * update mydata and following * remove body font style * user profile manage * update profile section * update activity feed tab * update task tab * update task tab * update task tab * Improve border radius for preview panel * update styling * fix key issue * update edit profile * cleanup summary panels with re-usable code to make changes efficient * css fixes * fix missing case for common details * fix layout * update profile edit popovers * remove access spacing at bottom * popover placements * fix some styling * css fixes and bug fixes * full-width update * fix styling * minor fixes * minor fixes * edit popover fix * dropdown class update * domain edit fix * delete profile * reply card css fixes * task feed card btn changes * css changes * task tab refactor for inline edit * profile edit * fix update persona issue * minor fix * minor fixes * updated layout for activity feed tab on entity page and users page * Revert "updated layout for activity feed tab on entity page and users page" This reverts commit 37789e4eb344d59bca1ff008059ffb5b2d0b324e. * cleaned code for activity and task tab * cleaned code for task tab and incident manager * cleaned code for profile updates * cleaned code for diff view * cleaned code for profile edits * refactor code * fix card hover issue * minor fix * minor fixes * addtress pr comments * address pr comments * address pr comments * address pr comments * Revert "address pr comments" This reverts commit cc8cf74a59e13146f255216b7a4d59498f2fd74e. * address pr comments * address pr comments * address pr comments * minor fixes * minor fixes * fix failing test for teams and roles * fix failing unit tests * change icon file names * minor fix * minor fix * fix failing unit test cases * profile css fixes and team bug fix * fix default card render for activity feed * fix manage profile for delete and change pw * fix closed task input issue * fix richtextpreview editor issue * fix task count update on refresh * fix task approve issue for non admin users * task tab link issue fix * minor fix related to preview editor * fix activity feed playwright tests * playwright test fixes for roles and users * fix entitySummaryPanel title * playwright fix for user spec * fix customize landing page playwright test * fix domain rbac playwright failure * sonarCloud fix * fix user spec playwright failure * count issue for incident manager --------- Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com>
2025-02-24 23:08:21 +05:30
const sendReply = page.waitForResponse('/api/v1/feed/*/posts');
await page.getByTestId('send-button').click({ force: true });
await sendReply;
await expect(
Feat: Revamp user profile Page (#19566) * new svg for user page * user page profile sidebar * sidebar fixes * activity feed left and right panel updates * activity feed editor and css fixes and profile edits * task tab initial feed * sidebar ht fix * task tab * task tab update * update task panel tab * update task and activity tab * update task and activity tab * update mydata and following * remove body font style * user profile manage * update profile section * update activity feed tab * update task tab * update task tab * update task tab * Improve border radius for preview panel * update styling * fix key issue * update edit profile * cleanup summary panels with re-usable code to make changes efficient * css fixes * fix missing case for common details * fix layout * update profile edit popovers * remove access spacing at bottom * popover placements * fix some styling * css fixes and bug fixes * full-width update * fix styling * minor fixes * minor fixes * edit popover fix * dropdown class update * domain edit fix * delete profile * reply card css fixes * task feed card btn changes * css changes * task tab refactor for inline edit * profile edit * fix update persona issue * minor fix * minor fixes * updated layout for activity feed tab on entity page and users page * Revert "updated layout for activity feed tab on entity page and users page" This reverts commit 37789e4eb344d59bca1ff008059ffb5b2d0b324e. * cleaned code for activity and task tab * cleaned code for task tab and incident manager * cleaned code for profile updates * cleaned code for diff view * cleaned code for profile edits * refactor code * fix card hover issue * minor fix * minor fixes * addtress pr comments * address pr comments * address pr comments * address pr comments * Revert "address pr comments" This reverts commit cc8cf74a59e13146f255216b7a4d59498f2fd74e. * address pr comments * address pr comments * address pr comments * minor fixes * minor fixes * fix failing test for teams and roles * fix failing unit tests * change icon file names * minor fix * minor fix * fix failing unit test cases * profile css fixes and team bug fix * fix default card render for activity feed * fix manage profile for delete and change pw * fix closed task input issue * fix richtextpreview editor issue * fix task count update on refresh * fix task approve issue for non admin users * task tab link issue fix * minor fix related to preview editor * fix activity feed playwright tests * playwright test fixes for roles and users * fix entitySummaryPanel title * playwright fix for user spec * fix customize landing page playwright test * fix domain rbac playwright failure * sonarCloud fix * fix user spec playwright failure * count issue for incident manager --------- Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com>
2025-02-24 23:08:21 +05:30
page.locator('.right-container [data-testid="feed-replies"]')
).toContainText('Reply message');
});
test('Update Description Task on Columns', async ({ page }) => {
const firstTaskValue: TaskDetails = {
term: entity4.entity.displayName,
assignee: user1.responseData.name,
description: 'Column Description 1',
columnName: entity4.entity.columns[0].name,
oldDescription: entity4.entity.columns[0].description,
};
const secondTaskValue: TaskDetails = {
...firstTaskValue,
description: 'Column Description 2',
columnName: entity4.entity.columns[1].name,
oldDescription: entity4.entity.columns[1].description,
};
await redirectToHomePage(page);
await entity4.visitEntityPage(page);
await page
.getByRole('cell', { name: 'The ID of the store. This' })
.getByTestId('task-element')
.click();
// create description task
await createDescriptionTask(page, secondTaskValue);
await page.getByTestId('schema').click();
// create 2nd task for column description
await page
.getByRole('cell', { name: 'Unique identifier for the' })
.getByTestId('task-element')
.click();
await createDescriptionTask(page, firstTaskValue);
// Task 1 - check the description in edit and accept suggestion
await checkDescriptionInEditModal(page, firstTaskValue);
await page.getByText('Cancel').click();
await page.waitForSelector('[role="dialog"].ant-modal', {
state: 'detached',
});
// Task 2 - check the description in edit and accept suggestion
await page.getByTestId('message-container').last().click();
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/);
// Task 1 - Resolved the task
const resolveTask2 = page.waitForResponse('/api/v1/feed/tasks/*/resolve');
await page.getByText('Accept Suggestion').click();
await resolveTask2;
await toastNotification(page, /Task resolved successfully/);
await checkTaskCountInActivityFeed(page, 0, 2);
});
test('Comment and Close Task should work in Task Flow', async ({ page }) => {
const value: TaskDetails = {
term: entity2.entity.displayName,
assignee: user1.responseData.name,
};
await redirectToHomePage(page);
await entity2.visitEntityPage(page);
await page.getByTestId('request-description').click();
await createDescriptionTask(page, value);
// Task 1 - Update Description right panel check
const descriptionTask = await page.getByTestId('task-title').innerText();
expect(descriptionTask).toContain('Request to update description');
// Close the task from the Button.Group, should throw error when no comment is added.
await page.getByRole('button', { name: 'down' }).click();
await page.waitForSelector('.ant-dropdown', {
state: 'visible',
});
await page.getByRole('menuitem', { name: 'close' }).click();
await toastNotification(page, 'Task cannot be closed without a comment.');
// Close the task from the Button.Group, with comment is added.
const commentInput = page.locator('[data-testid="comments-input-field"]');
await commentInput.scrollIntoViewIfNeeded();
await commentInput.click();
await page.fill(
'[data-testid="editor-wrapper"] .ql-editor',
'Closing the task with comment'
);
await page.getByTestId('send-button').click();
const commentWithCloseTask = page.waitForResponse(
'/api/v1/feed/tasks/*/close'
);
await page.getByRole('button', { name: 'down' }).click();
await page.waitForSelector('.ant-dropdown', {
state: 'visible',
});
await page.getByRole('menuitem', { name: 'close' }).click();
await commentWithCloseTask;
await toastNotification(page, 'Task closed successfully.');
await checkTaskCountInActivityFeed(page, 0, 1);
});
test('Replies should be visible in the task feed', async ({ page }) => {
const value: TaskDetails = {
term: entity2.entity.displayName,
assignee: user1.responseData.name,
};
await redirectToHomePage(page);
await entity2.visitEntityPage(page);
await page.getByTestId('request-description').click();
await createDescriptionTask(page, value);
// Task 1 - Update Description right panel check
const descriptionTask = await page.getByTestId('task-title').innerText();
expect(descriptionTask).toContain('Request to update description');
for (let i = 0; i < 10; i++) {
const commentInput = page.locator('[data-testid="comments-input-field"]');
commentInput.click();
await page.fill(
'[data-testid="editor-wrapper"] .ql-editor',
`Reply message ${i}`
);
const sendReply = page.waitForResponse('/api/v1/feed/*/posts');
await page.getByTestId('send-button').click({ force: true });
await sendReply;
}
await page.reload();
await page.waitForSelector('[data-testid="loader"]', {
state: 'hidden',
});
await page.waitForLoadState('networkidle');
await expect(page.getByTestId('feed-reply-card')).toHaveCount(10);
for (let i = 0; i < 10; i++) {
await expect(
page.locator('.right-container [data-testid="feed-replies"]')
).toContainText(`Reply message ${i}`);
}
});
test('Open and Closed Task Tab with approve from Task Feed Card', async ({
page,
}) => {
const value: TaskDetails = {
term: entity3.entity.displayName,
assignee: user1.responseData.name,
};
await redirectToHomePage(page);
await entity3.visitEntityPage(page);
await page.getByTestId('request-description').click();
// create description task
const openTaskAfterDescriptionResponse =
page.waitForResponse(TASK_OPEN_FETCH_LINK);
await createDescriptionTask(page, value);
await openTaskAfterDescriptionResponse;
// open task count after description
await checkTaskCountInActivityFeed(page, 1, 0);
await page.getByTestId('schema').click();
await page.getByTestId('request-entity-tags').click();
// create tag task
const openTaskAfterTagResponse = page.waitForResponse(TASK_OPEN_FETCH_LINK);
await createTagTask(page, { ...value, tag: 'PII.None' });
await openTaskAfterTagResponse;
// open task count after description
await checkTaskCountInActivityFeed(page, 2, 0);
page.locator('[data-testid="approve-button"]').first().click();
await toastNotification(page, 'Task resolved successfully');
await checkTaskCountInActivityFeed(page, 1, 1);
});
test('Assignee field should not be disabled for owned entity tasks', async ({
page,
}) => {
const value: TaskDetails = {
term: entity4.entity.displayName,
assignee: user1.responseData.name,
};
await redirectToHomePage(page);
await entity4.visitEntityPage(page);
await addOwner({
page,
owner: user2.responseData.displayName,
type: 'Users',
endpoint: EntityTypeEndpoint.Table,
dataTestId: 'data-assets-header',
});
await page.getByTestId('request-description').click();
// create description task
await createDescriptionTask(page, value);
});
test('Mention should work for the feed reply', async ({ page }) => {
await test.step('Add Mention in Feed', async () => {
await addMentionCommentInFeed(page, adminUser.responseData.name);
// Close drawer
await page.locator('[data-testid="closeDrawer"]').click();
// Get the feed text
const feedText = await page
.locator(`${FIRST_FEED_SELECTOR} [data-testid="headerText"]`)
.innerText();
// Click on @Mentions tab
const fetchMentionsFeedResponse = page.waitForResponse(
'/api/v1/feed?filterType=MENTIONS&userId=*'
);
await page
.locator('[data-testid="activity-feed-widget"]')
.locator('text=@Mentions')
.click();
await fetchMentionsFeedResponse;
const mentionedText = await page
.locator(`${FIRST_FEED_SELECTOR} [data-testid="headerText"]`)
.innerText();
expect(mentionedText).toContain(feedText);
});
await test.step(
'Add Mention should work if users having dot in their name',
async () => {
await addMentionCommentInFeed(page, 'aaron.warren5', true);
const feedContainer = `[data-testid="feed-replies"]`;
await expect(
page
.locator(feedContainer)
.locator(
'[data-testid="viewer-container"] [data-testid="markdown-parser"]'
)
.first()
).toContainText('Can you resolve this thread for me? @aaron.warren5');
// Close drawer
await page.locator('[data-testid="closeDrawer"]').click();
}
);
});
test('Check Task Filter in Landing Page Widget', async ({ browser }) => {
const { page: page1, afterAction: afterActionUser1 } =
await performUserLogin(browser, user1);
const { page: page2, afterAction: afterActionUser3 } =
await performUserLogin(browser, user3);
await base.step('Create and Assign Task to User 3', async () => {
await redirectToHomePage(page1);
await entity.visitEntityPage(page1);
// Create task for the user 3
await page1.getByTestId('request-description').click();
await createDescriptionTask(page1, {
term: entity.entity.displayName,
assignee: user3.responseData.name,
});
await afterActionUser1();
});
await base.step('Create and Validate Task as per Filters', async () => {
await redirectToHomePage(page2);
await entity.visitEntityPage(page2);
// Create task for the user 1
await page2.getByTestId('request-entity-tags').click();
await createTagTask(page2, {
term: entity.entity.displayName,
tag: 'PII.None',
assignee: user1.responseData.name,
});
await redirectToHomePage(page2);
const taskResponse = page2.waitForResponse(
'/api/v1/feed?type=Task&filterType=OWNER&taskStatus=Open&userId=*'
);
await page2
.getByTestId('activity-feed-widget')
.getByText('Tasks')
.click();
await taskResponse;
await page2.waitForLoadState('networkidle');
await expect(
page2.locator(
'[data-testid="activity-feed-widget"] [data-testid="no-data-placeholder"]'
)
).not.toBeVisible();
// Check the Task based on ALL task filter
await expect(page2.getByTestId('message-container')).toHaveCount(2);
// Check the Task based on Assigned task filter
await page2.getByTestId('filter-button').click();
await page2.waitForSelector('.ant-popover ', { state: 'visible' });
const taskAssignedResponse = page2.waitForResponse(
'/api/v1/feed?type=Task&filterType=ASSIGNED_TO&taskStatus=Open&userId=*'
);
await page2.getByText('Assigned').click();
await page2.getByTestId('selectable-list-update-btn').click();
await taskAssignedResponse;
await expect(page2.getByTestId('message-container')).toHaveCount(1);
await page2.getByTestId('task-feed-card').locator('.ant-avatar').hover();
await expect(
page2.getByText(user3.responseData.displayName).first()
).toBeVisible();
// Check the Task based on Created by me task filter
await page2.getByTestId('filter-button').click();
await page2.waitForSelector('.ant-popover ', { state: 'visible' });
const taskCreatedByResponse = page2.waitForResponse(
'/api/v1/feed?type=Task&filterType=ASSIGNED_BY&taskStatus=Open&userId=*'
);
await page2.getByText('Created By').click();
await page2.getByTestId('selectable-list-update-btn').click();
await taskCreatedByResponse;
await expect(page2.getByTestId('message-container')).toHaveCount(1);
await page2.getByTestId('task-feed-card').locator('.ant-avatar').hover();
await expect(
page2.getByText(user3.responseData.displayName).first()
).toBeVisible();
await afterActionUser3();
});
});
test('Verify feed count', async ({ page }) => {
await redirectToHomePage(page);
await entity5.visitEntityPage(page);
await page.getByTestId('request-description').click();
await createDescriptionTask(page, {
term: entity5.entity.displayName,
assignee: user4.responseData.name,
});
await page.waitForSelector('[data-testid="loader"]', { state: 'detached' });
await page.waitForLoadState('networkidle');
await expect(page.getByTestId('left-panel-task-count')).toHaveText('1');
});
});
base.describe('Activity feed with Data Consumer User', () => {
base.slow(true);
const id = uuid();
const rules: PolicyRulesType[] = [
{
name: 'viewRuleAllowed',
resources: ['All'],
operations: ['ViewAll'],
effect: 'allow',
},
{
effect: 'deny',
name: 'editNotAllowed',
operations: ['EditAll'],
resources: ['All'],
},
];
base.beforeAll('Setup pre-requests', async ({ browser }) => {
const { afterAction, apiContext } = await performAdminLogin(browser);
await entity.create(apiContext);
await entity2.create(apiContext);
await entity3.create(apiContext);
await user1.create(apiContext);
await user2.create(apiContext);
await afterAction();
});
base.afterAll('Cleanup', async ({ browser }) => {
const { afterAction, apiContext } = await performAdminLogin(browser);
await entity.delete(apiContext);
await entity2.delete(apiContext);
await entity3.delete(apiContext);
await user1.delete(apiContext);
await user2.delete(apiContext);
await afterAction();
});
base('Create and Assign Task with Suggestions', async ({ browser }) => {
const { page: page1, afterAction: afterActionUser1 } =
await performUserLogin(browser, user1);
const { page: page2, afterAction: afterActionUser2 } =
await performUserLogin(browser, user2);
const value: TaskDetails = {
term: entity.entity.displayName,
assignee: user2.responseData.name,
};
await base.step('Create, Close and Assign Task to User 2', async () => {
await redirectToHomePage(page1);
await entity.visitEntityPage(page1);
// Create 2 task for the same entity, one to close and 2nd for the user2 action
await page1.getByTestId('request-description').click();
await createDescriptionTask(page1, value);
await page1.getByTestId('schema').click();
await page1.getByTestId('request-entity-tags').click();
// create tag task
await createTagTask(page1, { ...value, tag: 'PII.None' });
// Should only see the close button
expect(page1.locator('[data-testid="close-button"]')).toBeVisible();
expect(
page1.locator('[data-testid="edit-accept-task-dropdown"]')
).not.toBeVisible();
const commentInput = page1.locator(
'[data-testid="comments-input-field"]'
);
await commentInput.scrollIntoViewIfNeeded();
await commentInput.click();
// Close 1st task
await page1.fill(
'[data-testid="editor-wrapper"] .ql-editor',
'Closing the task with comment'
);
2025-06-07 23:53:16 +05:30
const commentPostResponse = page1.waitForResponse('/api/v1/feed/*/posts');
await page1.locator('.activity-feed-editor-send-btn').click();
2025-06-07 23:53:16 +05:30
await commentPostResponse;
const commentWithCloseTask = page1.waitForResponse(
'/api/v1/feed/tasks/*/close'
);
await page1.locator('[data-testid="close-button"]').click();
await commentWithCloseTask;
await toastNotification(page1, 'Task closed successfully.');
await page1.waitForLoadState('networkidle');
await checkTaskCountInActivityFeed(page1, 1, 1);
await afterActionUser1();
});
await base.step('Accept Task By User 2', async () => {
await redirectToHomePage(page2);
const taskResponse = page2.waitForResponse(
'/api/v1/feed?type=Task&filterType=OWNER&taskStatus=Open&userId=*'
);
await page2
.getByTestId('activity-feed-widget')
.getByText('Tasks')
.click();
await taskResponse;
await expect(
page2.locator(
'[data-testid="activity-feed-widget"] [data-testid="no-data-placeholder"]'
)
).not.toBeVisible();
const entityPageTaskTab = page2.waitForResponse(TASK_OPEN_FETCH_LINK);
const tagsTask = page2.getByTestId('redirect-task-button-link').first();
const tagsTaskContent = await tagsTask.innerText();
expect(tagsTaskContent).toContain('Request to update description for');
await tagsTask.click();
await entityPageTaskTab;
await page2.waitForLoadState('networkidle');
// Count for task should be 1 both open and closed
2025-05-14 14:35:15 +05:30
await checkTaskCountInActivityFeed(page2, 1, 1);
// Should not see the close button
expect(page2.locator('[data-testid="close-button"]')).not.toBeVisible();
expect(
page2.locator('[data-testid="edit-accept-task-dropdown"]')
).toBeVisible();
const resolveTask = page2.waitForResponse('/api/v1/feed/tasks/*/resolve');
await page2.getByText('Accept Suggestion').scrollIntoViewIfNeeded();
await page2.getByText('Accept Suggestion').click();
await resolveTask;
await toastNotification(page2, /Task resolved successfully/);
await page2.waitForLoadState('networkidle');
2025-05-14 14:35:15 +05:30
await checkTaskCountInActivityFeed(page2, 0, 2);
await afterActionUser2();
});
});
base('Create and Assign Task without Suggestions', async ({ browser }) => {
const { page: page1, afterAction: afterActionUser1 } =
await performUserLogin(browser, user1);
const { page: page2, afterAction: afterActionUser2 } =
await performUserLogin(browser, user2);
const value: TaskDetails = {
term: entity2.entity.displayName,
assignee: user2.responseData.name,
};
await base.step('Create, Close and Assign Task to user 2', async () => {
await redirectToHomePage(page1);
await entity2.visitEntityPage(page1);
await updateDescription(page1, '');
// Create 2 task for the same entity, one to close and 2nd for the user2 action
await page1.getByTestId('request-description').click();
await createDescriptionTask(page1, value, false);
await page1.getByTestId('schema').click();
await page1.getByTestId('request-entity-tags').click();
// create tag task
await createTagTask(page1, value, false);
// Should only see the close, add and comment button
expect(
page1.locator('[data-testid="comments-input-field"]')
).toBeVisible();
expect(page1.locator('[data-testid="close-button"]')).toBeVisible();
expect(
page1.locator('[data-testid="edit-accept-task-dropdown"]')
).not.toBeVisible();
expect(
page1.locator('[data-testid="add-close-task-dropdown"]')
).not.toBeVisible();
await afterActionUser1();
});
await base.step(
'Accept Task By user 2 with adding suggestions',
async () => {
await redirectToHomePage(page2);
const taskResponse = page2.waitForResponse(
'/api/v1/feed?type=Task&filterType=OWNER&taskStatus=Open&userId=*'
);
await page2
.getByTestId('activity-feed-widget')
.getByText('Tasks')
.click();
await taskResponse;
await expect(
page2.locator(
'[data-testid="activity-feed-widget"] [data-testid="no-data-placeholder"]'
)
).not.toBeVisible();
const entityPageTaskTab = page2.waitForResponse(TASK_OPEN_FETCH_LINK);
const tagsTask = page2.getByTestId('redirect-task-button-link').first();
const tagsTaskContent = await tagsTask.innerText();
expect(tagsTaskContent).toContain('Request tags for');
await tagsTask.click();
await entityPageTaskTab;
expect(page2.getByText('no diff available').first()).toBeVisible();
// Should see the add_close dropdown and comment button
await expect(
page2.locator('[data-testid="comments-input-field"]')
).toBeVisible();
await expect(
page2.getByTestId('add-close-task-dropdown')
).toBeVisible();
await expect(
page2.locator('[data-testid="close-button"]')
).not.toBeVisible();
await expect(
page2.locator('[data-testid="edit-accept-task-dropdown"]')
).not.toBeVisible();
await page2.waitForSelector('.ant-skeleton-element', {
state: 'detached',
});
const tagsSuggestionResponse = page2.waitForResponse(
'/api/v1/search/query?q=***'
);
await page2.getByRole('button', { name: 'Add Tags' }).click();
await tagsSuggestionResponse;
await page2.waitForSelector('[role="dialog"].ant-modal');
const modalTitleContent = await page2
.locator('.ant-modal-header .ant-modal-title')
.innerText();
expect(modalTitleContent).toContain(
`Request tags for table ${value.term}`
);
// select the Tag
const suggestTags = page2.locator(
'[data-testid="tag-selector"] > .ant-select-selector .ant-select-selection-search-input'
);
await suggestTags.click();
const querySearchResponse = page2.waitForResponse(
`/api/v1/search/query?q=*${'PII.None'}*&index=tag_search_index&*`
);
await suggestTags.fill('PII.None');
await querySearchResponse;
// select value from dropdown
const dropdownValue = page2.getByTestId(`tag-PII.None`).first();
await dropdownValue.hover();
await dropdownValue.click();
await clickOutside(page2);
await expect(page2.getByTestId('selected-tag-PII.None')).toBeVisible();
await page2.getByText('OK').click();
await toastNotification(page2, /Task resolved successfully/);
// Accept the description task
await expect(page2.getByText('No Suggestion').first()).toBeVisible();
await page2.getByRole('button', { name: 'Add Description' }).click();
await page2.waitForSelector('[role="dialog"].ant-modal');
const modalTitleDescriptionContent = await page2
.locator('.ant-modal-header .ant-modal-title')
.innerText();
expect(modalTitleDescriptionContent).toContain(
`Request description for table ${value.term}`
);
await page2.locator(descriptionBox).fill('New description');
await page2.getByText('OK').click();
await toastNotification(page2, /Task resolved successfully/);
await afterActionUser2();
}
);
});
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 } =
await performUserLogin(browser, viewAllUser);
const value: TaskDetails = {
term: entity3.entity.displayName,
assignee: viewAllUser.responseData.name,
};
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 createDescriptionTask(page1, value);
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 entity3.visitEntityPage(page2);
await page2.getByTestId('activity_feed').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 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();
}
);
} finally {
await viewAllUser.delete(apiContext);
await viewAllPolicy.delete(apiContext);
await viewAllRoles.delete(apiContext);
await viewAllTeam.delete(apiContext);
await afterAction();
}
}
);
});