Files
ytplayer/tests/video-editor.smoke.spec.js
Claude Worker 8c0776f97d feat: Add support for editing video
Add an Edit
2026-07-18 16:43:15 +00:00

73 lines
3.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Smoke test for the "Edit & download" custom-video feature (Task #68).
*
* The editor lets a user cut parts out of a video and save the result as a
* custom offline video that can be added to playlists like any other. This
* spec runs against the static frontend (no backend), so it exercises the
* pieces that don't need the yt-dlp/ffmpeg server round-trip:
* • video-edit.js loads and exposes window.VideoEdit with correct maths.
* • The now-playing "Edit & download" button (#editBtn) is present.
* • The editor modal opens, accepts a cut, and reports the right final
* length via the shared keep-segment maths.
*/
const { test, expect } = require('@playwright/test');
test.describe('Video editor — Edit & download', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/');
await page.waitForSelector('.app', { state: 'attached' });
});
test('exposes window.VideoEdit with correct cut/keep maths', async ({ page }) => {
const ok = await page.evaluate(() => typeof window.VideoEdit === 'object' && window.VideoEdit !== null);
expect(ok).toBe(true);
const keep = await page.evaluate(() =>
window.VideoEdit.invertCuts([{ start: 10, end: 20 }], 60));
expect(keep).toEqual([{ start: 0, end: 10 }, { start: 20, end: 60 }]);
const param = await page.evaluate(() =>
window.VideoEdit.keepToParam(window.VideoEdit.invertCuts([{ start: 10, end: 20 }], 60)));
expect(param).toBe('0-10,20-60');
const finalLen = await page.evaluate(() =>
window.VideoEdit.keepDuration(window.VideoEdit.invertCuts([{ start: 10, end: 20 }], 60)));
expect(finalLen).toBe(50);
});
test('renders the now-playing Edit & download button', async ({ page }) => {
const btn = page.locator('#editBtn');
await expect(btn).toHaveCount(1);
await expect(btn).toContainText('Edit');
});
test('editor modal opens for a source video and computes the final length', async ({ page }) => {
// Drive openVideoEditor directly with a fake source that has a known
// duration, so the test doesn't depend on network playback. OPFS may be
// absent in the test browser; if so the editor toasts and returns — assert
// whichever path this browser takes so the test is deterministic.
const supported = await page.evaluate(() =>
!!(window.OPFS && window.OPFS.isSupported && window.OPFS.isSupported()));
const opened = await page.evaluate(() => {
window.openVideoEditor({ id: 'testsource1', title: 'Sample', duration: 100, thumbnail: '' });
const modal = document.getElementById('modal');
return modal && !modal.classList.contains('hidden');
});
if (!supported) {
// Without OPFS the editor declines to open — that's the correct guard.
expect(opened).toBe(false);
return;
}
expect(opened).toBe(true);
// Add a cut 0:100:40 → final length should be 100 - 30 = 70s = "1:10".
await page.fill('.video-editor .ve-from', '0:10');
await page.fill('.video-editor .ve-to', '0:40');
await page.click('.video-editor .ve-add');
await expect(page.locator('.video-editor .ve-cut')).toHaveCount(1);
await expect(page.locator('.video-editor .ve-summary')).toContainText('1:10');
});
});