fix(test): update e2e menu selectors (#1674)

This commit is contained in:
Sam Potts
2026-06-11 12:29:59 +10:00
committed by GitHub
parent f90a700a00
commit 6b0d3b6b2f
4 changed files with 27 additions and 47 deletions
+17 -30
View File
@@ -15,14 +15,22 @@ function withinControls(selector: string): string {
return `media-controls ${selector}, .media-controls ${selector}`;
}
/** Scope a descendant selector to each comma-separated panel matcher. */
function withinMenuPanel(panelSelector: string, descendant: string): string {
return panelSelector
function unchecked(selector: string): string {
return selector
.split(',')
.map((panel) => `${panel.trim()} ${descendant}`)
.map((part) => `${part.trim()}[aria-checked="false"]`)
.join(', ');
}
const menu = '[role="menu"]';
const item = '[role="menuitem"]';
const option = '[role="menuitemradio"]';
const activeMenu = `${menu}[data-menu-view-state="active"]`;
const playbackRateOptions = [
`#playback-rate-menu ${option}`,
withinControls(`.media-menu--playback-rate ${option}`),
].join(', ');
export const SELECTORS = {
// Player containers
// HTML: <video-player>, React: wrapper div around VideoSkin
@@ -47,37 +55,16 @@ export const SELECTORS = {
withinControls('.media-button--playback-rate'),
withinControls('button[aria-haspopup="menu"][aria-label^="Playback rate"]:not(.media-menu__item)'),
].join(', '),
playbackRateMenuPanel: '#playback-rate-menu[role="menu"], [role="menu"]#playback-rate-menu',
playbackRateMenuRadioItems: withinMenuPanel(
'#playback-rate-menu[role="menu"], [role="menu"]#playback-rate-menu',
'[role="menuitemradio"]'
),
/** Standalone playback rate menu items (HTML id + React open menu in controls). */
openPlaybackRateMenuRadioItems: [
withinMenuPanel('#playback-rate-menu[role="menu"], [role="menu"]#playback-rate-menu', '[role="menuitemradio"]'),
withinControls('[role="menu"] [role="menuitemradio"]'),
].join(', '),
/** Currently visible settings submenu panel (HTML + React). */
activeMenuPanel: '[role="menu"][data-menu-view-state="active"]',
activeMenuRadioItems: '[role="menu"][data-menu-view-state="active"] [role="menuitemradio"]',
playbackRateUncheckedOptions: unchecked(playbackRateOptions),
activeMenuOptions: `${activeMenu} ${option}`,
activeMenuUncheckedOptions: unchecked(`${activeMenu} ${option}`),
settingsButton: [
withinControls('.media-button--settings'),
withinControls('button[commandfor="settings-menu"]'),
withinControls('button[aria-label="Settings"]'),
].join(', '),
settingsCaptionsItem: [
'media-menu-item[commandfor="settings-captions-menu"]',
'[role="menuitem"]:has-text("Captions")',
].join(', '),
settingsSpeedItem: ['media-menu-item[commandfor="settings-speed-menu"]', '[role="menuitem"]:has-text("Speed")'].join(
', '
),
settingsSpeedMenuPanel: '#settings-speed-menu[role="menu"], [role="menu"]#settings-speed-menu',
settingsCaptionsMenuPanel: '#settings-captions-menu[role="menu"], [role="menu"]#settings-captions-menu',
settingsCaptionsMenuRadioItems: withinMenuPanel(
'#settings-captions-menu[role="menu"], [role="menu"]#settings-captions-menu',
'[role="menuitemradio"]'
),
settingsCaptionsItem: `${item}:has-text("Captions")`,
settingsSpeedItem: `${item}:has-text("Speed")`,
// Sliders
// HTML: <media-time-slider>, React: horizontal .media-slider inside .media-time-controls
+3 -11
View File
@@ -166,7 +166,7 @@ export class PlayerPage {
await this.settingsButton.click();
await expect(this.settingsSpeedItem).toBeVisible();
await this.settingsSpeedItem.click();
await expect(this.page.locator(`${SELECTORS.activeMenuPanel} [role="menuitemradio"]`).first()).toBeVisible();
await expect(this.page.locator(SELECTORS.activeMenuOptions).first()).toBeVisible();
}
async openCaptionsSettings(): Promise<void> {
@@ -174,7 +174,7 @@ export class PlayerPage {
await this.settingsButton.click();
await expect(this.settingsCaptionsItem).toBeVisible();
await this.settingsCaptionsItem.click();
await expect(this.page.locator(SELECTORS.activeMenuRadioItems).first()).toBeVisible();
await expect(this.page.locator(SELECTORS.activeMenuOptions).first()).toBeVisible();
}
async getPlaybackRate(): Promise<number> {
@@ -236,16 +236,8 @@ export class PlayerPage {
await this.playbackRateButton.click();
}
const uncheckedPlaybackRateOptions = SELECTORS.openPlaybackRateMenuRadioItems
.split(', ')
.map((selector) => `${selector.trim()}[aria-checked="false"]`)
.join(', ');
const option = this.page
.locator(
usesSettingsMenu
? `${SELECTORS.activeMenuPanel} [role="menuitemradio"][aria-checked="false"]`
: uncheckedPlaybackRateOptions
)
.locator(usesSettingsMenu ? SELECTORS.activeMenuUncheckedOptions : SELECTORS.playbackRateUncheckedOptions)
.first();
await expect(option).toBeVisible({ timeout: 5_000 });
// Menu popovers can intercept pointer events on nested radio items.
+5 -4
View File
@@ -1,5 +1,5 @@
import { expect, test } from '@playwright/test';
import { SELECTORS } from '../fixtures/selectors';
import { DATA_ATTRS, SELECTORS } from '../fixtures/selectors';
import { PlayerPage } from '../page-objects/player';
test.describe('Captions', () => {
@@ -11,10 +11,11 @@ test.describe('Captions', () => {
await player.waitForMediaReady();
});
test('captions settings hidden without subtitle tracks', async () => {
test('captions settings are unavailable without subtitle tracks', async () => {
await player.showControls();
await player.settingsButton.click();
await expect(player.settingsCaptionsItem).toBeHidden();
await expect(player.settingsCaptionsItem).toHaveAttribute(DATA_ATTRS.availability, 'unavailable');
await expect(player.settingsCaptionsItem).toHaveAttribute('aria-disabled', 'true');
});
test('captions settings lists tracks when subtitle track is added', async ({ page }) => {
@@ -33,7 +34,7 @@ test.describe('Captions', () => {
await player.showControls();
await player.openCaptionsSettings();
const options = page.locator(SELECTORS.activeMenuRadioItems);
const options = page.locator(SELECTORS.activeMenuOptions);
await expect(options).toHaveCount(2, { timeout: 5_000 });
});
});
+2 -2
View File
@@ -67,8 +67,8 @@ test.describe('Visual — Captions', () => {
await player.showControls();
await player.openCaptionsSettings();
await expect(page.locator(SELECTORS.activeMenuRadioItems)).toHaveCount(2);
await page.locator(SELECTORS.activeMenuRadioItems).nth(1).dispatchEvent('click');
await expect(page.locator(SELECTORS.activeMenuOptions)).toHaveCount(2);
await page.locator(SELECTORS.activeMenuOptions).nth(1).dispatchEvent('click');
// Play briefly so the caption cue at 0:00 activates, then pause
await player.play();