| // Copyright (C) 2023 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| import {createStore, Track, TrackDescriptor} from '../public'; |
| |
| import {createEmptyState} from './empty_state'; |
| import {TrackManager} from './track_cache'; |
| |
| function makeMockTrack(): Track { |
| return { |
| onCreate: jest.fn(), |
| onUpdate: jest.fn(), |
| onDestroy: jest.fn(), |
| |
| render: jest.fn(), |
| onFullRedraw: jest.fn(), |
| getSliceRect: jest.fn(), |
| getHeight: jest.fn(), |
| getTrackShellButtons: jest.fn(), |
| onMouseMove: jest.fn(), |
| onMouseClick: jest.fn(), |
| onMouseOut: jest.fn(), |
| }; |
| } |
| |
| async function settle() { |
| await new Promise((r) => setTimeout(r, 0)); |
| } |
| |
| let track: Track; |
| let td: TrackDescriptor; |
| let trackCache: TrackManager; |
| |
| beforeEach(() => { |
| track = makeMockTrack(); |
| td = { |
| uri: 'test', |
| trackFactory: () => track, |
| }; |
| const store = createStore(createEmptyState()); |
| trackCache = new TrackManager(store); |
| }); |
| |
| describe('TrackCache', () => { |
| it('calls track lifecycle hooks', async () => { |
| const entry = trackCache.resolveTrack('foo', td); |
| entry.update(); |
| await settle(); |
| expect(track.onUpdate).toHaveBeenCalledTimes(1); |
| }); |
| |
| it('reuses tracks', async () => { |
| const first = trackCache.resolveTrack('foo', td); |
| trackCache.flushOldTracks(); |
| first.update(); |
| const second = trackCache.resolveTrack('foo', td); |
| trackCache.flushOldTracks(); |
| second.update(); |
| |
| // Ensure onCreate only called once |
| expect(track.onCreate).toHaveBeenCalledTimes(1); |
| expect(first).toBe(second); |
| }); |
| |
| it('destroys tracks', async () => { |
| const t = trackCache.resolveTrack('foo', td); |
| t.update(); |
| |
| // Double flush should destroy all tracks |
| trackCache.flushOldTracks(); |
| trackCache.flushOldTracks(); |
| |
| await settle(); |
| |
| // Ensure onCreate only called once |
| expect(track.onDestroy).toHaveBeenCalledTimes(1); |
| }); |
| }); |
| |
| describe('TrackCacheEntry', () => { |
| it('updates', async () => { |
| const entry = trackCache.resolveTrack('foo', td); |
| entry.update(); |
| await settle(); |
| expect(track.onUpdate).toHaveBeenCalledTimes(1); |
| }); |
| |
| it('throws if updated when destroyed', async () => { |
| const entry = trackCache.resolveTrack('foo', td); |
| |
| // Double flush should destroy all tracks |
| trackCache.flushOldTracks(); |
| trackCache.flushOldTracks(); |
| |
| await settle(); |
| |
| expect(() => entry.update()).toThrow(); |
| }); |
| }); |