From ae6ee0093ef735f28bfa98b21c3d58ed691a7b18 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Wed, 21 Jun 2023 17:33:39 +0200 Subject: [PATCH] test(search): optimize search bar suite Signed-off-by: Camila Belo --- .../components/SearchBar/SearchBar.test.tsx | 163 +++++++----------- 1 file changed, 65 insertions(+), 98 deletions(-) diff --git a/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx b/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx index e4859861d9..5af5447740 100644 --- a/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx +++ b/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { screen, render, waitFor, act } from '@testing-library/react'; +import { screen, waitFor, act } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { configApiRef, analyticsApiRef } from '@backstage/core-plugin-api'; import { ConfigReader } from '@backstage/core-app-api'; @@ -41,16 +41,23 @@ const createInitialState = ({ }); describe('SearchBar', () => { + const user = userEvent.setup({ delay: null }); + const query = jest.fn().mockResolvedValue({ results: [] }); - const analyticsApiMock = new MockAnalyticsApi(); + const searchApiMock = { query }; const configApiMock = new ConfigReader({ - app: { title: 'Mock title' }, + app: { + title: 'Mock title', + analytics: { + ga: { + trackingId: 'xyz123', + }, + }, + }, }); - const searchApiMock = { query }; - beforeEach(() => { jest.clearAllMocks(); }); @@ -64,20 +71,20 @@ describe('SearchBar', () => { ]} > - + , ); - await waitFor(() => { - expect(screen.getByLabelText('Search')).toBeInTheDocument(); - }); + await waitFor(() => + expect(screen.getByLabelText('Search')).toBeInTheDocument(), + ); }); it('Renders with custom label', async () => { const label = 'label'; - const result = await renderWithEffects( + await renderWithEffects( { ]} > - + , ); - await waitFor(() => { - expect(result.getByLabelText(label)).toBeInTheDocument(); - }); + await waitFor(() => + expect(screen.getByLabelText(label)).toBeInTheDocument(), + ); }); it('Renders with custom placeholder', async () => { @@ -106,20 +113,20 @@ describe('SearchBar', () => { ]} > - + , ); - await waitFor(() => { - expect(screen.getByPlaceholderText(placeholder)).toBeInTheDocument(); - }); + await waitFor(() => + expect(screen.getByPlaceholderText(placeholder)).toBeInTheDocument(), + ); }); it('Renders based on initial search', async () => { const term = 'term'; - render( + await renderWithEffects( { ]} > - + , ); - await waitFor(() => { - expect(screen.getByRole('textbox', { name: 'Search' })).toHaveValue(term); - }); + await waitFor(() => + expect(screen.getByLabelText('Search')).toHaveValue(term), + ); }); it('Updates term state when text is entered', async () => { jest.useFakeTimers(); - const user = userEvent.setup({ delay: null }); await renderWithEffects( { , ); - const textbox = screen.getByRole('textbox', { name: 'Search' }); + const textbox = screen.getByLabelText('Search'); const value = 'value'; @@ -164,14 +170,13 @@ describe('SearchBar', () => { jest.advanceTimersByTime(200); }); - await waitFor(() => { - expect(textbox).toHaveValue(value); - }); + await waitFor(() => expect(textbox).toHaveValue(value)); expect(query).toHaveBeenLastCalledWith( expect.objectContaining({ term: value }), ); + jest.runAllTimers(); jest.useRealTimers(); }); @@ -186,22 +191,18 @@ describe('SearchBar', () => { ]} > - + , ); - const textbox = screen.getByRole('textbox', { name: 'Search' }); + const textbox = screen.getByLabelText('Search'); - await waitFor(() => { - expect(textbox).toHaveValue(term); - }); + await waitFor(() => expect(textbox).toHaveValue(term)); - await userEvent.click(screen.getByRole('button', { name: 'Clear' })); + await user.click(screen.getByLabelText('Clear')); - await waitFor(() => { - expect(textbox).toHaveValue(''); - }); + await waitFor(() => expect(textbox).toHaveValue('')); expect(query).toHaveBeenLastCalledWith( expect.objectContaining({ term: '' }), @@ -219,22 +220,20 @@ describe('SearchBar', () => { ]} > - + , ); - await waitFor(() => { - expect( - screen.queryByRole('button', { name: 'Clear' }), - ).not.toBeInTheDocument(); - }); + await waitFor(() => + expect(screen.queryByLabelText('Clear')).not.toBeInTheDocument(), + ); }); it('Adheres to provided debounceTime', async () => { jest.useFakeTimers(); - const user = userEvent.setup({ delay: null }); - const debounceTime = 600; + + const debounceTime = 100; await renderWithEffects( { , ); - const textbox = await screen.findByRole('textbox', { name: 'Search' }); + const textbox = screen.getByLabelText('Search'); const value = 'value'; await user.type(textbox, value); - await waitFor(() => { + await waitFor(() => expect(query).not.toHaveBeenLastCalledWith( expect.objectContaining({ term: value }), - ); - }); + ), + ); act(() => { jest.advanceTimersByTime(debounceTime); }); - await waitFor(() => { - expect(textbox).toHaveValue(value); - }); + await waitFor(() => expect(textbox).toHaveValue(value)); expect(query).toHaveBeenLastCalledWith( expect.objectContaining({ term: value }), ); + jest.runAllTimers(); jest.useRealTimers(); }); - it('does not capture analytics event if not enabled in app', async () => { - jest.useFakeTimers(); - const user = userEvent.setup({ delay: null }); + it('Does not capture analytics event if not enabled in app', async () => { + const analyticsApiMock = new MockAnalyticsApi(); await renderWithEffects( { ]} > - + , ); - const textbox = await screen.findByRole('textbox', { name: 'Search' }); + const textbox = screen.getByLabelText('Search'); const value = 'value'; await user.type(textbox, value); - act(() => { - jest.advanceTimersByTime(200); - }); - - await waitFor(() => { - expect(textbox).toHaveValue(value); - }); + await waitFor(() => expect(textbox).toHaveValue(value)); expect(analyticsApiMock.getEvents()).toHaveLength(0); - - jest.useRealTimers(); }); - it('captures analytics events if enabled in app', async () => { - jest.useFakeTimers(); - const user = userEvent.setup({ delay: null }); + it('Captures analytics events if enabled in app', async () => { + const analyticsApiMock = new MockAnalyticsApi(); + const types = ['techdocs', 'software-catalog']; await renderWithEffects( - + , ); - const textbox = await screen.findByRole('textbox', { name: 'Search' }); + const textbox = screen.getByLabelText('Search'); let value = 'value'; @@ -351,13 +328,9 @@ describe('SearchBar', () => { expect(analyticsApiMock.getEvents()).toHaveLength(0); - act(() => { - jest.advanceTimersByTime(200); - }); + await waitFor(() => expect(analyticsApiMock.getEvents()).toHaveLength(1)); - await waitFor(() => expect(textbox).toHaveValue(value)); - - expect(analyticsApiMock.getEvents()).toHaveLength(1); + expect(textbox).toHaveValue(value); expect(analyticsApiMock.getEvents()[0]).toEqual({ action: 'search', context: { @@ -376,13 +349,9 @@ describe('SearchBar', () => { // make sure new term is captured await user.type(textbox, value); - act(() => { - jest.advanceTimersByTime(200); - }); + await waitFor(() => expect(analyticsApiMock.getEvents()).toHaveLength(2)); - await waitFor(() => expect(textbox).toHaveValue(value)); - - expect(analyticsApiMock.getEvents()).toHaveLength(2); + expect(textbox).toHaveValue(value); expect(analyticsApiMock.getEvents()[1]).toEqual({ action: 'search', context: { @@ -393,7 +362,5 @@ describe('SearchBar', () => { }, subject: value, }); - - jest.useRealTimers(); }); });