1// Copyright (C) 2018 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 {produce} from 'immer'; 16 17import {StateActions} from './actions'; 18import { 19 createEmptyState, 20 SCROLLING_TRACK_GROUP, 21 State, 22 TrackState 23} from './state'; 24 25function fakeTrack(state: State, id: string): TrackState { 26 const track: TrackState = { 27 id, 28 engineId: '1', 29 kind: 'SOME_TRACK_KIND', 30 name: 'A track', 31 trackGroup: SCROLLING_TRACK_GROUP, 32 config: {}, 33 }; 34 state.tracks[id] = track; 35 return track; 36} 37 38test('navigate', () => { 39 const after = produce(createEmptyState(), draft => { 40 StateActions.navigate(draft, {route: '/foo'}); 41 }); 42 expect(after.route).toBe('/foo'); 43}); 44 45test('add scrolling tracks', () => { 46 const once = produce(createEmptyState(), draft => { 47 StateActions.addTrack(draft, { 48 engineId: '1', 49 kind: 'cpu', 50 name: 'Cpu 1', 51 trackGroup: SCROLLING_TRACK_GROUP, 52 config: {}, 53 }); 54 }); 55 const twice = produce(once, draft => { 56 StateActions.addTrack(draft, { 57 engineId: '2', 58 kind: 'cpu', 59 name: 'Cpu 2', 60 trackGroup: SCROLLING_TRACK_GROUP, 61 config: {}, 62 }); 63 }); 64 65 expect(Object.values(twice.tracks).length).toBe(2); 66 expect(twice.scrollingTracks.length).toBe(2); 67}); 68 69test('add track to track group', () => { 70 const state = createEmptyState(); 71 fakeTrack(state, 's'); 72 73 const afterGroup = produce(state, draft => { 74 StateActions.addTrackGroup(draft, { 75 engineId: '1', 76 name: 'A track group', 77 id: '123-123-123', 78 summaryTrackId: 's', 79 collapsed: false, 80 }); 81 }); 82 83 const afterTrackAdd = produce(afterGroup, draft => { 84 StateActions.addTrack(draft, { 85 id: '1', 86 engineId: '1', 87 kind: 'slices', 88 name: 'renderer 1', 89 trackGroup: '123-123-123', 90 config: {}, 91 }); 92 }); 93 94 expect(afterTrackAdd.trackGroups['123-123-123'].tracks[0]).toBe('1'); 95}); 96 97test('reorder tracks', () => { 98 const once = produce(createEmptyState(), draft => { 99 StateActions.addTrack(draft, { 100 engineId: '1', 101 kind: 'cpu', 102 name: 'Cpu 1', 103 config: {}, 104 }); 105 StateActions.addTrack(draft, { 106 engineId: '2', 107 kind: 'cpu', 108 name: 'Cpu 2', 109 config: {}, 110 }); 111 }); 112 113 const firstTrackId = once.scrollingTracks[0]; 114 const secondTrackId = once.scrollingTracks[1]; 115 116 const twice = produce(once, draft => { 117 StateActions.moveTrack(draft, { 118 srcId: `${firstTrackId}`, 119 op: 'after', 120 dstId: `${secondTrackId}`, 121 }); 122 }); 123 124 expect(twice.scrollingTracks[0]).toBe(secondTrackId); 125 expect(twice.scrollingTracks[1]).toBe(firstTrackId); 126}); 127 128test('reorder pinned to scrolling', () => { 129 const state = createEmptyState(); 130 fakeTrack(state, 'a'); 131 fakeTrack(state, 'b'); 132 fakeTrack(state, 'c'); 133 state.pinnedTracks = ['a', 'b']; 134 state.scrollingTracks = ['c']; 135 136 const after = produce(state, draft => { 137 StateActions.moveTrack(draft, { 138 srcId: 'b', 139 op: 'before', 140 dstId: 'c', 141 }); 142 }); 143 144 expect(after.pinnedTracks).toEqual(['a']); 145 expect(after.scrollingTracks).toEqual(['b', 'c']); 146}); 147 148test('reorder scrolling to pinned', () => { 149 const state = createEmptyState(); 150 fakeTrack(state, 'a'); 151 fakeTrack(state, 'b'); 152 fakeTrack(state, 'c'); 153 state.pinnedTracks = ['a']; 154 state.scrollingTracks = ['b', 'c']; 155 156 const after = produce(state, draft => { 157 StateActions.moveTrack(draft, { 158 srcId: 'b', 159 op: 'after', 160 dstId: 'a', 161 }); 162 }); 163 164 expect(after.pinnedTracks).toEqual(['a', 'b']); 165 expect(after.scrollingTracks).toEqual(['c']); 166}); 167 168test('reorder clamp bottom', () => { 169 const state = createEmptyState(); 170 fakeTrack(state, 'a'); 171 fakeTrack(state, 'b'); 172 fakeTrack(state, 'c'); 173 state.pinnedTracks = ['a', 'b']; 174 state.scrollingTracks = ['c']; 175 176 const after = produce(state, draft => { 177 StateActions.moveTrack(draft, { 178 srcId: 'a', 179 op: 'before', 180 dstId: 'a', 181 }); 182 }); 183 expect(after).toEqual(state); 184}); 185 186test('reorder clamp top', () => { 187 const state = createEmptyState(); 188 fakeTrack(state, 'a'); 189 fakeTrack(state, 'b'); 190 fakeTrack(state, 'c'); 191 state.pinnedTracks = ['a']; 192 state.scrollingTracks = ['b', 'c']; 193 194 const after = produce(state, draft => { 195 StateActions.moveTrack(draft, { 196 srcId: 'c', 197 op: 'after', 198 dstId: 'c', 199 }); 200 }); 201 expect(after).toEqual(state); 202}); 203 204test('pin', () => { 205 const state = createEmptyState(); 206 fakeTrack(state, 'a'); 207 fakeTrack(state, 'b'); 208 fakeTrack(state, 'c'); 209 state.pinnedTracks = ['a']; 210 state.scrollingTracks = ['b', 'c']; 211 212 const after = produce(state, draft => { 213 StateActions.toggleTrackPinned(draft, { 214 trackId: 'c', 215 }); 216 }); 217 expect(after.pinnedTracks).toEqual(['a', 'c']); 218 expect(after.scrollingTracks).toEqual(['b']); 219}); 220 221test('unpin', () => { 222 const state = createEmptyState(); 223 fakeTrack(state, 'a'); 224 fakeTrack(state, 'b'); 225 fakeTrack(state, 'c'); 226 state.pinnedTracks = ['a', 'b']; 227 state.scrollingTracks = ['c']; 228 229 const after = produce(state, draft => { 230 StateActions.toggleTrackPinned(draft, { 231 trackId: 'a', 232 }); 233 }); 234 expect(after.pinnedTracks).toEqual(['b']); 235 expect(after.scrollingTracks).toEqual(['a', 'c']); 236}); 237 238test('open trace', () => { 239 const state = createEmptyState(); 240 state.nextId = 100; 241 const recordConfig = state.recordConfig; 242 const after = produce(state, draft => { 243 StateActions.openTraceFromUrl(draft, { 244 url: 'https://example.com/bar', 245 }); 246 }); 247 248 const engineKeys = Object.keys(after.engines); 249 expect(after.nextId).toBe(101); 250 expect(engineKeys.length).toBe(1); 251 expect(after.engines[engineKeys[0]].source).toBe('https://example.com/bar'); 252 expect(after.route).toBe('/viewer'); 253 expect(after.recordConfig).toBe(recordConfig); 254}); 255 256test('open second trace from file', () => { 257 const once = produce(createEmptyState(), draft => { 258 StateActions.openTraceFromUrl(draft, { 259 url: 'https://example.com/bar', 260 }); 261 }); 262 263 const twice = produce(once, draft => { 264 StateActions.addTrack(draft, { 265 engineId: '1', 266 kind: 'cpu', 267 name: 'Cpu 1', 268 config: {}, 269 }); 270 }); 271 272 const thrice = produce(twice, draft => { 273 StateActions.openTraceFromUrl(draft, { 274 url: 'https://example.com/foo', 275 }); 276 }); 277 278 const engineKeys = Object.keys(thrice.engines); 279 expect(engineKeys.length).toBe(1); 280 expect(thrice.engines[engineKeys[0]].source).toBe('https://example.com/foo'); 281 expect(thrice.pinnedTracks.length).toBe(0); 282 expect(thrice.scrollingTracks.length).toBe(0); 283 expect(thrice.route).toBe('/viewer'); 284}); 285