go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/common/store/build_page/build_page.test.ts (about) 1 // Copyright 2021 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 { autorun } from 'mobx'; 16 import { addDisposer, destroy } from 'mobx-state-tree'; 17 18 import { ANONYMOUS_IDENTITY } from '@/common/api/auth_state'; 19 import { Build, GetBuildRequest } from '@/common/services/buildbucket'; 20 import { Store, StoreInstance } from '@/common/store'; 21 import { CacheOption } from '@/generic_libs/tools/cached_fn'; 22 23 describe('BuildPage', () => { 24 describe('cache', () => { 25 let store: StoreInstance; 26 let getBuildStub: jest.SpiedFunction< 27 (req: GetBuildRequest, cacheOpt?: CacheOption) => Promise<Build> 28 >; 29 30 beforeEach(() => { 31 const builderId = { 32 project: 'proj', 33 bucket: 'bucket', 34 builder: 'builder', 35 }; 36 jest.useFakeTimers(); 37 store = Store.create({ 38 authState: { value: { identity: ANONYMOUS_IDENTITY } }, 39 refreshTime: { value: jest.now() }, 40 }); 41 store.buildPage.setParams(builderId, '1'); 42 43 getBuildStub = jest.spyOn(store.services.builds!, 'getBuild'); 44 getBuildStub.mockResolvedValueOnce({ 45 number: 1, 46 id: '2', 47 builder: builderId, 48 } as Build); 49 getBuildStub.mockResolvedValueOnce({ 50 number: 1, 51 id: '2', 52 builder: builderId, 53 } as Build); 54 }); 55 56 afterEach(() => { 57 destroy(store); 58 jest.useRealTimers(); 59 }); 60 61 test('should accept cache when first querying build', async () => { 62 store.buildPage.build; 63 await jest.runAllTimersAsync(); 64 expect(getBuildStub.mock.calls[0][1]?.acceptCache).not.toBeFalsy(); 65 }); 66 67 test('should not accept cache after calling refresh', async () => { 68 store.buildPage.build; 69 await jest.runAllTimersAsync(); 70 71 await jest.advanceTimersByTimeAsync(10); 72 store.refreshTime.refresh(); 73 store.buildPage.build; 74 await jest.runAllTimersAsync(); 75 76 expect(getBuildStub.mock.calls[0][1]?.acceptCache).not.toBeFalsy(); 77 expect(getBuildStub.mock.calls[1][1]?.acceptCache).toBeFalsy(); 78 }); 79 }); 80 81 describe('params', () => { 82 let store: StoreInstance; 83 beforeEach(() => { 84 jest.useFakeTimers(); 85 store = Store.create({ 86 authState: { value: { identity: ANONYMOUS_IDENTITY } }, 87 refreshTime: { value: jest.now() }, 88 }); 89 }); 90 91 afterEach(() => { 92 destroy(store); 93 jest.useRealTimers(); 94 }); 95 96 test('ignore builderIdParam when buildNumOrIdParam is a buildId', async () => { 97 store.buildPage.setParams( 98 { 99 project: 'wrong_proj', 100 bucket: 'wrong_bucket', 101 builder: 'wrong_builder', 102 }, 103 'b123', 104 ); 105 106 const getBuildStub = jest.spyOn(store.services.builds!, 'getBuild'); 107 const batchCheckPermissionsStub = jest.spyOn( 108 store.services.milo!, 109 'batchCheckPermissions', 110 ); 111 112 const builderId = { 113 project: 'proj', 114 bucket: 'bucket', 115 builder: 'builder', 116 }; 117 getBuildStub.mockResolvedValueOnce({ 118 number: 1, 119 id: '123', 120 builder: builderId, 121 } as Build); 122 batchCheckPermissionsStub.mockResolvedValueOnce({ results: {} }); 123 124 addDisposer( 125 store, 126 autorun(() => { 127 store.buildPage.build; 128 store.buildPage.canRetry; 129 }), 130 ); 131 await jest.runAllTimersAsync(); 132 133 expect(getBuildStub.mock.calls[0][0].builder).toBeUndefined(); 134 expect(batchCheckPermissionsStub.mock.calls[0][0].realm).toStrictEqual( 135 `${builderId.project}:${builderId.bucket}`, 136 ); 137 }); 138 }); 139 });