mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-16 14:16:16 -08:00
Merge origin/master into claude/server-storage-pwa
Resolves tools/performance/journey-baselines.json: master's #1938 lowered renderer.initialBytes to 1,329,249; the merged tree measures 1,338,342 locally, so the branch's raise is now 9,093 bytes (0.7%), with its note updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
f6a216f59a
12 files changed
+388
-63
No files matched your search
@@ -0,0 +1,78 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
import { pressTab } from './e2e-helpers';
|
||||
import { expect } from './fixtures';
|
||||
|
||||
/** The computed colour a custom property resolves to on this page. */
|
||||
async function computedColor(page: Page, property: string): Promise<string> {
|
||||
return page.evaluate((name) => {
|
||||
const probe = document.createElement('span');
|
||||
probe.style.color = `var(${name})`;
|
||||
document.body.append(probe);
|
||||
const color = getComputedStyle(probe).color;
|
||||
probe.remove();
|
||||
return color;
|
||||
}, property);
|
||||
}
|
||||
|
||||
/**
|
||||
* The radio player's play/pause control is a `mat-icon-button` drawn as the
|
||||
* 56px primary circle the fab used to draw (the fab tokens alone were about
|
||||
* 6 KB of the initial stylesheet), with the icon centred, and keyboard focus
|
||||
* draws the app ring that the fab reset with `outline: none`.
|
||||
*/
|
||||
export async function verifyRadioPlayControl(
|
||||
page: Page,
|
||||
browserName: string
|
||||
): Promise<void> {
|
||||
const player = page.locator('app-audio-player');
|
||||
const play = player.locator('.play-btn');
|
||||
await expect(play).toBeVisible();
|
||||
await expect(play).toHaveClass(/mat-mdc-icon-button/);
|
||||
await expect(play).not.toHaveClass(/mat-mdc-fab/);
|
||||
|
||||
const style = await play.evaluate((button) => {
|
||||
const icon = button.querySelector('mat-icon') as HTMLElement;
|
||||
const box = button.getBoundingClientRect();
|
||||
const iconBox = icon.getBoundingClientRect();
|
||||
const { width, height, borderRadius, backgroundColor } =
|
||||
getComputedStyle(button);
|
||||
const centre = (rect: DOMRect) => [
|
||||
rect.left + rect.width / 2,
|
||||
rect.top + rect.height / 2,
|
||||
];
|
||||
const [x, y] = centre(box);
|
||||
const [iconX, iconY] = centre(iconBox);
|
||||
return {
|
||||
width,
|
||||
height,
|
||||
borderRadius,
|
||||
backgroundColor,
|
||||
iconColor: getComputedStyle(icon).color,
|
||||
iconFontSize: getComputedStyle(icon).fontSize,
|
||||
iconOffset: [Math.round(iconX - x), Math.round(iconY - y)],
|
||||
};
|
||||
});
|
||||
expect(style).toEqual({
|
||||
width: '56px',
|
||||
height: '56px',
|
||||
borderRadius: '50%',
|
||||
backgroundColor: await computedColor(page, '--app-selection-color'),
|
||||
iconColor: 'rgb(255, 255, 255)',
|
||||
iconFontSize: '32px',
|
||||
iconOffset: [0, 0],
|
||||
});
|
||||
|
||||
await player.locator('.skip-btn').first().focus();
|
||||
await pressTab(page, browserName);
|
||||
await expect(play).toBeFocused();
|
||||
const ring = await play.evaluate((button) => {
|
||||
const { outlineStyle, outlineWidth, outlineColor } =
|
||||
getComputedStyle(button);
|
||||
return { outlineStyle, outlineWidth, outlineColor };
|
||||
});
|
||||
expect(ring).toEqual({
|
||||
outlineStyle: 'solid',
|
||||
outlineWidth: '2px',
|
||||
outlineColor: await computedColor(page, '--app-focus-ring'),
|
||||
});
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
import { verifyStalkerSeasonMarkers } from './stalker-season-markers.fixture';
|
||||
import { verifyStalkerOpenInPlaylist } from './stalker-open-in-playlist.fixture';
|
||||
import { playFirstItvChannel } from './stalker-itv-playback.fixture';
|
||||
import { verifyRadioPlayControl } from './stalker-radio-player.fixture';
|
||||
import {
|
||||
AUTH_REJECTED_MAC,
|
||||
BACKEND_PROXY,
|
||||
@@ -296,6 +297,7 @@ test('@stalker ITV playback survives a category switch', async ({ page }) => {
|
||||
|
||||
test('@stalker radio — stations use the inline audio player without EPG', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await addStalkerPortal(page);
|
||||
|
||||
@@ -333,6 +335,7 @@ test('@stalker radio — stations use the inline audio player without EPG', asyn
|
||||
await expect(page.locator('app-audio-player')).toBeVisible({
|
||||
timeout: 20_000,
|
||||
});
|
||||
await verifyRadioPlayControl(page, browserName);
|
||||
|
||||
// Level 2: only the categories rail folds; the channels header turns
|
||||
// its title into a category dropdown that opens the same rail as a
|
||||
|
||||
Reference in new issue
Block a user