104 lines
6.2 KiB
JavaScript
104 lines
6.2 KiB
JavaScript
const { test, expect } = require('@playwright/test');
|
|
const { openClassic, showPlayingFixture } = require('./helpers/classic-fixture');
|
|
|
|
for (const width of [320, 390, 768, 1024, 1280, 1440]) {
|
|
test(`empty home is unclipped at ${width}px`, async ({ page }) => {
|
|
await page.setViewportSize({ width, height: 900 });
|
|
await openClassic(page);
|
|
const result = await page.evaluate(() => {
|
|
const stage = document.querySelector('.player-stage').getBoundingClientRect();
|
|
const hero = document.querySelector('.hero').getBoundingClientRect();
|
|
const chips = [...document.querySelectorAll('.hero .chip')].map(el => el.getBoundingClientRect());
|
|
return { stageBottom: stage.bottom, heroBottom: hero.bottom, stageTop: stage.top, heroTop: hero.top,
|
|
chipsFit: chips.every(r => r.right <= innerWidth && r.left >= 0 && r.bottom <= stage.bottom),
|
|
overflow: document.querySelector('.main').scrollWidth > document.querySelector('.main').clientWidth + 1 };
|
|
});
|
|
expect(result.heroTop).toBeGreaterThanOrEqual(result.stageTop);
|
|
expect(result.heroBottom).toBeLessThanOrEqual(result.stageBottom + 1);
|
|
expect(result.chipsFit).toBe(true);
|
|
expect(result.overflow).toBe(false);
|
|
await expect(page.locator('#bottomNav')).toBeVisible({ visible: width <= 860 });
|
|
});
|
|
}
|
|
|
|
for (const standalone of [false, true]) {
|
|
test(`navigation during playback and mini-player return (${standalone ? 'PWA' : 'browser'})`, async ({ page }) => {
|
|
await page.setViewportSize({ width: 390, height: 844 });
|
|
await openClassic(page, { populated: true, standalone });
|
|
await showPlayingFixture(page);
|
|
await expect(page.locator('#back10Btn')).toBeVisible();
|
|
await expect(page.locator('#fwd10Btn')).toBeVisible();
|
|
await page.locator('#bottomNav [data-view="settings"]').click();
|
|
await expect(page.locator('.settings')).toBeVisible();
|
|
await expect.poll(() => page.locator('.list-pane').evaluate(el => el.getBoundingClientRect().top)).toBeLessThan(130);
|
|
await expect(page.locator('#miniBar')).toBeVisible();
|
|
const boxes = await page.evaluate(() => ({
|
|
mini: document.getElementById('miniBar').getBoundingClientRect().bottom,
|
|
nav: document.getElementById('bottomNav').getBoundingClientRect().top,
|
|
}));
|
|
expect(boxes.mini).toBeLessThanOrEqual(boxes.nav + 1);
|
|
await page.locator('.body').evaluate(el => { el.scrollTop = el.scrollHeight; });
|
|
const last = page.locator('.settings .set-group').last();
|
|
await expect(last).toBeInViewport();
|
|
expect(await last.evaluate(el => el.getBoundingClientRect().bottom)).toBeLessThanOrEqual(boxes.nav);
|
|
await page.locator('#miniTitle').click();
|
|
await expect.poll(() => page.locator('.body').evaluate(el => el.scrollTop)).toBe(0);
|
|
expect(await page.evaluate(() => window.scrollY)).toBe(0);
|
|
await page.locator('#ctlMoreBtn').click();
|
|
await expect(page.locator('#modal')).toBeVisible();
|
|
});
|
|
}
|
|
|
|
test('playlist, appearance settings, rotation, and layout switching preserve data', async ({ page }) => {
|
|
await page.setViewportSize({ width: 1440, height: 960 });
|
|
await openClassic(page, { populated: true });
|
|
await expect(page.locator('#homePlGrid')).toContainText('Studio sessions');
|
|
await showPlayingFixture(page);
|
|
expect(await page.locator('.list-pane').evaluate(el => el.getBoundingClientRect().width)).toBeGreaterThanOrEqual(340);
|
|
expect(await page.locator('.card-info').first().evaluate(el => el.getBoundingClientRect().width)).toBeGreaterThan(120);
|
|
const original = await page.evaluate(() => JSON.stringify(data.playlists));
|
|
for (const theme of ['light', 'contrast', 'dark']) {
|
|
await page.evaluate(theme => { data.settings.theme = theme; applyAppearance(); }, theme);
|
|
expect(await page.locator('.hero-title').evaluate(el => getComputedStyle(el).webkitTextFillColor)).not.toBe('rgba(0, 0, 0, 0)');
|
|
}
|
|
for (const layout of ['glass-stage', 'sanctuary-stage', 'classic']) {
|
|
await page.evaluate(layout => { data.settings.layout = layout; applyAppearance(); }, layout);
|
|
await expect(page.locator('html')).toHaveAttribute('data-layout', layout);
|
|
expect(await page.evaluate(() => JSON.stringify(data.playlists))).toBe(original);
|
|
}
|
|
await page.setViewportSize({ width: 844, height: 390 });
|
|
await page.locator('#bottomNav [data-view="history"]').click();
|
|
await expect(page.locator('#listTitle')).toHaveText('History');
|
|
await page.setViewportSize({ width: 390, height: 844 });
|
|
await page.evaluate(() => { data.settings.fontScale = 'xl'; data.settings.density = 'compact'; applyAppearance(); });
|
|
await expect(page.locator('#bottomNav [data-view="settings"]')).toBeInViewport();
|
|
expect(await page.evaluate(() => document.querySelector('.main').scrollWidth <= document.querySelector('.main').clientWidth + 1)).toBe(true);
|
|
});
|
|
|
|
test('320px with extra-large text keeps navigation and controls reachable', async ({ page }) => {
|
|
await page.setViewportSize({ width: 320, height: 844 });
|
|
await openClassic(page, { populated: true, settings: { fontScale: 'xl' } });
|
|
await showPlayingFixture(page);
|
|
await expect(page.locator('#bottomNav [data-view="settings"]')).toBeInViewport();
|
|
expect(await page.locator('#controls').evaluate(el => el.scrollWidth <= el.clientWidth + 1)).toBe(true);
|
|
expect(await page.locator('.app').evaluate(el => Math.abs(el.getBoundingClientRect().height - innerHeight))).toBeLessThan(2);
|
|
expect(await page.locator('#bottomNav').evaluate(el => el.scrollWidth <= el.clientWidth + 1)).toBe(true);
|
|
await page.locator('#bottomNav [data-view="settings"]').click();
|
|
await expect(page.locator('.settings')).toBeVisible();
|
|
});
|
|
|
|
test.describe('Classic offline shell', () => {
|
|
test.use({ serviceWorkers: 'allow' });
|
|
test('caches the Classic stylesheet and restores it offline', async ({ page, context }) => {
|
|
await openClassic(page);
|
|
await page.evaluate(() => navigator.serviceWorker.ready);
|
|
await page.reload();
|
|
await page.waitForFunction(() => !!navigator.serviceWorker.controller);
|
|
expect(await page.evaluate(async () => !!(await caches.match('/theme-classic.css')))).toBe(true);
|
|
await context.setOffline(true);
|
|
await page.reload();
|
|
await expect(page.locator('html')).toHaveAttribute('data-layout', 'classic');
|
|
expect(await page.locator('html').evaluate(el => getComputedStyle(el).getPropertyValue('--bg').trim())).toBe('#121315');
|
|
});
|
|
});
|