mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-03 06:03:12 +00:00
Migrate advanced search tests (#17666)
* migrate advanced search tests * verify advanced search tests * fix minor config * push fixes * add before all timeout * increase test timeout * revert playwright config * add rule based search * migrate group tests (cherry picked from commit a63ad691000c5d49b251602f96a519d846a178da)
This commit is contained in:
parent
6fa662bfda
commit
32a85c0c96
@ -1,256 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 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 {
|
|
||||||
searchAndClickOnOption,
|
|
||||||
selectNullOption,
|
|
||||||
} from '../../common/advancedSearchQuickFilters';
|
|
||||||
import { interceptURL, verifyResponseStatusCode } from '../../common/common';
|
|
||||||
import { goToAdvanceSearch } from '../../common/Utils/AdvancedSearch';
|
|
||||||
import { addDomainToEntity } from '../../common/Utils/Domain';
|
|
||||||
import {
|
|
||||||
createEntityViaREST,
|
|
||||||
deleteEntityViaREST,
|
|
||||||
visitEntityDetailsPage,
|
|
||||||
} from '../../common/Utils/Entity';
|
|
||||||
import { getToken } from '../../common/Utils/LocalStorage';
|
|
||||||
import { addOwner, removeOwner } from '../../common/Utils/Owner';
|
|
||||||
import { assignTags, removeTags } from '../../common/Utils/Tags';
|
|
||||||
import { addTier, removeTier } from '../../common/Utils/Tier';
|
|
||||||
import {
|
|
||||||
FilterItem,
|
|
||||||
QUICK_FILTERS_BY_ASSETS,
|
|
||||||
SUPPORTED_EMPTY_FILTER_FIELDS,
|
|
||||||
} from '../../constants/advancedSearchQuickFilters.constants';
|
|
||||||
import { SEARCH_ENTITY_TABLE } from '../../constants/constants';
|
|
||||||
import { EntityType, SidebarItem } from '../../constants/Entity.interface';
|
|
||||||
import { DOMAIN_QUICK_FILTERS_DETAILS } from '../../constants/EntityConstant';
|
|
||||||
const ownerName = 'Aaron Johnson';
|
|
||||||
|
|
||||||
const preRequisitesForTests = () => {
|
|
||||||
cy.getAllLocalStorage().then((data) => {
|
|
||||||
const token = getToken(data);
|
|
||||||
|
|
||||||
createEntityViaREST({
|
|
||||||
body: DOMAIN_QUICK_FILTERS_DETAILS,
|
|
||||||
endPoint: EntityType.Domain,
|
|
||||||
token,
|
|
||||||
});
|
|
||||||
|
|
||||||
visitEntityDetailsPage({
|
|
||||||
term: SEARCH_ENTITY_TABLE.table_1.term,
|
|
||||||
entity: SEARCH_ENTITY_TABLE.table_1.entity,
|
|
||||||
serviceName: SEARCH_ENTITY_TABLE.table_1.serviceName,
|
|
||||||
});
|
|
||||||
addDomainToEntity(DOMAIN_QUICK_FILTERS_DETAILS.displayName);
|
|
||||||
addOwner(ownerName);
|
|
||||||
assignTags('PersonalData.Personal', EntityType.Table);
|
|
||||||
addTier('Tier1');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const postRequisitesForTests = () => {
|
|
||||||
cy.getAllLocalStorage().then((data) => {
|
|
||||||
const token = getToken(data);
|
|
||||||
// Domain 1 to test
|
|
||||||
deleteEntityViaREST({
|
|
||||||
entityName: DOMAIN_QUICK_FILTERS_DETAILS.name,
|
|
||||||
endPoint: EntityType.Domain,
|
|
||||||
token,
|
|
||||||
});
|
|
||||||
visitEntityDetailsPage({
|
|
||||||
term: SEARCH_ENTITY_TABLE.table_1.term,
|
|
||||||
entity: SEARCH_ENTITY_TABLE.table_1.entity,
|
|
||||||
serviceName: SEARCH_ENTITY_TABLE.table_1.serviceName,
|
|
||||||
});
|
|
||||||
removeOwner(ownerName);
|
|
||||||
removeTags('PersonalData.Personal', EntityType.Table);
|
|
||||||
removeTier();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// migrated to playwright
|
|
||||||
describe.skip(
|
|
||||||
`Advanced search quick filters should work properly for assets`,
|
|
||||||
{ tags: 'DataAssets' },
|
|
||||||
() => {
|
|
||||||
before(() => {
|
|
||||||
cy.login();
|
|
||||||
preRequisitesForTests();
|
|
||||||
});
|
|
||||||
|
|
||||||
after(() => {
|
|
||||||
cy.login();
|
|
||||||
postRequisitesForTests();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.login();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should show the quick filters for respective assets`, () => {
|
|
||||||
// Navigate to explore page
|
|
||||||
cy.sidebarClick(SidebarItem.EXPLORE);
|
|
||||||
QUICK_FILTERS_BY_ASSETS.map((asset) => {
|
|
||||||
cy.get(`[data-testid="${asset.tab}"]`).scrollIntoView().click();
|
|
||||||
|
|
||||||
asset.filters.map((filter) => {
|
|
||||||
cy.get(`[data-testid="search-dropdown-${filter.label}"]`)
|
|
||||||
.scrollIntoView()
|
|
||||||
.should('be.visible');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('search dropdown should work properly for tables', () => {
|
|
||||||
// Table
|
|
||||||
const asset = QUICK_FILTERS_BY_ASSETS[0];
|
|
||||||
|
|
||||||
// Navigate to explore page
|
|
||||||
cy.sidebarClick(SidebarItem.EXPLORE);
|
|
||||||
cy.get(`[data-testid="${asset.tab}"]`).scrollIntoView().click();
|
|
||||||
|
|
||||||
asset.filters
|
|
||||||
.filter((item: FilterItem) => item.select)
|
|
||||||
.map((filter: FilterItem) => {
|
|
||||||
cy.get(`[data-testid="search-dropdown-${filter.label}"]`).click();
|
|
||||||
searchAndClickOnOption(asset, filter, true);
|
|
||||||
|
|
||||||
const querySearchURL = `/api/v1/search/query?*index=${
|
|
||||||
asset.searchIndex
|
|
||||||
}*query_filter=*should*${filter.key}*${encodeURI(
|
|
||||||
Cypress._.toLower(filter.selectOption1).replace(' ', '+')
|
|
||||||
)}*`;
|
|
||||||
|
|
||||||
interceptURL('GET', querySearchURL, 'querySearchAPI');
|
|
||||||
|
|
||||||
cy.get('[data-testid="update-btn"]').click();
|
|
||||||
|
|
||||||
verifyResponseStatusCode('@querySearchAPI', 200);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should search for empty or null filters', () => {
|
|
||||||
const initialQuery = encodeURI(JSON.stringify({ query: { bool: {} } }));
|
|
||||||
// Table
|
|
||||||
interceptURL(
|
|
||||||
'GET',
|
|
||||||
`/api/v1/search/query?*index=table_search_index&*query_filter=${initialQuery}&*`,
|
|
||||||
'initialQueryAPI'
|
|
||||||
);
|
|
||||||
|
|
||||||
const asset = QUICK_FILTERS_BY_ASSETS[0];
|
|
||||||
cy.sidebarClick(SidebarItem.EXPLORE);
|
|
||||||
verifyResponseStatusCode('@initialQueryAPI', 200);
|
|
||||||
cy.get(`[data-testid="${asset.tab}"]`).scrollIntoView().click();
|
|
||||||
asset.filters
|
|
||||||
.filter((item) => SUPPORTED_EMPTY_FILTER_FIELDS.includes(item.key))
|
|
||||||
.map((filter) => {
|
|
||||||
selectNullOption(asset, filter);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should search for multiple values alongwith null filters', () => {
|
|
||||||
const initialQuery = encodeURI(JSON.stringify({ query: { bool: {} } }));
|
|
||||||
// Table
|
|
||||||
interceptURL(
|
|
||||||
'GET',
|
|
||||||
`/api/v1/search/query?*index=table_search_index&*query_filter=${initialQuery}&*`,
|
|
||||||
'initialQueryAPI'
|
|
||||||
);
|
|
||||||
|
|
||||||
const asset = QUICK_FILTERS_BY_ASSETS[0];
|
|
||||||
cy.sidebarClick(SidebarItem.EXPLORE);
|
|
||||||
verifyResponseStatusCode('@initialQueryAPI', 200);
|
|
||||||
cy.get(`[data-testid="${asset.tab}"]`).scrollIntoView().click();
|
|
||||||
// Checking Owner with multiple values
|
|
||||||
asset.filters
|
|
||||||
.filter((item) => SUPPORTED_EMPTY_FILTER_FIELDS.includes(item.key))
|
|
||||||
.map((filter: FilterItem) => {
|
|
||||||
selectNullOption(asset, filter, filter?.selectOptionTestId1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const testIsNullAndIsNotNullFilters = (operatorTitle, queryFilter, alias) => {
|
|
||||||
goToAdvanceSearch();
|
|
||||||
|
|
||||||
// Check Is Null or Is Not Null
|
|
||||||
cy.get('.rule--operator > .ant-select > .ant-select-selector').eq(0).click();
|
|
||||||
cy.get(`[title="${operatorTitle}"]`).click();
|
|
||||||
|
|
||||||
cy.intercept('GET', '/api/v1/search/query?*', (req) => {
|
|
||||||
req.alias = alias;
|
|
||||||
}).as(alias);
|
|
||||||
|
|
||||||
cy.get('[data-testid="apply-btn"]').click();
|
|
||||||
|
|
||||||
cy.wait(`@${alias}`).then((xhr) => {
|
|
||||||
const actualQueryFilter = JSON.parse(xhr.request.query['query_filter']);
|
|
||||||
|
|
||||||
expect(actualQueryFilter).to.deep.equal(queryFilter);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
describe(`Advanced Search Modal`, () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.login();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check isNull and isNotNull filters', () => {
|
|
||||||
// Check Is Null
|
|
||||||
const isNullQuery = {
|
|
||||||
query: {
|
|
||||||
bool: {
|
|
||||||
must: [
|
|
||||||
{
|
|
||||||
bool: {
|
|
||||||
must: [
|
|
||||||
{
|
|
||||||
bool: {
|
|
||||||
must_not: {
|
|
||||||
exists: { field: 'owners.displayName.keyword' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
testIsNullAndIsNotNullFilters('Is null', isNullQuery, 'searchAPI');
|
|
||||||
|
|
||||||
// Check Is Not Null
|
|
||||||
const isNotNullQuery = {
|
|
||||||
query: {
|
|
||||||
bool: {
|
|
||||||
must: [
|
|
||||||
{
|
|
||||||
bool: {
|
|
||||||
must: [{ exists: { field: 'owners.displayName.keyword' } }],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
testIsNullAndIsNotNullFilters(
|
|
||||||
'Is not null',
|
|
||||||
isNotNullQuery,
|
|
||||||
'newSearchAPI'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,135 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// The spec is related to advance search feature
|
|
||||||
|
|
||||||
import {
|
|
||||||
advancedSearchFlowCleanup,
|
|
||||||
advanceSearchPreRequests,
|
|
||||||
checkAddRuleWithOperator,
|
|
||||||
CONDITIONS_MUST,
|
|
||||||
CONDITIONS_MUST_NOT,
|
|
||||||
FIELDS,
|
|
||||||
OPERATOR,
|
|
||||||
} from '../../../common/Utils/AdvancedSearch';
|
|
||||||
import { getToken } from '../../../common/Utils/LocalStorage';
|
|
||||||
|
|
||||||
describe('Search with additional rule', () => {
|
|
||||||
const testData = {
|
|
||||||
user_1: {
|
|
||||||
id: '',
|
|
||||||
},
|
|
||||||
user_2: {
|
|
||||||
id: '',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
before(() => {
|
|
||||||
cy.login();
|
|
||||||
cy.getAllLocalStorage().then((data) => {
|
|
||||||
const token = getToken(data);
|
|
||||||
advanceSearchPreRequests(testData, token);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
after(() => {
|
|
||||||
cy.login();
|
|
||||||
cy.getAllLocalStorage().then((data) => {
|
|
||||||
const token = getToken(data);
|
|
||||||
|
|
||||||
advancedSearchFlowCleanup(token);
|
|
||||||
});
|
|
||||||
Cypress.session.clearAllSavedSessions();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.login();
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.values(OPERATOR).forEach((operator) => {
|
|
||||||
it(`Verify Add Rule functionality for All with ${operator.name} operator & condition ${CONDITIONS_MUST.equalTo.name} and ${CONDITIONS_MUST_NOT.notEqualTo.name} `, () => {
|
|
||||||
Object.values(FIELDS).forEach((field) => {
|
|
||||||
let val = field.searchCriteriaSecondGroup;
|
|
||||||
if (field.owner) {
|
|
||||||
val = field.responseValueSecondGroup;
|
|
||||||
}
|
|
||||||
checkAddRuleWithOperator({
|
|
||||||
condition_1: CONDITIONS_MUST.equalTo.name,
|
|
||||||
condition_2: CONDITIONS_MUST_NOT.notEqualTo.name,
|
|
||||||
fieldId: field.testId,
|
|
||||||
searchCriteria_1: field.isLocalSearch
|
|
||||||
? field.searchCriteriaFirstGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaFirstGroup),
|
|
||||||
searchCriteria_2: field.isLocalSearch
|
|
||||||
? field.searchCriteriaSecondGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaSecondGroup),
|
|
||||||
index_1: 0,
|
|
||||||
index_2: 1,
|
|
||||||
operatorIndex: operator.index,
|
|
||||||
filter_1: CONDITIONS_MUST.equalTo.filter,
|
|
||||||
filter_2: CONDITIONS_MUST_NOT.notEqualTo.filter,
|
|
||||||
response: field.isLocalSearch ? val : Cypress._.toLower(val),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`Verify Add Rule functionality for All with ${operator.name} operator & condition ${CONDITIONS_MUST.anyIn.name} and ${CONDITIONS_MUST_NOT.notIn.name} `, () => {
|
|
||||||
Object.values(FIELDS).forEach((field) => {
|
|
||||||
let val = field.searchCriteriaSecondGroup;
|
|
||||||
if (field.owner) {
|
|
||||||
val = field.responseValueSecondGroup;
|
|
||||||
}
|
|
||||||
checkAddRuleWithOperator({
|
|
||||||
condition_1: CONDITIONS_MUST.anyIn.name,
|
|
||||||
condition_2: CONDITIONS_MUST_NOT.notIn.name,
|
|
||||||
fieldId: field.testId,
|
|
||||||
searchCriteria_1: field.isLocalSearch
|
|
||||||
? field.searchCriteriaFirstGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaFirstGroup),
|
|
||||||
searchCriteria_2: field.isLocalSearch
|
|
||||||
? field.searchCriteriaSecondGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaSecondGroup),
|
|
||||||
index_1: 0,
|
|
||||||
index_2: 1,
|
|
||||||
operatorIndex: operator.index,
|
|
||||||
filter_1: CONDITIONS_MUST.anyIn.filter,
|
|
||||||
filter_2: CONDITIONS_MUST_NOT.notIn.filter,
|
|
||||||
response: field.isLocalSearch ? val : Cypress._.toLower(val),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`Verify Add Rule functionality for All with ${operator.name} operator & condition ${CONDITIONS_MUST.contains.name} and ${CONDITIONS_MUST_NOT.notContains.name} `, () => {
|
|
||||||
Object.values(FIELDS).forEach((field) => {
|
|
||||||
const val = field.searchCriteriaSecondGroup;
|
|
||||||
checkAddRuleWithOperator({
|
|
||||||
condition_1: CONDITIONS_MUST.contains.name,
|
|
||||||
condition_2: CONDITIONS_MUST_NOT.notContains.name,
|
|
||||||
fieldId: field.testId,
|
|
||||||
searchCriteria_1: field.isLocalSearch
|
|
||||||
? field.searchCriteriaFirstGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaFirstGroup),
|
|
||||||
searchCriteria_2: field.isLocalSearch
|
|
||||||
? field.searchCriteriaSecondGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaSecondGroup),
|
|
||||||
index_1: 0,
|
|
||||||
index_2: 1,
|
|
||||||
operatorIndex: operator.index,
|
|
||||||
filter_1: CONDITIONS_MUST.contains.filter,
|
|
||||||
filter_2: CONDITIONS_MUST_NOT.notContains.filter,
|
|
||||||
response: field.isLocalSearch ? val : Cypress._.toLower(val),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,120 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// The spec is related to advance search feature
|
|
||||||
|
|
||||||
import {
|
|
||||||
advancedSearchFlowCleanup,
|
|
||||||
advanceSearchPreRequests,
|
|
||||||
checkAddGroupWithOperator,
|
|
||||||
CONDITIONS_MUST,
|
|
||||||
CONDITIONS_MUST_NOT,
|
|
||||||
FIELDS,
|
|
||||||
OPERATOR,
|
|
||||||
} from '../../../common/Utils/AdvancedSearch';
|
|
||||||
import { getToken } from '../../../common/Utils/LocalStorage';
|
|
||||||
|
|
||||||
describe('Group search', () => {
|
|
||||||
const testData = {
|
|
||||||
user_1: {
|
|
||||||
id: '',
|
|
||||||
},
|
|
||||||
user_2: {
|
|
||||||
id: '',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
before(() => {
|
|
||||||
cy.login();
|
|
||||||
cy.getAllLocalStorage().then((data) => {
|
|
||||||
const token = getToken(data);
|
|
||||||
advanceSearchPreRequests(testData, token);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
after(() => {
|
|
||||||
cy.login();
|
|
||||||
cy.getAllLocalStorage().then((data) => {
|
|
||||||
const token = getToken(data);
|
|
||||||
|
|
||||||
advancedSearchFlowCleanup(token);
|
|
||||||
});
|
|
||||||
Cypress.session.clearAllSavedSessions();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.login();
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.values(OPERATOR).forEach((operator) => {
|
|
||||||
it(`Verify Add group functionality for All with ${operator.name} operator & condition ${CONDITIONS_MUST.equalTo.name} and ${CONDITIONS_MUST_NOT.notEqualTo.name} `, () => {
|
|
||||||
Object.values(FIELDS).forEach((field) => {
|
|
||||||
checkAddGroupWithOperator({
|
|
||||||
condition_1: CONDITIONS_MUST.equalTo.name,
|
|
||||||
condition_2: CONDITIONS_MUST_NOT.notEqualTo.name,
|
|
||||||
fieldId: field.testId,
|
|
||||||
searchCriteria_1: field.isLocalSearch
|
|
||||||
? field.searchCriteriaFirstGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaFirstGroup),
|
|
||||||
searchCriteria_2: field.isLocalSearch
|
|
||||||
? field.searchCriteriaSecondGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaSecondGroup),
|
|
||||||
index_1: 0,
|
|
||||||
index_2: 1,
|
|
||||||
operatorIndex: operator.index,
|
|
||||||
isLocalSearch: field.isLocalSearch,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`Verify Add group functionality for All with ${operator.name} operator & condition ${CONDITIONS_MUST.anyIn.name} and ${CONDITIONS_MUST_NOT.notIn.name} `, () => {
|
|
||||||
Object.values(FIELDS).forEach((field) => {
|
|
||||||
checkAddGroupWithOperator({
|
|
||||||
condition_1: CONDITIONS_MUST.anyIn.name,
|
|
||||||
condition_2: CONDITIONS_MUST_NOT.notIn.name,
|
|
||||||
fieldId: field.testId,
|
|
||||||
searchCriteria_1: field.isLocalSearch
|
|
||||||
? field.searchCriteriaFirstGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaFirstGroup),
|
|
||||||
searchCriteria_2: field.isLocalSearch
|
|
||||||
? field.searchCriteriaSecondGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaSecondGroup),
|
|
||||||
index_1: 0,
|
|
||||||
index_2: 1,
|
|
||||||
operatorIndex: operator.index,
|
|
||||||
isLocalSearch: field.isLocalSearch,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`Verify Add group functionality for All with ${operator.name} operator & condition ${CONDITIONS_MUST.contains.name} and ${CONDITIONS_MUST_NOT.notContains.name} `, () => {
|
|
||||||
Object.values(FIELDS).forEach((field) => {
|
|
||||||
checkAddGroupWithOperator({
|
|
||||||
condition_1: CONDITIONS_MUST.contains.name,
|
|
||||||
condition_2: CONDITIONS_MUST_NOT.notContains.name,
|
|
||||||
fieldId: field.testId,
|
|
||||||
searchCriteria_1: field.isLocalSearch
|
|
||||||
? field.searchCriteriaFirstGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaFirstGroup),
|
|
||||||
searchCriteria_2: field.isLocalSearch
|
|
||||||
? field.searchCriteriaSecondGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaSecondGroup),
|
|
||||||
index_1: 0,
|
|
||||||
index_2: 1,
|
|
||||||
operatorIndex: operator.index,
|
|
||||||
isLocalSearch: field.isLocalSearch,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// The spec is related to advance search feature
|
|
||||||
|
|
||||||
import {
|
|
||||||
advancedSearchFlowCleanup,
|
|
||||||
advanceSearchPreRequests,
|
|
||||||
checkMustPaths,
|
|
||||||
checkMust_notPaths,
|
|
||||||
CONDITIONS_MUST,
|
|
||||||
CONDITIONS_MUST_NOT,
|
|
||||||
FIELDS,
|
|
||||||
} from '../../../common/Utils/AdvancedSearch';
|
|
||||||
import { getToken } from '../../../common/Utils/LocalStorage';
|
|
||||||
|
|
||||||
describe('Single filed search', () => {
|
|
||||||
const testData = {
|
|
||||||
user_1: {
|
|
||||||
id: '',
|
|
||||||
},
|
|
||||||
user_2: {
|
|
||||||
id: '',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
before(() => {
|
|
||||||
cy.login();
|
|
||||||
cy.getAllLocalStorage().then((data) => {
|
|
||||||
const token = getToken(data);
|
|
||||||
advanceSearchPreRequests(testData, token);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
after(() => {
|
|
||||||
cy.login();
|
|
||||||
cy.getAllLocalStorage().then((data) => {
|
|
||||||
const token = getToken(data);
|
|
||||||
|
|
||||||
advancedSearchFlowCleanup(token);
|
|
||||||
});
|
|
||||||
Cypress.session.clearAllSavedSessions();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.login();
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.values(FIELDS).forEach((field) => {
|
|
||||||
it(`Verify advance search results for ${field.name} field and all conditions`, () => {
|
|
||||||
Object.values(CONDITIONS_MUST).forEach((condition) => {
|
|
||||||
checkMustPaths(
|
|
||||||
condition.name,
|
|
||||||
field.testId,
|
|
||||||
field.isLocalSearch
|
|
||||||
? field.searchCriteriaFirstGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaFirstGroup),
|
|
||||||
0,
|
|
||||||
field.responseValueFirstGroup,
|
|
||||||
field.isLocalSearch
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.values(CONDITIONS_MUST_NOT).forEach((condition) => {
|
|
||||||
checkMust_notPaths(
|
|
||||||
condition.name,
|
|
||||||
field.testId,
|
|
||||||
field.isLocalSearch
|
|
||||||
? field.searchCriteriaFirstGroup
|
|
||||||
: Cypress._.toLower(field.searchCriteriaFirstGroup),
|
|
||||||
0,
|
|
||||||
field.responseValueFirstGroup,
|
|
||||||
field.isLocalSearch
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* 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 from '@playwright/test';
|
||||||
|
import { SidebarItem } from '../../constant/sidebar';
|
||||||
|
import { TableClass } from '../../support/entity/TableClass';
|
||||||
|
import { TopicClass } from '../../support/entity/TopicClass';
|
||||||
|
import { UserClass } from '../../support/user/UserClass';
|
||||||
|
import {
|
||||||
|
FIELDS,
|
||||||
|
OPERATOR,
|
||||||
|
runRuleGroupTests,
|
||||||
|
verifyAllConditions,
|
||||||
|
} from '../../utils/advancedSearch';
|
||||||
|
import { createNewPage, redirectToHomePage } from '../../utils/common';
|
||||||
|
import { addMultiOwner, assignTag, assignTier } from '../../utils/entity';
|
||||||
|
import { sidebarClick } from '../../utils/sidebar';
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
let searchCriteria = {};
|
||||||
|
|
||||||
|
test.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||||
|
test.setTimeout(150000);
|
||||||
|
|
||||||
|
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),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 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 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 assignTag(page, 'PII.None');
|
||||||
|
|
||||||
|
// Add Tier To the topic 1
|
||||||
|
await topic1.visitEntityPage(page);
|
||||||
|
await assignTier(page, 'Tier1', topic1.endpoint);
|
||||||
|
|
||||||
|
// Add Tier To the topic 2
|
||||||
|
await topic2.visitEntityPage(page);
|
||||||
|
await assignTier(page, 'Tier2', topic2.endpoint);
|
||||||
|
|
||||||
|
// Update Search Criteria here
|
||||||
|
searchCriteria = {
|
||||||
|
'owners.displayName.keyword': [user1.getUserName(), user2.getUserName()],
|
||||||
|
'tags.tagFQN': ['PersonalData.Personal', 'PII.None'],
|
||||||
|
'tier.tagFQN': ['Tier.Tier1', 'Tier.Tier2'],
|
||||||
|
'service.displayName.keyword': [table1.service.name, table2.service.name],
|
||||||
|
'database.displayName.keyword': [
|
||||||
|
table1.database.name,
|
||||||
|
table2.database.name,
|
||||||
|
],
|
||||||
|
'databaseSchema.displayName.keyword': [
|
||||||
|
table1.schema.name,
|
||||||
|
table2.schema.name,
|
||||||
|
],
|
||||||
|
'columns.name.keyword': ['email', 'shop_id'],
|
||||||
|
};
|
||||||
|
|
||||||
|
await afterAction();
|
||||||
|
});
|
||||||
|
|
||||||
|
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),
|
||||||
|
]);
|
||||||
|
await afterAction();
|
||||||
|
});
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await redirectToHomePage(page);
|
||||||
|
await sidebarClick(page, SidebarItem.EXPLORE);
|
||||||
|
});
|
||||||
|
|
||||||
|
FIELDS.forEach((field) => {
|
||||||
|
test(`Verify All conditions for ${field.id} field`, async ({ page }) => {
|
||||||
|
test.slow(true);
|
||||||
|
|
||||||
|
await verifyAllConditions(page, field, searchCriteria[field.name][0]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.values(OPERATOR).forEach(({ name: operator }) => {
|
||||||
|
FIELDS.forEach((field) => {
|
||||||
|
// Rule based search
|
||||||
|
test(`Verify Rule functionality for field ${field.id} with ${operator} operator`, async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
test.slow(true);
|
||||||
|
|
||||||
|
await runRuleGroupTests(page, field, operator, false, searchCriteria);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Group based search
|
||||||
|
test(`Verify Group functionality for field ${field.id} with ${operator} operator`, async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
test.slow(true);
|
||||||
|
|
||||||
|
await runRuleGroupTests(page, field, operator, true, searchCriteria);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,471 @@
|
|||||||
|
/*
|
||||||
|
* 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, Locator, Page } from '@playwright/test';
|
||||||
|
import { clickOutside } from './common';
|
||||||
|
|
||||||
|
type EntityFields = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
localSearch: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FIELDS: EntityFields[] = [
|
||||||
|
{
|
||||||
|
id: 'Owner',
|
||||||
|
name: 'owners.displayName.keyword',
|
||||||
|
localSearch: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Tags',
|
||||||
|
name: 'tags.tagFQN',
|
||||||
|
localSearch: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Tier',
|
||||||
|
name: 'tier.tagFQN',
|
||||||
|
localSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Service',
|
||||||
|
name: 'service.displayName.keyword',
|
||||||
|
localSearch: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Database',
|
||||||
|
name: 'database.displayName.keyword',
|
||||||
|
localSearch: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Database Schema',
|
||||||
|
name: 'databaseSchema.displayName.keyword',
|
||||||
|
localSearch: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Column',
|
||||||
|
name: 'columns.name.keyword',
|
||||||
|
localSearch: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const OPERATOR = {
|
||||||
|
AND: {
|
||||||
|
name: 'AND',
|
||||||
|
index: 1,
|
||||||
|
},
|
||||||
|
OR: {
|
||||||
|
name: 'OR',
|
||||||
|
index: 2,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CONDITIONS_MUST = {
|
||||||
|
equalTo: {
|
||||||
|
name: '==',
|
||||||
|
filter: 'must',
|
||||||
|
},
|
||||||
|
contains: {
|
||||||
|
name: 'Contains',
|
||||||
|
filter: 'must',
|
||||||
|
},
|
||||||
|
anyIn: {
|
||||||
|
name: 'Any in',
|
||||||
|
filter: 'must',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CONDITIONS_MUST_NOT = {
|
||||||
|
notEqualTo: {
|
||||||
|
name: '!=',
|
||||||
|
filter: 'must_not',
|
||||||
|
},
|
||||||
|
notIn: {
|
||||||
|
name: 'Not in',
|
||||||
|
filter: 'must_not',
|
||||||
|
},
|
||||||
|
notContains: {
|
||||||
|
name: 'Not contains',
|
||||||
|
filter: 'must_not',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NULL_CONDITIONS = {
|
||||||
|
isNull: {
|
||||||
|
name: 'Is null',
|
||||||
|
filter: 'empty',
|
||||||
|
},
|
||||||
|
isNotNull: {
|
||||||
|
name: 'Is not null',
|
||||||
|
filter: 'empty',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const showAdvancedSearchDialog = async (page: Page) => {
|
||||||
|
await page.getByTestId('advance-search-button').click();
|
||||||
|
|
||||||
|
await expect(page.locator('[role="dialog"].ant-modal')).toBeVisible();
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectOption = async (
|
||||||
|
page: Page,
|
||||||
|
dropdownLocator: Locator,
|
||||||
|
optionTitle: string
|
||||||
|
) => {
|
||||||
|
await dropdownLocator.click();
|
||||||
|
await page.click(`.ant-select-dropdown:visible [title="${optionTitle}"]`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fillRule = async (
|
||||||
|
page: Page,
|
||||||
|
{
|
||||||
|
condition,
|
||||||
|
field,
|
||||||
|
searchCriteria,
|
||||||
|
index,
|
||||||
|
}: {
|
||||||
|
condition: string;
|
||||||
|
field: EntityFields;
|
||||||
|
searchCriteria: string;
|
||||||
|
index: number;
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
const ruleLocator = page.locator('.rule').nth(index - 1);
|
||||||
|
|
||||||
|
// Perform click on rule field
|
||||||
|
await selectOption(
|
||||||
|
page,
|
||||||
|
ruleLocator.locator('.rule--field .ant-select'),
|
||||||
|
field.id
|
||||||
|
);
|
||||||
|
|
||||||
|
// Perform click on operator
|
||||||
|
await selectOption(
|
||||||
|
page,
|
||||||
|
ruleLocator.locator('.rule--operator .ant-select'),
|
||||||
|
condition
|
||||||
|
);
|
||||||
|
|
||||||
|
if (searchCriteria) {
|
||||||
|
const inputElement = ruleLocator.locator(
|
||||||
|
'.rule--widget--TEXT input[type="text"]'
|
||||||
|
);
|
||||||
|
const searchData = field.localSearch
|
||||||
|
? searchCriteria
|
||||||
|
: searchCriteria.toLowerCase();
|
||||||
|
|
||||||
|
if (await inputElement.isVisible()) {
|
||||||
|
await inputElement.fill(searchData);
|
||||||
|
} else {
|
||||||
|
const dropdownInput = ruleLocator.locator(
|
||||||
|
'.widget--widget > .ant-select > .ant-select-selector input'
|
||||||
|
);
|
||||||
|
let aggregateRes;
|
||||||
|
|
||||||
|
if (!field.localSearch) {
|
||||||
|
aggregateRes = page.waitForResponse('/api/v1/search/aggregate?*');
|
||||||
|
}
|
||||||
|
|
||||||
|
await dropdownInput.click();
|
||||||
|
await dropdownInput.fill(searchData);
|
||||||
|
|
||||||
|
if (aggregateRes) {
|
||||||
|
await aggregateRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator(`.ant-select-dropdown [title="${searchData}"]`)
|
||||||
|
.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
await clickOutside(page);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const checkMustPaths = async (
|
||||||
|
page: Page,
|
||||||
|
{ condition, field, searchCriteria, index }
|
||||||
|
) => {
|
||||||
|
const searchData = field.localSearch
|
||||||
|
? searchCriteria
|
||||||
|
: searchCriteria.toLowerCase();
|
||||||
|
|
||||||
|
await fillRule(page, {
|
||||||
|
condition,
|
||||||
|
field,
|
||||||
|
searchCriteria,
|
||||||
|
index,
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchRes = page.waitForResponse(
|
||||||
|
'/api/v1/search/query?*index=dataAsset&from=0&size=10*'
|
||||||
|
);
|
||||||
|
await page.getByTestId('apply-btn').click();
|
||||||
|
await searchRes.then(async (res) => {
|
||||||
|
await expect(res.request().url()).toContain(encodeURI(searchData));
|
||||||
|
|
||||||
|
await res.json().then(async (json) => {
|
||||||
|
await expect(JSON.stringify(json.hits.hits)).toContain(searchCriteria);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByTestId('advance-search-filter-container')
|
||||||
|
).toContainText(searchData);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const checkMustNotPaths = async (
|
||||||
|
page: Page,
|
||||||
|
{ condition, field, searchCriteria, index }
|
||||||
|
) => {
|
||||||
|
const searchData = field.localSearch
|
||||||
|
? searchCriteria
|
||||||
|
: searchCriteria.toLowerCase();
|
||||||
|
|
||||||
|
await fillRule(page, {
|
||||||
|
condition,
|
||||||
|
field,
|
||||||
|
searchCriteria,
|
||||||
|
index,
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchRes = page.waitForResponse(
|
||||||
|
'/api/v1/search/query?*index=dataAsset&from=0&size=10*'
|
||||||
|
);
|
||||||
|
await page.getByTestId('apply-btn').click();
|
||||||
|
await searchRes.then(async (res) => {
|
||||||
|
await expect(res.request().url()).toContain(encodeURI(searchData));
|
||||||
|
|
||||||
|
if (!['columns.name.keyword'].includes(field.name)) {
|
||||||
|
await res.json().then(async (json) => {
|
||||||
|
await expect(JSON.stringify(json.hits.hits)).not.toContain(
|
||||||
|
searchCriteria
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByTestId('advance-search-filter-container')
|
||||||
|
).toContainText(searchData);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const checkNullPaths = async (
|
||||||
|
page: Page,
|
||||||
|
{ condition, field, searchCriteria, index }
|
||||||
|
) => {
|
||||||
|
await fillRule(page, {
|
||||||
|
condition,
|
||||||
|
field,
|
||||||
|
searchCriteria,
|
||||||
|
index,
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchRes = page.waitForResponse(
|
||||||
|
'/api/v1/search/query?*index=dataAsset&from=0&size=10*'
|
||||||
|
);
|
||||||
|
await page.getByTestId('apply-btn').click();
|
||||||
|
await searchRes.then(async (res) => {
|
||||||
|
const urlParams = new URLSearchParams(res.request().url());
|
||||||
|
const queryFilter = JSON.parse(urlParams.get('query_filter') ?? '');
|
||||||
|
|
||||||
|
const resultQuery =
|
||||||
|
condition === 'Is null'
|
||||||
|
? {
|
||||||
|
query: {
|
||||||
|
bool: {
|
||||||
|
must: [
|
||||||
|
{
|
||||||
|
bool: {
|
||||||
|
must: [
|
||||||
|
{
|
||||||
|
bool: {
|
||||||
|
must_not: {
|
||||||
|
exists: { field: field.name },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
query: {
|
||||||
|
bool: {
|
||||||
|
must: [
|
||||||
|
{
|
||||||
|
bool: {
|
||||||
|
must: [{ exists: { field: field.name } }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await expect(JSON.stringify(queryFilter)).toContain(
|
||||||
|
JSON.stringify(resultQuery)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const verifyAllConditions = async (
|
||||||
|
page: Page,
|
||||||
|
field: EntityFields,
|
||||||
|
searchCriteria: string
|
||||||
|
) => {
|
||||||
|
// Check for Must conditions
|
||||||
|
for (const condition of Object.values(CONDITIONS_MUST)) {
|
||||||
|
await showAdvancedSearchDialog(page);
|
||||||
|
await checkMustPaths(page, {
|
||||||
|
condition: condition.name,
|
||||||
|
field,
|
||||||
|
searchCriteria: searchCriteria,
|
||||||
|
index: 1,
|
||||||
|
});
|
||||||
|
await page.getByTestId('clear-filters').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for Must Not conditions
|
||||||
|
for (const condition of Object.values(CONDITIONS_MUST_NOT)) {
|
||||||
|
await showAdvancedSearchDialog(page);
|
||||||
|
await checkMustNotPaths(page, {
|
||||||
|
condition: condition.name,
|
||||||
|
field,
|
||||||
|
searchCriteria: searchCriteria,
|
||||||
|
index: 1,
|
||||||
|
});
|
||||||
|
await page.getByTestId('clear-filters').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for Null and Not Null conditions
|
||||||
|
for (const condition of Object.values(NULL_CONDITIONS)) {
|
||||||
|
await showAdvancedSearchDialog(page);
|
||||||
|
await checkNullPaths(page, {
|
||||||
|
condition: condition.name,
|
||||||
|
field,
|
||||||
|
searchCriteria: undefined,
|
||||||
|
index: 1,
|
||||||
|
});
|
||||||
|
await page.getByTestId('clear-filters').click();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const checkAddRuleOrGroupWithOperator = async (
|
||||||
|
page,
|
||||||
|
{
|
||||||
|
field,
|
||||||
|
operator,
|
||||||
|
condition1,
|
||||||
|
condition2,
|
||||||
|
searchCriteria1,
|
||||||
|
searchCriteria2,
|
||||||
|
}: {
|
||||||
|
field: EntityFields;
|
||||||
|
operator: string;
|
||||||
|
condition1: string;
|
||||||
|
condition2: string;
|
||||||
|
searchCriteria1: string;
|
||||||
|
searchCriteria2: string;
|
||||||
|
},
|
||||||
|
isGroupTest = false
|
||||||
|
) => {
|
||||||
|
await showAdvancedSearchDialog(page);
|
||||||
|
await fillRule(page, {
|
||||||
|
condition: condition1,
|
||||||
|
field,
|
||||||
|
searchCriteria: searchCriteria1,
|
||||||
|
index: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isGroupTest) {
|
||||||
|
await page.getByTestId('advanced-search-add-rule').nth(1).click();
|
||||||
|
} else {
|
||||||
|
await page.getByTestId('advanced-search-add-group').first().click();
|
||||||
|
}
|
||||||
|
|
||||||
|
await fillRule(page, {
|
||||||
|
condition: condition2,
|
||||||
|
field,
|
||||||
|
searchCriteria: searchCriteria2,
|
||||||
|
index: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (operator === 'OR') {
|
||||||
|
await page
|
||||||
|
.getByTestId('advanced-search-modal')
|
||||||
|
.getByRole('button', { name: 'Or' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchRes = page.waitForResponse(
|
||||||
|
'/api/v1/search/query?*index=dataAsset&from=0&size=10*'
|
||||||
|
);
|
||||||
|
await page.getByTestId('apply-btn').click();
|
||||||
|
await searchRes;
|
||||||
|
await searchRes.then(async (res) => {
|
||||||
|
await res.json().then(async (json) => {
|
||||||
|
if (field.id !== 'Column') {
|
||||||
|
if (operator === 'Or') {
|
||||||
|
await expect(JSON.stringify(json)).toContain(searchCriteria1);
|
||||||
|
await expect(JSON.stringify(json)).toContain(searchCriteria2);
|
||||||
|
} else {
|
||||||
|
await expect(JSON.stringify(json)).toContain(searchCriteria1);
|
||||||
|
await expect(JSON.stringify(json)).not.toContain(searchCriteria2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const runRuleGroupTests = async (
|
||||||
|
page: Page,
|
||||||
|
field: EntityFields,
|
||||||
|
operator: string,
|
||||||
|
isGroupTest: boolean,
|
||||||
|
searchCriteria: Record<string, string[]>
|
||||||
|
) => {
|
||||||
|
const searchCriteria1 = searchCriteria[field.name][0];
|
||||||
|
const searchCriteria2 = searchCriteria[field.name][1];
|
||||||
|
|
||||||
|
const testCases = [
|
||||||
|
{
|
||||||
|
condition1: CONDITIONS_MUST.equalTo.name,
|
||||||
|
condition2: CONDITIONS_MUST_NOT.notEqualTo.name,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
condition1: CONDITIONS_MUST.contains.name,
|
||||||
|
condition2: CONDITIONS_MUST_NOT.notContains.name,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
condition1: CONDITIONS_MUST.anyIn.name,
|
||||||
|
condition2: CONDITIONS_MUST_NOT.notIn.name,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const { condition1, condition2 } of testCases) {
|
||||||
|
await checkAddRuleOrGroupWithOperator(
|
||||||
|
page,
|
||||||
|
{
|
||||||
|
field,
|
||||||
|
operator,
|
||||||
|
condition1,
|
||||||
|
condition2,
|
||||||
|
searchCriteria1,
|
||||||
|
searchCriteria2,
|
||||||
|
},
|
||||||
|
isGroupTest
|
||||||
|
);
|
||||||
|
await page.getByTestId('clear-filters').click();
|
||||||
|
}
|
||||||
|
};
|
@ -115,6 +115,7 @@ export const renderAdvanceSearchButtons: RenderSettings['renderButton'] = (
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
CloseCircleOutlined as React.ForwardRefExoticComponent<any>
|
CloseCircleOutlined as React.ForwardRefExoticComponent<any>
|
||||||
}
|
}
|
||||||
|
data-testid="advanced-search-delete-rule"
|
||||||
onClick={props?.onClick}
|
onClick={props?.onClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -123,6 +124,7 @@ export const renderAdvanceSearchButtons: RenderSettings['renderButton'] = (
|
|||||||
<Button
|
<Button
|
||||||
ghost
|
ghost
|
||||||
className="action action--ADD-RULE"
|
className="action action--ADD-RULE"
|
||||||
|
data-testid="advanced-search-add-rule"
|
||||||
icon={<PlusOutlined />}
|
icon={<PlusOutlined />}
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={props?.onClick}>
|
onClick={props?.onClick}>
|
||||||
@ -133,6 +135,7 @@ export const renderAdvanceSearchButtons: RenderSettings['renderButton'] = (
|
|||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
className="action action--ADD-GROUP"
|
className="action action--ADD-GROUP"
|
||||||
|
data-testid="advanced-search-add-group"
|
||||||
icon={<PlusOutlined />}
|
icon={<PlusOutlined />}
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={props?.onClick}>
|
onClick={props?.onClick}>
|
||||||
@ -147,6 +150,7 @@ export const renderAdvanceSearchButtons: RenderSettings['renderButton'] = (
|
|||||||
})}
|
})}
|
||||||
className="action action--DELETE cursor-pointer align-middle"
|
className="action action--DELETE cursor-pointer align-middle"
|
||||||
component={IconDeleteColored}
|
component={IconDeleteColored}
|
||||||
|
data-testid="advanced-search-delete-group"
|
||||||
style={{ fontSize: '16px' }}
|
style={{ fontSize: '16px' }}
|
||||||
onClick={props?.onClick as () => void}
|
onClick={props?.onClick as () => void}
|
||||||
/>
|
/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user