diff --git a/.changeset/cool-moons-lay.md b/.changeset/cool-moons-lay.md new file mode 100644 index 0000000000..98367ff979 --- /dev/null +++ b/.changeset/cool-moons-lay.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-react': patch +--- + +Capture the number of search results in the search analytics event that correspond to the term entered. diff --git a/plugins/search-react/src/context/SearchContext.test.tsx b/plugins/search-react/src/context/SearchContext.test.tsx index f858715adb..796eca351f 100644 --- a/plugins/search-react/src/context/SearchContext.test.tsx +++ b/plugins/search-react/src/context/SearchContext.test.tsx @@ -421,31 +421,34 @@ describe('SearchContext', () => { }); describe('analytics', () => { - it('captures analytics events if enabled in app', async () => { - const analyticsApiMock = mockApis.analytics(); + const analyticsApiMock = mockApis.analytics(); + const Wrapper = ({ children }: React.PropsWithChildren) => ( + + + {children} + + + ); - searchApiMock.query.mockResolvedValue({ - results: [], - numberOfResults: 3, - }); + it('captures analytics events if enabled in app', async () => { + searchApiMock.query + .mockResolvedValueOnce({ + results: [], + numberOfResults: 10, + }) + .mockResolvedValueOnce({ + results: [], + numberOfResults: 3, + }); const { result } = renderHook(() => useSearch(), { - wrapper: ({ children }) => { - const configApiMock = mockApis.config(); - return ( - - - {children} - - - ); - }, + wrapper: Wrapper, }); await waitFor(() => { @@ -476,59 +479,62 @@ describe('SearchContext', () => { }); }); }); - }); - it('captures analytics events even if number of results does not exist', async () => { - const analyticsApiMock = mockApis.analytics(); - - searchApiMock.query.mockResolvedValue({ - results: [], - }); - - const { result } = renderHook(() => useSearch(), { - wrapper: ({ children }) => { - const configApiMock = mockApis.config(); - return ( - - - {children} - - - ); - }, - }); - - await waitFor(() => { - expect(result.current).toEqual(expect.objectContaining(initialState)); - }); - - const term = 'term'; - - await act(async () => { - result.current.setTerm(term); - }); - - await waitFor(() => { - expect(searchApiMock.query).toHaveBeenLastCalledWith({ - term: 'term', - types: ['*'], - filters: {}, + it('does not capture analytics events if term is empty', async () => { + searchApiMock.query.mockResolvedValue({ + results: [], + numberOfResults: 10, }); - expect(analyticsApiMock.captureEvent).toHaveBeenCalledWith({ - action: 'search', - subject: 'term', - value: undefined, - context: { - extension: 'App', - pluginId: 'root', - routeRef: 'unknown', - }, + + renderHook(() => useSearch(), { + wrapper: Wrapper, + }); + + await waitFor(() => { + expect(searchApiMock.query).toHaveBeenCalledWith({ + term: '', + types: ['*'], + filters: {}, + }); + expect(analyticsApiMock.captureEvent).not.toHaveBeenCalled(); + }); + }); + + it('captures analytics events even if number of results does not exist', async () => { + searchApiMock.query.mockResolvedValue({ + results: [], + }); + + const { result } = renderHook(() => useSearch(), { + wrapper: Wrapper, + }); + + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); + + const term = 'term'; + + await act(async () => { + result.current.setTerm(term); + }); + + await waitFor(() => { + expect(searchApiMock.query).toHaveBeenLastCalledWith({ + term: 'term', + types: ['*'], + filters: {}, + }); + expect(analyticsApiMock.captureEvent).toHaveBeenCalledWith({ + action: 'search', + subject: 'term', + value: undefined, + context: { + extension: 'App', + pluginId: 'root', + routeRef: 'unknown', + }, + }); }); }); }); diff --git a/plugins/search-react/src/context/SearchContext.tsx b/plugins/search-react/src/context/SearchContext.tsx index f09ebac42a..ef9063ba30 100644 --- a/plugins/search-react/src/context/SearchContext.tsx +++ b/plugins/search-react/src/context/SearchContext.tsx @@ -140,7 +140,7 @@ const useSearchContextValue = ( }); if (term) { analytics.captureEvent('search', term, { - value: result.value?.numberOfResults ?? undefined, + value: resultSet.numberOfResults, }); } return resultSet;