diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts index 07871962aa4..b8e4f98eb7d 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts @@ -48,6 +48,7 @@ import { confirmationDragAndDropGlossary, createDescriptionTaskForGlossary, createGlossary, + createGlossaryTerm, createGlossaryTerms, createTagTaskForGlossary, deleteGlossaryOrGlossaryTerm, @@ -1197,4 +1198,89 @@ test.describe('Glossary tests', () => { await afterAction(); } }); + + test('should check for glossary term pagination', async ({ browser }) => { + test.slow(true); + + const { page, afterAction, apiContext } = await performAdminLogin(browser); + const glossaries = []; + for (let i = 0; i < 60; i++) { + const glossary = new Glossary(`PW_GLOSSARY_TEST_${i + 1}`); + await glossary.create(apiContext); + glossaries.push(glossary); + } + + try { + await redirectToHomePage(page); + const glossaryRes = page.waitForResponse('/api/v1/glossaries?*'); + await sidebarClick(page, SidebarItem.GLOSSARY); + await glossaryRes; + + const glossaryAfterRes = page.waitForResponse( + '/api/v1/glossaries?*after=*' + ); + await page + .getByTestId('glossary-left-panel-scroller') + .scrollIntoViewIfNeeded(); + + const res = await glossaryAfterRes; + const json = await res.json(); + + const firstGlossaryName = json.data[0].displayName; + + await expect( + page.getByRole('menuitem', { name: firstGlossaryName }) + ).toBeVisible(); + + const lastGlossaryName = json.data[json.data.length - 1].displayName; + + await expect( + page.getByRole('menuitem', { name: lastGlossaryName }) + ).toBeVisible(); + } finally { + for (const glossary of glossaries) { + await glossary.delete(apiContext); + } + await afterAction(); + } + }); + + test('Add Glossary Term inside another Term', async ({ browser }) => { + const { page, afterAction, apiContext } = await performAdminLogin(browser); + const glossary1 = new Glossary(); + const glossaryTerm1 = new GlossaryTerm(glossary1); + const glossary2 = new Glossary(); + glossary2.data.terms = [new GlossaryTerm(glossary2)]; + + try { + await glossary1.create(apiContext); + await glossaryTerm1.create(apiContext); + await redirectToHomePage(page); + await sidebarClick(page, SidebarItem.GLOSSARY); + await selectActiveGlossary(page, glossary1.data.displayName); + await selectActiveGlossaryTerm(page, glossaryTerm1.data.displayName); + await page.getByTestId('terms').click(); + + await createGlossaryTerm( + page, + glossary2.data.terms[0].data, + 'Approved', + false, + true + ); + } finally { + await glossaryTerm1.delete(apiContext); + await glossary1.delete(apiContext); + await afterAction(); + } + }); + + test.afterAll(async ({ browser }) => { + const { afterAction, apiContext } = await performAdminLogin(browser); + await user1.delete(apiContext); + await user2.delete(apiContext); + await user3.create(apiContext); + await team.delete(apiContext); + await afterAction(); + }); }); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts index c06c7b2eddf..fe36cca5a15 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts @@ -392,12 +392,18 @@ export const deleteGlossary = async (page: Page, glossary: GlossaryData) => { export const fillGlossaryTermDetails = async ( page: Page, term: GlossaryTermData, - validateCreateForm = true + validateCreateForm = true, + isGlossaryTerm = false ) => { // Safety check to close potential glossary not found alert // Arrived due to parallel testing await closeFirstPopupAlert(page); - await page.click('[data-testid="add-new-tag-button-header"]'); + + if (isGlossaryTerm) { + await page.click('[data-testid="add-placeholder-button"]'); + } else { + await page.click('[data-testid="add-new-tag-button-header"]'); + } await page.waitForSelector('[role="dialog"].edit-glossary-modal'); @@ -590,28 +596,39 @@ export const updateGlossaryTermDataFromTree = async ( export const validateGlossaryTerm = async ( page: Page, term: GlossaryTermData, - status: 'Draft' | 'Approved' + status: 'Draft' | 'Approved', + isGlossaryTermPage = false ) => { // 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 (isGlossaryTermPage) { + await expect(page.getByTestId(term.name)).toBeVisible(); + } else { + await expect(page.locator(termSelector)).toContainText(term.name); + await expect(page.locator(statusSelector)).toContainText(status); + } }; export const createGlossaryTerm = async ( page: Page, term: GlossaryTermData, status: 'Draft' | 'Approved', - validateCreateForm = true + validateCreateForm = true, + isGlossaryTermPage = false ) => { - await fillGlossaryTermDetails(page, term, validateCreateForm); + await fillGlossaryTermDetails( + page, + term, + validateCreateForm, + isGlossaryTermPage + ); const glossaryTermResponse = page.waitForResponse('/api/v1/glossaryTerms'); await page.click('[data-testid="save-glossary-term"]'); await glossaryTermResponse; - await validateGlossaryTerm(page, term, status); + await validateGlossaryTerm(page, term, status, isGlossaryTermPage); }; export const createGlossaryTerms = async ( diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/useGlossary.store.ts b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/useGlossary.store.ts index 9b5c6f2afe4..90bcd4dc45c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/useGlossary.store.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/useGlossary.store.ts @@ -72,12 +72,28 @@ export const useGlossaryStore = create<{ } }, insertNewGlossaryTermToChildTerms: (glossary: GlossaryTerm) => { - const { glossaryChildTerms } = get(); + const { glossaryChildTerms, activeGlossary } = get(); - // Typically used to updated the glossary term list in the glossary page - set({ - glossaryChildTerms: findAndUpdateNested(glossaryChildTerms, glossary), - }); + const glossaryTerm = 'glossary' in activeGlossary; + + // If activeGlossary is Glossary term & User is adding term to the activeGlossary term + // we don't need to find in hierarchy + if ( + glossaryTerm && + activeGlossary.fullyQualifiedName === glossary.parent?.fullyQualifiedName + ) { + set({ + glossaryChildTerms: [ + ...glossaryChildTerms, + glossary, + ] as ModifiedGlossary[], + }); + } else { + // Typically used to updated the glossary term list in the glossary page + set({ + glossaryChildTerms: findAndUpdateNested(glossaryChildTerms, glossary), + }); + } }, setGlossaryChildTerms: (glossaryChildTerms: ModifiedGlossary[]) => { set({ glossaryChildTerms });