go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/test_verdict/pages/test_search/test_search.test.tsx (about)

     1  // Copyright 2023 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  import {
    16    act,
    17    cleanup,
    18    fireEvent,
    19    render,
    20    screen,
    21  } from '@testing-library/react';
    22  
    23  import {
    24    QueryTestsRequest,
    25    TestHistoryService,
    26  } from '@/common/services/luci_analysis';
    27  import { CacheOption } from '@/generic_libs/tools/cached_fn';
    28  import { FakeContextProvider } from '@/testing_tools/fakes/fake_context_provider';
    29  
    30  import { TestSearch } from './test_search';
    31  
    32  describe('TestSearch', () => {
    33    beforeEach(() => {
    34      jest
    35        .spyOn(TestHistoryService.prototype, 'queryTests')
    36        .mockImplementation((req: QueryTestsRequest, _: CacheOption = {}) => {
    37          if (req.testIdSubstring === 'query') {
    38            return Promise.resolve({
    39              testIds: ['test_id_1', 'test_id_2'],
    40            });
    41          } else {
    42            return Promise.reject(new Error('unknown test id'));
    43          }
    44        });
    45      jest.useFakeTimers();
    46    });
    47    afterEach(() => {
    48      cleanup();
    49      jest.useRealTimers();
    50      jest.resetAllMocks();
    51    });
    52  
    53    it('should read params from URL', async () => {
    54      render(
    55        <FakeContextProvider
    56          routerOptions={{
    57            initialEntries: ['/?q=query'],
    58          }}
    59        >
    60          <TestSearch />
    61        </FakeContextProvider>,
    62      );
    63  
    64      // Ensure that the filters are not overwritten after all event hooks are
    65      // executed.
    66      await act(async () => await jest.runAllTimersAsync());
    67  
    68      await screen.findByText('test_id_1');
    69      expect(screen.getByText('test_id_2')).toBeInTheDocument();
    70    });
    71  
    72    it('should sync params with URL', async () => {
    73      render(
    74        <FakeContextProvider>
    75          <TestSearch />
    76        </FakeContextProvider>,
    77      );
    78      fireEvent.change(screen.getByTestId('search-input'), {
    79        target: { value: 'query' },
    80      });
    81  
    82      await screen.findByText('test_id_1');
    83      expect(screen.getByText('test_id_2')).toBeInTheDocument();
    84    });
    85  
    86    it('should throttle requests', async () => {
    87      jest
    88        .spyOn(TestHistoryService.prototype, 'queryTests')
    89        .mockImplementation((req: QueryTestsRequest, _: CacheOption = {}) => {
    90          const result = ['test_id_1', 'test_id_2'].filter((id) =>
    91            id.startsWith(req.testIdSubstring),
    92          );
    93          return Promise.resolve({
    94            testIds: result,
    95          });
    96        });
    97  
    98      render(
    99        <FakeContextProvider>
   100          <TestSearch />
   101        </FakeContextProvider>,
   102      );
   103      fireEvent.change(screen.getByTestId('search-input'), {
   104        target: { value: 'test_id' },
   105      });
   106      expect(screen.queryByText('test_id_1')).not.toBeInTheDocument();
   107      expect(screen.queryByText('test_id_2')).not.toBeInTheDocument();
   108      fireEvent.change(screen.getByTestId('search-input'), {
   109        target: { value: 'test_id_2' },
   110      });
   111      act(() => jest.advanceTimersByTime(600));
   112      await screen.findByText('test_id_2');
   113      expect(screen.queryByText('test_id_1')).not.toBeInTheDocument();
   114    });
   115  });