• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2023 The Android Open Source Project
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
15import {createStore, Track, TrackDescriptor} from '../public';
16
17import {createEmptyState} from './empty_state';
18import {TrackManager} from './track_cache';
19
20function makeMockTrack(): Track {
21  return {
22    onCreate: jest.fn(),
23    onUpdate: jest.fn(),
24    onDestroy: jest.fn(),
25
26    render: jest.fn(),
27    onFullRedraw: jest.fn(),
28    getSliceRect: jest.fn(),
29    getHeight: jest.fn(),
30    getTrackShellButtons: jest.fn(),
31    onMouseMove: jest.fn(),
32    onMouseClick: jest.fn(),
33    onMouseOut: jest.fn(),
34  };
35}
36
37async function settle() {
38  await new Promise((r) => setTimeout(r, 0));
39}
40
41let track: Track;
42let td: TrackDescriptor;
43let trackCache: TrackManager;
44
45beforeEach(() => {
46  track = makeMockTrack();
47  td = {
48    uri: 'test',
49    trackFactory: () => track,
50  };
51  const store = createStore(createEmptyState());
52  trackCache = new TrackManager(store);
53});
54
55describe('TrackCache', () => {
56  it('calls track lifecycle hooks', async () => {
57    const entry = trackCache.resolveTrack('foo', td);
58    entry.update();
59    await settle();
60    expect(track.onUpdate).toHaveBeenCalledTimes(1);
61  });
62
63  it('reuses tracks', async () => {
64    const first = trackCache.resolveTrack('foo', td);
65    trackCache.flushOldTracks();
66    first.update();
67    const second = trackCache.resolveTrack('foo', td);
68    trackCache.flushOldTracks();
69    second.update();
70
71    // Ensure onCreate only called once
72    expect(track.onCreate).toHaveBeenCalledTimes(1);
73    expect(first).toBe(second);
74  });
75
76  it('destroys tracks', async () => {
77    const t = trackCache.resolveTrack('foo', td);
78    t.update();
79
80    // Double flush should destroy all tracks
81    trackCache.flushOldTracks();
82    trackCache.flushOldTracks();
83
84    await settle();
85
86    // Ensure onCreate only called once
87    expect(track.onDestroy).toHaveBeenCalledTimes(1);
88  });
89});
90
91describe('TrackCacheEntry', () => {
92  it('updates', async () => {
93    const entry = trackCache.resolveTrack('foo', td);
94    entry.update();
95    await settle();
96    expect(track.onUpdate).toHaveBeenCalledTimes(1);
97  });
98
99  it('throws if updated when destroyed', async () => {
100    const entry = trackCache.resolveTrack('foo', td);
101
102    // Double flush should destroy all tracks
103    trackCache.flushOldTracks();
104    trackCache.flushOldTracks();
105
106    await settle();
107
108    expect(() => entry.update()).toThrow();
109  });
110});
111