mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-26 17:34:41 +00:00
playwright: migrate glossary version page spec (#16671)
This commit is contained in:
parent
57e51df05f
commit
282327cf27
@ -32,7 +32,8 @@ import {
|
|||||||
REVIEWER_DETAILS,
|
REVIEWER_DETAILS,
|
||||||
} from '../../constants/Version.constants';
|
} from '../../constants/Version.constants';
|
||||||
|
|
||||||
describe(
|
// migrated to playwright
|
||||||
|
describe.skip(
|
||||||
'Glossary and glossary term version pages should work properly',
|
'Glossary and glossary term version pages should work properly',
|
||||||
{ tags: 'Glossary' },
|
{ tags: 'Glossary' },
|
||||||
() => {
|
() => {
|
||||||
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
export const GLOSSARY_PATCH_PAYLOAD = [
|
||||||
|
{
|
||||||
|
op: 'add',
|
||||||
|
path: '/tags/0',
|
||||||
|
value: {
|
||||||
|
labelType: 'Manual',
|
||||||
|
state: 'Confirmed',
|
||||||
|
source: 'Classification',
|
||||||
|
tagFQN: 'PersonalData.SpecialCategory',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: 'add',
|
||||||
|
path: '/tags/1',
|
||||||
|
value: {
|
||||||
|
labelType: 'Manual',
|
||||||
|
state: 'Confirmed',
|
||||||
|
source: 'Classification',
|
||||||
|
tagFQN: 'PII.Sensitive',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: 'replace',
|
||||||
|
path: '/description',
|
||||||
|
value: 'Description for newly added glossary',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const GLOSSARY_TERM_PATCH_PAYLOAD = [
|
||||||
|
{
|
||||||
|
op: 'add',
|
||||||
|
path: '/synonyms/0',
|
||||||
|
value: 'test-synonym',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: 'add',
|
||||||
|
path: '/references/0',
|
||||||
|
value: {
|
||||||
|
name: 'reference1',
|
||||||
|
endpoint: 'https://example.com',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: 'add',
|
||||||
|
path: '/tags/0',
|
||||||
|
value: {
|
||||||
|
labelType: 'Manual',
|
||||||
|
state: 'Confirmed',
|
||||||
|
source: 'Classification',
|
||||||
|
tagFQN: 'PersonalData.SpecialCategory',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: 'add',
|
||||||
|
path: '/tags/1',
|
||||||
|
value: {
|
||||||
|
labelType: 'Manual',
|
||||||
|
state: 'Confirmed',
|
||||||
|
source: 'Classification',
|
||||||
|
tagFQN: 'PII.Sensitive',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: 'replace',
|
||||||
|
path: '/description',
|
||||||
|
value: 'Description for newly added glossaryTerm',
|
||||||
|
},
|
||||||
|
];
|
@ -24,6 +24,7 @@ import { TableClass } from '../../support/entity/TableClass';
|
|||||||
import { TopicClass } from '../../support/entity/TopicClass';
|
import { TopicClass } from '../../support/entity/TopicClass';
|
||||||
import {
|
import {
|
||||||
createNewPage,
|
createNewPage,
|
||||||
|
getApiContext,
|
||||||
getAuthContext,
|
getAuthContext,
|
||||||
getToken,
|
getToken,
|
||||||
redirectToHomePage,
|
redirectToHomePage,
|
||||||
@ -133,8 +134,7 @@ entities.forEach((EntityClass) => {
|
|||||||
// increase timeout as it using single test for multiple steps
|
// increase timeout as it using single test for multiple steps
|
||||||
test.slow(true);
|
test.slow(true);
|
||||||
|
|
||||||
const token = await getToken(page);
|
const { apiContext, afterAction } = await getApiContext(page);
|
||||||
const apiContext = await getAuthContext(token);
|
|
||||||
await entity.prepareCustomProperty(apiContext);
|
await entity.prepareCustomProperty(apiContext);
|
||||||
|
|
||||||
await test.step(`Set ${titleText} Custom Property`, async () => {
|
await test.step(`Set ${titleText} Custom Property`, async () => {
|
||||||
@ -158,6 +158,7 @@ entities.forEach((EntityClass) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await entity.cleanupCustomProperty(apiContext);
|
await entity.cleanupCustomProperty(apiContext);
|
||||||
|
await afterAction();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* 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 test, { expect } from '@playwright/test';
|
||||||
|
import { GLOSSARY_PATCH_PAYLOAD } from '../../constant/version';
|
||||||
|
import { EntityTypeEndpoint } from '../../support/entity/Entity.interface';
|
||||||
|
import { Glossary } from '../../support/glossary/Glossary';
|
||||||
|
import { UserClass } from '../../support/user/UserClass';
|
||||||
|
import {
|
||||||
|
createNewPage,
|
||||||
|
getApiContext,
|
||||||
|
redirectToHomePage,
|
||||||
|
} from '../../utils/common';
|
||||||
|
import { addOwner } from '../../utils/entity';
|
||||||
|
import { addMultiOwner, setupGlossaryAndTerms } from '../../utils/glossary';
|
||||||
|
|
||||||
|
// use the admin user to login
|
||||||
|
test.use({ storageState: 'playwright/.auth/admin.json' });
|
||||||
|
|
||||||
|
const user = new UserClass();
|
||||||
|
const reviewer = new UserClass();
|
||||||
|
|
||||||
|
test.beforeAll(async ({ browser }) => {
|
||||||
|
const { afterAction, apiContext } = await createNewPage(browser);
|
||||||
|
await user.create(apiContext);
|
||||||
|
await reviewer.create(apiContext);
|
||||||
|
await afterAction();
|
||||||
|
});
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await redirectToHomePage(page);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Glossary', async ({ page }) => {
|
||||||
|
const glossary = new Glossary();
|
||||||
|
const { afterAction, apiContext } = await getApiContext(page);
|
||||||
|
await glossary.create(apiContext);
|
||||||
|
await glossary.patch(apiContext, GLOSSARY_PATCH_PAYLOAD);
|
||||||
|
|
||||||
|
await test.step('Version changes', async () => {
|
||||||
|
await glossary.visitPage(page);
|
||||||
|
|
||||||
|
await page.click('[data-testid="version-button"]');
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByTestId('asset-description-container')
|
||||||
|
.getByTestId('markdown-parser')
|
||||||
|
.locator('span')
|
||||||
|
.filter({ hasText: 'Description' })
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator(
|
||||||
|
'.diff-added [data-testid="tag-PersonalData.SpecialCategory"]'
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator('.diff-added [data-testid="tag-PII.Sensitive"]')
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Should display the owner & reviewer changes', async () => {
|
||||||
|
await glossary.visitPage(page);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('version-button')).toHaveText(/0.2/);
|
||||||
|
|
||||||
|
await addOwner(
|
||||||
|
page,
|
||||||
|
user.getUserName(),
|
||||||
|
'Users',
|
||||||
|
EntityTypeEndpoint.Glossary,
|
||||||
|
'glossary-right-panel-owner-link'
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.reload();
|
||||||
|
const versionPageResponse = page.waitForResponse(
|
||||||
|
`/api/v1/glossaries/${glossary.responseData.id}/versions/0.2`
|
||||||
|
);
|
||||||
|
await page.click('[data-testid="version-button"]');
|
||||||
|
await versionPageResponse;
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator(
|
||||||
|
'[data-testid="glossary-right-panel-owner-link"] [data-testid="diff-added"]'
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await page.click('[data-testid="version-button"]');
|
||||||
|
await versionPageResponse;
|
||||||
|
|
||||||
|
await addMultiOwner({
|
||||||
|
page,
|
||||||
|
ownerNames: [reviewer.getUserName()],
|
||||||
|
activatorBtnDataTestId: 'Add',
|
||||||
|
resultTestId: 'glossary-reviewer-name',
|
||||||
|
endpoint: EntityTypeEndpoint.Glossary,
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.reload();
|
||||||
|
await page.click('[data-testid="version-button"]');
|
||||||
|
await versionPageResponse;
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator(
|
||||||
|
'[data-testid="glossary-reviewer"] [data-testid="diff-added"]'
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
await glossary.delete(apiContext);
|
||||||
|
await afterAction();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('GlossaryTerm', async ({ page }) => {
|
||||||
|
const { term1, term2, cleanup } = await setupGlossaryAndTerms(page);
|
||||||
|
|
||||||
|
await test.step('Version changes', async () => {
|
||||||
|
await term2.visitPage(page);
|
||||||
|
|
||||||
|
await page.click('[data-testid="version-button"]');
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByTestId('asset-description-container')
|
||||||
|
.getByTestId('markdown-parser')
|
||||||
|
.locator('span')
|
||||||
|
.filter({ hasText: 'Description' })
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator(
|
||||||
|
'.diff-added [data-testid="tag-PersonalData.SpecialCategory"]'
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator('.diff-added [data-testid="tag-PII.Sensitive"]')
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator('[data-testid="test-synonym"].diff-added')
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator(`[data-testid="${term1.data.displayName}"].diff-added`)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator('.diff-added [data-testid="reference-link-reference1"]')
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Should display the owner & reviewer changes', async () => {
|
||||||
|
await term2.visitPage(page);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('version-button')).toHaveText(/0.2/);
|
||||||
|
|
||||||
|
await addOwner(
|
||||||
|
page,
|
||||||
|
user.getUserName(),
|
||||||
|
'Users',
|
||||||
|
EntityTypeEndpoint.GlossaryTerm,
|
||||||
|
'glossary-right-panel-owner-link'
|
||||||
|
);
|
||||||
|
await page.reload();
|
||||||
|
const versionPageResponse = page.waitForResponse(
|
||||||
|
`/api/v1/glossaryTerms/${term2.responseData.id}/versions/0.2`
|
||||||
|
);
|
||||||
|
await page.click('[data-testid="version-button"]');
|
||||||
|
await versionPageResponse;
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator(
|
||||||
|
'[data-testid="glossary-right-panel-owner-link"] [data-testid="diff-added"]'
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await page.click('[data-testid="version-button"]');
|
||||||
|
await versionPageResponse;
|
||||||
|
|
||||||
|
await addMultiOwner({
|
||||||
|
page,
|
||||||
|
ownerNames: [reviewer.getUserName()],
|
||||||
|
activatorBtnDataTestId: 'Add',
|
||||||
|
resultTestId: 'glossary-reviewer-name',
|
||||||
|
endpoint: EntityTypeEndpoint.GlossaryTerm,
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.reload();
|
||||||
|
await page.click('[data-testid="version-button"]');
|
||||||
|
await versionPageResponse;
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator(
|
||||||
|
'[data-testid="glossary-reviewer"] [data-testid="diff-added"]'
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
await cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
test.afterAll(async ({ browser }) => {
|
||||||
|
const { afterAction, apiContext } = await createNewPage(browser);
|
||||||
|
|
||||||
|
await user.delete(apiContext);
|
||||||
|
await reviewer.delete(apiContext);
|
||||||
|
await afterAction();
|
||||||
|
});
|
@ -13,8 +13,8 @@
|
|||||||
import { APIRequestContext, Page } from '@playwright/test';
|
import { APIRequestContext, Page } from '@playwright/test';
|
||||||
import { CustomPropertySupportedEntityList } from '../../constant/customProperty';
|
import { CustomPropertySupportedEntityList } from '../../constant/customProperty';
|
||||||
import {
|
import {
|
||||||
CustomProperty,
|
|
||||||
createCustomPropertyForEntity,
|
createCustomPropertyForEntity,
|
||||||
|
CustomProperty,
|
||||||
setValueForProperty,
|
setValueForProperty,
|
||||||
validateValueForProperty,
|
validateValueForProperty,
|
||||||
} from '../../utils/customProperty';
|
} from '../../utils/customProperty';
|
||||||
@ -37,15 +37,15 @@ import {
|
|||||||
replyAnnouncement,
|
replyAnnouncement,
|
||||||
softDeleteEntity,
|
softDeleteEntity,
|
||||||
unFollowEntity,
|
unFollowEntity,
|
||||||
upVote,
|
|
||||||
updateDescription,
|
updateDescription,
|
||||||
updateDisplayNameForEntity,
|
updateDisplayNameForEntity,
|
||||||
updateOwner,
|
updateOwner,
|
||||||
|
upVote,
|
||||||
validateFollowedEntityToWidget,
|
validateFollowedEntityToWidget,
|
||||||
} from '../../utils/entity';
|
} from '../../utils/entity';
|
||||||
import { Domain } from '../domain/Domain';
|
import { Domain } from '../domain/Domain';
|
||||||
import { GlossaryTerm } from '../glossary/GlossaryTerm';
|
import { GlossaryTerm } from '../glossary/GlossaryTerm';
|
||||||
import { ENTITY_PATH, EntityTypeEndpoint } from './Entity.interface';
|
import { EntityTypeEndpoint, ENTITY_PATH } from './Entity.interface';
|
||||||
|
|
||||||
export class EntityClass {
|
export class EntityClass {
|
||||||
type: string;
|
type: string;
|
||||||
@ -123,7 +123,7 @@ export class EntityClass {
|
|||||||
) {
|
) {
|
||||||
await addOwner(page, owner1, type, this.endpoint, 'data-assets-header');
|
await addOwner(page, owner1, type, this.endpoint, 'data-assets-header');
|
||||||
await updateOwner(page, owner2, type, this.endpoint, 'data-assets-header');
|
await updateOwner(page, owner2, type, this.endpoint, 'data-assets-header');
|
||||||
await removeOwner(page, this.endpoint, 'data-assets-header');
|
await removeOwner(page, this.endpoint, owner2, 'data-assets-header');
|
||||||
}
|
}
|
||||||
|
|
||||||
async tier(page: Page, tier1: string, tier2: string) {
|
async tier(page: Page, tier1: string, tier2: string) {
|
||||||
|
@ -10,8 +10,9 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { APIRequestContext } from '@playwright/test';
|
import { APIRequestContext, expect, Page } from '@playwright/test';
|
||||||
import { uuid } from '../../utils/common';
|
import { uuid } from '../../utils/common';
|
||||||
|
import { visitGlossaryPage } from '../../utils/glossary';
|
||||||
import { getRandomFirstName } from '../../utils/user';
|
import { getRandomFirstName } from '../../utils/user';
|
||||||
|
|
||||||
type ResponseDataType = {
|
type ResponseDataType = {
|
||||||
@ -43,6 +44,14 @@ export class Glossary {
|
|||||||
this.data.name = name ?? this.data.name;
|
this.data.name = name ?? this.data.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async visitPage(page: Page) {
|
||||||
|
await visitGlossaryPage(page, this.data.displayName);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('entity-header-display-name')).toHaveText(
|
||||||
|
this.data.displayName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async create(apiContext: APIRequestContext) {
|
async create(apiContext: APIRequestContext) {
|
||||||
const response = await apiContext.post('/api/v1/glossaries', {
|
const response = await apiContext.post('/api/v1/glossaries', {
|
||||||
data: this.data,
|
data: this.data,
|
||||||
@ -53,6 +62,22 @@ export class Glossary {
|
|||||||
return await response.json();
|
return await response.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async patch(apiContext: APIRequestContext, data: Record<string, unknown>[]) {
|
||||||
|
const response = await apiContext.patch(
|
||||||
|
`/api/v1/glossaries/${this.responseData.id}`,
|
||||||
|
{
|
||||||
|
data,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json-patch+json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.responseData = await response.json();
|
||||||
|
|
||||||
|
return await response.json();
|
||||||
|
}
|
||||||
|
|
||||||
get() {
|
get() {
|
||||||
return this.responseData;
|
return this.responseData;
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,9 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { APIRequestContext } from '@playwright/test';
|
import { APIRequestContext, expect, Page } from '@playwright/test';
|
||||||
import { uuid } from '../../utils/common';
|
import { uuid } from '../../utils/common';
|
||||||
|
import { visitGlossaryPage } from '../../utils/glossary';
|
||||||
import { getRandomLastName } from '../../utils/user';
|
import { getRandomLastName } from '../../utils/user';
|
||||||
|
|
||||||
type ResponseDataType = {
|
type ResponseDataType = {
|
||||||
@ -23,7 +24,7 @@ type ResponseDataType = {
|
|||||||
synonyms: unknown[];
|
synonyms: unknown[];
|
||||||
mutuallyExclusive: boolean;
|
mutuallyExclusive: boolean;
|
||||||
tags: unknown[];
|
tags: unknown[];
|
||||||
glossary: Record<string, unknown>;
|
glossary: Record<string, string>;
|
||||||
id: string;
|
id: string;
|
||||||
fullyQualifiedName: string;
|
fullyQualifiedName: string;
|
||||||
};
|
};
|
||||||
@ -45,6 +46,32 @@ export class GlossaryTerm {
|
|||||||
this.data.name = name ?? this.data.name;
|
this.data.name = name ?? this.data.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async visitPage(page: Page) {
|
||||||
|
await visitGlossaryPage(page, this.responseData.glossary.displayName);
|
||||||
|
const expandCollapseButtonText = await page
|
||||||
|
.locator('[data-testid="expand-collapse-all-button"]')
|
||||||
|
.textContent();
|
||||||
|
const isExpanded = expandCollapseButtonText?.includes('Expand All');
|
||||||
|
if (isExpanded) {
|
||||||
|
const glossaryTermListResponse = page.waitForResponse(
|
||||||
|
`/api/v1/glossaryTerms?*glossary=${this.responseData.glossary.id}*`
|
||||||
|
);
|
||||||
|
await page.click('[data-testid="expand-collapse-all-button"]');
|
||||||
|
await glossaryTermListResponse;
|
||||||
|
}
|
||||||
|
const glossaryTermResponse = page.waitForResponse(
|
||||||
|
`/api/v1/glossaryTerms/name/${encodeURIComponent(
|
||||||
|
this.responseData.fullyQualifiedName
|
||||||
|
)}?*`
|
||||||
|
);
|
||||||
|
await page.getByTestId(this.data.displayName).click();
|
||||||
|
await glossaryTermResponse;
|
||||||
|
|
||||||
|
await expect(page.getByTestId('entity-header-display-name')).toHaveText(
|
||||||
|
this.data.displayName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async create(apiContext: APIRequestContext) {
|
async create(apiContext: APIRequestContext) {
|
||||||
const response = await apiContext.post('/api/v1/glossaryTerms', {
|
const response = await apiContext.post('/api/v1/glossaryTerms', {
|
||||||
data: this.data,
|
data: this.data,
|
||||||
@ -55,6 +82,22 @@ export class GlossaryTerm {
|
|||||||
return await response.json();
|
return await response.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async patch(apiContext: APIRequestContext, data: Record<string, unknown>[]) {
|
||||||
|
const response = await apiContext.patch(
|
||||||
|
`/api/v1/glossaryTerms/${this.responseData.id}`,
|
||||||
|
{
|
||||||
|
data,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json-patch+json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.responseData = await response.json();
|
||||||
|
|
||||||
|
return await response.json();
|
||||||
|
}
|
||||||
|
|
||||||
get() {
|
get() {
|
||||||
return this.responseData;
|
return this.responseData;
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,7 @@ export const updateOwner = async (
|
|||||||
export const removeOwner = async (
|
export const removeOwner = async (
|
||||||
page: Page,
|
page: Page,
|
||||||
endpoint: EntityTypeEndpoint,
|
endpoint: EntityTypeEndpoint,
|
||||||
|
ownerName: string,
|
||||||
dataTestId?: string
|
dataTestId?: string
|
||||||
) => {
|
) => {
|
||||||
await page.getByTestId('edit-owner').click();
|
await page.getByTestId('edit-owner').click();
|
||||||
@ -120,8 +121,8 @@ export const removeOwner = async (
|
|||||||
await page.getByTestId('remove-owner').locator('svg').click();
|
await page.getByTestId('remove-owner').locator('svg').click();
|
||||||
await patchRequest;
|
await patchRequest;
|
||||||
|
|
||||||
await expect(page.getByTestId(dataTestId ?? 'owner-link')).toContainText(
|
await expect(page.getByTestId(dataTestId ?? 'owner-link')).not.toContainText(
|
||||||
'No Owner'
|
ownerName
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* 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 { SidebarItem } from '../constant/sidebar';
|
||||||
|
import { GLOSSARY_TERM_PATCH_PAYLOAD } from '../constant/version';
|
||||||
|
import { EntityTypeEndpoint } from '../support/entity/Entity.interface';
|
||||||
|
import { Glossary } from '../support/glossary/Glossary';
|
||||||
|
import { GlossaryTerm } from '../support/glossary/GlossaryTerm';
|
||||||
|
import { getApiContext, redirectToHomePage } from './common';
|
||||||
|
import { sidebarClick } from './sidebar';
|
||||||
|
|
||||||
|
export const visitGlossaryPage = async (page: Page, glossaryName: string) => {
|
||||||
|
await redirectToHomePage(page);
|
||||||
|
const glossaryResponse = page.waitForResponse('/api/v1/glossaries?fields=*');
|
||||||
|
await sidebarClick(page, SidebarItem.GLOSSARY);
|
||||||
|
await glossaryResponse;
|
||||||
|
await page.getByRole('menuitem', { name: glossaryName }).click();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addMultiOwner = async (data: {
|
||||||
|
page: Page;
|
||||||
|
ownerNames: string | string[];
|
||||||
|
activatorBtnDataTestId: string;
|
||||||
|
endpoint: EntityTypeEndpoint;
|
||||||
|
resultTestId?: string;
|
||||||
|
isSelectableInsideForm?: boolean;
|
||||||
|
}) => {
|
||||||
|
const {
|
||||||
|
page,
|
||||||
|
ownerNames,
|
||||||
|
activatorBtnDataTestId,
|
||||||
|
resultTestId = 'owner-link',
|
||||||
|
isSelectableInsideForm = false,
|
||||||
|
endpoint,
|
||||||
|
} = data;
|
||||||
|
const isMultipleOwners = Array.isArray(ownerNames);
|
||||||
|
const owners = isMultipleOwners ? ownerNames : [ownerNames];
|
||||||
|
|
||||||
|
const getUsers = page.waitForResponse('/api/v1/users?*isBot=false*');
|
||||||
|
|
||||||
|
await page.click(`[data-testid="${activatorBtnDataTestId}"]`);
|
||||||
|
|
||||||
|
expect(page.locator("[data-testid='select-owner-tabs']")).toBeVisible();
|
||||||
|
|
||||||
|
await page.click('.ant-tabs [id*=tab-users]');
|
||||||
|
await getUsers;
|
||||||
|
await page.waitForSelector('[data-testid="loader"]', { state: 'detached' });
|
||||||
|
|
||||||
|
if (isMultipleOwners) {
|
||||||
|
await page.click('[data-testid="clear-all-button"]');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const ownerName of owners) {
|
||||||
|
const searchOwner = page.waitForResponse(
|
||||||
|
'api/v1/search/query?q=*&index=user_search_index*'
|
||||||
|
);
|
||||||
|
await page.locator('[data-testid="owner-select-users-search-bar"]').clear();
|
||||||
|
await page.fill('[data-testid="owner-select-users-search-bar"]', ownerName);
|
||||||
|
await searchOwner;
|
||||||
|
await page.waitForSelector('[data-testid="loader"]', { state: 'detached' });
|
||||||
|
await page.getByRole('listitem', { name: ownerName }).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
const patchResponse = page.waitForResponse(`/api/v1/${endpoint}/*`);
|
||||||
|
if (isMultipleOwners) {
|
||||||
|
await page.click('[data-testid="selectable-list-update-btn"]');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isSelectableInsideForm) {
|
||||||
|
await patchResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const name of owners) {
|
||||||
|
await expect(page.locator(`[data-testid="${resultTestId}"]`)).toContainText(
|
||||||
|
name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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.data.name);
|
||||||
|
const term2 = new GlossaryTerm(glossary.data.name);
|
||||||
|
|
||||||
|
// 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 };
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user