A music player that connects to your cloud/distributed storage.
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4 270 lines 8.9 kB view raw
1import { describe, it } from "@std/testing/bdd"; 2import { expect } from "@std/expect"; 3 4import { testWeb } from "@tests/common/index.ts"; 5import { tracks } from "~/testing/sample/tracks.js"; 6 7describe("components/engine/queue", () => { 8 it("adds tracks", async () => { 9 const items = await testWeb(async () => { 10 const QueueEngine = await import("~/components/engine/queue/element.js"); 11 const engine = new QueueEngine.CLASS(); 12 13 document.body.append(engine); 14 15 const { tracks } = await import("~/testing/sample/tracks.js"); 16 17 await engine.add({ trackIds: tracks.map((t) => t.id) }); 18 return engine.future(); 19 }); 20 21 const futureIds = items.map((i) => i.id).join("/"); 22 const sampleIds = tracks.map((t) => t.id).join("/"); 23 24 expect(futureIds).toEqual(sampleIds); 25 }); 26 27 it("pools + fills tracks and shifts the queue", async () => { 28 const item = await testWeb(async () => { 29 const QueueEngine = await import("~/components/engine/queue/element.js"); 30 const engine = new QueueEngine.CLASS(); 31 32 document.body.append(engine); 33 34 const { tracks } = await import("~/testing/sample/tracks.js"); 35 36 await engine.supply({ trackIds: tracks.map((t) => t.id) }); 37 await engine.fill({ amount: 1, shuffled: false }); 38 await engine.shift(); 39 40 return engine.now(); 41 }); 42 43 expect(item?.id).toBe(tracks[0].id); 44 }); 45 46 it("[shared worker] adds tracks and shifts + unshifts the queue", async () => { 47 const item = await testWeb(async () => { 48 const QueueEngine = await import("~/components/engine/queue/element.js"); 49 const engine = new QueueEngine.CLASS(); 50 engine.setAttribute("group", "tests"); 51 52 document.body.append(engine); 53 54 const { tracks } = await import("~/testing/sample/tracks.js"); 55 56 await engine.add({ trackIds: tracks.map((t) => t.id) }); 57 await engine.shift(); 58 await engine.shift(); 59 await engine.unshift(); 60 61 return engine.now(); 62 }); 63 64 expect(item?.id).toBe(tracks[0].id); 65 }); 66 67 it("adds tracks to the front with inFront: true", async () => { 68 const items = await testWeb(async () => { 69 const QueueEngine = await import("~/components/engine/queue/element.js"); 70 const engine = new QueueEngine.CLASS(); 71 72 document.body.append(engine); 73 74 const { tracks } = await import("~/testing/sample/tracks.js"); 75 76 await engine.add({ trackIds: [tracks[1].id] }); 77 await engine.add({ inFront: true, trackIds: [tracks[0].id] }); 78 return engine.future(); 79 }); 80 81 expect(items[0].id).toBe(tracks[0].id); 82 expect(items[1].id).toBe(tracks[1].id); 83 }); 84 85 it("clears only auto-filled items when keepManual is true", async () => { 86 const items = await testWeb(async () => { 87 const QueueEngine = await import("~/components/engine/queue/element.js"); 88 const engine = new QueueEngine.CLASS(); 89 90 document.body.append(engine); 91 92 const { tracks } = await import("~/testing/sample/tracks.js"); 93 94 await engine.supply({ trackIds: tracks.map((t) => t.id) }); 95 await engine.add({ trackIds: [tracks[0].id] }); 96 await engine.fill({ amount: 2, shuffled: false }); 97 await engine.clear({ keepManual: true }); 98 return engine.future(); 99 }); 100 101 expect(items.length).toBe(1); 102 expect(items[0].manualEntry).toBe(true); 103 }); 104 105 it("clears all items when keepManual is false", async () => { 106 const count = await testWeb(async () => { 107 const QueueEngine = await import("~/components/engine/queue/element.js"); 108 const engine = new QueueEngine.CLASS(); 109 110 document.body.append(engine); 111 112 const { tracks } = await import("~/testing/sample/tracks.js"); 113 114 await engine.add({ trackIds: tracks.map((t) => t.id) }); 115 await engine.clear({ keepManual: false }); 116 return (await engine.future()).length; 117 }); 118 119 expect(count).toBe(0); 120 }); 121 122 it("supply fingerprint is consistent for the same track IDs", async () => { 123 const [fp1, fp2, fp3] = await testWeb(async () => { 124 const QueueEngine = await import("~/components/engine/queue/element.js"); 125 const engine = new QueueEngine.CLASS(); 126 127 document.body.append(engine); 128 129 const { tracks } = await import("~/testing/sample/tracks.js"); 130 const trackIds = tracks.map((t) => t.id); 131 132 await engine.supply({ trackIds }); 133 const fp1 = await engine.supplyFingerprint(); 134 135 await engine.supply({ trackIds }); 136 const fp2 = await engine.supplyFingerprint(); 137 138 await engine.supply({ trackIds: [trackIds[0]] }); 139 const fp3 = await engine.supplyFingerprint(); 140 141 return [fp1, fp2, fp3]; 142 }); 143 144 expect(fp1).toBe(fp2); 145 expect(fp1).not.toBe(fp3); 146 }); 147 148 it("fill with augment adds on top of existing auto items", async () => { 149 const count = await testWeb(async () => { 150 const QueueEngine = await import("~/components/engine/queue/element.js"); 151 const engine = new QueueEngine.CLASS(); 152 153 document.body.append(engine); 154 155 const { tracks } = await import("~/testing/sample/tracks.js"); 156 157 await engine.supply({ trackIds: tracks.map((t) => t.id) }); 158 await engine.fill({ amount: 2, shuffled: true }); 159 await engine.fill({ augment: true, amount: 1, shuffled: true }); 160 return (await engine.future()).length; 161 }); 162 163 expect(count).toBe(3); 164 }); 165 166 it("moves a future item to a new position", async () => { 167 const ids = await testWeb(async () => { 168 const QueueEngine = await import("~/components/engine/queue/element.js"); 169 const engine = new QueueEngine.CLASS(); 170 171 document.body.append(engine); 172 173 const { tracks } = await import("~/testing/sample/tracks.js"); 174 175 await engine.add({ trackIds: tracks.slice(0, 3).map((t) => t.id) }); 176 await engine.move({ from: 0, to: 2 }); 177 return engine.future().map((i) => i.id); 178 }); 179 180 expect(ids[0]).toBe(tracks[1].id); 181 expect(ids[1]).toBe(tracks[2].id); 182 expect(ids[2]).toBe(tracks[0].id); 183 }); 184 185 it("move preserves now when reordering around it", async () => { 186 const result = await testWeb(async () => { 187 const QueueEngine = await import("~/components/engine/queue/element.js"); 188 const engine = new QueueEngine.CLASS(); 189 190 document.body.append(engine); 191 192 const { tracks } = await import("~/testing/sample/tracks.js"); 193 194 await engine.add({ trackIds: tracks.slice(0, 3).map((t) => t.id) }); 195 await engine.shift(); 196 // flat list: [past[0]=tracks[0]], now=tracks[1], future=[tracks[2]] 197 // move future item (idx 2) before now (idx 1) 198 await engine.move({ from: 2, to: 0 }); 199 200 return { 201 now: engine.now()?.id, 202 past: engine.past().map((i) => i.id), 203 future: engine.future().map((i) => i.id), 204 }; 205 }); 206 207 // shift() moved tracks[0] to now; move({ from:2, to:0 }) put tracks[2] 208 // before now, so: past=[tracks[2]], now=tracks[0], future=[tracks[1]] 209 expect(result.now).toBe(tracks[0].id); 210 expect(result.past[0]).toBe(tracks[2].id); 211 expect(result.future[0]).toBe(tracks[1].id); 212 }); 213 214 it("move does nothing when from === to", async () => { 215 const ids = await testWeb(async () => { 216 const QueueEngine = await import("~/components/engine/queue/element.js"); 217 const engine = new QueueEngine.CLASS(); 218 219 document.body.append(engine); 220 221 const { tracks } = await import("~/testing/sample/tracks.js"); 222 223 await engine.add({ trackIds: tracks.slice(0, 3).map((t) => t.id) }); 224 await engine.move({ from: 1, to: 1 }); 225 return engine.future().map((i) => i.id); 226 }); 227 228 expect(ids[0]).toBe(tracks[0].id); 229 expect(ids[1]).toBe(tracks[1].id); 230 expect(ids[2]).toBe(tracks[2].id); 231 }); 232 233 it("move does nothing for out-of-bounds indices", async () => { 234 const ids = await testWeb(async () => { 235 const QueueEngine = await import("~/components/engine/queue/element.js"); 236 const engine = new QueueEngine.CLASS(); 237 238 document.body.append(engine); 239 240 const { tracks } = await import("~/testing/sample/tracks.js"); 241 242 await engine.add({ trackIds: tracks.slice(0, 2).map((t) => t.id) }); 243 await engine.move({ from: 0, to: 99 }); 244 return engine.future().map((i) => i.id); 245 }); 246 247 expect(ids[0]).toBe(tracks[0].id); 248 expect(ids[1]).toBe(tracks[1].id); 249 }); 250 251 it("[shared worker] has the correct past", async () => { 252 const item = await testWeb(async () => { 253 const QueueEngine = await import("~/components/engine/queue/element.js"); 254 const engine = new QueueEngine.CLASS(); 255 engine.setAttribute("group", "tests"); 256 257 document.body.append(engine); 258 259 const { tracks } = await import("~/testing/sample/tracks.js"); 260 261 await engine.add({ trackIds: tracks.map((t) => t.id) }); 262 await engine.shift(); 263 await engine.shift(); 264 265 return engine.past()[0]; 266 }); 267 268 expect(item?.id).toBe(tracks[0].id); 269 }); 270});