Files
ArtPlayer/test/browser/accessibility-mini.spec.js
T

143 lines
6.6 KiB
JavaScript

import { expect, test } from './fixtures.js'
async function setup(page) {
await page.goto('/test/player.html?core=candidate&chapter=published')
await page.evaluate(() => {
window.miniCalls = []
const outside = document.createElement('button')
outside.id = 'mini-outside'
outside.textContent = 'Outside'
document.body.append(outside)
window.art = new window.Artplayer({
container: '.player',
url: '/test/pattern.mp4',
muted: true,
hotkey: true,
controls: [{ name: 'mini-trigger', position: 'right', html: 'Mini', click() { this.mini = true } }],
})
window.art.on('mini', value => window.miniCalls.push(['mini', value]))
window.art.on('play', () => window.miniCalls.push(['play']))
window.art.on('pause', () => window.miniCalls.push(['pause']))
window.art.on('hotkey', event => window.miniCalls.push(['hotkey', event.code]))
})
await expect.poll(() => page.evaluate(() => window.art.isReady)).toBe(true)
}
test('candidate: mini keyboard entry reaches close and stable playback controls and Escape returns focus', async ({ page }, testInfo) => {
await setup(page)
const trigger = page.locator('.art-control-mini-trigger')
await trigger.focus()
await page.keyboard.press('Enter')
const popup = page.locator('.art-mini-popup')
await expect(popup.locator('.art-mini-close')).toBeFocused()
await expect(popup.locator('.art-mini-close')).toHaveAttribute('aria-label', 'Close')
await page.keyboard.press('Tab')
await expect(popup.locator('.art-mini-state')).toBeFocused()
await expect(popup.locator('.art-mini-state')).toHaveAttribute('aria-label', 'Play')
await page.keyboard.press('Space')
await expect.poll(() => page.evaluate(() => window.art.playing)).toBe(true)
await expect(popup.locator('.art-mini-state')).toBeFocused()
await expect(popup.locator('.art-mini-state')).toHaveAttribute('aria-label', 'Pause')
await page.keyboard.press('Enter')
await expect.poll(() => page.evaluate(() => window.art.playing)).toBe(false)
await popup.screenshot({ path: testInfo.outputPath('mini-keyboard.png') })
await page.keyboard.press('Escape')
await expect(popup).toBeHidden()
await expect(trigger).toBeFocused()
expect(await page.evaluate(() => window.miniCalls)).toEqual([['mini', true], ['play'], ['pause'], ['mini', false]])
})
test('candidate: mini pointer entry preserves focus and Space closes after keyboard navigation', async ({ page }) => {
await setup(page)
await page.locator('#mini-outside').focus()
await page.locator('.art-control-mini-trigger').click()
await expect(page.locator('.art-mini-close')).not.toBeFocused()
await page.locator('.art-mini-close').focus()
await page.keyboard.press('Space')
await expect(page.locator('.art-mini-popup')).toBeHidden()
await expect(page.locator('.art-control-mini-trigger')).toBeFocused()
expect(await page.evaluate(() => window.miniCalls)).toEqual([['mini', true], ['mini', false]])
})
test('candidate: programmatic mini exit preserves external focus and removed return targets use the player', async ({ page }) => {
await setup(page)
await page.locator('.art-control-mini-trigger').focus()
await page.keyboard.press('Enter')
await page.locator('#mini-outside').focus()
await page.evaluate(() => {
window.art.mini = false
})
await expect(page.locator('#mini-outside')).toBeFocused()
await page.locator('.art-control-mini-trigger').focus()
await page.keyboard.press('Enter')
await page.evaluate(() => window.art.controls.remove('mini-trigger'))
await page.keyboard.press('Escape')
await expect(page.locator('.art-video-player')).toBeFocused()
await expect(page.locator('.art-mini-popup')).toBeHidden()
})
test('candidate: destroying from mini return focus cancels late notifications and retained controls', async ({ page }) => {
await setup(page)
await page.locator('.art-control-mini-trigger').focus()
await page.keyboard.press('Enter')
await page.evaluate(() => {
window.retainedMini = window.art.template.$mini
window.art.controls['mini-trigger'].addEventListener('focus', () => window.art.destroy(false), { once: true })
window.miniCalls.length = 0
})
await page.keyboard.press('Escape')
expect(await page.evaluate(() => window.art.isDestroy)).toBe(true)
await page.evaluate(() => {
window.retainedMini.querySelector('.art-mini-close').click()
window.retainedMini.querySelector('.art-icon-play').click()
})
expect(await page.evaluate(() => window.miniCalls)).toEqual([])
})
test('candidate: mini reuse keeps keyboard entry and never returns to a stale or hidden origin', async ({ page }) => {
await setup(page)
const trigger = page.locator('.art-control-mini-trigger')
await trigger.focus()
await page.keyboard.press('Enter')
await page.keyboard.press('Escape')
await page.keyboard.press('Enter')
await expect(page.locator('.art-mini-close')).toBeFocused()
await page.evaluate(() => {
window.art.controls['mini-trigger'].style.visibility = 'hidden'
})
await page.keyboard.press('Escape')
await expect(page.locator('.art-video-player')).toBeFocused()
await page.evaluate(() => {
window.art.controls['mini-trigger'].style.visibility = ''
})
await page.locator('#mini-outside').focus()
await page.evaluate(() => {
window.art.mini = true
})
await expect(page.locator('#mini-outside')).toBeFocused()
await page.locator('.art-mini-close').focus()
await page.keyboard.press('Escape')
await expect(page.locator('.art-video-player')).toBeFocused()
})
test('candidate: mini names use existing i18n keys and hidden controls cannot reactivate the mode', async ({ page }) => {
await setup(page)
await page.evaluate(() => {
const get = window.art.i18n.get.bind(window.art.i18n)
const names = { 'Close': 'Localized close', 'Play': 'Localized play', 'Pause': 'Localized pause', 'Mini Player': 'Localized mini' }
window.art.i18n.get = key => names[key] || get(key)
})
await page.locator('.art-control-mini-trigger').focus()
await page.keyboard.press('Enter')
await expect(page.locator('.art-mini-popup')).toHaveAttribute('aria-label', 'Localized mini')
await expect(page.locator('.art-mini-close')).toHaveAttribute('aria-label', 'Localized close')
await expect(page.locator('.art-mini-state')).toHaveAttribute('aria-label', 'Localized play')
await page.keyboard.press('Escape')
await page.evaluate(() => {
window.miniCalls.length = 0
for (const selector of ['.art-mini-close', '.art-mini-state'])
document.querySelector(selector).dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true, cancelable: true }))
})
expect(await page.evaluate(() => window.miniCalls)).toEqual([])
})