Harshit Shah fc50cce12a
Support default persona selection (#22592)
* Support default persona selection

* address comments and add styling changes

* fix failing tests

* fix failing tests

* update api calls

* fix failing tests
2025-07-29 14:20:36 +05:30

530 lines
16 KiB
TypeScript

/*
* Copyright 2025 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, test as base } from '@playwright/test';
import {
ECustomizedDataAssets,
ECustomizedGovernance,
} from '../../constant/customizeDetail';
import { GlobalSettingOptions } from '../../constant/settings';
import { SidebarItem } from '../../constant/sidebar';
import { EntityDataClass } from '../../support/entity/EntityDataClass';
import { EntityDataClassCreationConfig } from '../../support/entity/EntityDataClass.interface';
import { PersonaClass } from '../../support/persona/PersonaClass';
import { AdminClass } from '../../support/user/AdminClass';
import { UserClass } from '../../support/user/UserClass';
import { performAdminLogin } from '../../utils/admin';
import { redirectToHomePage, toastNotification } from '../../utils/common';
import {
getCustomizeDetailsDefaultTabs,
getCustomizeDetailsEntity,
} from '../../utils/customizeDetails';
import {
checkDefaultStateForNavigationTree,
validateLeftSidebarWithHiddenItems,
} from '../../utils/customizeNavigation';
import { settingClick } from '../../utils/sidebar';
const persona = new PersonaClass();
// Keeping it separate so that it won't affect other tests
const navigationPersona = new PersonaClass();
const adminUser = new AdminClass();
const user = new UserClass();
const creationConfig: EntityDataClassCreationConfig = {
table: true,
entityDetails: true,
topic: true,
dashboard: true,
mlModel: true,
pipeline: true,
dashboardDataModel: true,
apiCollection: true,
searchIndex: true,
container: true,
storedProcedure: true,
apiEndpoint: true,
database: true,
databaseSchema: true,
};
const test = base.extend<{
adminPage: Page;
userPage: Page;
}>({
adminPage: async ({ browser }, use) => {
const adminPage = await browser.newPage();
await adminUser.login(adminPage);
await use(adminPage);
await adminPage.close();
},
userPage: async ({ browser }, use) => {
const page = await browser.newPage();
await user.login(page);
await use(page);
await page.close();
},
});
test.beforeAll('Setup Customize tests', async ({ browser }) => {
const { apiContext, afterAction } = await performAdminLogin(browser);
await adminUser.create(apiContext);
await adminUser.setAdminRole(apiContext);
await user.create(apiContext);
await user.setAdminRole(apiContext);
await persona.create(apiContext);
await navigationPersona.create(apiContext);
// Assign persona to user to validate page changes
await user.patch({
apiContext,
patchData: [
{
op: 'add',
path: '/personas/0',
value: {
id: persona.responseData.id,
name: persona.responseData.name,
displayName: persona.responseData.displayName,
fullyQualifiedName: persona.responseData.fullyQualifiedName,
type: 'persona',
},
},
{
op: 'add',
path: '/personas/1',
value: {
id: navigationPersona.responseData.id,
name: navigationPersona.responseData.name,
displayName: navigationPersona.responseData.displayName,
fullyQualifiedName: navigationPersona.responseData.fullyQualifiedName,
type: 'persona',
},
},
{
op: 'add',
path: '/defaultPersona',
value: {
id: persona.responseData.id,
name: persona.responseData.name,
displayName: persona.responseData.displayName,
fullyQualifiedName: persona.responseData.fullyQualifiedName,
type: 'persona',
},
},
],
});
await afterAction();
});
test.afterAll('Cleanup Customize tests', async ({ browser }) => {
test.slow();
const { apiContext, afterAction } = await performAdminLogin(browser);
await adminUser.delete(apiContext);
await user.delete(apiContext);
await persona.delete(apiContext);
await navigationPersona.delete(apiContext);
await afterAction();
});
test.describe('Persona customize UI tab', async () => {
test.beforeEach(async ({ adminPage }) => {
await redirectToHomePage(adminPage);
// Navigate to persona page
await settingClick(adminPage, GlobalSettingOptions.PERSONA);
await adminPage.waitForLoadState('networkidle');
await adminPage.waitForSelector('[data-testid="loader"]', {
state: 'detached',
});
await adminPage.getByText(persona.responseData.displayName).click();
await adminPage.getByRole('tab', { name: 'Customize UI' }).click();
});
test('should show all the customize options', async ({ adminPage }) => {
await expect(adminPage.getByText('Navigation')).toBeVisible();
await expect(adminPage.getByText('Home Page')).toBeVisible();
await expect(adminPage.getByText('Governance')).toBeVisible();
await expect(adminPage.getByText('Data Assets')).toBeVisible();
});
test('should show all the data assets customize options', async ({
adminPage,
}) => {
await adminPage.getByText('Data Assets').click();
for (const type of Object.values(ECustomizedDataAssets)) {
await expect(adminPage.getByText(type, { exact: true })).toBeVisible();
}
});
test('should show all the governance customize options', async ({
adminPage,
}) => {
await adminPage.getByText('Governance').click();
for (const type of Object.values(ECustomizedGovernance)) {
await expect(adminPage.getByText(type, { exact: true })).toBeVisible();
}
});
test('Navigation check default state', async ({ adminPage }) => {
await adminPage.getByText('Navigation').click();
await checkDefaultStateForNavigationTree(adminPage);
});
test('customize navigation should work', async ({ adminPage, userPage }) => {
test.slow();
await adminPage.getByText('Navigation').click();
await test.step(
'hide navigation items and validate with persona',
async () => {
// Hide Explore
await adminPage
.getByTestId('page-layout-v1')
.getByText('Explore')
.getByRole('switch')
.click();
await expect(
adminPage
.getByTestId('page-layout-v1')
.getByText('Explore')
.getByRole('switch')
).not.toBeChecked();
// Hide Metrics
await adminPage
.getByTestId('page-layout-v1')
.getByText('Metrics')
.getByRole('switch')
.click();
await expect(
adminPage
.getByTestId('page-layout-v1')
.getByText('Metrics')
.getByRole('switch')
).not.toBeChecked();
await adminPage.getByTestId('save-button').click();
await toastNotification(
adminPage,
/^Page layout (created|updated) successfully\.$/
);
// Select navigation persona
await redirectToHomePage(userPage);
await userPage.reload();
await userPage.waitForLoadState('networkidle');
// Validate changes in navigation tree
await validateLeftSidebarWithHiddenItems(userPage, [
SidebarItem.EXPLORE,
SidebarItem.METRICS,
]);
}
);
await test.step(
'show navigation items and validate with persona',
async () => {
// Show Explore
await adminPage
.getByTestId('page-layout-v1')
.getByText('Explore')
.getByRole('switch')
.click();
await expect(
adminPage
.getByTestId('page-layout-v1')
.getByText('Explore')
.getByRole('switch')
).toBeChecked();
// Show Metrics
await adminPage
.getByTestId('page-layout-v1')
.getByText('Metrics')
.getByRole('switch')
.click();
await expect(
adminPage
.getByTestId('page-layout-v1')
.getByText('Metrics')
.getByRole('switch')
).toBeChecked();
// Hide Glossary
await adminPage
.getByTestId('page-layout-v1')
.getByText('Glossary')
.getByRole('switch')
.click();
await expect(
adminPage
.getByTestId('page-layout-v1')
.getByText('Glossary')
.getByRole('switch')
).not.toBeChecked();
// Hide Incident Manager
await adminPage
.getByTestId('page-layout-v1')
.getByText('Incident Manager')
.getByRole('switch')
.click();
await adminPage.getByTestId('save-button').click();
await toastNotification(
adminPage,
/^Page layout (created|updated) successfully\.$/
);
// Reload user page to validate changes
await userPage.reload();
await userPage.waitForLoadState('networkidle');
// Validate changes in navigation tree
await validateLeftSidebarWithHiddenItems(userPage, [
SidebarItem.GLOSSARY,
SidebarItem.INCIDENT_MANAGER,
]);
}
);
});
});
test.describe('Persona customization', () => {
test.beforeAll(async ({ browser }) => {
test.slow();
const { apiContext, afterAction } = await performAdminLogin(browser);
await EntityDataClass.preRequisitesForTests(apiContext, creationConfig);
await afterAction();
});
test.afterAll(async ({ browser }) => {
test.slow();
const { apiContext, afterAction } = await performAdminLogin(browser);
await EntityDataClass.postRequisitesForTests(apiContext, creationConfig);
await afterAction();
});
Object.values(ECustomizedDataAssets).forEach(async (type) => {
test(`${type} - customization should work`, async ({
adminPage,
userPage,
}) => {
test.slow();
await test.step(
`should show all the tabs & widget as default when no customization is done`,
async () => {
await settingClick(adminPage, GlobalSettingOptions.PERSONA);
await adminPage.waitForLoadState('networkidle');
await adminPage
.getByTestId(`persona-details-card-${persona.data.name}`)
.click();
await adminPage.getByRole('tab', { name: 'Customize UI' }).click();
await adminPage.waitForLoadState('networkidle');
await adminPage.getByText('Data Assets').click();
await adminPage.getByText(type, { exact: true }).click();
await adminPage.waitForSelector('[data-testid="loader"]', {
state: 'detached',
});
const expectedTabs = getCustomizeDetailsDefaultTabs(type);
const tabs = adminPage
.getByTestId('customize-tab-card')
.getByRole('button')
.filter({ hasNotText: 'Add Tab' });
await expect(tabs).toHaveCount(expectedTabs.length);
for (const tabName of expectedTabs) {
await expect(
adminPage
.getByTestId('customize-tab-card')
.getByTestId(`tab-${tabName}`)
).toBeVisible();
}
}
);
await test.step('apply customization', async () => {
expect(
adminPage.locator('#KnowledgePanel\\.Description')
).toBeVisible();
await adminPage
.locator('#KnowledgePanel\\.Description')
.getByTestId('remove-widget-button')
.click();
await adminPage.getByRole('button', { name: 'Add tab' }).click();
await adminPage
.getByRole('dialog')
.getByRole('button', { name: 'Add' })
.click();
await adminPage.getByTestId('add-widget-button').click();
await adminPage.getByTestId('Description-widget').click();
await adminPage
.getByTestId('add-widget-modal')
.getByTestId('add-widget-button')
.click();
await adminPage.getByTestId('save-button').click();
await toastNotification(
adminPage,
/^Page layout (created|updated) successfully\.$/
);
});
await test.step('Validate customization', async () => {
await redirectToHomePage(userPage);
const entity = getCustomizeDetailsEntity(type);
await entity.visitEntityPageWithCustomSearchBox(userPage);
await userPage.waitForLoadState('networkidle');
await userPage.waitForSelector('[data-testid="loader"]', {
state: 'detached',
});
expect(userPage.getByRole('tab', { name: 'New Tab' })).toBeVisible();
await userPage.getByRole('tab', { name: 'New Tab' }).click();
const visibleDescription = userPage
.getByTestId(/KnowledgePanel.Description-/)
.locator('visible=true');
await expect(visibleDescription).toBeVisible();
});
});
});
Object.values(ECustomizedGovernance).forEach(async (type) => {
test(`${type} - customization should work`, async ({
adminPage,
userPage,
}) => {
test.slow();
await test.step(
`should show all the tabs & widget as default when no customization is done`,
async () => {
await settingClick(adminPage, GlobalSettingOptions.PERSONA);
await adminPage.waitForLoadState('networkidle');
await adminPage
.getByTestId(`persona-details-card-${persona.data.name}`)
.click();
await adminPage.getByRole('tab', { name: 'Customize UI' }).click();
await adminPage.waitForLoadState('networkidle');
await adminPage.getByText('Governance').click();
await adminPage.getByText(type, { exact: true }).click();
await adminPage.waitForSelector('[data-testid="loader"]', {
state: 'detached',
});
const expectedTabs = getCustomizeDetailsDefaultTabs(type);
const tabs = adminPage
.getByTestId('customize-tab-card')
.getByRole('button')
.filter({ hasNotText: 'Add Tab' });
await expect(tabs).toHaveCount(expectedTabs.length);
for (const tabName of expectedTabs) {
await expect(
adminPage.getByTestId('customize-tab-card').getByRole('button', {
name: tabName,
})
).toBeVisible();
}
}
);
await test.step('apply customization', async () => {
expect(
adminPage.locator('#KnowledgePanel\\.Description')
).toBeVisible();
await adminPage
.locator('#KnowledgePanel\\.Description')
.getByTestId('remove-widget-button')
.click();
await adminPage.getByRole('button', { name: 'Add tab' }).click();
await adminPage
.getByRole('dialog')
.getByRole('button', { name: 'Add' })
.click();
await adminPage.getByTestId('add-widget-button').click();
await adminPage.getByTestId('Description-widget').click();
await adminPage
.getByTestId('add-widget-modal')
.getByTestId('add-widget-button')
.click();
await adminPage.getByTestId('save-button').click();
await toastNotification(
adminPage,
/^Page layout (created|updated) successfully\.$/
);
});
await test.step('Validate customization', async () => {
await redirectToHomePage(userPage);
const entity = getCustomizeDetailsEntity(type);
await entity.visitEntityPageWithCustomSearchBox(userPage);
await userPage.waitForLoadState('networkidle');
await userPage.waitForSelector('[data-testid="loader"]', {
state: 'detached',
});
expect(userPage.getByRole('tab', { name: 'New Tab' })).toBeVisible();
await userPage.getByRole('tab', { name: 'New Tab' }).click();
const visibleDescription = userPage
.getByTestId(/KnowledgePanel.Description-/)
.locator('visible=true');
await expect(visibleDescription).toBeVisible();
});
});
});
});