A music player that connects to your cloud/distributed storage.
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 manualOnly 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({ manualOnly: 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 manualOnly 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({ manualOnly: 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("[shared worker] has the correct past", async () => {
167 const item = await testWeb(async () => {
168 const QueueEngine = await import("~/components/engine/queue/element.js");
169 const engine = new QueueEngine.CLASS();
170 engine.setAttribute("group", "tests");
171
172 document.body.append(engine);
173
174 const { tracks } = await import("~/testing/sample/tracks.js");
175
176 await engine.add({ trackIds: tracks.map((t) => t.id) });
177 await engine.shift();
178 await engine.shift();
179
180 return engine.past()[0];
181 });
182
183 expect(item?.id).toBe(tracks[0].id);
184 });
185});