// Test réseau de YoutubeInformation / SpotifyInformation / Finder (cache + limiteur), sans démarrer le bot. const assert = require("assert"); const path = require("path"); const SRC = require("path").resolve(__dirname, "../../src"); // Logs loguix dans le scratchpad (sinon LogType.error plante : flux non initialisé) require(path.join(SRC, "../node_modules/loguix")).setup(path.join(__dirname, "logs"), path.join(SRC, "../package.json")); // Configuration factice : évite de lire data/config.json (et son process.exit sans token) const confPath = require.resolve(path.join(SRC, "utils/Database/Configuration.js")); const fakeConf = { id: "", secret: "" }; require.cache[confPath] = { id: confPath, filename: confPath, loaded: true, exports: { getSpotifyClientId: () => fakeConf.id, getSpotifyClientSecret: () => fakeConf.secret, } }; const yt = require(path.join(SRC, "media/YoutubeInformation.js")); const spotify = require(path.join(SRC, "media/SpotifyInformation.js")); const Finder = require(path.join(SRC, "player/Finder.js")); const { Playlist } = require(path.join(SRC, "playlists/Playlist.js")); async function timed(label, fn) { const t = Date.now(); const r = await fn(); const ms = Date.now() - t; console.log(`${label}: ${ms} ms`); return [r, ms]; } (async () => { // 1) Recherche : 2e appel servi par le cache const [s1, m1] = await timed("getQuery #1 (réseau)", () => yt.getQuery("Daft Punk Around the World", true)); assert.ok(Array.isArray(s1) && s1.length > 0, "résultats attendus"); const [s2, m2] = await timed("getQuery #2 (cache)", () => yt.getQuery(" daft punk around the world ", false)); assert.ok(s2 && s2.url === s1[0].url, "même premier résultat"); assert.ok(m2 < 20, "le 2e appel doit venir du cache"); assert.notStrictEqual(s2, s1[0], "instances Song distinctes"); // 2) Vidéo par id : 2e appel + getSecondsFromUrl servis par le cache const url = "https://www.youtube.com/watch?v=jNQXAC9IVRw"; const [v1] = await timed("getVideo #1 (réseau)", () => yt.getVideo(url)); assert.ok(v1 && v1.id === "jNQXAC9IVRw" && v1.duration > 0, JSON.stringify(v1)); const [v2, mv2] = await timed("getVideo #2 (cache)", () => yt.getVideo(url)); assert.ok(mv2 < 20 && v2.title === v1.title); const [secs, ms3] = await timed("getSecondsFromUrl (cache)", () => yt.getSecondsFromUrl("https://youtu.be/jNQXAC9IVRw")); assert.strictEqual(secs, v1.duration); assert.ok(ms3 < 20); // 3) Appels simultanés dédupliqués (1 seul scrape) const [[a, b], md] = await timed("2 recherches simultanées identiques", () => Promise.all([yt.getQuery("lofi hip hop radio"), yt.getQuery("LOFI hip hop radio")])); assert.ok(a && b && a.url === b.url); // 4) Durée d'une vidéo issue d'une recherche : déjà en cache const [secs2, ms4] = await timed("getSecondsFromUrl d'un résultat de recherche", () => yt.getSecondsFromUrl(s1[1].url)); assert.ok(ms4 < 20 && secs2 === s1[1].duration); // 5) Playlists YouTube (nouvelle mise en page) + avatar ; 2e appel servi par le cache for (const listUrl of ["https://www.youtube.com/playlist?list=PLdXJrX9OsbOVq2TKvUc3xGUp2Rm8nTUVh", "https://www.youtube.com/watch?v=fcnDmrtj6Sk&list=PL4fGSI1pDJn6puJdseH2Rt9sMvt9E2M4i"]) { const [p1] = await timed("getPlaylist #1 (réseau)", () => yt.getPlaylist(listUrl)); assert.ok(p1 && p1.songs.length > 0, "playlist attendue"); const s0 = p1.songs[0]; console.log(" playlist:", p1.title, "| auteur:", p1.author, p1.authorId, "| titres:", p1.songs.length, "| durée:", p1.readduration, "| avatar:", String(p1.authorAvatar).slice(0, 50)); console.log(" 1er titre:", s0.title, "|", s0.author, s0.authorId, "|", s0.readduration, s0.url); assert.ok(s0.url.startsWith("https://www.youtube.com/watch?v=") && s0.type === "youtube" && s0.duration > 0); const [p2, mp2] = await timed("getPlaylist #2 (cache)", () => yt.getPlaylist(listUrl)); assert.ok(mp2 < 20 && p2.songs.length === p1.songs.length && p2.authorAvatar === p1.authorAvatar); const [sec, ms5] = await timed("getSecondsFromUrl d'un titre de playlist", () => yt.getSecondsFromUrl(s0.url)); assert.ok(ms5 < 20 && sec === s0.duration); } // Avatar d'une chaîne (en-têtes navigateur + consentement), 2e appel en cache // 6) getTracks : concurrence 3, ordre conservé, titres invalides ignorés, idempotent const pl = new Playlist("Test", "https://open.spotify.com/playlist/x"); pl.type = "spotify"; pl.songs = [ { id: "t1", name: "Get Lucky", artists: [{ name: "Daft Punk" }], duration_ms: 248000 }, null, { id: "t2", name: "Bohemian Rhapsody", artists: [{ name: "Queen" }], duration_ms: 354000 }, { id: "pod", name: "Episode", artists: [] }, { id: "t3", name: "Billie Jean", artists: [{ name: "Michael Jackson" }], duration_ms: 294000 }, ]; const [out] = await timed("getTracks (3 titres)", () => spotify.getTracks(pl)); assert.strictEqual(out, pl); assert.deepStrictEqual(out.songs.map(s => s.id), ["t1", "t2", "t3"]); assert.ok(out.songs.every(s => s.type === "youtube" && s.url.startsWith("https://www.youtube.com/watch?v="))); assert.strictEqual(out.duration, 248 + 354 + 294); const [, mi] = await timed("getTracks idempotent", () => spotify.getTracks(pl)); assert.ok(mi < 20 && pl.songs.length === 3); // 7) Finder : playlist Spotify convertie (spotify.getPlaylist simulé), échec total → null const realGetPlaylist = spotify.getPlaylist; spotify.getPlaylist = async () => { const p = new Playlist("Sim", "u"); p.type = "spotify"; p.songs = [{ id: "z", name: "Get Lucky", artists: [{ name: "Daft Punk" }], duration_ms: 1000 }]; return p; }; const fp = await Finder.search("https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M", true); assert.ok(fp instanceof Playlist && fp.songs[0].type === "youtube" && fp.songs[0].url, "Finder doit renvoyer des Song convertis"); const fp2 = await Finder.search("https://open.spotify.com/intl-fr/playlist/37i9dQZF1DXcBWIGoYBM5M?si=abc", false, "PLAYLIST"); assert.ok(fp2 && fp2.songs[0].url); spotify.getPlaylist = async () => { const p = new Playlist("Vide", "u"); p.type = "spotify"; p.songs = [null]; return p; }; assert.strictEqual(await Finder.search("https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M", true), null); spotify.getPlaylist = realGetPlaylist; console.log("Finder Spotify: OK"); // 8) Spotify sans identifiants : erreur propre (pas d'appel réseau), lecture paresseuse assert.strictEqual(await spotify.getSong("https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC"), null); process.emit("CONFIG_UPDATE"); console.log("Spotify sans identifiants: OK (null)"); console.log("\nTOUS LES TESTS RÉUSSIS"); process.exit(0); })().catch(e => { console.error("ÉCHEC", e); process.exit(1); });