Karan Hotchandani 23096fa2f3
migrate glossary tests to playwright (#17617)
* move glossary tests to playwright

* fix tests
2024-08-29 11:38:31 +05:30

998 lines
29 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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.
*/
import { expect, Page } from '@playwright/test';
import { get, isUndefined } from 'lodash';
import { SidebarItem } from '../constant/sidebar';
import { GLOSSARY_TERM_PATCH_PAYLOAD } from '../constant/version';
import { DashboardClass } from '../support/entity/DashboardClass';
import { EntityTypeEndpoint } from '../support/entity/Entity.interface';
import { TableClass } from '../support/entity/TableClass';
import { TopicClass } from '../support/entity/TopicClass';
import { Glossary } from '../support/glossary/Glossary';
import {
GlossaryData,
GlossaryTermData,
} from '../support/glossary/Glossary.interface';
import { GlossaryTerm } from '../support/glossary/GlossaryTerm';
import {
clickOutside,
getApiContext,
INVALID_NAMES,
NAME_MAX_LENGTH_VALIDATION_ERROR,
NAME_VALIDATION_ERROR,
redirectToHomePage,
toastNotification,
} from './common';
import { addMultiOwner } from './entity';
import { sidebarClick } from './sidebar';
import { TaskDetails, TASK_OPEN_FETCH_LINK } from './task';
export const descriptionBox =
'.toastui-editor-md-container > .toastui-editor > .ProseMirror';
export const checkDisplayName = async (page: Page, displayName: string) => {
await expect(page.getByTestId('entity-header-display-name')).toHaveText(
displayName
);
};
export const selectActiveGlossary = async (
page: Page,
glossaryName: string
) => {
const menuItem = page.getByRole('menuitem', { name: glossaryName });
const isSelected = await menuItem.evaluate((element) => {
return element.classList.contains('ant-menu-item-selected');
});
if (!isSelected) {
const glossaryResponse = page.waitForResponse('/api/v1/glossaryTerms*');
await menuItem.click();
await glossaryResponse;
}
};
export const selectActiveGlossaryTerm = async (
page: Page,
glossaryTermName: string
) => {
await page.getByTestId(glossaryTermName).click();
await expect(
page.locator('[data-testid="entity-header-display-name"]')
).toContainText(glossaryTermName);
};
export const goToAssetsTab = async (
page: Page,
displayName: string,
count = 0
) => {
await selectActiveGlossaryTerm(page, displayName);
await page.getByTestId('assets').click();
await page.waitForSelector('.ant-tabs-tab-active:has-text("Assets")');
await expect(
page.getByTestId('assets').getByTestId('filter-count')
).toContainText(`${count}`);
};
export const removeReviewer = async (
page: Page,
endpoint: EntityTypeEndpoint
) => {
const patchResponse = page.waitForResponse(`/api/v1/${endpoint}/*`);
await page.click('[data-testid="edit-reviewer-button"]');
await page.click('[data-testid="clear-all-button"]');
await page.click('[data-testid="selectable-list-update-btn"]');
await patchResponse;
await expect(
page.locator('[data-testid="glossary-reviewer"] [data-testid="Add"]')
).toBeVisible();
};
// Create a glossary and two glossary terms, then link them with a related term relationship
export const setupGlossaryAndTerms = async (page: Page) => {
const glossary = new Glossary();
const term1 = new GlossaryTerm(glossary);
const term2 = new GlossaryTerm(glossary);
// Get API context for performing operations
const { apiContext, afterAction } = await getApiContext(page);
// Create glossary and terms
await glossary.create(apiContext);
await term1.create(apiContext);
await term2.create(apiContext);
// Prepare the payload for linking term2 as a related term to term1
const relatedTermLink = {
op: 'add',
path: '/relatedTerms/0',
value: {
id: term1.responseData.id,
type: 'glossaryTerm',
displayName: term1.responseData.displayName,
name: term1.responseData.name,
},
};
// Update term2 to include term1 as a related term
await term2.patch(apiContext, [
...GLOSSARY_TERM_PATCH_PAYLOAD,
relatedTermLink,
]);
const cleanup = async () => {
await glossary.delete(apiContext);
await afterAction();
};
return { glossary, term1, term2, cleanup };
};
export const validateForm = async (page) => {
// Error messages
await expect(page.locator('#name_help')).toHaveText('Name is required');
await expect(page.locator('#description_help')).toHaveText(
'Description is required'
);
// Max length validation
await page.locator('[data-testid="name"]').type(INVALID_NAMES.MAX_LENGTH);
await expect(page.locator('#name_help')).toHaveText(
NAME_MAX_LENGTH_VALIDATION_ERROR
);
// With special char validation
await page.locator('[data-testid="name"]').clear();
await page
.locator('[data-testid="name"]')
.type(INVALID_NAMES.WITH_SPECIAL_CHARS);
await expect(page.locator('#name_help')).toHaveText(NAME_VALIDATION_ERROR);
};
export const addTeamAsReviewer = async (
page: Page,
teamName: string,
activatorBtnDataTestId: string,
dataTestId?: string,
isSelectableInsideForm = false
) => {
const teamsResponse = page.waitForResponse(
'/api/v1/search/query?q=*&from=0&size=*&index=team_search_index&sort_field=displayName.keyword&sort_order=asc'
);
const teamsSearchResponse = page.waitForResponse(
`api/v1/search/query?q=*${encodeURI(teamName)}*`
);
await page.click(`[data-testid="${activatorBtnDataTestId}"]`);
await expect(page.locator("[data-testid='select-owner-tabs']")).toBeVisible();
await teamsResponse;
await page.fill('[data-testid="owner-select-teams-search-bar"]', teamName);
await teamsSearchResponse;
const ownerItem = page.locator(`.ant-popover [title="${teamName}"]`);
if (isSelectableInsideForm) {
await ownerItem.click();
} else {
const patchRequest = page.waitForRequest(
(request) => request.method() === 'PATCH'
);
await ownerItem.click();
await patchRequest;
}
await expect(
page.locator(`[data-testid=${dataTestId ?? 'owner-link'}]`)
).toContainText(teamName);
};
export const createGlossary = async (
page: Page,
glossaryData: GlossaryData,
bValidateForm: boolean
) => {
// Click on the "Add Glossary" button
await page.click('[data-testid="add-glossary"]');
// Validate redirection to the add glossary page
await page.waitForSelector('[data-testid="form-heading"]');
await expect(page.locator('[data-testid="form-heading"]')).toHaveText(
'Add Glossary'
);
// Perform glossary creation steps
await page.click('[data-testid="save-glossary"]');
if (bValidateForm) {
await validateForm(page);
}
await page.fill('[data-testid="name"]', glossaryData.name);
await page.fill(descriptionBox, glossaryData.description);
await expect(
page.locator('[data-testid="form-item-alert"]')
).not.toBeVisible();
if (glossaryData.mutuallyExclusive) {
await page.click('[data-testid="mutually-exclusive-button"]');
await expect(page.locator('[data-testid="form-item-alert"]')).toBeVisible();
}
if (glossaryData.tags && glossaryData.tags.length > 0) {
const tagsResponse = page.waitForResponse('/api/v1/search/query');
// Add tag
await page.click('[data-testid="tag-selector"]');
await page.fill(
'[data-testid="tag-selector"] input[type="search"]',
glossaryData.tags[0]
);
await tagsResponse;
await page.click(`[data-testid="tag-${glossaryData.tags[0]}"]`);
await page.click('[data-testid="right-panel"]');
}
if (glossaryData.reviewers.length > 0) {
// Add reviewer
if (glossaryData.reviewers[0].type === 'user') {
await addMultiOwner({
page,
ownerNames: glossaryData.reviewers.map((reviewer) => reviewer.name),
activatorBtnDataTestId: 'add-reviewers',
resultTestId: 'reviewers-container',
endpoint: EntityTypeEndpoint.Glossary,
isSelectableInsideForm: true,
type: 'Users',
});
} else {
await addTeamAsReviewer(
page,
glossaryData.reviewers[0].name,
'add-reviewers',
'reviewers-container',
true
);
}
}
const glossaryResponse = page.waitForResponse('/api/v1/glossaries');
await page.click('[data-testid="save-glossary"]');
await glossaryResponse;
await expect(page).toHaveURL(/\/glossary\//);
await checkDisplayName(page, glossaryData.name);
};
export const verifyGlossaryDetails = async (
page: Page,
glossaryDetails: GlossaryData
) => {
await page
.getByRole('menuitem', { name: glossaryDetails.name })
.locator('span')
.click();
await checkDisplayName(page, glossaryDetails.name);
const viewerContainerText = await page.textContent(
'[data-testid="viewer-container"]'
);
await expect(viewerContainerText).toContain(glossaryDetails.description);
// Owner
if (glossaryDetails.owners.length > 0) {
for (const owner of glossaryDetails.owners) {
await expect(
page
.getByTestId('glossary-right-panel-owner-link')
.getByTestId('owner-label')
).toContainText(owner.name);
}
}
// Reviewer
if (glossaryDetails.reviewers.length > 0) {
for (const reviewer of glossaryDetails.reviewers) {
await expect(
page.getByTestId('glossary-reviewer').getByTestId('owner-link')
).toContainText(reviewer.name);
}
}
// Tags
if (glossaryDetails.tags && glossaryDetails.tags.length > 0) {
const tagVisibility = await page.isVisible(
`[data-testid="tag-${glossaryDetails.tags[0]}"]`
);
await expect(tagVisibility).toBe(true);
}
};
export const deleteGlossary = async (page: Page, glossary: GlossaryData) => {
await page
.getByRole('menuitem', { name: glossary.displayName })
.locator('span')
.click();
await page.click('[data-testid="manage-button"]');
await page.click('[data-testid="delete-button"]');
await page.waitForSelector('[data-testid="delete-confirmation-modal"]');
await expect(page.locator('[role="dialog"]')).toBeVisible();
await expect(page.locator('[data-testid="modal-header"]')).toBeVisible();
await expect(page.locator('[data-testid="modal-header"]')).toContainText(
glossary.displayName
);
await page.fill('[data-testid="confirmation-text-input"]', 'DELETE');
const deleteGlossary = page.waitForResponse(
(response) =>
response.url().includes('/api/v1/glossaries/') &&
response.request().method() === 'DELETE' &&
response.status() === 200
);
await page.click('[data-testid="confirm-button"]');
// Wait for the API response and verify the status code
await deleteGlossary;
// Display toast notification
await expect(page.locator('.toast-notification')).toHaveText(
'"Glossary" deleted successfully!'
);
};
export const fillGlossaryTermDetails = async (
page: Page,
term: GlossaryTermData,
validateCreateForm = true
) => {
await page.click('[data-testid="add-new-tag-button-header"]');
await page.waitForSelector('[role="dialog"].edit-glossary-modal');
await expect(
page.locator('[role="dialog"].edit-glossary-modal')
).toBeVisible();
await expect(page.locator('.ant-modal-title')).toContainText(
'Add Glossary Term'
);
// Validation should work
await page.click('[data-testid="save-glossary-term"]');
if (validateCreateForm) {
await validateForm(page);
}
await expect(page.locator('[data-testid="name"]')).toBeVisible();
await page.locator('[data-testid="name"]').fill(term.name);
await expect(page.locator(descriptionBox)).toBeVisible();
await page.locator(descriptionBox).fill(term.description);
const synonyms = (term.synonyms ?? '').split(',');
await expect(page.locator('[data-testid="synonyms"]')).toBeVisible();
for (const synonym of synonyms) {
if (synonym === '') {
continue;
}
await page
.locator('[data-testid="synonyms"] input[type="search"]')
.fill(`${synonym}`);
await page
.locator('[data-testid="synonyms"] input[type="search"]')
.press('Enter');
}
await expect(
page.locator('[data-testid="form-item-alert"]')
).not.toBeVisible();
if (term.mutuallyExclusive) {
await page.click('[data-testid="mutually-exclusive-button"]');
await expect(page.locator('[data-testid="form-item-alert"]')).toBeVisible();
}
await expect(page.locator('[data-testid="add-reference"]')).toBeVisible();
await page.click('[data-testid="add-reference"]');
await expect(page.locator('#name-0')).toBeVisible();
await page.locator('#name-0').fill('test');
await expect(page.locator('#url-0')).toBeVisible();
await page.locator('#url-0').fill('https://test.com');
if (term.icon) {
await page.locator('[data-testid="icon-url"]').fill(term.icon);
}
if (term.color) {
await page.locator('[data-testid="color-color-input"]').fill(term.color);
}
if (!isUndefined(term.owners)) {
await addMultiOwner({
page,
ownerNames: term.owners.map((owner) => owner.name),
activatorBtnDataTestId: 'add-owner',
resultTestId: 'owner-container',
endpoint: EntityTypeEndpoint.GlossaryTerm,
isSelectableInsideForm: true,
type: 'Users',
});
}
};
const validateGlossaryTermTask = async (page: Page, term: GlossaryTermData) => {
await page.click('[data-testid="activity_feed"]');
const taskFeeds = page.waitForResponse(TASK_OPEN_FETCH_LINK);
await page
.getByTestId('global-setting-left-panel')
.getByText('Tasks')
.click();
await taskFeeds;
const taskFeedCards = page.locator('[data-testid="task-feed-card"]');
// Filter to find the specific card that contains the text
const cardWithText = taskFeedCards.filter({
has: page.locator('[data-testid="entity-link"]', {
hasText: term.name,
}),
});
await expect(cardWithText).toHaveCount(1);
};
export const approveGlossaryTermTask = async (
page: Page,
term: GlossaryTermData
) => {
await validateGlossaryTermTask(page, term);
const taskResolve = page.waitForResponse('/api/v1/feed/tasks/*/resolve');
await page.getByRole('button', { name: 'Approve' }).click();
await taskResolve;
// Display toast notification
await expect(page.locator('.Toastify__toast-body')).toHaveText(
/Task resolved successfully/
);
};
export const validateGlossaryTerm = async (
page: Page,
term: GlossaryTermData,
status: 'Draft' | 'Approved'
) => {
// eslint-disable-next-line no-useless-escape
const escapedFqn = term.fullyQualifiedName.replace(/\"/g, '\\"');
const termSelector = `[data-row-key="${escapedFqn}"]`;
const statusSelector = `[data-testid="${escapedFqn}-status"]`;
await expect(page.locator(termSelector)).toContainText(term.name);
await expect(page.locator(statusSelector)).toContainText(status);
if (status === 'Draft') {
await validateGlossaryTermTask(page, term);
await page.click('[data-testid="terms"]');
}
};
export const createGlossaryTerm = async (
page: Page,
term: GlossaryTermData,
status: 'Draft' | 'Approved',
validateCreateForm = true
) => {
await fillGlossaryTermDetails(page, term, validateCreateForm);
const glossaryTermResponse = page.waitForResponse('/api/v1/glossaryTerms');
await page.click('[data-testid="save-glossary-term"]');
await glossaryTermResponse;
await validateGlossaryTerm(page, term, status);
};
export const createGlossaryTerms = async (
page: Page,
glossary: GlossaryData
) => {
await selectActiveGlossary(page, glossary.name);
const termStatus = glossary.reviewers.length > 0 ? 'Draft' : 'Approved';
for (const term of glossary.terms) {
await createGlossaryTerm(page, term.data, termStatus, false);
}
};
export const checkAssetsCount = async (page: Page, assetsCount: number) => {
await expect(
page.locator('[data-testid="assets"] [data-testid="filter-count"]')
).toHaveText(assetsCount.toString());
};
export const addAssetToGlossaryTerm = async (
page: Page,
assets: (TableClass | TopicClass | DashboardClass)[],
hasExistingAssets = false
) => {
if (!hasExistingAssets) {
await page.waitForSelector(
'text=Adding a new Asset is easy, just give it a spin!'
);
}
await page.click('[data-testid="glossary-term-add-button-menu"]');
await page.getByRole('menuitem', { name: 'Assets' }).click();
await expect(page.locator('[role="dialog"].ant-modal')).toBeVisible();
await expect(
page.locator('[data-testid="asset-selection-modal"] .ant-modal-title')
).toContainText('Add Assets');
for (const asset of assets) {
const entityFqn = get(asset, 'entityResponseData.fullyQualifiedName');
const entityName = get(asset, 'entityResponseData.name');
const searchRes = page.waitForResponse('/api/v1/search/query*');
await page
.locator(
'[data-testid="asset-selection-modal"] [data-testid="searchbar"]'
)
.fill(entityName);
await searchRes;
await page.click(
`[data-testid="table-data-card_${entityFqn}"] input[type="checkbox"]`
);
}
await page.click('[data-testid="save-btn"]');
await checkAssetsCount(page, assets.length);
};
export const updateNameForGlossaryTerm = async (
page: Page,
name: string,
endPoint: string
) => {
await page.click('[data-testid="manage-button"]');
await page.click('[data-testid="rename-button"]');
await expect(page.locator('#name')).toBeVisible();
await page.fill('#name', name);
const updateNameResponsePromise = page.waitForResponse(
`/api/v1/${endPoint}/*`
);
await page.click('[data-testid="save-button"]');
const updateNameResponse = await updateNameResponsePromise;
const data = await updateNameResponse.json();
await expect(page.locator('[data-testid="entity-header-name"]')).toHaveText(
name
);
return data;
};
export const verifyGlossaryTermAssets = async (
page: Page,
glossary: GlossaryData,
glossaryTermData: GlossaryTermData,
assetsLength: number
) => {
await page.click('[data-testid="overview"]');
await redirectToHomePage(page);
await sidebarClick(page, SidebarItem.GLOSSARY);
await selectActiveGlossary(page, glossary.displayName);
await goToAssetsTab(page, glossaryTermData.displayName, assetsLength);
};
export const renameGlossaryTerm = async (
page: Page,
glossaryTerm: GlossaryTerm,
glossaryNewName: string
) => {
const data = await updateNameForGlossaryTerm(
page,
glossaryNewName,
EntityTypeEndpoint.GlossaryTerm
);
await glossaryTerm.rename(data.name, data.fullyQualifiedName);
};
export const dragAndDropTerm = async (
page: Page,
dragElement: string,
dropTarget: string
) => {
await page.getByRole('cell', { name: dragElement }).hover();
await page.mouse.down();
await page.getByRole('cell', { name: dropTarget }).hover();
await page.mouse.up();
};
export const confirmationDragAndDropGlossary = async (
page: Page,
dragElement: string,
dropElement: string,
isHeader = false
) => {
await expect(
page.locator('[data-testid="confirmation-modal"] .ant-modal-body')
).toContainText(
`Click on Confirm if youd like to move ${
isHeader
? `${dragElement} under ${dropElement} .`
: `${dragElement} term under ${dropElement} term.`
}`
);
const patchGlossaryTermResponse = page.waitForResponse(
'/api/v1/glossaryTerms/*'
);
await page.getByRole('button', { name: 'Confirm' }).click();
await patchGlossaryTermResponse;
};
export const changeTermHierarchyFromModal = async (
page: Page,
dragElement: string,
dropElement: string
) => {
await selectActiveGlossaryTerm(page, dragElement);
await page.getByTestId('manage-button').click();
await page.getByTestId('change-parent-button').click();
await page
.locator('[data-testid="change-parent-select"] > .ant-select-selector')
.click();
await page.getByTitle(dropElement).click();
const saveRes = page.waitForResponse('/api/v1/glossaryTerms/*');
await page.getByRole('button', { name: 'Submit' }).click();
await saveRes;
};
export const deleteGlossaryOrGlossaryTerm = async (
page: Page,
entityName: string,
isGlossaryTerm = false
) => {
await page.click('[data-testid="manage-button"]');
await page.click('[data-testid="delete-button"]');
await expect(page.locator('[role="dialog"]')).toBeVisible();
await expect(page.locator('[data-testid="modal-header"]')).toContainText(
entityName
);
await page.fill('[data-testid="confirmation-text-input"]', 'DELETE');
const endpoint = isGlossaryTerm
? '/api/v1/glossaryTerms/*'
: '/api/v1/glossaries/*';
const deleteRes = page.waitForResponse(endpoint);
await page.click('[data-testid="confirm-button"]');
await deleteRes;
if (isGlossaryTerm) {
await toastNotification(page, /"Glossary Term" deleted successfully!/);
} else {
await toastNotification(page, /"Glossary" deleted successfully!/);
}
};
export const addSynonyms = async (page: Page, synonyms: string[]) => {
await page.getByTestId('synonym-add-button').click();
await page.locator('.ant-select-selection-overflow').click();
for (const synonym of synonyms) {
await page.locator('#synonyms-select').fill(synonym);
await page.locator('#synonyms-select').press('Enter');
}
const saveRes = page.waitForResponse('/api/v1/glossaryTerms/*');
await page.getByTestId('save-synonym-btn').click();
await saveRes;
for (const synonym of synonyms) {
await expect(page.getByTestId(synonym)).toBeVisible();
}
};
export const addReferences = async (
page: Page,
references: { name: string; url: string }[]
) => {
await page.getByTestId('term-references-add-button').click();
await expect(
page.getByTestId('glossary-term-references-modal').getByText('References')
).toBeVisible();
for (const [index, value] of references.entries()) {
await page.locator(`#references_${index}_name`).fill(value.name);
await page.locator(`#references_${index}_endpoint`).fill(value.url);
if (index < references.length - 1) {
await page.getByTestId('add-references-button').click();
}
}
const saveRes = page.waitForResponse('/api/v1/glossaryTerms/*');
await page.getByTestId('save-btn').click();
await saveRes;
for (const reference of references) {
await expect(
page.getByTestId(`reference-link-${reference.name}`)
).toBeVisible();
}
};
export const addRelatedTerms = async (
page: Page,
relatedTerms: GlossaryTerm[]
) => {
await page.getByTestId('related-term-add-button').click();
for (const term of relatedTerms) {
const entityName = get(term, 'responseData.name');
const entityFqn = get(term, 'responseData.fullyQualifiedName');
await page.locator('#tagsForm_tags').fill(entityName);
await page.getByTestId(`tag-${entityFqn}`).click();
}
const saveRes = page.waitForResponse('/api/v1/glossaryTerms/*');
await page.getByTestId('saveAssociatedTag').click();
await saveRes;
for (const term of relatedTerms) {
const entityName = get(term, 'responseData.displayName');
await expect(page.getByTestId(entityName)).toBeVisible();
}
};
export const assignTagToGlossaryTerm = async (
page: Page,
tag: string,
action: 'Add' | 'Edit' = 'Add',
parentTestId = 'entity-right-panel'
) => {
await page
.getByTestId(parentTestId)
.getByTestId('tags-container')
.getByTestId(action === 'Add' ? 'add-tag' : 'edit-button')
.click();
const searchTags = page.waitForResponse(
`/api/v1/search/query?q=*${encodeURIComponent(tag)}*`
);
await page.locator('#tagsForm_tags').fill(tag);
await searchTags;
await page.getByTestId(`tag-${tag}`).click();
await expect(page.getByTestId('saveAssociatedTag')).toBeEnabled();
await page.getByTestId('saveAssociatedTag').click();
await expect(page.getByRole('heading')).toContainText(
'Would you like to proceed with updating the tags?'
);
const validateRes = page.waitForResponse('/api/v1/glossaryTerms/*');
await page.getByRole('button', { name: 'Yes, confirm' }).click();
await validateRes;
await expect(
page
.getByTestId(parentTestId)
.getByTestId('tags-container')
.getByTestId(`tag-${tag}`)
).toBeVisible();
};
export const createDescriptionTaskForGlossary = async (
page: Page,
value: TaskDetails,
entity: Glossary | GlossaryTerm,
isGlossary = true,
addDescription = true
) => {
const entityType = isGlossary ? 'glossary' : 'glossaryTerm';
const entityName = get(entity, 'responseData.displayName');
expect(await page.locator('#title').inputValue()).toBe(
`${
addDescription ? 'Update' : 'Request'
} description for ${entityType} ${entityName}`
);
if (isUndefined(value.assignee)) {
expect(
await page
.locator('[data-testid="select-assignee"] > .ant-select-selector')
.innerText()
).toBe(value.assignee);
expect(
await page
.locator('[data-testid="select-assignee"] > .ant-select-selector input')
.isDisabled()
);
} else {
const assigneeField = page.locator(
'[data-testid="select-assignee"] > .ant-select-selector #assignees'
);
await assigneeField.click();
const userSearchResponse = page.waitForResponse(
`/api/v1/search/suggest?q=${value.assignee}&index=user_search_index%2Cteam_search_index`
);
await assigneeField.fill(value.assignee);
await userSearchResponse;
// select value from dropdown
const dropdownValue = page.getByTestId(value.assignee);
await dropdownValue.hover();
await dropdownValue.click();
await clickOutside(page);
}
if (addDescription) {
await page
.locator(descriptionBox)
.fill(value.description ?? 'Updated description');
}
await page.click('button[type="submit"]');
await toastNotification(page, /Task created successfully./);
};
export const createTagTaskForGlossary = async (
page: Page,
value: TaskDetails,
entity: Glossary | GlossaryTerm,
isGlossary = true,
addTag = true
) => {
const entityType = isGlossary ? 'glossary' : 'glossaryTerm';
const entityName = get(entity, 'responseData.displayName');
expect(await page.locator('#title').inputValue()).toBe(
`Request tags for ${entityType} ${entityName}`
);
if (isUndefined(value.assignee)) {
expect(
await page
.locator('[data-testid="select-assignee"] > .ant-select-selector')
.innerText()
).toBe(value.assignee);
expect(
await page
.locator('[data-testid="select-assignee"] > .ant-select-selector input')
.isDisabled()
);
} else {
// select assignee
const assigneeField = page.locator(
'[data-testid="select-assignee"] > .ant-select-selector #assignees'
);
await assigneeField.click();
const userSearchResponse = page.waitForResponse(
`/api/v1/search/suggest?q=${value.assignee}&index=user_search_index%2Cteam_search_index`
);
await assigneeField.fill(value.assignee);
await userSearchResponse;
// select value from dropdown
const dropdownValue = page.getByTestId(value.assignee);
await dropdownValue.hover();
await dropdownValue.click();
await clickOutside(page);
}
if (addTag) {
// select tags
const suggestTags = page.locator(
'[data-testid="tag-selector"] > .ant-select-selector .ant-select-selection-search-input'
);
await suggestTags.click();
const querySearchResponse = page.waitForResponse(
`/api/v1/search/query?q=*${value.tag}*&index=tag_search_index&*`
);
await suggestTags.fill(value.tag ?? '');
await querySearchResponse;
// select value from dropdown
const dropdownValue = page.getByTestId(`tag-${value.tag ?? ''}`);
await dropdownValue.hover();
await dropdownValue.click();
await clickOutside(page);
}
await page.click('button[type="submit"]');
await toastNotification(page, /Task created successfully./);
};
export const approveTagsTask = async (
page: Page,
value: TaskDetails,
entity: Glossary | GlossaryTerm
) => {
await redirectToHomePage(page);
await sidebarClick(page, SidebarItem.GLOSSARY);
await selectActiveGlossary(page, entity.data.displayName);
await page.click('[data-testid="activity_feed"]');
const taskFeeds = page.waitForResponse(TASK_OPEN_FETCH_LINK);
await page
.getByTestId('global-setting-left-panel')
.getByText('Tasks')
.click();
await taskFeeds;
const taskResolve = page.waitForResponse('/api/v1/feed/tasks/*/resolve');
await page.click('.ant-btn-compact-first-item:has-text("Accept Suggestion")');
await taskResolve;
await redirectToHomePage(page);
await sidebarClick(page, SidebarItem.GLOSSARY);
await selectActiveGlossary(page, entity.data.displayName);
const tagVisibility = await page.isVisible(
`[data-testid="tag-${value.tag}"]`
);
await expect(tagVisibility).toBe(true);
};