diff --git a/.changes/playback-player-settings-panel.md b/.changes/playback-player-settings-panel.md index 0ab266108..983fd6e6f 100644 --- a/.changes/playback-player-settings-panel.md +++ b/.changes/playback-player-settings-panel.md @@ -1,7 +1,6 @@ --- type: feature area: playback -highlight: Player settings panel --- Audio, subtitles, quality, speed and aspect ratio now live in one settings diff --git a/.changes/playback-up-next-card.md b/.changes/playback-up-next-card.md index 670036029..96f9cc6fa 100644 --- a/.changes/playback-up-next-card.md +++ b/.changes/playback-up-next-card.md @@ -1,7 +1,6 @@ --- type: feature area: playback -highlight: Up next in the player --- In the last minutes of a series episode the player shows an "Up next" card diff --git a/.changes/settings-search.md b/.changes/settings-search.md index 137d7eff1..0b27dc810 100644 --- a/.changes/settings-search.md +++ b/.changes/settings-search.md @@ -1,7 +1,7 @@ --- type: feature area: settings -highlight: Search your settings +screenshot: settings-search --- Settings are now searchable: type in the search box on the Settings page to diff --git a/tools/release/capture-navigation-setup-actions.ts b/tools/release/capture-navigation-setup-actions.ts index cbeb140aa..6bb49bf1b 100644 --- a/tools/release/capture-navigation-setup-actions.ts +++ b/tools/release/capture-navigation-setup-actions.ts @@ -164,6 +164,36 @@ async function openSettingsEpg(page: Page): Promise { await page.waitForTimeout(500); } +/** + * Settings with a term typed into the header search, so the page shows the + * ranked results list and the per-section match counts instead of a section. + * The term lives only in the `q` query param: the next action's navigation + * clears it, and nothing is staged in the settings form. + */ +async function openSettingsSearch( + page: Page, + term: string | null +): Promise { + if (!term) { + throw new Error('open-settings-search needs a term: open-settings-search='); + } + + await openSettings(page); + await page + .locator('app-workspace-shell-header input[type="search"]') + .fill(term, { timeout: 10_000 }); + await page.waitForURL(/\/workspace\/settings\/general\?q=/, { + timeout: 15_000, + }); + const results = page.locator('[data-test-id="settings-search-results"]'); + await results.waitFor({ state: 'visible', timeout: 15_000 }); + await results + .locator('[data-test-id^="settings-search-result-"]') + .first() + .waitFor({ state: 'visible', timeout: 10_000 }); + await settleUi(page); +} + /* ------------------------------------------------------------------ */ /* Remote control (guide shots) */ /* ------------------------------------------------------------------ */ @@ -301,6 +331,7 @@ export const SETUP_ACTIONS: Readonly> = { 'open-add-playlist-stalker': openAddPlaylistStalker, 'open-add-playlist-m3u-url': openAddPlaylistM3uUrl, 'open-settings-epg': openSettingsEpg, + 'open-settings-search': openSettingsSearch, 'open-settings-tmdb': openSettingsTmdb, 'open-settings-remote-control': openSettingsRemoteControl, 'enable-remote-control': enableRemoteControl, diff --git a/tools/release/project.json b/tools/release/project.json index 6b56d349c..c71c7dedd 100644 --- a/tools/release/project.json +++ b/tools/release/project.json @@ -21,6 +21,7 @@ "{workspaceRoot}/tools/release/nightly-version.mjs", "{workspaceRoot}/tools/release/screenshot-guards.mjs", "{workspaceRoot}/tools/release/screenshots.manifest.json", + "{workspaceRoot}/tools/release/capture-navigation-*-actions.ts", "{workspaceRoot}/.github/workflows/build-and-make.yaml", "{workspaceRoot}/tools/release/release-notes.test.mjs", "{workspaceRoot}/tools/release/release-note-gate.test.mjs", diff --git a/tools/release/screenshot-guards.mjs b/tools/release/screenshot-guards.mjs index 9d7641010..a805f8402 100644 --- a/tools/release/screenshot-guards.mjs +++ b/tools/release/screenshot-guards.mjs @@ -70,6 +70,7 @@ export const KNOWN_ACTIONS = [ 'open-m3u-channel-menu', 'open-epg-mapping-dialog', 'open-settings-tmdb', + 'open-settings-search', ]; /** diff --git a/tools/release/screenshot-guards.test.mjs b/tools/release/screenshot-guards.test.mjs index fa61b90b3..f29706bfb 100644 --- a/tools/release/screenshot-guards.test.mjs +++ b/tools/release/screenshot-guards.test.mjs @@ -26,6 +26,7 @@ import { snapshotDatabaseState, stubbedResponseFor, DEFAULT_SHOT_GROUP, + KNOWN_ACTIONS, FICTIONAL_STALKER_MAC, outputDirectoryFor, shotGroup, @@ -81,6 +82,35 @@ describe('manifest validation', () => { assert.deepEqual(validateManifest(validManifest()), []); }); + it('accepts the committed screenshots.manifest.json', () => { + const manifest = JSON.parse( + readFileSync(new URL('./screenshots.manifest.json', import.meta.url), 'utf8') + ); + + assert.deepEqual(validateManifest(manifest), []); + }); + + it('knows exactly the setup actions the capture navigation dispatches', () => { + // The dispatcher is TypeScript and cannot be imported here, so read + // the action tables' keys from source: an action added on one side + // only would fail the manifest check or the capture run. + const dir = new URL('./', import.meta.url); + const dispatched = readdirSync(dir) + .filter((name) => /^capture-navigation-.+-actions\.ts$/.test(name)) + .flatMap((name) => { + const source = readFileSync(new URL(name, dir), 'utf8'); + const table = source.match( + /_ACTIONS: Readonly> = \{([^}]*)\}/ + ); + assert.ok(table, `${name} exports no action table`); + return [...table[1].matchAll(/'([a-z0-9-]+)':/g)].map( + ([, action]) => action + ); + }); + + assert.deepEqual([...dispatched].sort(), [...KNOWN_ACTIONS].sort()); + }); + it('rejects unknown setup actions, bad slugs and duplicates', () => { const manifest = validManifest(); manifest.shots.push( diff --git a/tools/release/screenshots.manifest.json b/tools/release/screenshots.manifest.json index d9dc53582..ec58e8b06 100644 --- a/tools/release/screenshots.manifest.json +++ b/tools/release/screenshots.manifest.json @@ -23,6 +23,13 @@ "open-settings" ] }, + { + "slug": "settings-search", + "title": "Settings search results", + "setup": [ + "open-settings-search=player" + ] + }, { "slug": "xtream-vod-details", "title": "Movie details",