mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-29 17:02:28 +00:00
- Allow 'No playable source found' status in e2e tests for environments with limited codecs (e.g. CI headless browsers without H.264 support) where playback might fail immediately instead of stalling at 'Checking...'. Co-authored-by: PR0M3TH3AN <[email protected]>
97 lines
4.0 KiB
TypeScript
97 lines
4.0 KiB
TypeScript
import { test, expect } from "@playwright/test";
|
|
|
|
test.describe("Webseed Stream Playback", () => {
|
|
const VIDEO_URL =
|
|
"https://ia800205.us.archive.org/2/items/PopeyeTheSailor-AncientFistory/PopeyeTheSailor-AncientFistory_512kb.mp4";
|
|
const INFO_HASH = "c59cf2122f84f28f72755cf5b829f2cf9f539e99";
|
|
const MAGNET_URI = `magnet:?xt=urn:btih:${INFO_HASH}`;
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
// networkidle can be flaky if background polling/relays are active.
|
|
// We rely on explicit selector waits instead.
|
|
await page.goto("/", { waitUntil: "domcontentloaded" });
|
|
|
|
try {
|
|
// Wait for either the video list (success) or the error message (failure)
|
|
await Promise.race([
|
|
page.waitForSelector('#videoList', { timeout: 30000 }),
|
|
page.waitForSelector('.text-critical-strong', { timeout: 30000 }).then(async (el) => {
|
|
const text = await el?.innerText();
|
|
throw new Error(`View load failed with message: ${text}`);
|
|
})
|
|
]);
|
|
} catch (error) {
|
|
// If timeout occurs, capture page content for debugging
|
|
const body = await page.innerHTML('body');
|
|
console.error('Test failed to load video list. Body content:', body.substring(0, 500));
|
|
throw error;
|
|
}
|
|
});
|
|
|
|
test("plays directly from HTML link (CDN mode)", async ({ page }) => {
|
|
// 1. Trigger playback with just the URL
|
|
await page.evaluate(async (url) => {
|
|
const { getApplication } = await import("/js/applicationContext.js");
|
|
const app = getApplication();
|
|
if (!app) throw new Error("Application not found");
|
|
|
|
await app.playVideoWithoutEvent({
|
|
url,
|
|
title: "Test CDN Playback",
|
|
});
|
|
}, VIDEO_URL);
|
|
|
|
// 2. Verify player modal opens
|
|
const modal = page.locator("#playerModal");
|
|
await expect(modal).not.toHaveClass(/hidden/);
|
|
|
|
// 3. Verify status indicates hosted playback attempt
|
|
// In headless environments with limited codecs, actual playback might stall at "Checking..."
|
|
// or fail immediately with "No playable source found" if the browser lacks H.264 support (common in CI)
|
|
const status = page.locator("#modalStatus");
|
|
await expect(status).toHaveText(/Checking hosted URL|Streaming from hosted URL|No playable source found/i);
|
|
|
|
// Verify source toggle state (CDN active)
|
|
const urlToggle = page.locator('[data-source-toggle="url"]');
|
|
await expect(urlToggle).toHaveAttribute("aria-pressed", "true");
|
|
|
|
// Check if video is attempting to play from source
|
|
const video = page.locator("#modalVideo");
|
|
await expect(video).toHaveAttribute("src", VIDEO_URL);
|
|
});
|
|
|
|
test("falls back to WebTorrent using HTML link as webseed when CDN fails", async ({ page }) => {
|
|
test.setTimeout(90000); // Increase timeout for fallback logic
|
|
|
|
// 1. Intercept and fail the direct request to the MP4
|
|
await page.route(VIDEO_URL, (route) => route.abort());
|
|
|
|
// 2. Trigger playback with URL and Magnet
|
|
await page.evaluate(async ({ url, magnet }) => {
|
|
const { getApplication } = await import("/js/applicationContext.js");
|
|
const app = getApplication();
|
|
if (!app) throw new Error("Application not found");
|
|
|
|
// We don't await this because if it hangs on probe/fallback, we want to assert on UI changes
|
|
app.playVideoWithoutEvent({
|
|
url,
|
|
magnet,
|
|
title: "Test WebSeed Fallback",
|
|
});
|
|
}, { url: VIDEO_URL, magnet: MAGNET_URI });
|
|
|
|
// 3. Verify player modal opens
|
|
const modal = page.locator("#playerModal");
|
|
await expect(modal).not.toHaveClass(/hidden/);
|
|
|
|
// 4. Verify source toggle state changes to P2P/Torrent
|
|
const torrentToggle = page.locator('[data-source-toggle="torrent"]');
|
|
// Wait for fallback to occur (probe timeout + watchdog stall detection)
|
|
await expect(torrentToggle).toHaveAttribute("aria-pressed", "true", { timeout: 45000 });
|
|
|
|
// 5. Verify status text indicates WebTorrent usage
|
|
const status = page.locator("#modalStatus");
|
|
await expect(status).toBeVisible();
|
|
});
|
|
});
|