Skip to content

Commit f6b282c

Browse files
committed
Streamline deduplication logic, add test, and increment package version
1 parent ac321ba commit f6b282c

File tree

5 files changed

+77
-19
lines changed

5 files changed

+77
-19
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@yext/search-ui-react",
3-
"version": "1.8.3",
3+
"version": "1.8.4",
44
"description": "A library of React Components for powering Yext Search integrations",
55
"author": "watson@yext.com",
66
"license": "BSD-3-Clause",

src/components/GenerativeDirectAnswer.tsx

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -189,22 +189,17 @@ function Citations(props: CitationsProps) {
189189
citationClickHandler
190190
} = props;
191191
const citationResults = React.useMemo(() => {
192+
// If an entity is returned by multiple different verticals, it will be present in
193+
// searchResults multiple times. We want to only show it once in the citations.
194+
let citationIds = new Set(gdaResponse.citations);
192195
return searchResults.filter(result => {
193196
const {uid, name} = result.rawData ?? {};
194-
if (!uid || typeof uid != 'string' || !name) {
197+
const dataIsInvalid = !uid || !name || typeof name != 'string' || typeof uid != 'string';
198+
if (dataIsInvalid || !citationIds.has(uid)) {
195199
return false;
196200
}
197-
return gdaResponse.citations.includes(uid);
198-
}).filter((result, index, self) => {
199-
// If an entity is returned by multiple different verticals, it will be present in
200-
// searchResults multiple times. We want to only show it once in the citations.
201-
const {uid} = result.rawData ?? {};
202-
if (!uid) {
203-
return false;
204-
}
205-
return self.findIndex(r => {
206-
return uid === r.rawData?.uid;
207-
}) === index;
201+
citationIds.delete(uid);
202+
return true;
208203
});
209204
}, [gdaResponse.citations, searchResults]);
210205

tests/__fixtures__/data/universalresults.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,32 @@ const vertical3: VerticalResults = {
7171
verticalKey: 'vertical3'
7272
};
7373

74+
const vertical4: VerticalResults = {
75+
appliedQueryFilters: [],
76+
queryDurationMillis: 500,
77+
results: [{
78+
rawData: {
79+
name: 'title3',
80+
description: 'text3',
81+
uid: 'uid3'
82+
},
83+
source: Source.KnowledgeManager,
84+
id: 'id3'
85+
}],
86+
resultsCount: 1,
87+
source: Source.KnowledgeManager,
88+
verticalKey: 'vertical4'
89+
};
90+
7491
export const verticalResults = [
7592
vertical1,
7693
vertical2,
7794
vertical3
78-
];
95+
];
96+
97+
export const verticalResultsWithDuplicateEntity = [
98+
vertical1,
99+
vertical2,
100+
vertical3,
101+
vertical4
102+
];

tests/components/GenerativeDirectAnswer.test.tsx

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import { useAnalytics } from '../../src/hooks/useAnalytics';
55

66
import { State } from '@yext/search-headless-react';
77
import { mockAnswersState, ignoreLinkClickErrors } from '../__utils__/mocks';
8-
import { verticalResults } from '../__fixtures__/data/universalresults';
8+
import {
9+
verticalResults,
10+
verticalResultsWithDuplicateEntity
11+
} from '../__fixtures__/data/universalresults';
912
import { generativeDirectAnswerText, generativeDirectAnswerLink, generativeDirectAnswerResponse } from '../__fixtures__/data/generativeDirectAnswer';
1013
import userEvent from '@testing-library/user-event';
1114
import React from 'react';
@@ -27,6 +30,23 @@ const mockedState: Partial<State> = {
2730
}
2831
};
2932

33+
const mockedStateWithDuplicateEntity: Partial<State> = {
34+
generativeDirectAnswer: {
35+
isLoading: false,
36+
response: generativeDirectAnswerResponse,
37+
},
38+
universal: {
39+
verticals: verticalResultsWithDuplicateEntity
40+
},
41+
query: {
42+
queryId: '[queryId]',
43+
mostRecentSearch: 'test'
44+
},
45+
meta: {
46+
searchType: 'universal'
47+
}
48+
};
49+
3050
const CustomCitationsComponent = (props: CitationsProps) => {
3151
return (
3252
<>
@@ -109,6 +129,17 @@ describe('GenerativeDirectAnswer with sufficient citation fields', () => {
109129
expect(screen.getByText(generativeDirectAnswerText)).toBeDefined();
110130
expect(screen.getByText("CustomCitationsComponentTest")).toBeTruthy();
111131
});
132+
133+
it('citations are deduplicated', () => {
134+
mockAnswersState(mockedStateWithDuplicateEntity);
135+
render(<GenerativeDirectAnswer />);
136+
expect(screen.getByText(generativeDirectAnswerText)).toBeDefined();
137+
expect(screen.getByText('Sources (2)')).toBeDefined();
138+
139+
checkResultData(verticalResultsWithDuplicateEntity[0].results[0].rawData, false); //not a citation
140+
checkResultData(verticalResultsWithDuplicateEntity[0].results[1].rawData, true);
141+
checkResultData(verticalResultsWithDuplicateEntity[1].results[0].rawData, true);
142+
});
112143
});
113144

114145
describe('GenerativeDirectAnswer without sufficient citation fields', () => {
@@ -139,6 +170,14 @@ describe('GenerativeDirectAnswer without sufficient citation fields', () => {
139170
});
140171
});
141172

173+
// describe('GenerativeDirectAnswer with same entity appearing twice in search results', () => {
174+
// beforeEach(() => {
175+
// mockAnswersState(mockedStateWithDuplicateEntity);
176+
// });
177+
//
178+
//
179+
// });
180+
142181
function checkResultData(resultData: Record<string, unknown>, shouldDisplay: boolean) {
143182
if (typeof resultData.name === 'string') {
144183
if (shouldDisplay) {
@@ -153,5 +192,5 @@ function checkResultData(resultData: Record<string, unknown>, shouldDisplay: boo
153192
} else {
154193
expect(screen.queryByText(resultData.description)).toBeNull();
155194
}
156-
}
157-
}
195+
}
196+
}

0 commit comments

Comments
 (0)