mirror of
https://github.com/zoriya/v10.git
synced 2026-08-05 05:37:21 +00:00
fix(test): update e2e menu selectors (#1674)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user