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 {TrackNode, Workspace} from './workspace'; 16 17describe('workspace', () => { 18 test('getNodeByKey', () => { 19 const workspace = new Workspace(); 20 const track = new TrackNode({id: 'foo'}); 21 workspace.addChildLast(track); 22 23 expect(workspace.getTrackById('foo')).toEqual(track); 24 }); 25 26 test('getNodeByKey', () => { 27 const track = new TrackNode({id: 'bar'}); 28 29 const group = new TrackNode(); 30 group.addChildLast(track); 31 32 // Add group to workspace AFTER adding the track to the group 33 const workspace = new Workspace(); 34 workspace.addChildLast(group); 35 36 expect(workspace.getTrackById('bar')).toBe(track); 37 }); 38 39 test('nested index lookup', () => { 40 const track = new TrackNode({id: 'bar'}); 41 42 const group = new TrackNode(); 43 44 // Add group to workspace before adding the track to the group 45 const workspace = new Workspace(); 46 workspace.addChildLast(group); 47 group.addChildLast(track); 48 49 expect(workspace.getTrackById('bar')).toBe(track); 50 }); 51 52 test('nested index lookup', () => { 53 const workspace = new Workspace(); 54 55 const group = new TrackNode(); 56 57 const track = new TrackNode({id: 'bar'}); 58 group.addChildLast(track); 59 60 // Add group to workspace 61 workspace.addChildLast(group); 62 workspace.removeChild(group); 63 64 expect(workspace.getTrackById('bar')).toBe(undefined); 65 }); 66 67 test('findTrackByUri()', () => { 68 const workspace = new Workspace(); 69 70 const group = new TrackNode(); 71 72 const track = new TrackNode({uri: 'foo'}); 73 group.addChildLast(track); 74 75 // Add group to workspace 76 workspace.addChildLast(group); 77 78 expect(workspace.findTrackByUri('foo')).toBe(track); 79 }); 80 81 test('findClosestVisibleAncestor()', () => { 82 const child = new TrackNode(); 83 child.expand(); // Expanding the child node should have no effect 84 85 const parent = new TrackNode(); 86 parent.expand(); 87 parent.addChildLast(child); 88 89 // While everything is expanded and the child node is visible, the child 90 // should be returned. 91 expect(child.findClosestVisibleAncestor()).toBe(child); 92 93 // Collapse the parent node and this parent should be returned, as from the 94 // point of view of the root, this is the closest we can get to our target 95 // node without expanding any more nodes. 96 parent.collapse(); 97 expect(child.findClosestVisibleAncestor()).toBe(parent); 98 }); 99}); 100 101describe('TrackNode.addChildInOrder', () => { 102 let container: TrackNode; 103 104 beforeEach(() => { 105 container = new TrackNode(); 106 }); 107 108 test('inserts a child into an empty container', () => { 109 const child = new TrackNode({id: 'track1'}); 110 111 container.addChildInOrder(child); 112 113 expect(container.children).toHaveLength(1); 114 expect(container.children[0]).toBe(child); 115 }); 116 117 test('inserts a child with a lower sortOrder before an existing child', () => { 118 const child1 = new TrackNode({sortOrder: 10}); 119 const child2 = new TrackNode({sortOrder: 5}); 120 121 container.addChildInOrder(child1); 122 container.addChildInOrder(child2); 123 124 expect(container.children).toHaveLength(2); 125 expect(container.children[0]).toBe(child2); 126 expect(container.children[1]).toBe(child1); 127 }); 128 129 test('inserts a child with a higher sortOrder after an existing child', () => { 130 const child1 = new TrackNode({sortOrder: 5}); 131 const child2 = new TrackNode({sortOrder: 10}); 132 133 container.addChildInOrder(child1); 134 container.addChildInOrder(child2); 135 136 expect(container.children).toHaveLength(2); 137 expect(container.children[0]).toBe(child1); 138 expect(container.children[1]).toBe(child2); 139 }); 140 141 test('inserts a child with the same sortOrder after an existing child', () => { 142 const child1 = new TrackNode({sortOrder: 5}); 143 const child2 = new TrackNode({sortOrder: 5}); 144 145 container.addChildInOrder(child1); 146 container.addChildInOrder(child2); 147 148 expect(container.children).toHaveLength(2); 149 expect(container.children[0]).toBe(child1); 150 expect(container.children[1]).toBe(child2); 151 }); 152 153 test('inserts multiple children and maintains order', () => { 154 const child1 = new TrackNode({sortOrder: 15}); 155 const child2 = new TrackNode({sortOrder: 10}); 156 const child3 = new TrackNode({sortOrder: 20}); 157 158 container.addChildInOrder(child1); 159 container.addChildInOrder(child2); 160 container.addChildInOrder(child3); 161 162 expect(container.children).toHaveLength(3); 163 expect(container.children[0]).toBe(child2); 164 expect(container.children[1]).toBe(child1); 165 expect(container.children[2]).toBe(child3); 166 }); 167 168 test('inserts a child with undefined sortOrder as 0', () => { 169 const child1 = new TrackNode({sortOrder: 10}); 170 171 // sortOrder is undefined, treated as 0 172 const child2 = new TrackNode(); 173 174 container.addChildInOrder(child1); 175 container.addChildInOrder(child2); 176 177 expect(container.children).toHaveLength(2); 178 179 // child2 (sortOrder 0) should be first 180 expect(container.children[0]).toBe(child2); 181 expect(container.children[1]).toBe(child1); 182 }); 183}); 184 185test('TrackNode::flatTracksOrdered', () => { 186 const root = new TrackNode(); 187 188 const removeme = new TrackNode({id: 'removeme'}); 189 root.addChildFirst(removeme); 190 191 const foo = new TrackNode({id: 'foo'}); 192 root.addChildLast(foo); 193 foo.addChildLast(new TrackNode({id: 'fooBar'})); // <-- Note this one is added as a child of foo 194 const bar = new TrackNode({id: 'bar'}); 195 root.addChildLast(bar); 196 root.addChildFirst(new TrackNode({id: 'baz'})); // <- Note this one is added first so should appear before the others in flatTracks 197 198 root.removeChild(removeme); 199 200 expect(root.flatTracksOrdered.map(({id}) => id)).toEqual([ 201 'baz', 202 'foo', 203 'fooBar', 204 'bar', 205 ]); 206}); 207 208test('TrackNode::flatTracks', () => { 209 const root = new TrackNode(); 210 211 const removeme = new TrackNode({id: 'removeme'}); 212 root.addChildFirst(removeme); 213 214 const foo = new TrackNode({id: 'foo'}); 215 root.addChildLast(foo); 216 foo.addChildLast(new TrackNode({id: 'fooBar'})); // <-- Note this one is added as a child of foo 217 root.addChildLast(new TrackNode({id: 'bar'})); 218 root.addChildFirst(new TrackNode({id: 'baz'})); // <- Note this one is added first so should appear before the others in flatTracks 219 220 root.removeChild(removeme); 221 222 expect(root.flatTracks.map(({id}) => id)).toEqual( 223 expect.arrayContaining(['baz', 'foo', 'fooBar', 'bar']), 224 ); 225 expect(root.flatTracks.length).toBe(4); 226}); 227