Files
ytplayer/tests/download-actions.spec.js
2026-10-04 02:48:08 +08:00

42 lines
3.5 KiB
JavaScript

const { test, expect } = require('@playwright/test');
const { openClassic } = require('./helpers/classic-fixture');
const { mkdirSync } = require('node:fs');
const before = process.env.CAPTURE_BEFORE === '1';
for (const layout of ['classic', 'glass-stage']) for (const width of [390, 1440]) for (const screen of ['downloads', 'settings']) test(`${layout} ${width} ${screen}: failed download actions`, async ({ page }, info) => {
await page.setViewportSize({ width, height: 844 });
await openClassic(page);
await page.evaluate(({ layout, screen }) => {
data.settings.layout = layout; applyAppearance();
window.actionCalls = [];
Downloads.configure({ slots: () => 4, files: async () => [], playlists: () => [], jobs: () => [{ id: 'aaaaaaaaaaa', title: 'A long worship recording with piano, strings and choir — evening session', channel: 'Studio', thumbnail: '/fixture-cover.svg', status: 'failed', error: 'ERROR: [youtube] Video unavailable' }], action: (id, action) => actionCalls.push([id, action]) });
API.cacheList = async () => ({ ok: true, items: [], total: 0 });
view = { type: screen }; render();
}, { layout, screen });
if (screen === 'settings') await page.getByRole('button', { name: /Downloads & storage/ }).click();
const retry = page.getByRole('button', { name: /^Retry A long/ });
const cancel = page.getByRole('button', { name: /^Cancel A long/ });
await expect(retry).toBeVisible(); await expect(cancel).toBeVisible();
await retry.scrollIntoViewIfNeeded();
if (before) {
mkdirSync('/home/josh/deliverables/ytplayer-done12', { recursive: true });
await page.screenshot({ path: `/home/josh/deliverables/ytplayer-done12/before-${layout}-${width}-${screen}-${info.project.name}.png` }); return;
}
for (const button of [retry, cancel]) {
await expect(button.locator('svg')).toHaveAttribute('aria-hidden', 'true');
const rect = await button.boundingBox(); expect(rect.height).toBeGreaterThanOrEqual(44); expect(rect.width).toBeGreaterThanOrEqual(44);
await expect(button.locator('span')).toHaveText(button === retry ? 'Retry' : 'Cancel');
}
const a = await retry.boundingBox(), b = await cancel.boundingBox();
expect(a.x + a.width <= b.x || a.y + a.height <= b.y).toBe(true);
const visual = await retry.evaluate(el => { const s = getComputedStyle(el), probe = document.createElement('span'); probe.style.backgroundColor = getComputedStyle(document.documentElement).getPropertyValue(document.documentElement.dataset.layout === 'glass-stage' ? '--tile' : '--bg-2').trim(); document.body.append(probe); const expected = getComputedStyle(probe).backgroundColor; probe.remove(); return { radius: s.borderRadius, background: s.backgroundColor, expected }; });
expect(visual.radius).toBe(layout === 'glass-stage' ? '18px' : '8px');
expect(visual.background).toBe(visual.expected);
await page.keyboard.press('Tab'); await retry.focus(); expect(await retry.evaluate(el => getComputedStyle(el).outlineStyle)).not.toBe('none');
mkdirSync('/home/josh/deliverables/ytplayer-done12', { recursive: true });
await page.screenshot({ path: `/home/josh/deliverables/ytplayer-done12/after-${layout}-${width}-${screen}-${info.project.name}.png` });
await retry.click(); expect(await page.evaluate(() => actionCalls)).toContainEqual(['aaaaaaaaaaa', 'retry']);
await cancel.click();
if (screen === 'downloads') await page.locator('.modal').getByRole('button', { name: 'Cancel save', exact: true }).click();
expect(await page.evaluate(() => actionCalls)).toContainEqual(['aaaaaaaaaaa', 'cancel']);
});