go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/build/pages/builder_search_page/builder_search_page.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 import { VirtuosoMockContext } from 'react-virtuoso'; 23 24 import { UiPage } from '@/common/constants/view'; 25 import { 26 ListBuildersRequest, 27 ListBuildersResponse, 28 MiloInternalClientImpl, 29 } from '@/proto/go.chromium.org/luci/milo/proto/v1/rpc.pb'; 30 import { FakeContextProvider } from '@/testing_tools/fakes/fake_context_provider'; 31 32 import { BuilderSearchPage } from './builder_search_page'; 33 34 describe('<BuilderSearchPage />', () => { 35 beforeEach(() => { 36 jest.useFakeTimers(); 37 }); 38 afterEach(() => { 39 cleanup(); 40 jest.useRealTimers(); 41 jest.resetAllMocks(); 42 }); 43 44 it('should throttle search requests', async () => { 45 jest 46 .spyOn(MiloInternalClientImpl.prototype, 'ListBuilders') 47 .mockImplementation(async (_: ListBuildersRequest) => 48 ListBuildersResponse.fromPartial({ 49 builders: Object.freeze([ 50 { 51 id: { 52 bucket: 'test_bucket', 53 builder: 'builder', 54 project: 'chromium', 55 }, 56 }, 57 { 58 id: { 59 bucket: 'test_bucket', 60 builder: 'builder-id', 61 project: 'chromium', 62 }, 63 }, 64 { 65 id: { 66 bucket: 'test_bucket', 67 builder: 'builder-id-with-suffix', 68 project: 'chromium', 69 }, 70 }, 71 { 72 id: { 73 bucket: 'test_bucket', 74 builder: 'another-builder', 75 project: 'chromium', 76 }, 77 }, 78 { 79 id: { 80 bucket: 'test_bucket', 81 builder: 'another-builder-id', 82 project: 'chromium', 83 }, 84 }, 85 ]), 86 }), 87 ); 88 89 render( 90 <FakeContextProvider 91 pageMeta={{ 92 selectedPage: UiPage.Builders, 93 }} 94 > 95 <VirtuosoMockContext.Provider 96 value={{ viewportHeight: 1000, itemHeight: 1 }} 97 > 98 <BuilderSearchPage /> 99 </VirtuosoMockContext.Provider> 100 </FakeContextProvider>, 101 ); 102 103 fireEvent.change(screen.getByTestId('search-input'), { 104 target: { value: 'builder' }, 105 }); 106 await act(() => jest.advanceTimersByTimeAsync(10)); 107 expect(screen.queryAllByTestId('builder-data').length).toBe(5); 108 109 fireEvent.change(screen.getByTestId('search-input'), { 110 target: { value: 'builder-id' }, 111 }); 112 await act(() => jest.advanceTimersByTimeAsync(10)); 113 expect(screen.queryAllByTestId('builder-data').length).toBe(5); 114 115 fireEvent.change(screen.getByTestId('search-input'), { 116 target: { value: 'builder-id-with-suffix' }, 117 }); 118 await act(() => jest.advanceTimersByTimeAsync(200)); 119 expect(screen.queryAllByTestId('builder-data').length).toBe(5); 120 121 await act(() => jest.advanceTimersByTimeAsync(200)); 122 expect(screen.getAllByTestId('builder-data').length).toBe(1); 123 expect(screen.getByText('builder-id-with-suffix')).toBeInTheDocument(); 124 125 // Using another filter. 126 fireEvent.change(screen.getByTestId('search-input'), { 127 target: { value: 'another-builder' }, 128 }); 129 await act(() => jest.advanceTimersByTimeAsync(10)); 130 expect(screen.getAllByTestId('builder-data').length).toBe(1); 131 expect(screen.getByText('builder-id-with-suffix')).toBeInTheDocument(); 132 133 fireEvent.change(screen.getByTestId('search-input'), { 134 target: { value: 'another-builder-id' }, 135 }); 136 act(() => jest.runAllTimers()); 137 expect(screen.getAllByTestId('builder-data').length).toBe(1); 138 expect(screen.getByText('another-builder-id')).toBeInTheDocument(); 139 }); 140 });