diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/AdvancedSearch.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/AdvancedSearch.spec.ts index 9f94b424d7c5..ca63d8f31dfd 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/AdvancedSearch.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/AdvancedSearch.spec.ts @@ -12,10 +12,7 @@ */ import test from '@playwright/test'; import { SidebarItem } from '../../constant/sidebar'; -import { TableClass } from '../../support/entity/TableClass'; -import { TopicClass } from '../../support/entity/TopicClass'; -import { TagClass } from '../../support/tag/TagClass'; -import { UserClass } from '../../support/user/UserClass'; +import { EntityDataClass } from '../../support/entity/EntityDataClass'; import { FIELDS, OPERATOR, @@ -23,7 +20,7 @@ import { verifyAllConditions, } from '../../utils/advancedSearch'; import { createNewPage, redirectToHomePage } from '../../utils/common'; -import { addMultiOwner, assignTag, assignTier } from '../../utils/entity'; +import { assignTier } from '../../utils/entity'; import { sidebarClick } from '../../utils/sidebar'; test.describe.configure({ @@ -35,83 +32,170 @@ test.describe('Advanced Search', { tag: '@advanced-search' }, () => { // use the admin user to login test.use({ storageState: 'playwright/.auth/admin.json' }); - const user1 = new UserClass(); - const user2 = new UserClass(); - const table1 = new TableClass(); - const table2 = new TableClass(); - const topic1 = new TopicClass(); - const topic2 = new TopicClass(); - const tierTag1 = new TagClass({ classification: 'Tier' }); - const tierTag2 = new TagClass({ classification: 'Tier' }); - let searchCriteria: Record = {}; test.beforeAll('Setup pre-requests', async ({ browser }) => { const { page, apiContext, afterAction } = await createNewPage(browser); - await Promise.all([ - user1.create(apiContext), - user2.create(apiContext), - table1.create(apiContext), - table2.create(apiContext), - topic1.create(apiContext), - topic2.create(apiContext), - tierTag1.create(apiContext), - tierTag2.create(apiContext), - ]); + await EntityDataClass.preRequisitesForTests(apiContext); // Add Owner & Tag to the table - await table1.visitEntityPage(page); - await addMultiOwner({ - page, - ownerNames: [user1.getUserName()], - activatorBtnDataTestId: 'edit-owner', - resultTestId: 'data-assets-header', - endpoint: table1.endpoint, - type: 'Users', + await EntityDataClass.table1.visitEntityPage(page); + await EntityDataClass.table1.patch({ + apiContext, + patchData: [ + { + op: 'add', + value: { + type: 'user', + id: EntityDataClass.user1.responseData.id, + }, + path: '/owners/0', + }, + { + op: 'add', + value: { + tagFQN: 'PersonalData.Personal', + }, + path: '/tags/0', + }, + { + op: 'add', + path: '/domain', + value: { + id: EntityDataClass.domain1.responseData.id, + type: 'domain', + name: EntityDataClass.domain1.responseData.name, + displayName: EntityDataClass.domain1.responseData.displayName, + }, + }, + ], }); - await assignTag(page, 'PersonalData.Personal'); - await table2.visitEntityPage(page); - await addMultiOwner({ - page, - ownerNames: [user2.getUserName()], - activatorBtnDataTestId: 'edit-owner', - resultTestId: 'data-assets-header', - endpoint: table1.endpoint, - type: 'Users', + await EntityDataClass.table2.visitEntityPage(page); + await EntityDataClass.table2.patch({ + apiContext, + patchData: [ + { + op: 'add', + value: { + type: 'user', + id: EntityDataClass.user2.responseData.id, + }, + path: '/owners/0', + }, + { + op: 'add', + value: { + tagFQN: 'PII.None', + }, + path: '/tags/0', + }, + { + op: 'add', + path: '/domain', + value: { + id: EntityDataClass.domain2.responseData.id, + type: 'domain', + name: EntityDataClass.domain2.responseData.name, + displayName: EntityDataClass.domain2.responseData.displayName, + }, + }, + ], }); - await assignTag(page, 'PII.None'); // Add Tier To the topic 1 - await topic1.visitEntityPage(page); - await assignTier(page, tierTag1.data.displayName, topic1.endpoint); + await EntityDataClass.topic1.visitEntityPage(page); + await assignTier( + page, + EntityDataClass.tierTag1.data.displayName, + EntityDataClass.topic1.endpoint + ); // Add Tier To the topic 2 - await topic2.visitEntityPage(page); - await assignTier(page, tierTag2.data.displayName, topic2.endpoint); + await EntityDataClass.topic2.visitEntityPage(page); + await assignTier( + page, + EntityDataClass.tierTag2.data.displayName, + EntityDataClass.topic2.endpoint + ); // Update Search Criteria here searchCriteria = { - 'owners.displayName.keyword': [user1.getUserName(), user2.getUserName()], + 'owners.displayName.keyword': [ + EntityDataClass.user1.getUserName(), + EntityDataClass.user2.getUserName(), + ], 'tags.tagFQN': ['PersonalData.Personal', 'PII.None'], 'tier.tagFQN': [ - tierTag1.responseData.fullyQualifiedName, - tierTag2.responseData.fullyQualifiedName, + EntityDataClass.tierTag1.responseData.fullyQualifiedName, + EntityDataClass.tierTag2.responseData.fullyQualifiedName, + ], + 'service.displayName.keyword': [ + EntityDataClass.table1.service.name, + EntityDataClass.table2.service.name, ], - 'service.displayName.keyword': [table1.service.name, table2.service.name], 'database.displayName.keyword': [ - table1.database.name, - table2.database.name, + EntityDataClass.table1.database.name, + EntityDataClass.table2.database.name, ], 'databaseSchema.displayName.keyword': [ - table1.schema.name, - table2.schema.name, + EntityDataClass.table1.schema.name, + EntityDataClass.table2.schema.name, ], 'columns.name.keyword': ['email', 'shop_id'], 'displayName.keyword': [ - table1.entity.displayName, - table2.entity.displayName, + EntityDataClass.table1.entity.displayName, + EntityDataClass.table2.entity.displayName, + ], + serviceType: [ + EntityDataClass.table1.service.serviceType, + EntityDataClass.topic1.service.serviceType, + ], + 'messageSchema.schemaFields.name.keyword': [ + EntityDataClass.topic1.entity.messageSchema.schemaFields[0].name, + EntityDataClass.topic1.entity.messageSchema.schemaFields[1].name, + ], + 'dataModel.columns.name.keyword': [ + EntityDataClass.dashboard1.dataModel.columns[0].name, + EntityDataClass.dashboard1.dataModel.columns[1].name, + ], + dataModelType: [ + EntityDataClass.dashboard1.dataModel.dataModelType, + EntityDataClass.dashboard2.dataModel.dataModelType, + ], + 'fields.name.keyword': [ + EntityDataClass.searchIndex1.entity.fields[1].name, + EntityDataClass.searchIndex1.entity.fields[3].name, + ], + 'tasks.displayName.keyword': [ + EntityDataClass.pipeline1.entity.tasks[0].displayName, + EntityDataClass.pipeline1.entity.tasks[1].displayName, + ], + 'domain.displayName.keyword': [ + EntityDataClass.domain1.data.displayName, + EntityDataClass.domain2.data.displayName, + ], + 'responseSchema.schemaFields.name.keyword': [ + EntityDataClass.apiCollection1.apiEndpoint.responseSchema + .schemaFields[0].name, + EntityDataClass.apiCollection1.apiEndpoint.responseSchema + .schemaFields[1].name, + ], + 'requestSchema.schemaFields.name.keyword': [ + EntityDataClass.apiCollection1.apiEndpoint.requestSchema.schemaFields[0] + .name, + EntityDataClass.apiCollection1.apiEndpoint.requestSchema.schemaFields[1] + .name, + ], + 'name.keyword': [ + EntityDataClass.table1.entity.name, + EntityDataClass.table2.entity.name, + ], + 'project.keyword': [ + EntityDataClass.dashboardDataModel1.entity.project, + EntityDataClass.dashboardDataModel2.entity.project, ], + status: ['Approved', 'In Review'], }; await afterAction(); @@ -119,16 +203,7 @@ test.describe('Advanced Search', { tag: '@advanced-search' }, () => { test.afterAll('Cleanup', async ({ browser }) => { const { apiContext, afterAction } = await createNewPage(browser); - await Promise.all([ - user1.delete(apiContext), - user2.delete(apiContext), - table1.delete(apiContext), - table2.delete(apiContext), - topic1.delete(apiContext), - topic2.delete(apiContext), - tierTag1.delete(apiContext), - tierTag2.delete(apiContext), - ]); + await EntityDataClass.postRequisitesForTests(apiContext); await afterAction(); }); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/ApiCollectionClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/ApiCollectionClass.ts index 27edd96029f0..0b822daf0369 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/ApiCollectionClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/ApiCollectionClass.ts @@ -94,6 +94,12 @@ export class ApiCollectionClass extends EntityClass { }, ], }, + { + name: 'secondary', + dataType: 'RECORD', + fullyQualifiedName: `${this.fqn}.secondary`, + tags: [], + }, ], }, responseSchema: { @@ -139,6 +145,12 @@ export class ApiCollectionClass extends EntityClass { }, ], }, + { + name: 'secondary', + dataType: 'RECORD', + fullyQualifiedName: `${this.fqn}.secondary`, + tags: [], + }, ], }, }; diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/DashboardClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/DashboardClass.ts index 14777bda65ae..6350f15ce96b 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/DashboardClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/DashboardClass.ts @@ -53,6 +53,20 @@ export class DashboardClass extends EntityClass { service: this.service.name, }; children = [ + { + name: 'merchant', + dataType: 'VARCHAR', + dataLength: 256, + dataTypeDisplay: 'varchar', + description: 'merchant', + }, + { + name: 'notes', + dataType: 'VARCHAR', + dataLength: 256, + dataTypeDisplay: 'varchar', + description: 'merchant', + }, { name: 'country_name', dataType: 'VARCHAR', @@ -76,12 +90,13 @@ export class DashboardClass extends EntityClass { {} as ResponseDataWithServiceType; chartsResponseData: ResponseDataType = {} as ResponseDataType; - constructor(name?: string) { + constructor(name?: string, dataModelType = 'SupersetDataModel') { super(EntityTypeEndpoint.Dashboard); this.service.name = name ?? this.service.name; this.type = 'Dashboard'; this.serviceCategory = SERVICE_TYPE.Dashboard; this.serviceType = ServiceTypes.DASHBOARD_SERVICES; + this.dataModel.dataModelType = dataModelType; } async create(apiContext: APIRequestContext) { diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/DashboardDataModelClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/DashboardDataModelClass.ts index 738460fdb742..d1b32af7d797 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/DashboardDataModelClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/DashboardDataModelClass.ts @@ -25,6 +25,7 @@ import { EntityClass } from './EntityClass'; export class DashboardDataModelClass extends EntityClass { private dashboardDataModelName = `pw-dashboard-data-model-${uuid()}`; + private projectName = `pw-project-${uuid()}`; service = { name: `pw-dashboard-service-${uuid()}`, serviceType: 'Superset', @@ -58,6 +59,7 @@ export class DashboardDataModelClass extends EntityClass { service: this.service.name, columns: this.children, dataModelType: 'SupersetDataModel', + project: this.projectName, }; serviceResponseData: ResponseDataType = {} as ResponseDataType; diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/EntityDataClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/EntityDataClass.ts index d66920a060b2..c66020bb4a96 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/EntityDataClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/EntityDataClass.ts @@ -17,6 +17,14 @@ import { GlossaryTerm } from '../glossary/GlossaryTerm'; import { TagClass } from '../tag/TagClass'; import { TeamClass } from '../team/TeamClass'; import { UserClass } from '../user/UserClass'; +import { ApiCollectionClass } from './ApiCollectionClass'; +import { DashboardClass } from './DashboardClass'; +import { DashboardDataModelClass } from './DashboardDataModelClass'; +import { MlModelClass } from './MlModelClass'; +import { PipelineClass } from './PipelineClass'; +import { SearchIndexClass } from './SearchIndexClass'; +import { TableClass } from './TableClass'; +import { TopicClass } from './TopicClass'; export class EntityDataClass { static readonly domain1 = new Domain(); @@ -31,6 +39,24 @@ export class EntityDataClass { static readonly team1 = new TeamClass(); static readonly team2 = new TeamClass(); static readonly tierTag1 = new TagClass({ classification: 'Tier' }); + static readonly tierTag2 = new TagClass({ classification: 'Tier' }); + static readonly table1 = new TableClass(); + static readonly table2 = new TableClass(); + static readonly topic1 = new TopicClass(); + static readonly topic2 = new TopicClass(); + static readonly dashboard1 = new DashboardClass(); + static readonly dashboard2 = new DashboardClass( + 'Dashboard 2', + 'LookMlExplore' + ); + static readonly mlModel1 = new MlModelClass(); + static readonly pipeline1 = new PipelineClass(); + static readonly dashboardDataModel1 = new DashboardDataModelClass(); + static readonly dashboardDataModel2 = new DashboardDataModelClass(); + static readonly apiCollection1 = new ApiCollectionClass(); + static readonly apiCollection2 = new ApiCollectionClass(); + static readonly searchIndex1 = new SearchIndexClass(); + static readonly searchIndex2 = new SearchIndexClass(); static async preRequisitesForTests(apiContext: APIRequestContext) { // Add pre-requisites for tests @@ -46,6 +72,21 @@ export class EntityDataClass { await this.team1.create(apiContext); await this.team2.create(apiContext); await this.tierTag1.create(apiContext); + await this.tierTag2.create(apiContext); + await this.table1.create(apiContext); + await this.table2.create(apiContext); + await this.topic1.create(apiContext); + await this.topic2.create(apiContext); + await this.dashboard1.create(apiContext); + await this.dashboard2.create(apiContext); + await this.mlModel1.create(apiContext); + await this.pipeline1.create(apiContext); + await this.dashboardDataModel1.create(apiContext); + await this.dashboardDataModel2.create(apiContext); + await this.apiCollection1.create(apiContext); + await this.apiCollection2.create(apiContext); + await this.searchIndex1.create(apiContext); + await this.searchIndex2.create(apiContext); } static async postRequisitesForTests(apiContext: APIRequestContext) { @@ -61,5 +102,20 @@ export class EntityDataClass { await this.team1.delete(apiContext); await this.team2.delete(apiContext); await this.tierTag1.delete(apiContext); + await this.tierTag2.delete(apiContext); + await this.table1.delete(apiContext); + await this.table2.delete(apiContext); + await this.topic1.delete(apiContext); + await this.topic2.delete(apiContext); + await this.dashboard1.delete(apiContext); + await this.dashboard2.delete(apiContext); + await this.mlModel1.delete(apiContext); + await this.pipeline1.delete(apiContext); + await this.dashboardDataModel1.delete(apiContext); + await this.dashboardDataModel2.delete(apiContext); + await this.apiCollection1.delete(apiContext); + await this.apiCollection2.delete(apiContext); + await this.searchIndex1.delete(apiContext); + await this.searchIndex2.delete(apiContext); } } diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/MlModelClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/MlModelClass.ts index b959705e3075..119ee9401dae 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/MlModelClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/MlModelClass.ts @@ -44,6 +44,11 @@ export class MlModelClass extends EntityClass { dataType: 'numerical', description: 'Sales amount', }, + { + name: 'persona', + dataType: 'categorical', + description: 'type of buyer', + }, ]; entity = { diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/PipelineClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/PipelineClass.ts index 6f82dd496267..e7c461ae2afc 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/PipelineClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/PipelineClass.ts @@ -39,7 +39,10 @@ export class PipelineClass extends EntityClass { }, }; - children = [{ name: 'snowflake_task' }]; + children = [ + { name: 'snowflake_task', displayName: 'Snowflake Task' }, + { name: 'presto_task', displayName: 'Presto Task' }, + ]; entity = { name: this.pipelineName, diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/SearchIndexClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/SearchIndexClass.ts index 46bd8b9c61df..6cb7f3c2b142 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/SearchIndexClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/SearchIndexClass.ts @@ -52,6 +52,14 @@ export class SearchIndexClass extends EntityClass { fullyQualifiedName: `${this.fqn}.name`, tags: [], }, + { + name: 'databaseSchema', + dataType: 'TEXT', + dataTypeDisplay: 'text', + description: 'Table Entity Database Schema.', + fullyQualifiedName: `${this.fqn}.databaseSchema`, + tags: [], + }, { name: 'description', dataType: 'TEXT', diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/TopicClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/TopicClass.ts index b223f22d4fc2..abbac469cb39 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/TopicClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/TopicClass.ts @@ -83,6 +83,13 @@ export class TopicClass extends EntityClass { }, ], }, + { + name: 'secondary', + dataType: 'RECORD', + fullyQualifiedName: `${this.fqn}.secondary`, + tags: [], + children: [], + }, ]; entity = { diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/advancedSearch.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/advancedSearch.ts index b8d911fa594e..e3e5feae0a17 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/advancedSearch.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/advancedSearch.ts @@ -63,6 +63,52 @@ export const FIELDS: EntityFields[] = [ localSearch: false, skipConditions: ['isNull', 'isNotNull'], // Null and isNotNull conditions are not present for display name }, + { + id: 'Service Type', + name: 'serviceType', + localSearch: false, + }, + { + id: 'Schema Field', + name: 'messageSchema.schemaFields.name.keyword', + localSearch: false, + }, + { + id: 'Container Column', + name: 'dataModel.columns.name.keyword', + localSearch: false, + }, + { + id: 'Data Model Type', + name: 'dataModelType', + localSearch: false, + }, + { + id: 'Field', + name: 'fields.name.keyword', + localSearch: false, + }, + { + id: 'Task', + name: 'tasks.displayName.keyword', + localSearch: false, + }, + { + id: 'Domain', + name: 'domain.displayName.keyword', + localSearch: false, + }, + { + id: 'Name', + name: 'name.keyword', + localSearch: false, + skipConditions: ['isNull', 'isNotNull'], // Null and isNotNull conditions are not present for name + }, + { + id: 'Project', + name: 'project.keyword', + localSearch: false, + }, ]; export const OPERATOR = {