mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-10 16:25:37 +00:00
Playwright: E2E tests for landing page widgets (#23694)
* Playwright: E2E tests for landing page widgets * update tests * address comments and fix failing tests * fix failing tests * fix failing users.spec --------- Co-authored-by: Shailesh Parmar <shailesh.parmar.webdev@gmail.com>
This commit is contained in:
parent
ebfb98a022
commit
d22dd3cfad
@ -259,4 +259,43 @@ test.describe('Customize Landing Page Flow', () => {
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('Widget drag and drop reordering', async ({ adminPage }) => {
|
||||
test.slow(true);
|
||||
|
||||
await navigateToCustomizeLandingPage(adminPage, {
|
||||
personaName: persona.responseData.name,
|
||||
});
|
||||
|
||||
// Test dragging widgets to reorder them
|
||||
const widget1 = adminPage.locator('[data-testid="KnowledgePanel.MyData"]');
|
||||
const widget2 = adminPage.locator(
|
||||
'[data-testid="KnowledgePanel.Following"]'
|
||||
);
|
||||
|
||||
if ((await widget1.count()) > 0 && (await widget2.count()) > 0) {
|
||||
// Get initial positions
|
||||
const widget1Box = await widget1.boundingBox();
|
||||
const widget2Box = await widget2.boundingBox();
|
||||
|
||||
if (widget1Box && widget2Box) {
|
||||
// Test drag functionality (may not actually reorder in test environment)
|
||||
await widget1.hover();
|
||||
|
||||
await expect(widget1).toBeVisible();
|
||||
await expect(widget2).toBeVisible();
|
||||
|
||||
// Verify widgets remain functional after attempted drag
|
||||
await saveCustomizeLayoutPage(adminPage);
|
||||
await redirectToHomePage(adminPage);
|
||||
|
||||
await expect(
|
||||
adminPage.getByTestId('KnowledgePanel.MyData')
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
adminPage.getByTestId('KnowledgePanel.Following')
|
||||
).toBeVisible();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -11,8 +11,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { expect, Page, test as base } from '@playwright/test';
|
||||
import { SearchIndex } from '../../../src/enums/search.enum';
|
||||
import { KPI_DATA } from '../../constant/dataInsight';
|
||||
import { SidebarItem } from '../../constant/sidebar';
|
||||
import { DataProduct } from '../../support/domain/DataProduct';
|
||||
import { Domain } from '../../support/domain/Domain';
|
||||
import { EntityDataClass } from '../../support/entity/EntityDataClass';
|
||||
import { EntityDataClassCreationConfig } from '../../support/entity/EntityDataClass.interface';
|
||||
import { PersonaClass } from '../../support/persona/PersonaClass';
|
||||
import { UserClass } from '../../support/user/UserClass';
|
||||
import { performAdminLogin } from '../../utils/admin';
|
||||
@ -21,7 +26,13 @@ import {
|
||||
addAndVerifyWidget,
|
||||
removeAndVerifyWidget,
|
||||
setUserDefaultPersona,
|
||||
verifyWidgetEntityNavigation,
|
||||
verifyWidgetFooterViewMore,
|
||||
verifyWidgetHeaderNavigation,
|
||||
} from '../../utils/customizeLandingPage';
|
||||
import { addKpi, deleteKpiRequest } from '../../utils/dataInsight';
|
||||
import { followEntity, waitForAllLoadersToDisappear } from '../../utils/entity';
|
||||
import { sidebarClick } from '../../utils/sidebar';
|
||||
import {
|
||||
verifyActivityFeedFilters,
|
||||
verifyDataFilters,
|
||||
@ -42,6 +53,10 @@ const testDataProducts = [
|
||||
new DataProduct([testDomain], 'pw-data-product-marketing'),
|
||||
];
|
||||
|
||||
const creationConfig: EntityDataClassCreationConfig = {
|
||||
entityDetails: true,
|
||||
};
|
||||
|
||||
const createdDataProducts: DataProduct[] = [];
|
||||
|
||||
const test = base.extend<{ page: Page }>({
|
||||
@ -53,11 +68,66 @@ const test = base.extend<{ page: Page }>({
|
||||
},
|
||||
});
|
||||
|
||||
base.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||
test.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||
test.slow(true);
|
||||
|
||||
const { afterAction, apiContext } = await performAdminLogin(browser);
|
||||
await adminUser.create(apiContext);
|
||||
await adminUser.setAdminRole(apiContext);
|
||||
await persona.create(apiContext, [adminUser.responseData.id]);
|
||||
await EntityDataClass.preRequisitesForTests(apiContext, creationConfig);
|
||||
|
||||
// Set adminUser as owner for entities created by entityDetails config
|
||||
// Only domains and glossaries from entityDetails typically support owners
|
||||
const entitiesToPatch = [];
|
||||
|
||||
// Since creationConfig has entityDetails: true, these entities are created:
|
||||
// domains, glossaries, users, teams, tags, classifications
|
||||
// Only domains and glossaries support ownership
|
||||
if (creationConfig.entityDetails) {
|
||||
entitiesToPatch.push(
|
||||
{ entity: EntityDataClass.domain1, endpoint: 'domains' },
|
||||
{ entity: EntityDataClass.domain2, endpoint: 'domains' },
|
||||
{ entity: EntityDataClass.glossary1, endpoint: 'glossaries' },
|
||||
{ entity: EntityDataClass.glossary2, endpoint: 'glossaries' }
|
||||
);
|
||||
}
|
||||
|
||||
// Patch entities with owner in parallel
|
||||
const ownerPatchPromises = entitiesToPatch.map(
|
||||
async ({ entity, endpoint }) => {
|
||||
// Check for the appropriate id property based on entity type
|
||||
const entityId =
|
||||
(entity as any).responseData?.id ||
|
||||
(entity as any).entityResponseData?.id;
|
||||
|
||||
if (entityId) {
|
||||
try {
|
||||
await apiContext.patch(`/api/v1/${endpoint}/${entityId}`, {
|
||||
data: [
|
||||
{
|
||||
op: 'add',
|
||||
path: '/owners',
|
||||
value: [
|
||||
{
|
||||
id: adminUser.responseData.id,
|
||||
type: 'user',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
headers: {
|
||||
'Content-Type': 'application/json-patch+json',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
// Some entities may not support owners, skip silently
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
await Promise.allSettled(ownerPatchPromises);
|
||||
|
||||
// Create test domain first
|
||||
await testDomain.create(apiContext);
|
||||
@ -68,21 +138,8 @@ base.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||
createdDataProducts.push(dp);
|
||||
}
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
|
||||
base.afterAll('Cleanup', async ({ browser }) => {
|
||||
const { afterAction, apiContext } = await performAdminLogin(browser);
|
||||
await adminUser.delete(apiContext);
|
||||
await persona.delete(apiContext);
|
||||
|
||||
// Delete test data products
|
||||
for (const dp of createdDataProducts) {
|
||||
await dp.delete(apiContext);
|
||||
}
|
||||
|
||||
// Delete test domain
|
||||
await testDomain.delete(apiContext);
|
||||
// Delete all existing KPIs before running the test
|
||||
await deleteKpiRequest(apiContext);
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
@ -97,183 +154,544 @@ test.describe('Widgets', () => {
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await redirectToHomePage(page);
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
});
|
||||
|
||||
test('Activity Feed', async ({ page }) => {
|
||||
test.slow(true);
|
||||
|
||||
await expect(page.getByTestId('KnowledgePanel.ActivityFeed')).toBeVisible();
|
||||
const widgetKey = 'KnowledgePanel.ActivityFeed';
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
await verifyActivityFeedFilters(page, 'KnowledgePanel.ActivityFeed');
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
await removeAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.ActivityFeed',
|
||||
persona.responseData.name
|
||||
);
|
||||
await expect(widget).toBeVisible();
|
||||
|
||||
await addAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.ActivityFeed',
|
||||
persona.responseData.name
|
||||
);
|
||||
await test.step('Test widget header and navigation', async () => {
|
||||
await verifyWidgetHeaderNavigation(
|
||||
page,
|
||||
widgetKey,
|
||||
'Activity Feed',
|
||||
'/explore'
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Test widget filters', async () => {
|
||||
await verifyActivityFeedFilters(page, widgetKey);
|
||||
});
|
||||
|
||||
await test.step('Test widget footer navigation', async () => {
|
||||
await verifyWidgetFooterViewMore(page, {
|
||||
widgetKey,
|
||||
link: `/users/${adminUser.responseData.name}/activity_feed/all`,
|
||||
});
|
||||
|
||||
await redirectToHomePage(page);
|
||||
});
|
||||
|
||||
await test.step('Test widget customization', async () => {
|
||||
await removeAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
await addAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
});
|
||||
});
|
||||
|
||||
test('Data Assets', async ({ page }) => {
|
||||
test.slow(true);
|
||||
|
||||
await expect(page.getByTestId('KnowledgePanel.DataAssets')).toBeVisible();
|
||||
const widgetKey = 'KnowledgePanel.DataAssets';
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
await removeAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.DataAssets',
|
||||
persona.responseData.name
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
await expect(widget).toBeVisible();
|
||||
|
||||
await test.step('Test widget header and navigation', async () => {
|
||||
await verifyWidgetHeaderNavigation(
|
||||
page,
|
||||
widgetKey,
|
||||
'Data Assets',
|
||||
'/explore'
|
||||
);
|
||||
});
|
||||
|
||||
await test.step(
|
||||
'Test widget displays entities and navigation',
|
||||
async () => {
|
||||
// Data Assets widget needs special handling for multiple search indexes
|
||||
const searchIndexes = [
|
||||
SearchIndex.TABLE,
|
||||
SearchIndex.TOPIC,
|
||||
SearchIndex.DASHBOARD,
|
||||
SearchIndex.PIPELINE,
|
||||
SearchIndex.MLMODEL,
|
||||
SearchIndex.CONTAINER,
|
||||
SearchIndex.SEARCH_INDEX,
|
||||
SearchIndex.API_ENDPOINT_INDEX,
|
||||
];
|
||||
|
||||
await verifyWidgetEntityNavigation(page, {
|
||||
widgetKey,
|
||||
entitySelector: '[data-testid^="data-asset-service-"]',
|
||||
urlPattern: '/explore',
|
||||
verifyElement: '[data-testid="explore-page"]',
|
||||
apiResponseUrl: '/api/v1/search/query',
|
||||
searchQuery: searchIndexes,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
await addAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.DataAssets',
|
||||
persona.responseData.name
|
||||
);
|
||||
await test.step('Test widget footer navigation', async () => {
|
||||
await verifyWidgetFooterViewMore(page, {
|
||||
widgetKey,
|
||||
link: 'explore',
|
||||
});
|
||||
|
||||
await redirectToHomePage(page);
|
||||
});
|
||||
|
||||
await test.step('Test widget customization', async () => {
|
||||
await removeAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
await addAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
});
|
||||
});
|
||||
|
||||
test('My Data', async ({ page }) => {
|
||||
test.slow(true);
|
||||
|
||||
await expect(page.getByTestId('KnowledgePanel.MyData')).toBeVisible();
|
||||
const widgetKey = 'KnowledgePanel.MyData';
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
await verifyDataFilters(page, 'KnowledgePanel.MyData');
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
await removeAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.MyData',
|
||||
persona.responseData.name
|
||||
await expect(widget).toBeVisible();
|
||||
|
||||
await test.step('Test widget header and navigation', async () => {
|
||||
await verifyWidgetHeaderNavigation(
|
||||
page,
|
||||
widgetKey,
|
||||
'My Data',
|
||||
`/users/${adminUser.responseData.name}/mydata`
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Test widget filters', async () => {
|
||||
await verifyDataFilters(page, widgetKey);
|
||||
});
|
||||
|
||||
await test.step(
|
||||
'Test widget displays entities and navigation',
|
||||
async () => {
|
||||
await verifyWidgetEntityNavigation(page, {
|
||||
widgetKey,
|
||||
entitySelector: '[data-testid^="My-Data-"]',
|
||||
urlPattern: '/', // My Data can navigate to various entity types
|
||||
apiResponseUrl: '/api/v1/search/query',
|
||||
searchQuery: `index=${SearchIndex.ALL}`,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
await addAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.MyData',
|
||||
persona.responseData.name
|
||||
);
|
||||
await test.step('Test widget footer navigation', async () => {
|
||||
// My Data footer navigates to explore with owner filter
|
||||
await verifyWidgetFooterViewMore(page, {
|
||||
widgetKey,
|
||||
link: 'explore',
|
||||
});
|
||||
|
||||
await redirectToHomePage(page);
|
||||
});
|
||||
|
||||
await test.step('Test widget customization', async () => {
|
||||
await removeAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
await addAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
});
|
||||
});
|
||||
|
||||
test('KPI', async ({ page }) => {
|
||||
test.slow(true);
|
||||
|
||||
await expect(page.getByTestId('KnowledgePanel.KPI')).toBeVisible();
|
||||
await test.step('Add KPI', async () => {
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
await removeAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.KPI',
|
||||
persona.responseData.name
|
||||
);
|
||||
await sidebarClick(page, SidebarItem.DATA_INSIGHT);
|
||||
await page.getByRole('menuitem', { name: 'KPIs' }).click();
|
||||
|
||||
await addAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.KPI',
|
||||
persona.responseData.name
|
||||
);
|
||||
await page.getByTestId('add-kpi-btn').click();
|
||||
await addKpi(page, KPI_DATA[1]);
|
||||
});
|
||||
|
||||
await redirectToHomePage(page);
|
||||
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
const widgetKey = 'KnowledgePanel.KPI';
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
await expect(widget).toBeVisible();
|
||||
|
||||
await test.step('Test widget header and navigation', async () => {
|
||||
await verifyWidgetHeaderNavigation(
|
||||
page,
|
||||
widgetKey,
|
||||
'KPI',
|
||||
'/data-insights/kpi'
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Test widget footer navigation', async () => {
|
||||
await verifyWidgetFooterViewMore(page, {
|
||||
widgetKey,
|
||||
link: 'data-insights/kpi',
|
||||
});
|
||||
|
||||
await redirectToHomePage(page);
|
||||
});
|
||||
|
||||
await test.step('Test widget loads KPI data correctly', async () => {
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
// Wait for the KPI list API to be called
|
||||
const kpiListResponse = page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/api/v1/kpi') &&
|
||||
response.url().includes('fields=dataInsightChart')
|
||||
);
|
||||
|
||||
// Wait for KPI results API to be called
|
||||
const kpiResultsResponse = page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/api/v1/kpi/') &&
|
||||
response.url().includes('/kpiResult')
|
||||
);
|
||||
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
await expect(widget).toBeVisible();
|
||||
|
||||
await kpiListResponse;
|
||||
await kpiResultsResponse;
|
||||
|
||||
// Wait for skeleton loader to disappear
|
||||
await waitForAllLoadersToDisappear(page, 'entity-list-skeleton');
|
||||
|
||||
// Check if the KPI widget content is visible
|
||||
const kpiWidgetContent = widget.locator('[data-testid="kpi-widget"]');
|
||||
|
||||
await expect(kpiWidgetContent).toBeVisible();
|
||||
|
||||
// Check if there's either a chart or empty state
|
||||
const hasChart = await widget
|
||||
.locator('.recharts-responsive-container')
|
||||
.isVisible()
|
||||
.catch(() => false);
|
||||
|
||||
const hasEmptyState = await widget
|
||||
.locator('[data-testid="widget-empty-state"]')
|
||||
.isVisible()
|
||||
.catch(() => false);
|
||||
|
||||
expect(hasChart || hasEmptyState).toBeTruthy();
|
||||
|
||||
if (hasChart) {
|
||||
// If chart exists, verify it's rendered properly
|
||||
await expect(
|
||||
widget.locator('.recharts-responsive-container')
|
||||
).toBeVisible();
|
||||
|
||||
// Verify chart elements are present
|
||||
await expect(widget.locator('.recharts-area')).toBeVisible();
|
||||
}
|
||||
});
|
||||
|
||||
await test.step('Test widget customization', async () => {
|
||||
await removeAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
await addAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
});
|
||||
});
|
||||
|
||||
test('Total Data Assets', async ({ page }) => {
|
||||
test.slow(true);
|
||||
|
||||
await expect(page.getByTestId('KnowledgePanel.TotalAssets')).toBeVisible();
|
||||
const widgetKey = 'KnowledgePanel.TotalAssets';
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
await verifyTotalDataAssetsFilters(page, 'KnowledgePanel.TotalAssets');
|
||||
// Wait for the widgets data to appear
|
||||
await waitForAllLoadersToDisappear(page, 'entity-list-skeleton');
|
||||
|
||||
await removeAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.TotalAssets',
|
||||
persona.responseData.name
|
||||
);
|
||||
await expect(widget).toBeVisible();
|
||||
|
||||
await addAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.TotalAssets',
|
||||
persona.responseData.name
|
||||
);
|
||||
await test.step('Test widget header and navigation', async () => {
|
||||
await verifyWidgetHeaderNavigation(
|
||||
page,
|
||||
widgetKey,
|
||||
'Total Data Assets',
|
||||
'/data-insights'
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Test widget filters', async () => {
|
||||
await verifyTotalDataAssetsFilters(page, widgetKey);
|
||||
});
|
||||
|
||||
await test.step('Test widget footer navigation', async () => {
|
||||
await verifyWidgetFooterViewMore(page, {
|
||||
widgetKey,
|
||||
link: 'data-insights',
|
||||
});
|
||||
|
||||
await redirectToHomePage(page);
|
||||
});
|
||||
|
||||
await test.step('Test widget customization', async () => {
|
||||
await removeAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
await addAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
});
|
||||
});
|
||||
|
||||
test('Following Assets', async ({ page }) => {
|
||||
test.slow(true);
|
||||
|
||||
await expect(page.getByTestId('KnowledgePanel.Following')).toBeVisible();
|
||||
await testDomain.visitEntityPage(page);
|
||||
|
||||
await verifyDataFilters(page, 'KnowledgePanel.Following');
|
||||
await followEntity(page, testDomain.endpoint);
|
||||
|
||||
await removeAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.Following',
|
||||
persona.responseData.name
|
||||
);
|
||||
await redirectToHomePage(page);
|
||||
// wait for the page loader to disappear
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
await addAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.Following',
|
||||
persona.responseData.name
|
||||
);
|
||||
const widgetKey = 'KnowledgePanel.Following';
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
// Wait for the widgets data to appear
|
||||
await waitForAllLoadersToDisappear(page, 'entity-list-skeleton');
|
||||
|
||||
await expect(widget).toBeVisible();
|
||||
|
||||
await test.step('Test widget header and navigation', async () => {
|
||||
await verifyWidgetHeaderNavigation(
|
||||
page,
|
||||
widgetKey,
|
||||
'Following',
|
||||
`/users/${adminUser.responseData.name}/following`
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Test widget filters', async () => {
|
||||
await verifyDataFilters(page, widgetKey);
|
||||
});
|
||||
|
||||
await test.step('Test widget displays followed entities', async () => {
|
||||
// Verify that followed entities appear in the widget
|
||||
await verifyWidgetEntityNavigation(page, {
|
||||
widgetKey,
|
||||
entitySelector: '[data-testid^="Following-"]',
|
||||
urlPattern: '/', // Following can navigate to various entity types
|
||||
apiResponseUrl: '/api/v1/search/query',
|
||||
searchQuery: `index=${SearchIndex.ALL}`,
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('Test widget footer navigation', async () => {
|
||||
// Following footer navigates to explore with following filter
|
||||
await verifyWidgetFooterViewMore(page, {
|
||||
widgetKey,
|
||||
link: 'explore',
|
||||
});
|
||||
|
||||
await redirectToHomePage(page);
|
||||
});
|
||||
|
||||
await test.step('Test widget customization', async () => {
|
||||
await removeAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
await addAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
});
|
||||
});
|
||||
|
||||
test('Domains', async ({ page }) => {
|
||||
test.slow(true);
|
||||
|
||||
await expect(page.getByTestId('KnowledgePanel.Domains')).not.toBeVisible();
|
||||
const widgetKey = 'KnowledgePanel.Domains';
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
await addAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.Domains',
|
||||
persona.responseData.name
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
await expect(widget).not.toBeVisible();
|
||||
|
||||
await test.step('Add widget', async () => {
|
||||
await addAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
});
|
||||
|
||||
await test.step('Test widget header and navigation', async () => {
|
||||
await verifyWidgetHeaderNavigation(page, widgetKey, 'Domains', '/domain');
|
||||
});
|
||||
|
||||
await test.step('Test widget filters', async () => {
|
||||
await verifyDomainsFilters(page, widgetKey);
|
||||
});
|
||||
|
||||
await test.step(
|
||||
'Test widget displays entities and navigation',
|
||||
async () => {
|
||||
await verifyWidgetEntityNavigation(page, {
|
||||
widgetKey,
|
||||
entitySelector: '[data-testid^="domain-card-"]',
|
||||
urlPattern: '/domain',
|
||||
apiResponseUrl: '/api/v1/search/query',
|
||||
searchQuery: `index=${SearchIndex.DOMAIN}`,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
await verifyDomainsFilters(page, 'KnowledgePanel.Domains');
|
||||
await test.step('Test widget footer navigation', async () => {
|
||||
await verifyWidgetFooterViewMore(page, {
|
||||
widgetKey,
|
||||
link: 'domain',
|
||||
});
|
||||
});
|
||||
|
||||
await removeAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.Domains',
|
||||
persona.responseData.name
|
||||
);
|
||||
await test.step('Remove widget', async () => {
|
||||
await redirectToHomePage(page);
|
||||
await removeAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
});
|
||||
});
|
||||
|
||||
test('My Tasks', async ({ page }) => {
|
||||
test.slow(true);
|
||||
|
||||
await expect(page.getByTestId('KnowledgePanel.MyTask')).not.toBeVisible();
|
||||
await test.step('Create a task', async () => {
|
||||
const glossary1 = EntityDataClass.glossary1;
|
||||
// Navigate to one of the created glossaries to create a task
|
||||
await glossary1.visitEntityPage(page);
|
||||
|
||||
await addAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.MyTask',
|
||||
persona.responseData.name
|
||||
// Create a description task for the glossary
|
||||
await page.getByTestId('request-description').click();
|
||||
|
||||
// Wait for the task form to load
|
||||
await page.waitForSelector('#title', { state: 'visible' });
|
||||
|
||||
// Fill in the task details
|
||||
const taskTitle = page.locator('#title');
|
||||
|
||||
await expect(taskTitle).toHaveValue(
|
||||
`Update description for glossary ${glossary1.responseData.displayName}`
|
||||
);
|
||||
|
||||
// Set assignee to adminUser
|
||||
await page.getByTestId('select-assignee').click();
|
||||
await page.getByTitle(adminUser.responseData.displayName).click();
|
||||
|
||||
// Type in the rich text editor
|
||||
const editor = page
|
||||
.locator('.ProseMirror[contenteditable="true"]')
|
||||
.first();
|
||||
await editor.click();
|
||||
await editor.fill('Test task description for My Tasks widget test');
|
||||
|
||||
// Submit the task
|
||||
const createTaskResponse = page.waitForResponse('/api/v1/feed');
|
||||
await page.getByTestId('submit-btn').click();
|
||||
await createTaskResponse;
|
||||
|
||||
// Wait for success toast
|
||||
await expect(page.getByText(/Task created successfully/)).toBeVisible();
|
||||
});
|
||||
|
||||
// Navigate back to home to test the widget
|
||||
await redirectToHomePage(page);
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
const widgetKey = 'KnowledgePanel.MyTask';
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
await expect(widget).not.toBeVisible();
|
||||
|
||||
await test.step('Add widget', async () => {
|
||||
await addAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
});
|
||||
|
||||
await test.step('Test widget header and navigation', async () => {
|
||||
await verifyWidgetHeaderNavigation(
|
||||
page,
|
||||
widgetKey,
|
||||
'My Tasks',
|
||||
`/users/${adminUser.responseData.name}/task`
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Test widget filters', async () => {
|
||||
await verifyTaskFilters(page, widgetKey);
|
||||
});
|
||||
|
||||
await test.step(
|
||||
'Test widget displays entities and navigation',
|
||||
async () => {
|
||||
await verifyWidgetEntityNavigation(page, {
|
||||
widgetKey,
|
||||
entitySelector:
|
||||
'[data-testid="task-feed-card"] [data-testid="redirect-task-button-link"]',
|
||||
urlPattern: '/glossary', // Tasks can navigate to various entity detail pages
|
||||
apiResponseUrl: '/api/v1/feed',
|
||||
searchQuery: 'type=Task', // My Tasks uses feed API with type=Task
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
await verifyTaskFilters(page, 'KnowledgePanel.MyTask');
|
||||
|
||||
await removeAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.MyTask',
|
||||
persona.responseData.name
|
||||
);
|
||||
await test.step('Remove widget', async () => {
|
||||
await redirectToHomePage(page);
|
||||
await removeAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
});
|
||||
});
|
||||
|
||||
test('Data Products', async ({ page }) => {
|
||||
test.slow(true);
|
||||
|
||||
await expect(
|
||||
page.getByTestId('KnowledgePanel.DataProducts')
|
||||
).not.toBeVisible();
|
||||
const widgetKey = 'KnowledgePanel.DataProducts';
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
await addAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.DataProducts',
|
||||
persona.responseData.name
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
await expect(widget).not.toBeVisible();
|
||||
|
||||
await test.step('Add widget', async () => {
|
||||
await addAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
});
|
||||
|
||||
await test.step('Test widget header and navigation', async () => {
|
||||
await verifyWidgetHeaderNavigation(
|
||||
page,
|
||||
widgetKey,
|
||||
'Data Products',
|
||||
'/explore?tab=data_product'
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Test widget filters', async () => {
|
||||
await verifyDataProductsFilters(page, widgetKey);
|
||||
});
|
||||
|
||||
await test.step(
|
||||
'Test widget displays entities and navigation',
|
||||
async () => {
|
||||
await verifyWidgetEntityNavigation(page, {
|
||||
widgetKey,
|
||||
entitySelector: '[data-testid^="data-product-card-"]',
|
||||
urlPattern: '/dataProduct',
|
||||
apiResponseUrl: '/api/v1/search/query',
|
||||
searchQuery: `index=${SearchIndex.DATA_PRODUCT}`,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
await verifyDataProductsFilters(page, 'KnowledgePanel.DataProducts');
|
||||
await test.step('Test widget footer navigation', async () => {
|
||||
await verifyWidgetFooterViewMore(page, {
|
||||
widgetKey,
|
||||
link: '/explore',
|
||||
});
|
||||
});
|
||||
|
||||
await removeAndVerifyWidget(
|
||||
page,
|
||||
'KnowledgePanel.DataProducts',
|
||||
persona.responseData.name
|
||||
);
|
||||
await test.step('Remove widget', async () => {
|
||||
await redirectToHomePage(page);
|
||||
await removeAndVerifyWidget(page, widgetKey, persona.responseData.name);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -118,8 +118,8 @@ test.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||
await tableEntity2.create(apiContext);
|
||||
await policy.create(apiContext, DATA_STEWARD_RULES);
|
||||
await role.create(apiContext, [policy.responseData.name]);
|
||||
await persona1.create(apiContext);
|
||||
await persona2.create(apiContext);
|
||||
await persona1.create(apiContext, [adminUser.responseData.id]);
|
||||
await persona2.create(apiContext, [adminUser.responseData.id]);
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
@ -531,33 +531,11 @@ test.describe('User Profile Feed Interactions', () => {
|
||||
});
|
||||
|
||||
test.describe('User Profile Dropdown Persona Interactions', () => {
|
||||
test.beforeAll(async ({ adminPage }) => {
|
||||
await redirectToHomePage(adminPage);
|
||||
|
||||
test.beforeAll('Prerequisites', async ({ adminPage }) => {
|
||||
// First, add personas to the user profile for testing
|
||||
await visitOwnProfilePage(adminPage);
|
||||
await adminPage.waitForSelector('[data-testid="persona-details-card"]');
|
||||
|
||||
// Add personas to user profile
|
||||
await adminPage
|
||||
.locator('[data-testid="edit-user-persona"]')
|
||||
.first()
|
||||
.click();
|
||||
await adminPage.waitForSelector('[data-testid="persona-select-list"]');
|
||||
await adminPage.locator('[data-testid="persona-select-list"]').click();
|
||||
await adminPage.waitForSelector('.ant-select-dropdown', {
|
||||
state: 'visible',
|
||||
});
|
||||
|
||||
// Select both personas
|
||||
await adminPage.getByTestId(`${persona1.data.displayName}-option`).click();
|
||||
await adminPage.getByTestId(`${persona2.data.displayName}-option`).click();
|
||||
|
||||
await adminPage
|
||||
.locator('[data-testid="user-profile-persona-edit-save"]')
|
||||
.click();
|
||||
await adminPage.waitForResponse('/api/v1/users/*');
|
||||
|
||||
// Set default persona
|
||||
await adminPage
|
||||
.locator('[data-testid="default-edit-user-persona"]')
|
||||
|
@ -18,6 +18,7 @@ import {
|
||||
visitOwnProfilePage,
|
||||
} from './common';
|
||||
import { waitForAllLoadersToDisappear } from './entity';
|
||||
import { navigateToPersonaWithPagination } from './persona';
|
||||
import { settingClick } from './sidebar';
|
||||
|
||||
// Entity types mapping from CURATED_ASSETS_LIST
|
||||
@ -146,9 +147,10 @@ export const navigateToCustomizeLandingPage = async (
|
||||
`/api/v1/docStore/name/persona.${encodeURIComponent(personaName)}`
|
||||
);
|
||||
|
||||
// Navigate to the customize landing page
|
||||
await page.getByTestId(`persona-details-card-${personaName}`).click();
|
||||
// Need to find persona card and click as the list might get paginated
|
||||
await navigateToPersonaWithPagination(page, personaName, true, 3);
|
||||
|
||||
// Navigate to the customize landing page
|
||||
await page.getByRole('tab', { name: 'Customize UI' }).click();
|
||||
|
||||
await page.getByTestId('LandingPage').click();
|
||||
@ -273,18 +275,27 @@ export const addAndVerifyWidget = async (
|
||||
await openAddCustomizeWidgetModal(page);
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
await page.locator(`[data-testid="${widgetKey}"]`).click();
|
||||
await page
|
||||
.getByRole('dialog', { name: 'Customize Home' })
|
||||
.getByTestId(widgetKey)
|
||||
.click();
|
||||
|
||||
await page.locator('[data-testid="apply-btn"]').click();
|
||||
|
||||
await expect(page.getByTestId(widgetKey)).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId('page-layout-v1').getByTestId(widgetKey)
|
||||
).toBeVisible();
|
||||
|
||||
await page.locator('[data-testid="save-button"]').click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
await redirectToHomePage(page);
|
||||
|
||||
await expect(page.getByTestId(widgetKey)).toBeVisible();
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
await expect(
|
||||
page.getByTestId('page-layout-v1').getByTestId(widgetKey)
|
||||
).toBeVisible();
|
||||
};
|
||||
|
||||
export const addCuratedAssetPlaceholder = async ({
|
||||
@ -363,3 +374,213 @@ export const selectAssetTypes = async (
|
||||
// Close the dropdown
|
||||
await page.getByText('Select Asset Type').click();
|
||||
};
|
||||
|
||||
// Helper function to test widget footer "View More" button
|
||||
export const verifyWidgetFooterViewMore = async (
|
||||
page: Page,
|
||||
{
|
||||
widgetKey,
|
||||
expectedLink,
|
||||
link,
|
||||
}: {
|
||||
widgetKey: string;
|
||||
expectedLink?: string;
|
||||
link?: string;
|
||||
}
|
||||
) => {
|
||||
// Wait for the page to load
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
await expect(widget).toBeVisible();
|
||||
|
||||
// Wait for the data to appear in the widget
|
||||
await waitForAllLoadersToDisappear(page, 'entity-list-skeleton');
|
||||
|
||||
// Check for widget footer
|
||||
const widgetFooter = widget.locator('[data-testid="widget-footer"]');
|
||||
const footerExists = await widgetFooter.isVisible().catch(() => false);
|
||||
|
||||
if (!footerExists) {
|
||||
// No footer is expected for this widget
|
||||
return;
|
||||
}
|
||||
|
||||
// Footer exists, check for view more button
|
||||
const viewMoreButton = widget.locator('.footer-view-more-button');
|
||||
const buttonExists = await viewMoreButton.isVisible().catch(() => false);
|
||||
|
||||
if (!buttonExists) {
|
||||
// No view more button in footer
|
||||
return;
|
||||
}
|
||||
|
||||
// View more button exists, verify it
|
||||
await expect(viewMoreButton).toBeVisible();
|
||||
|
||||
// Get and verify the href
|
||||
const href = await viewMoreButton.getAttribute('href');
|
||||
|
||||
if (expectedLink) {
|
||||
// Exact link match
|
||||
expect(href).toBe(expectedLink);
|
||||
} else if (link) {
|
||||
// Pattern match
|
||||
expect(href).toContain(link);
|
||||
}
|
||||
|
||||
// Click and verify navigation
|
||||
await viewMoreButton.click();
|
||||
|
||||
if (expectedLink) {
|
||||
// Wait for the specific URL
|
||||
await page.waitForURL(expectedLink);
|
||||
} else if (link) {
|
||||
const currentUrl = page.url();
|
||||
|
||||
// Wait for URL matching pattern
|
||||
expect(currentUrl).toContain(link);
|
||||
}
|
||||
};
|
||||
|
||||
export const verifyWidgetEntityNavigation = async (
|
||||
page: Page,
|
||||
{
|
||||
widgetKey,
|
||||
entitySelector,
|
||||
urlPattern,
|
||||
emptyStateTestId,
|
||||
verifyElement,
|
||||
apiResponseUrl,
|
||||
searchQuery,
|
||||
}: {
|
||||
widgetKey: string;
|
||||
entitySelector: string;
|
||||
urlPattern: string;
|
||||
emptyStateTestId?: string;
|
||||
verifyElement?: string;
|
||||
apiResponseUrl: string;
|
||||
searchQuery: string | string[];
|
||||
}
|
||||
) => {
|
||||
// Wait for API response matching the search query
|
||||
const response = page.waitForResponse((response) => {
|
||||
if (!response.url().includes(apiResponseUrl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle multiple query parts (for complex queries like Data Assets)
|
||||
if (Array.isArray(searchQuery)) {
|
||||
return searchQuery.every((query) => response.url().includes(query));
|
||||
}
|
||||
|
||||
// Handle single query string
|
||||
return response.url().includes(searchQuery);
|
||||
});
|
||||
|
||||
await redirectToHomePage(page);
|
||||
|
||||
await response;
|
||||
|
||||
// Wait for loaders after navigation
|
||||
await waitForAllLoadersToDisappear(page, 'entity-list-skeleton');
|
||||
|
||||
// Get widget after navigation to home page
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
// Wait for widget to be visible
|
||||
await expect(widget).toBeVisible();
|
||||
|
||||
// Wait again for any widget-specific loaders
|
||||
await waitForAllLoadersToDisappear(page, 'entity-list-skeleton');
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Check for entity items in the widget
|
||||
const entityItems = widget.locator(entitySelector);
|
||||
const hasEntities = (await entityItems.count()) > 0;
|
||||
|
||||
if (hasEntities) {
|
||||
await expect(entityItems.first()).toBeVisible();
|
||||
|
||||
// Get the first entity item
|
||||
const firstEntity = entityItems.first();
|
||||
|
||||
// Check if it's a link or button and click appropriately
|
||||
const isLink = (await firstEntity.locator('.item-link').count()) > 0;
|
||||
|
||||
if (isLink) {
|
||||
// For widgets with links inside (like My Data)
|
||||
const entityLink = firstEntity.locator('.item-link').first();
|
||||
await entityLink.click();
|
||||
} else {
|
||||
// For widgets with direct clickable cards (like Domains, Data Products)
|
||||
await firstEntity.click();
|
||||
}
|
||||
|
||||
// Wait for navigation
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Verify we're on the correct page
|
||||
const currentUrl = page.url();
|
||||
|
||||
expect(currentUrl).toContain(urlPattern);
|
||||
|
||||
// Verify page element is visible if specified
|
||||
if (verifyElement) {
|
||||
const pageElement = page.locator(verifyElement);
|
||||
|
||||
await expect(pageElement).toBeVisible();
|
||||
}
|
||||
|
||||
// Navigate back to home for next tests
|
||||
await redirectToHomePage(page);
|
||||
} else {
|
||||
// Check for empty state if no entities
|
||||
const emptyState = widget.locator('[data-testid="widget-empty-state"]');
|
||||
|
||||
await expect(emptyState).toBeVisible();
|
||||
|
||||
if (emptyStateTestId) {
|
||||
const emptyStateComponent = page.getByTestId(emptyStateTestId);
|
||||
|
||||
await expect(emptyStateComponent).toBeVisible();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const verifyWidgetHeaderNavigation = async (
|
||||
page: Page,
|
||||
widgetKey: string,
|
||||
expectedTitle: string,
|
||||
navigationUrl: string
|
||||
) => {
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
await expect(widget).toBeVisible();
|
||||
|
||||
// Wait for loaders before interacting with widget header
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
// Verify widget header
|
||||
const widgetHeader = widget.getByTestId('widget-header');
|
||||
|
||||
await expect(widgetHeader).toBeVisible();
|
||||
|
||||
// Verify header title
|
||||
const headerTitle = widgetHeader.getByTestId('widget-title');
|
||||
|
||||
await expect(headerTitle).toBeVisible();
|
||||
await expect(headerTitle).toContainText(expectedTitle);
|
||||
|
||||
// Click header title to navigate
|
||||
await headerTitle.click();
|
||||
|
||||
const currentUrl = page.url();
|
||||
|
||||
// Wait for navigation
|
||||
expect(currentUrl).toContain(navigationUrl);
|
||||
|
||||
// Navigate back to home page for next tests
|
||||
await redirectToHomePage(page);
|
||||
};
|
||||
|
@ -11,15 +11,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { expect, Page } from '@playwright/test';
|
||||
import { waitForAllLoadersToDisappear } from './entity';
|
||||
|
||||
export const verifyActivityFeedFilters = async (
|
||||
page: Page,
|
||||
widgetKey: string
|
||||
) => {
|
||||
// Wait for the page to load
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
await expect(
|
||||
page.getByTestId(widgetKey).getByTestId('widget-sort-by-dropdown')
|
||||
).toBeVisible();
|
||||
|
||||
// Wait for the widget feed to load
|
||||
await waitForAllLoadersToDisappear(page, 'entity-list-skeleton');
|
||||
|
||||
const myDataFilter = page.waitForResponse(
|
||||
'/api/v1/feed?type=Conversation&filterType=OWNER&*'
|
||||
);
|
||||
@ -52,6 +59,12 @@ export const verifyActivityFeedFilters = async (
|
||||
};
|
||||
|
||||
export const verifyDataFilters = async (page: Page, widgetKey: string) => {
|
||||
// Wait for the page to load
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
// Wait for the widget data to appear
|
||||
await waitForAllLoadersToDisappear(page, 'entity-list-skeleton');
|
||||
|
||||
await expect(
|
||||
page.getByTestId(widgetKey).getByTestId('widget-sort-by-dropdown')
|
||||
).toBeVisible();
|
||||
@ -91,6 +104,8 @@ export const verifyTotalDataAssetsFilters = async (
|
||||
page: Page,
|
||||
widgetKey: string
|
||||
) => {
|
||||
await waitForAllLoadersToDisappear(page, 'entity-list-skeleton');
|
||||
|
||||
await expect(
|
||||
page.getByTestId(widgetKey).getByTestId('widget-sort-by-dropdown')
|
||||
).toBeVisible();
|
||||
@ -121,7 +136,10 @@ export const verifyDataProductsFilters = async (
|
||||
page: Page,
|
||||
widgetKey: string
|
||||
) => {
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
|
||||
const sortDropdown = widget.getByTestId('widget-sort-by-dropdown');
|
||||
|
||||
await expect(sortDropdown).toBeVisible();
|
||||
@ -149,6 +167,8 @@ export const verifyDataProductsFilters = async (
|
||||
};
|
||||
|
||||
export const verifyDomainsFilters = async (page: Page, widgetKey: string) => {
|
||||
await waitForAllLoadersToDisappear(page, 'entity-list-skeleton');
|
||||
|
||||
await expect(
|
||||
page.getByTestId(widgetKey).getByTestId('widget-sort-by-dropdown')
|
||||
).toBeVisible();
|
||||
@ -185,6 +205,8 @@ export const verifyDomainsFilters = async (page: Page, widgetKey: string) => {
|
||||
};
|
||||
|
||||
export const verifyTaskFilters = async (page: Page, widgetKey: string) => {
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
|
||||
await expect(
|
||||
page.getByTestId(widgetKey).getByTestId('widget-sort-by-dropdown')
|
||||
).toBeVisible();
|
||||
@ -219,3 +241,67 @@ export const verifyTaskFilters = async (page: Page, widgetKey: string) => {
|
||||
await page.getByRole('menuitem', { name: 'All' }).click();
|
||||
await allTasksFilter;
|
||||
};
|
||||
|
||||
export const verifyDataAssetsFilters = async (
|
||||
page: Page,
|
||||
widgetKey: string
|
||||
) => {
|
||||
const widget = page.getByTestId(widgetKey);
|
||||
await waitForAllLoadersToDisappear(page, 'entity-list-skeleton');
|
||||
|
||||
const sortDropdown = widget.getByTestId('widget-sort-by-dropdown');
|
||||
|
||||
await expect(sortDropdown).toBeVisible();
|
||||
|
||||
// Test A to Z sorting
|
||||
const aToZFilter = page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/api/v1/search/query') &&
|
||||
response.url().includes('table_search_index')
|
||||
);
|
||||
await sortDropdown.click();
|
||||
await page.getByRole('menuitem', { name: 'A to Z' }).click();
|
||||
await aToZFilter;
|
||||
|
||||
// Wait for UI to update
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Test Z to A sorting
|
||||
const zToAFilter = page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/api/v1/search/query') &&
|
||||
response.url().includes('table_search_index')
|
||||
);
|
||||
await sortDropdown.click();
|
||||
await page.getByRole('menuitem', { name: 'Z to A' }).click();
|
||||
await zToAFilter;
|
||||
|
||||
// Wait for UI to update
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Test High to Low sorting
|
||||
const highToLowFilter = page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/api/v1/search/query') &&
|
||||
response.url().includes('table_search_index')
|
||||
);
|
||||
await sortDropdown.click();
|
||||
await page.getByRole('menuitem', { name: 'High to Low' }).click();
|
||||
await highToLowFilter;
|
||||
|
||||
// Wait for UI to update
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Test Low to High sorting
|
||||
const lowToHighFilter = page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/api/v1/search/query') &&
|
||||
response.url().includes('table_search_index')
|
||||
);
|
||||
await sortDropdown.click();
|
||||
await page.getByRole('menuitem', { name: 'Low to High' }).click();
|
||||
await lowToHighFilter;
|
||||
|
||||
// Wait for UI to update
|
||||
await page.waitForLoadState('networkidle');
|
||||
};
|
||||
|
@ -96,6 +96,7 @@ const WidgetHeader = ({
|
||||
)}
|
||||
<Typography.Paragraph
|
||||
className="widget-title cursor-pointer"
|
||||
data-testid="widget-title"
|
||||
ellipsis={{ tooltip: true }}
|
||||
style={{
|
||||
maxWidth: widgetWidth === 1 ? '145px' : '525px',
|
||||
|
@ -150,6 +150,7 @@ const DomainsWidget = ({
|
||||
'domain-card-full': isFullSize,
|
||||
'p-0': !isFullSize,
|
||||
})}
|
||||
data-testid={`domain-card-${domain.id || domain.name}`}
|
||||
key={domain.id}
|
||||
onClick={() => handleDomainClick(domain)}>
|
||||
{isFullSize ? (
|
||||
|
Loading…
x
Reference in New Issue
Block a user