Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions e2e/dashboard.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
its Content-Security-Policy in force. */

const { test, expect } = require('@playwright/test');
const { seedConfig, dismissSetupPrompt, app } = require('./helpers');
const { seedConfig, dismissSetupPrompt, app, widgetFramesLoaded } = require('./helpers');

/* The dashboard shows the first-run prompt until it is dismissed, and builds no
tiles behind it. */
Expand Down Expand Up @@ -138,8 +138,7 @@ test('one rotation into the phone layout loads each widget once', async ({ page,
await stubPolls(page);
await page.setViewportSize({ width: 844, height: 390 });
await page.goto('/');
await page.locator('iframe').first().waitFor({ state: 'attached' });
await page.waitForTimeout(500);
await widgetFramesLoaded(page);
let loads = 0;
page.on('framenavigated', f => {
if (f !== page.mainFrame() && f.url().includes('/widgets/')) loads++;
Expand All @@ -157,8 +156,7 @@ test('a safe-area change rebuilds the phone layout once', async ({ page, request
await page.setViewportSize({ width: 390, height: 844 });
await page.goto('/');
await page.locator('body.is-mob').waitFor({ state: 'attached' });
await page.locator('iframe').first().waitFor({ state: 'attached' });
await page.waitForTimeout(500);
await widgetFramesLoaded(page);
let loads = 0;
page.on('framenavigated', f => {
if (f !== page.mainFrame() && f.url().includes('/widgets/')) loads++;
Expand Down
15 changes: 15 additions & 0 deletions e2e/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,20 @@ async function animationsDone(page) {
});
}

/** Resolve once every widget frame on the page has finished loading its widget.
@param {import('@playwright/test').Page} page */
async function widgetFramesLoaded(page) {
await page.waitForFunction(() => {
const frames = [...document.querySelectorAll('iframe')];
return (
frames.length > 0 &&
frames.every(
f => f.contentWindow?.location.pathname.includes('/widgets/') && f.contentDocument?.readyState === 'complete',
)
);
});
}

/** The colour at one point, once it has stopped changing. A panel that fades in
is still moving when it first becomes visible.
@param {import('@playwright/test').Locator} locator
Expand Down Expand Up @@ -232,5 +246,6 @@ module.exports = {
pixelAt,
settledPixelAt,
animationsDone,
widgetFramesLoaded,
contrast,
};
6 changes: 3 additions & 3 deletions e2e/tile-names.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
tile. A badge is also not a live region. */

const { test, expect } = require('@playwright/test');
const { seedConfig, dismissSetupPrompt, app } = require('./helpers');
const { seedConfig, dismissSetupPrompt, app, animationsDone } = require('./helpers');

/* A host that cannot resolve, so the check fails the same way on every run. */
const DEAD = 'http://does-not-resolve.invalid/';
Expand Down Expand Up @@ -77,13 +77,13 @@ test.describe('tile names', () => {
await seedConfig(request, { items: [app('plain', 'Plain')], settings: { showLabels: { desktop: false } } });
await page.goto('/');
await page.locator('.icon').first().waitFor({ state: 'visible' });
await page.waitForTimeout(500);
await animationsDone(page);
const without = await readLive();

await seedConfig(request, { items: ITEMS, settings: { showLabels: { desktop: false } } });
await page.goto('/');
await page.locator('.badge.on').nth(2).waitFor({ state: 'visible' });
await page.waitForTimeout(500);
await animationsDone(page);
const with3 = await readLive();

expect(
Expand Down
8 changes: 2 additions & 6 deletions e2e/wheel-paging.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
a wheel inside it never reaches the dashboard unless it is handed on. */

const { test, expect } = require('@playwright/test');
const { seedConfig, dismissSetupPrompt, app } = require('./helpers');
const { seedConfig, dismissSetupPrompt, app, widgetFramesLoaded } = require('./helpers');

const MANY = Array.from({ length: 48 }, (_, i) => app(`a${i}`, `App ${i}`));
const clock = {
Expand All @@ -23,11 +23,7 @@ async function open(page, request) {
await page.route('**/api/health', r => r.fulfill({ status: 200, contentType: 'application/json', body: '{}' }));
await page.goto('/');
await page.locator('#dots .dot').nth(1).waitFor({ state: 'visible' });
await page.locator('.widget iframe').first().waitFor({ state: 'attached' });
await page.waitForFunction(() => {
const f = /** @type {HTMLIFrameElement|null} */ (document.querySelector('.widget iframe'));
return !!f && f.contentDocument?.readyState === 'complete';
});
await widgetFramesLoaded(page);
}

const current = page => page.locator('#dots .dot').evaluateAll(ds => ds.findIndex(d => d.classList.contains('on')));
Expand Down
Loading