Skip to content

Commit

Permalink
Fix #16278 : Search to display Draft glossaryTerms on Explore page (#…
Browse files Browse the repository at this point in the history
…16462)

* Fix #16278 : Search to display Draft glossaryTerms as well on Explore page

* add term status quick filter

* change aggregation key for status field

* change aggregation key for status field

* add lowercase_normalizer in status filed for aggregate api

* add cypress tests

* fix cypress

---------

Co-authored-by: karanh37 <[email protected]>
Co-authored-by: Karan Hotchandani <[email protected]>
  • Loading branch information
3 people authored May 30, 2024
1 parent 541df25 commit ae5e9d6
Show file tree
Hide file tree
Showing 23 changed files with 233 additions and 125 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -380,10 +380,7 @@ public Response search(SearchRequest request) throws IOException {
}

if (request.getIndex().equalsIgnoreCase("glossary_term_search_index")) {
searchSourceBuilder.query(
QueryBuilders.boolQuery()
.must(searchSourceBuilder.query())
.must(QueryBuilders.matchQuery("status", "Approved")));
searchSourceBuilder.query(QueryBuilders.boolQuery().must(searchSourceBuilder.query()));

if (request.isGetHierarchy()) {
/*
Expand Down Expand Up @@ -1170,6 +1167,7 @@ private static SearchSourceBuilder buildGlossaryTermSearchBuilder(
AggregationBuilders.terms("glossary.name.keyword").field("glossary.name.keyword"));
searchSourceBuilder.aggregation(
AggregationBuilders.terms("fqnParts_agg").field("fqnParts").size(1000));
searchSourceBuilder.aggregation(AggregationBuilders.terms("status").field("status"));
return addAggregation(searchSourceBuilder);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,10 +378,7 @@ public Response search(SearchRequest request) throws IOException {
}

if (request.getIndex().equalsIgnoreCase("glossary_term_search_index")) {
searchSourceBuilder.query(
QueryBuilders.boolQuery()
.must(searchSourceBuilder.query())
.must(QueryBuilders.matchQuery("status", "Approved")));
searchSourceBuilder.query(QueryBuilders.boolQuery().must(searchSourceBuilder.query()));

if (request.isGetHierarchy()) {
/*
Expand Down Expand Up @@ -1169,6 +1166,7 @@ private static SearchSourceBuilder buildGlossaryTermSearchBuilder(
AggregationBuilders.terms("glossary.name.keyword").field("glossary.name.keyword"));
searchSourceBuilder.aggregation(
AggregationBuilders.terms("fqnParts_agg").field("fqnParts").size(1000));
searchSourceBuilder.aggregation(AggregationBuilders.terms("status").field("status"));
return addAggregation(searchSourceBuilder);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@
"type": "text"
},
"status": {
"type": "text"
"type": "keyword",
"normalizer": "lowercase_normalizer"
},
"entityType": {
"type": "keyword"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,8 @@
"type": "text"
},
"status": {
"type": "text"
"type": "keyword",
"normalizer": "lowercase_normalizer"
},
"entityType": {
"type": "keyword"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,15 +342,16 @@
"type": "keyword"
},
"state": {
"type": "keyword"
"type": "keyword",
"normalizer": "lowercase_normalizer"
}
}
},
"deleted": {
"type": "text"
},
"status": {
"type": "text"
"type": "keyword"
},
"suggest": {
"type": "completion",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ export const deleteEntity = (
'getDatabaseSchemas'
);

cy.get('[data-testid="breadcrumb-link"]').last().click();
cy.get('[data-testid="breadcrumb-link"]:last-child').click({ force: true });
verifyResponseStatusCode('@getDatabaseSchemas', 200);

cy.get('[data-testid="show-deleted"]')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ export const GLOSSARY_DROPDOWN_ITEMS = [
label: 'Glossaries',
key: 'glossary.name.keyword',
},
{
label: 'Status',
key: 'status',
},
];

export const TAG_DROPDOWN_ITEMS = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -423,19 +423,22 @@ export const NEW_GLOSSARY_TERMS = {
description: 'This is the Cypress Purchase',
synonyms: 'buy,collect,acquire',
fullyQualifiedName: `${cypressGlossaryName}.CypressPurchase`,
owner: 'Aaron Johnson',
},
term_2: {
name: 'CypressSales',
description: 'This is the Cypress Sales',
synonyms: 'give,disposal,deal',
fullyQualifiedName: `${cypressGlossaryName}.CypressSales`,
owner: 'Aaron Johnson',
},
term_3: {
name: 'Cypress Space',
description: 'This is the Cypress with space',
synonyms: 'tea,coffee,water',
fullyQualifiedName: `${cypressGlossaryName}.Cypress Space`,
assets: COMMON_ASSETS,
owner: 'admin',
},
};
export const GLOSSARY_TERM_WITH_DETAILS = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,28 @@
* limitations under the License.
*/

import { uuid } from './constants';

export const GLOSSARY_OWNER_LINK_TEST_ID = 'glossary-right-panel-owner-link';

export const GLOSSARY_DETAILS1 = {
name: `Cypress%QFTEST ${uuid()}`,
displayName: `Cypress % QFTEST ${uuid()}`,
description: 'Test Glossary',
reviewers: [],
tags: [],
mutuallyExclusive: false,
};

export const GLOSSARY_TERM_DETAILS1 = {
name: `CypressQFTEST_TERM-${uuid()}`,
displayName: 'Cypress QFTEST_TERM',
description: 'Quick filter test.',
reviewers: [],
relatedTerms: [],
synonyms: [],
mutuallyExclusive: false,
tags: [],
style: {},
glossary: GLOSSARY_DETAILS1.name,
};
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
generateRandomUser,
removeOwner,
} from '../../common/Utils/Owner';
import { GLOSSARY_DROPDOWN_ITEMS } from '../../constants/advancedSearchQuickFilters.constants';
import {
COLUMN_NAME_FOR_APPLY_GLOSSARY_TERM,
CYPRESS_ASSETS_GLOSSARY,
Expand All @@ -52,6 +53,27 @@ const userName = `${CREDENTIALS.firstName}${CREDENTIALS.lastName}`;

let createdUserId = '';

const selectOwner = (ownerName: string, dataTestId?: string) => {
interceptURL('GET', '/api/v1/users?*isBot=false*', 'getUsers');
cy.get('[data-testid="add-owner"]').scrollIntoView().click();
cy.get("[data-testid='select-owner-tabs']").should('be.visible');
cy.get('.ant-tabs [id*=tab-users]').click();
verifyResponseStatusCode('@getUsers', 200);
interceptURL(
'GET',
`api/v1/search/query?q=*&index=user_search_index*`,
'searchOwner'
);

cy.get('[data-testid="owner-select-users-search-bar"]').type(ownerName);
verifyResponseStatusCode('@searchOwner', 200);
cy.get(`.ant-popover [title="${ownerName}"]`).click();
cy.get(`[data-testid=${dataTestId ?? 'owner-link'}]`).should(
'contain',
ownerName
);
};

const visitGlossaryTermPage = (
termName: string,
fqn: string,
Expand Down Expand Up @@ -175,6 +197,17 @@ const checkDisplayName = (displayName) => {
});
};

const verifyGlossaryTermDataInTable = (term, status: string) => {
const escapedName = Cypress.$.escapeSelector(term.fullyQualifiedName);
const selector = `[data-row-key=${escapedName}]`;
cy.get(selector).scrollIntoView().should('be.visible');
cy.get(`${selector} [data-testid="${escapedName}-status"]`).contains(status);
// If empty owner, the creator is the owner
cy.get(`${selector} [data-testid="owner-link"]`).contains(
term.owner ?? 'admin'
);
};

const checkAssetsCount = (assetsCount) => {
cy.get('[data-testid="assets"] [data-testid="filter-count"]')
.scrollIntoView()
Expand Down Expand Up @@ -268,6 +301,10 @@ const fillGlossaryTermDetails = (
.scrollIntoView()
.type(term.color);
}

if (term.owner) {
selectOwner(term.owner, 'owner-container');
}
};

const addAssetToGlossaryTerm = (glossaryTerm, glossary) => {
Expand Down Expand Up @@ -566,7 +603,6 @@ const downVoting = (api: string) => {

cy.wait(api).then(({ request, response }) => {
expect(request.body.updatedVoteType).to.equal('votedDown');

expect(response.statusCode).to.equal(200);
});

Expand All @@ -582,7 +618,6 @@ const initialVoting = (api: string) => {

cy.wait(api).then(({ request, response }) => {
expect(request.body.updatedVoteType).to.equal('unVoted');

expect(response.statusCode).to.equal(200);
});

Expand All @@ -597,9 +632,7 @@ const voteGlossary = (isGlossary?: boolean) => {
interceptURL('PUT', '/api/v1/glossaryTerms/*/vote', 'voteGlossaryTerm');
}
upVoting(isGlossary ? '@voteGlossary' : '@voteGlossaryTerm');

downVoting(isGlossary ? '@voteGlossary' : '@voteGlossaryTerm');

initialVoting(isGlossary ? '@voteGlossary' : '@voteGlossaryTerm');
};

Expand Down Expand Up @@ -716,6 +749,29 @@ const deleteUser = () => {
});
};

const verifyStatusFilterInExplore = (statusField: string) => {
const fieldName = Cypress._.toLower(statusField);
const glossaryTermStatusFilter = GLOSSARY_DROPDOWN_ITEMS.find(
(item) => item.key === 'status'
);

cy.sidebarClick(SidebarItem.EXPLORE);
cy.get(`[data-testid="glossary terms-tab"]`).scrollIntoView().click();
cy.get(`[data-testid="search-dropdown-${glossaryTermStatusFilter.label}"]`)
.scrollIntoView()
.click();
cy.get(`[data-testid=${fieldName}]`)
.should('exist')
.and('be.visible')
.click();

const querySearchURL = `/api/v1/search/query?*index=glossary_term_search_index*query_filter=*should*${glossaryTermStatusFilter.key}*${fieldName}*`;

interceptURL('GET', querySearchURL, 'querySearchAPI');
cy.get('[data-testid="update-btn"]').click();
verifyResponseStatusCode('@querySearchAPI', 200);
};

describe('Glossary page should work properly', { tags: 'Governance' }, () => {
before(() => {
// Prerequisites - Create a user with data consumer role
Expand Down Expand Up @@ -841,17 +897,21 @@ describe('Glossary page should work properly', { tags: 'Governance' }, () => {
it('Create glossary term should work properly', () => {
const terms = Object.values(NEW_GLOSSARY_TERMS);
selectActiveGlossary(NEW_GLOSSARY.name);
terms.forEach((term, index) =>
createGlossaryTerm(term, NEW_GLOSSARY, 'Draft', true, index === 0)
);
terms.forEach((term, index) => {
createGlossaryTerm(term, NEW_GLOSSARY, 'Draft', true, index === 0);
verifyGlossaryTermDataInTable(term, 'Draft');
});

// Glossary term for Product glossary
selectActiveGlossary(NEW_GLOSSARY_1.name);

const ProductTerms = Object.values(NEW_GLOSSARY_1_TERMS);
ProductTerms.forEach((term) =>
createGlossaryTerm(term, NEW_GLOSSARY_1, 'Approved', false, false)
);
ProductTerms.forEach((term) => {
createGlossaryTerm(term, NEW_GLOSSARY_1, 'Approved', false, false);
verifyGlossaryTermDataInTable(term, 'Approved');
});
verifyStatusFilterInExplore('Approved');
verifyStatusFilterInExplore('Draft');
});

it('Approval Workflow for Glossary Term', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import { Link, useParams } from 'react-router-dom';
import { useTourProvider } from '../../../context/TourProvider/TourProvider';
import { EntityType } from '../../../enums/entity.enum';
import { OwnerType } from '../../../enums/user.enum';
import {
GlossaryTerm,
Status,
} from '../../../generated/entity/data/glossaryTerm';
import { EntityReference } from '../../../generated/entity/type';
import {
getEntityPlaceHolder,
Expand All @@ -32,6 +36,7 @@ import { stringToHTML } from '../../../utils/StringsUtils';
import { getEntityIcon, getUsagePercentile } from '../../../utils/TableUtils';
import TitleBreadcrumb from '../../common/TitleBreadcrumb/TitleBreadcrumb.component';
import TableDataCardBody from '../../Database/TableDataCardBody/TableDataCardBody';
import { GlossaryStatusBadge } from '../../Glossary/GlossaryStatusBadge/GlossaryStatusBadge.component';
import './explore-search-card.less';
import { ExploreSearchCardProps } from './ExploreSearchCard.interface';

Expand Down Expand Up @@ -170,6 +175,10 @@ const ExploreSearchCard: React.FC<ExploreSearchCardProps> = forwardRef<
}, [source, showEntityIcon, getEntityIcon]);

const header = useMemo(() => {
const hasGlossaryTermStatus =
source.entityType === EntityType.GLOSSARY_TERM &&
(source as GlossaryTerm).status !== Status.Approved;

return (
<Row gutter={[8, 8]}>
{showCheckboxes && (
Expand Down Expand Up @@ -216,7 +225,10 @@ const ExploreSearchCard: React.FC<ExploreSearchCardProps> = forwardRef<
{entityIcon}

<Link
className="no-underline line-height-22 w-full"
className={classNames('no-underline line-height-22 ', {
'w-full': !hasGlossaryTermStatus,
'm-r-xs': hasGlossaryTermStatus,
})}
data-testid="entity-link"
target={searchClassBase.getSearchEntityLinkTarget(
source,
Expand All @@ -229,6 +241,12 @@ const ExploreSearchCard: React.FC<ExploreSearchCardProps> = forwardRef<
{stringToHTML(searchClassBase.getEntityName(source))}
</Typography.Text>
</Link>

{hasGlossaryTermStatus && (
<GlossaryStatusBadge
status={(source as GlossaryTerm).status ?? Status.Approved}
/>
)}
</div>
)}
</Col>
Expand Down
Loading

0 comments on commit ae5e9d6

Please sign in to comment.