test(detail): cover the widest heading translation in the Back lane E2E

Review follow-up. The E2E now switches the app to Dutch, the widest
"Seasons and Episodes" translation, and checks the heading stays on one
line at the lane (1280/780px) and bar (700/375px) widths. Below those a
translation wider than the pane itself wraps by design instead of losing
words to an ellipsis; the release note and UI guideline now say exactly
that rather than promising one line at every width.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Opus 5.5 committed 2026-09-30 20:39:36 +02:00
1 parent 38b9e4e267
commit 660fd04671
3 files changed
+49 -2

No files matched your search

+1 -1
View File
@@ -3,4 +3,4 @@ type: fix
area: detail
---
On movie and series pages, the Back button no longer covers the start of the "Seasons and Episodes" heading or the corner of the player while you scroll, and the heading stays on one line in narrow windows.
On movie and series pages, the Back button no longer covers the start of the "Seasons and Episodes" heading or the corner of the player while you scroll, and in narrow windows the heading no longer gets squeezed onto several lines beside its buttons.
@@ -1,11 +1,15 @@
import type { Locator, Page } from '@playwright/test';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import {
addXtreamPortal,
clickFirstGridListCard,
closeElectronApp,
expect,
launchElectronApp,
openSettings,
resetMockServers,
saveSettings,
test,
waitForXtreamWorkspaceReady,
} from './electron-test-fixtures';
@@ -28,6 +32,16 @@ import {
const widths = [1280, 780];
const compactWidths = [700, 375];
const playerCorner = 56;
/** The widest translation of the heading; it must fit wherever English does. */
const widestLocale = 'nl';
const widestHeading = (
JSON.parse(
readFileSync(
join(__dirname, `../../web/src/assets/i18n/${widestLocale}.json`),
'utf8'
)
) as { PORTALS: { SEASONS_AND_EPISODES: string } }
).PORTALS.SEASONS_AND_EPISODES;
type Sweep = {
overlaps: string[];
@@ -232,6 +246,35 @@ async function expectBackClearOfContent(
}
}
/**
* Re-checks the heading in the widest translation at the lane and bar widths.
* Below them (a ~220px header beside the category panel) a translation wider
* than the pane itself wraps by design rather than losing words to an
* ellipsis.
*/
async function expectWidestHeadingOnOneLine(
page: Page,
detailUrl: string
): Promise<void> {
await page.setViewportSize({ width: widths[0], height: 800 });
await openSettings(page);
await page.getByTestId('select-language').click();
await page.getByTestId(widestLocale).click();
await saveSettings(page);
await page.goBack();
await page.waitForURL(detailUrl);
await expect(page.locator('.section-title')).toHaveText(widestHeading, {
timeout: 20_000,
});
for (const width of [...widths, ...compactWidths]) {
await page.setViewportSize({ width, height: 800 });
expect(
await headingLineCount(page),
`${widestLocale} at ${width}px`
).toBe(1);
}
}
/**
* The actions move onto their own row before the heading wraps, at every
* pane width that can hold the heading at all — including the widths where
@@ -266,6 +309,7 @@ test.describe('Portal detail Back lane', () => {
/\/workspace\/xtreams\/[^/]+\/series\/[^/]+\/[^/]+$/
);
const detailUrl = page.url();
const shell = page.locator('app-portal-detail-shell');
const episodes = page.locator('.episode-card');
await expect(page.locator('.section-title')).toBeVisible({
@@ -284,6 +328,7 @@ test.describe('Portal detail Back lane', () => {
).toBeVisible({ timeout: 20_000 });
await expectBackClearOfContent(page, 'watch');
await expectWidestHeadingOnOneLine(page, detailUrl);
} finally {
await closeElectronApp(app);
}
+3 -1
View File
@@ -630,7 +630,9 @@ partial so Xtream and Stalker share the same behavior.
The season header's actions wrap onto their own row, starting under the
"Seasons and Episodes" heading, before the heading itself would wrap. The
detail pane is narrower than the window (context panel, the sticky Back lane),
so the header's own width decides, not a viewport breakpoint.
so the header's own width decides, not a viewport breakpoint. A translation
wider than the pane itself wraps rather than ellipsizing: unlike a fixed-height
panel title, a content heading has room to wrap and should not lose words.
Browser regression coverage measures the composited neutral edges and selected
toggle fill, in addition to capturing light/dark grid and list screenshots.