// HLS (.m3u8) support — see js/services/hlsPlayback.js. // // Scenario spec (SCN-hls-*): bitvid used to attach every hosted source with // `videoEl.src = url`, which only plays HLS on Safari. Nostr clients publishing // bitvid's v3 schema with HLS ladders (nostube/slidestr) were unplayable on // Chrome/Firefox, and the URL-health probe reported every healthy HLS stream as // offline. These tests pin the observable decisions at those boundaries: // detection, engine selection, teardown, and the manifest probe. // // The hls.js engine itself is never loaded here — the tests exercise the // native-HLS branch and the fetch-based manifest probe, which are the two paths // that do not require a real MediaSource implementation. import { test } from "node:test"; import assert from "node:assert/strict"; import { HLS_MIME_TYPES, attachHlsSource, detachHls, getAttachedHls, isHlsMimeType, isHlsSource, isHlsUrl, prefersNativeHls, probeHlsManifest, supportsMse, supportsNativeHls, } from "../../js/services/hlsPlayback.js"; // --- SCN-hls-detect ------------------------------------------------------- // Given a hosted URL, when its path ends in .m3u8, then it is treated as HLS — // regardless of query strings (signed CDN URLs) or fragments. test("isHlsUrl matches .m3u8 paths, including with query/fragment", () => { assert.equal( isHlsUrl( "https://almond.apps2.slidestr.net/3751b84f27234fc8ce3227d132b422f7e00f4a50c6cdc322080fed89a302d7dd.m3u8" ), true ); assert.equal(isHlsUrl("https://cdn.example/v.M3U8"), true); assert.equal(isHlsUrl("https://cdn.example/v.m3u8?token=abc&exp=1"), true); assert.equal(isHlsUrl("https://cdn.example/v.m3u8#t=10"), true); assert.equal(isHlsUrl(" https://cdn.example/v.m3u8 "), true); }); test("isHlsUrl rejects non-playlist URLs and incidental .m3u8 substrings", () => { assert.equal(isHlsUrl("https://cdn.example/v.mp4"), false); assert.equal(isHlsUrl("https://cdn.example/v.webm"), false); // .m3u8 must terminate the PATH, not merely appear somewhere in the URL. assert.equal(isHlsUrl("https://cdn.example/v.m3u8.mp4"), false); assert.equal(isHlsUrl("https://cdn.example/?next=/a.m3u8"), false); assert.equal(isHlsUrl(""), false); assert.equal(isHlsUrl(null), false); assert.equal(isHlsUrl(undefined), false); assert.equal(isHlsUrl(42), false); }); test("isHlsMimeType covers the canonical and legacy playlist types", () => { for (const type of HLS_MIME_TYPES) { assert.equal(isHlsMimeType(type), true, `${type} should be HLS`); assert.equal(isHlsMimeType(type.toUpperCase()), true); } // Parameters must not defeat the match (servers append charset). assert.equal(isHlsMimeType("application/vnd.apple.mpegurl; charset=utf-8"), true); assert.equal(isHlsMimeType("video/mp4"), false); assert.equal(isHlsMimeType("text/plain"), false); assert.equal(isHlsMimeType(""), false); assert.equal(isHlsMimeType(null), false); }); test("isHlsSource accepts either the URL or an imeta mime hint", () => { assert.equal(isHlsSource({ url: "https://cdn.example/v.m3u8" }), true); assert.equal( isHlsSource({ url: "https://cdn.example/stream", mimeType: "application/vnd.apple.mpegurl" }), true ); assert.equal(isHlsSource({ url: "https://cdn.example/v.mp4" }), false); assert.equal(isHlsSource({}), false); assert.equal(isHlsSource(), false); }); // --- SCN-hls-engine-choice ------------------------------------------------ // Given a browser that CLAIMS native HLS support via canPlayType, when MSE is // also available, then hls.js must win. This is not a preference — it is a // correctness requirement measured in real browsers: // // Firefox 146: canPlayType("application/vnd.apple.mpegurl") === "" // bare