// Tests des fonctions pures de backend/src/playlists/Google/Utils.js (aucune dépendance) const assert = require("assert") const U = require(require("path").resolve(__dirname, "../../src/playlists/Google/Utils.js")) ;(async () => { // --- parseIsoDuration --- const cases = [["PT1H2M3S", 3723], ["PT4M13S", 253], ["PT45S", 45], ["PT0S", 0], ["P0D", 0], ["P1DT2H", 93600], ["PT10M", 600], ["P1W", 604800], ["PT1.5S", 1], ["pt3m", 180], ["P", null], ["PT", null], ["", null], ["1:23", null], [null, null], [123, null], ["P1Y", null], ["PT1H2M3", null]] for (const [input, expected] of cases) assert.strictEqual(U.parseIsoDuration(input), expected, "parseIsoDuration(" + input + ")") // --- collectPages : pagination simulée (3 pages de 50 + 1 de 20 = 170) --- const makeFetcher = (total, size, log) => async (token) => { log.push(token) const start = token ? Number(token) : 0 const items = Array.from({ length: Math.min(size, total - start) }, (_, i) => start + i) const next = start + size < total ? String(start + size) : undefined return { items, nextPageToken: next } } let log = [] let r = await U.collectPages(makeFetcher(170, 50, log), { maxItems: 500 }) assert.strictEqual(r.items.length, 170); assert.strictEqual(r.truncated, false); assert.strictEqual(r.pages, 4) assert.deepStrictEqual(log, [undefined, "50", "100", "150"]) // limite atteinte au milieu d'une page log = [] r = await U.collectPages(makeFetcher(1000, 50, log), { maxItems: 120 }) assert.strictEqual(r.items.length, 120); assert.strictEqual(r.truncated, true); assert.strictEqual(r.pages, 3) assert.deepStrictEqual(r.items.slice(-1), [119]) // limite atteinte pile en fin de page alors que Google annonce encore une page r = await U.collectPages(makeFetcher(1000, 50, []), { maxItems: 100 }) assert.strictEqual(r.items.length, 100); assert.strictEqual(r.truncated, true); assert.strictEqual(r.pages, 2) // limite pile sur le total : pas tronqué r = await U.collectPages(makeFetcher(100, 50, []), { maxItems: 100 }) assert.strictEqual(r.truncated, false); assert.strictEqual(r.items.length, 100) // jeton répété : pas de boucle infinie let calls = 0 r = await U.collectPages(async () => { calls++; return { items: [calls], nextPageToken: "SAME" } }, { maxItems: 500 }) assert.strictEqual(calls, 2); assert.strictEqual(r.items.length, 2) // maxPages r = await U.collectPages(makeFetcher(1000, 10, []), { maxItems: 500, maxPages: 3 }) assert.strictEqual(r.items.length, 30); assert.strictEqual(r.truncated, true) // page vide / réponse inattendue r = await U.collectPages(async () => null) assert.deepStrictEqual(r.items, []) // erreur propagée await assert.rejects(U.collectPages(async () => { throw new Error("boom") }), /boom/) // --- chunk --- assert.deepStrictEqual(U.chunk([1, 2, 3, 4, 5], 2), [[1, 2], [3, 4], [5]]) assert.strictEqual(U.chunk(Array.from({ length: 120 }), 50).length, 3) assert.deepStrictEqual(U.chunk([], 50), []) // --- createStateStore (horloge simulée) --- let now = 1_000_000 const store = U.createStateStore({ ttlMs: 10 * 60 * 1000, maxPerKey: 3, now: () => now }) const s1 = store.create("alice") assert.match(s1, /^[0-9a-f]{48}$/) assert.strictEqual(store.consume(s1, "bob"), false, "autre utilisateur refusé") assert.strictEqual(store.consume(s1, "alice"), true, "propriétaire accepté") assert.strictEqual(store.consume(s1, "alice"), false, "usage unique") const s2 = store.create("alice") now += 10 * 60 * 1000 + 1 assert.strictEqual(store.consume(s2, "alice"), false, "expiré après 10 min") const s3 = store.create("alice") now += 9 * 60 * 1000 assert.strictEqual(store.consume(s3, "alice"), true, "valide avant 10 min") // maxPerKey : les plus anciens sont évincés const olds = [store.create("carol"), store.create("carol"), store.create("carol"), store.create("carol")] assert.strictEqual(store.consume(olds[0], "carol"), false, "plus ancien évincé") assert.strictEqual(store.consume(olds[3], "carol"), true) store.clear("carol") assert.strictEqual(store.consume(olds[2], "carol"), false, "clear") assert.strictEqual(store.consume(undefined, "carol"), false) assert.strictEqual(store.consume(12, "carol"), false) // --- pickTokens / bestThumbnail --- assert.deepStrictEqual(U.pickTokens({ access_token: "a", refresh_token: null, expiry_date: 5, foo: 1 }), { access_token: "a", expiry_date: 5 }) assert.deepStrictEqual(U.pickTokens(null), {}) assert.strictEqual(U.bestThumbnail({ default: { url: "d" }, high: { url: "h" } }), "h") assert.strictEqual(U.bestThumbnail({}), null) assert.strictEqual(U.bestThumbnail(undefined), null) console.log("google-utils.test.js : OK") })().catch((e) => { console.error(e); process.exit(1) })