mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-09 03:46:16 -08:00
128 lines
6.2 KiB
JavaScript
128 lines
6.2 KiB
JavaScript
import { expect, test } from './fixtures.js'
|
|
|
|
async function setup(page) {
|
|
await page.addInitScript(() => Object.defineProperty(navigator, 'userAgent', { configurable: true, value: 'ArtPlayer Android keyboard fixture' }))
|
|
await page.goto('/test/player.html?core=candidate&chapter=published')
|
|
await page.evaluate(() => {
|
|
const outside = document.createElement('button')
|
|
outside.id = 'lock-outside'
|
|
outside.textContent = 'Outside'
|
|
document.body.append(outside)
|
|
window.lockEvents = []
|
|
window.art = new window.Artplayer({ container: '.player', url: '/test/pattern.mp4', muted: true, lock: true, hotkey: true })
|
|
window.art.on('lock', value => window.lockEvents.push([value, window.art.isLock, window.art.plugins.lock.state]))
|
|
})
|
|
await expect.poll(() => page.evaluate(() => window.art.isReady)).toBe(true)
|
|
}
|
|
|
|
test('candidate: lock uses one stable keyboard button, Escape unlocks and hidden controls leave Tab order', async ({ page }) => {
|
|
await setup(page)
|
|
const lock = page.locator('.art-layer-lock')
|
|
await lock.focus()
|
|
await expect(lock).toBeFocused()
|
|
await expect(lock).toHaveAttribute('aria-label', 'Lock')
|
|
await page.keyboard.press('Space')
|
|
await expect(lock).toHaveAttribute('aria-pressed', 'true')
|
|
await expect(lock).toBeFocused()
|
|
await page.keyboard.press('Tab')
|
|
await expect(page.locator('#play')).toBeFocused()
|
|
await page.keyboard.press('Shift+Tab')
|
|
await expect(lock).toBeFocused()
|
|
await page.keyboard.press('Escape')
|
|
await expect(lock).toHaveAttribute('aria-pressed', 'false')
|
|
await expect(lock).toBeFocused()
|
|
expect(await page.evaluate(() => window.lockEvents)).toEqual([[true, true, true], [false, false, false]])
|
|
await page.keyboard.press('Tab')
|
|
await expect(page.locator('.art-control-progress')).toBeFocused()
|
|
})
|
|
|
|
test('candidate: programmatic lock moves hidden control focus to unlock and caller tabindex survives', async ({ page }) => {
|
|
await setup(page)
|
|
await page.locator('.art-control-progress').focus()
|
|
await page.evaluate(() => {
|
|
window.art.controls.add({ name: 'custom', position: 'right', html: '<button tabindex="3">Custom</button>' })
|
|
window.art.plugins.lock.state = true
|
|
})
|
|
await expect(page.locator('.art-layer-lock')).toBeFocused()
|
|
await expect(page.locator('.art-bottom')).toHaveAttribute('inert')
|
|
await expect(page.locator('.art-control-custom button')).toHaveAttribute('tabindex', '-1')
|
|
await page.keyboard.press('Enter')
|
|
await expect(page.locator('.art-bottom')).not.toHaveAttribute('inert')
|
|
await expect(page.locator('.art-control-custom button')).toHaveAttribute('tabindex', '3')
|
|
})
|
|
|
|
test('candidate: locked additions stay out of Tab order and removal or destruction releases focus attributes', async ({ page }) => {
|
|
await setup(page)
|
|
await page.evaluate(() => {
|
|
window.art.plugins.lock.state = true
|
|
window.art.controls.add({ name: 'late', position: 'right', html: '<button>Late</button>' })
|
|
})
|
|
await expect(page.locator('.art-control-late button')).toHaveAttribute('tabindex', '-1')
|
|
await page.evaluate(() => {
|
|
window.retainedLock = window.art.layers.lock
|
|
window.art.layers.remove('lock')
|
|
})
|
|
await expect(page.locator('.art-bottom')).not.toHaveAttribute('inert')
|
|
await expect(page.locator('.art-control-late button')).not.toHaveAttribute('tabindex')
|
|
await page.evaluate(() => {
|
|
window.lockEvents.length = 0
|
|
window.retainedLock.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true, cancelable: true }))
|
|
window.art.destroy(false)
|
|
})
|
|
expect(await page.evaluate(() => window.lockEvents)).toEqual([])
|
|
})
|
|
|
|
test('candidate: lock Tab fallback works without native inert and preserves caller focus attributes', async ({ page }) => {
|
|
await setup(page)
|
|
await page.locator('.art-layer-lock').focus()
|
|
await page.keyboard.press('Enter')
|
|
await page.evaluate(() => window.art.template.$bottom.removeAttribute('inert'))
|
|
await page.keyboard.press('Tab')
|
|
await expect(page.locator('#play')).toBeFocused()
|
|
await page.keyboard.press('Shift+Tab')
|
|
await expect(page.locator('.art-layer-lock')).toBeFocused()
|
|
await page.keyboard.press('Escape')
|
|
await page.evaluate(() => {
|
|
window.art.template.$bottom.setAttribute('inert', 'caller-owned')
|
|
window.art.template.$bottom.setAttribute('aria-hidden', 'false')
|
|
window.art.plugins.lock.state = true
|
|
window.art.plugins.lock.state = false
|
|
})
|
|
await expect(page.locator('.art-bottom')).toHaveAttribute('inert', 'caller-owned')
|
|
await expect(page.locator('.art-bottom')).toHaveAttribute('aria-hidden', 'false')
|
|
})
|
|
|
|
test('candidate: moving a control outside a locked region restores its tabindex and cleanup preserves later caller edits', async ({ page }) => {
|
|
await setup(page)
|
|
await page.evaluate(() => {
|
|
window.art.controls.add({ name: 'borrowed', position: 'right', html: '<button id="borrowed-focus" tabindex="2">Borrowed</button>' })
|
|
window.art.plugins.lock.state = true
|
|
})
|
|
await expect(page.locator('#borrowed-focus')).toHaveAttribute('tabindex', '-1')
|
|
await page.evaluate(() => document.body.append(document.querySelector('#borrowed-focus')))
|
|
await expect(page.locator('#borrowed-focus')).toHaveAttribute('tabindex', '2')
|
|
await page.evaluate(() => {
|
|
window.art.controls.progress.setAttribute('tabindex', '4')
|
|
window.art.plugins.lock.state = false
|
|
})
|
|
await expect(page.locator('.art-control-progress')).toHaveAttribute('tabindex', '4')
|
|
})
|
|
|
|
test('candidate: remounting an already locked layer reflects actual state and replaces its keyboard scope', async ({ page }) => {
|
|
await setup(page)
|
|
await page.evaluate(() => {
|
|
window.art.plugins.lock.state = true
|
|
window.art.layers.update({ name: 'lock' })
|
|
window.lockEvents.length = 0
|
|
})
|
|
const lock = page.locator('.art-layer-lock')
|
|
await expect(lock).toHaveAttribute('aria-pressed', 'true')
|
|
await expect(lock.locator('.art-icon-lock')).toBeVisible()
|
|
expect(await lock.locator('.art-icon-lock').evaluate(element => element.style.display)).toBe('inline-flex')
|
|
await expect(lock.locator('.art-icon-unlock')).toHaveCSS('display', 'none')
|
|
await lock.focus()
|
|
await page.keyboard.press('Space')
|
|
await expect(page.locator('.art-bottom')).not.toHaveAttribute('inert')
|
|
expect(await page.evaluate(() => window.lockEvents)).toEqual([[false, false, false]])
|
|
})
|