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

Configure Feed

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

at v4 174 lines 5.3 kB view raw
1import { describe, it } from "@std/testing/bdd"; 2import { expect } from "@std/expect"; 3 4import { testWeb } from "@tests/common/index.ts"; 5 6describe("components/configurator/scrobbles", () => { 7 it("scrobblers returns empty array when there are no children", async () => { 8 const result = await testWeb(async () => { 9 const mod = await import( 10 "~/components/configurator/scrobbles/element.js" 11 ); 12 const configurator = new mod.CLASS(); 13 document.body.append(configurator); 14 return configurator.scrobblers().length; 15 }); 16 17 expect(result).toBe(0); 18 }); 19 20 it("nowPlaying resolves without throwing when there are no active scrobblers", async () => { 21 const result = await testWeb(async () => { 22 const mod = await import( 23 "~/components/configurator/scrobbles/element.js" 24 ); 25 const configurator = new mod.CLASS(); 26 document.body.append(configurator); 27 28 const track = { 29 $type: "sh.diffuse.output.track" as const, 30 id: "t1", 31 uri: "https://example.com/audio.mp3", 32 }; 33 34 await configurator.nowPlaying(track); 35 return true; 36 }); 37 38 expect(result).toBe(true); 39 }); 40 41 it("scrobble resolves without throwing when there are no active scrobblers", async () => { 42 const result = await testWeb(async () => { 43 const mod = await import( 44 "~/components/configurator/scrobbles/element.js" 45 ); 46 const configurator = new mod.CLASS(); 47 document.body.append(configurator); 48 49 const track = { 50 $type: "sh.diffuse.output.track" as const, 51 id: "t1", 52 uri: "https://example.com/audio.mp3", 53 }; 54 55 await configurator.scrobble(track, Date.now()); 56 return true; 57 }); 58 59 expect(result).toBe(true); 60 }); 61 62 it("scrobblers includes child elements that have the scrobble interface", async () => { 63 const result = await testWeb(async () => { 64 const mod = await import( 65 "~/components/configurator/scrobbles/element.js" 66 ); 67 const configurator = new mod.CLASS(); 68 69 // Mock scrobbler with the required interface 70 const mock = document.createElement("div"); 71 (mock as any).isAuthenticated = () => true; 72 (mock as any).nowPlaying = async () => {}; 73 (mock as any).scrobble = async () => {}; 74 configurator.appendChild(mock); 75 76 document.body.append(configurator); 77 78 return configurator.scrobblers().length; 79 }); 80 81 expect(result).toBe(1); 82 }); 83 84 it("scrobblers excludes children that do not have the scrobble interface", async () => { 85 const result = await testWeb(async () => { 86 const mod = await import( 87 "~/components/configurator/scrobbles/element.js" 88 ); 89 const configurator = new mod.CLASS(); 90 91 // Plain element without scrobble methods 92 const plain = document.createElement("div"); 93 configurator.appendChild(plain); 94 95 document.body.append(configurator); 96 97 return configurator.scrobblers().length; 98 }); 99 100 expect(result).toBe(0); 101 }); 102 103 it("nowPlaying calls all authenticated scrobblers", async () => { 104 const result = await testWeb(async () => { 105 const mod = await import( 106 "~/components/configurator/scrobbles/element.js" 107 ); 108 const configurator = new mod.CLASS(); 109 110 const calls: string[] = []; 111 112 const auth = document.createElement("div"); 113 (auth as any).isAuthenticated = () => true; 114 (auth as any).nowPlaying = async () => { calls.push("auth"); }; 115 (auth as any).scrobble = async () => {}; 116 117 const unauth = document.createElement("div"); 118 (unauth as any).isAuthenticated = () => false; 119 (unauth as any).nowPlaying = async () => { calls.push("unauth"); }; 120 (unauth as any).scrobble = async () => {}; 121 122 configurator.appendChild(auth); 123 configurator.appendChild(unauth); 124 document.body.append(configurator); 125 126 const track = { 127 $type: "sh.diffuse.output.track" as const, 128 id: "t1", 129 uri: "https://example.com/audio.mp3", 130 }; 131 132 await configurator.nowPlaying(track); 133 return calls; 134 }); 135 136 expect(result).toEqual(["auth"]); 137 }); 138 139 it("scrobble calls all authenticated scrobblers", async () => { 140 const result = await testWeb(async () => { 141 const mod = await import( 142 "~/components/configurator/scrobbles/element.js" 143 ); 144 const configurator = new mod.CLASS(); 145 146 const calls: string[] = []; 147 148 const auth = document.createElement("div"); 149 (auth as any).isAuthenticated = () => true; 150 (auth as any).nowPlaying = async () => {}; 151 (auth as any).scrobble = async () => { calls.push("auth"); }; 152 153 const unauth = document.createElement("div"); 154 (unauth as any).isAuthenticated = () => false; 155 (unauth as any).nowPlaying = async () => {}; 156 (unauth as any).scrobble = async () => { calls.push("unauth"); }; 157 158 configurator.appendChild(auth); 159 configurator.appendChild(unauth); 160 document.body.append(configurator); 161 162 const track = { 163 $type: "sh.diffuse.output.track" as const, 164 id: "t1", 165 uri: "https://example.com/audio.mp3", 166 }; 167 168 await configurator.scrobble(track, Date.now()); 169 return calls; 170 }); 171 172 expect(result).toEqual(["auth"]); 173 }); 174});