mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-08 19:06:15 -08:00
156 lines
7.9 KiB
JavaScript
156 lines
7.9 KiB
JavaScript
import { expect, test } from './fixtures.js'
|
|
|
|
async function setup(page, options = {}) {
|
|
await page.goto('/test/player.html?core=candidate&chapter=published')
|
|
await page.evaluate((options) => {
|
|
const before = document.createElement('button')
|
|
before.id = 'before-player'
|
|
before.textContent = 'Before player'
|
|
document.body.prepend(before)
|
|
window.Artplayer.SEEK_STEP = 0.5
|
|
window.Artplayer.VOLUME_STEP = 0.05
|
|
window.art = new window.Artplayer({ container: '.player', url: '/test/pattern.mp4', muted: true, hotkey: true, ...options })
|
|
window.sliderEvents = []
|
|
window.art.on('hotkey', event => window.sliderEvents.push(['hotkey', event.code]))
|
|
window.art.on('seek', (actual, value) => window.sliderEvents.push(['seek', value]))
|
|
window.art.on('setBar', (kind, ratio, event) => {
|
|
if (kind === 'played')
|
|
window.sliderEvents.push(['setBar', ratio, event?.type ?? null])
|
|
})
|
|
}, options)
|
|
await expect.poll(() => page.evaluate(() => window.art.isReady)).toBe(true)
|
|
await page.locator('#before-player').focus()
|
|
await page.keyboard.press('Tab')
|
|
if (await page.locator('.art-video').evaluate(element => element.ownerDocument.activeElement === element))
|
|
await page.keyboard.press('Tab')
|
|
await expect(page.locator('.art-control-progress')).toBeFocused()
|
|
}
|
|
|
|
test('candidate: progress is the first control, seeks with owned keys and follows actual media time', async ({ page }) => {
|
|
await setup(page)
|
|
const slider = page.locator('.art-control-progress')
|
|
await expect(slider).toHaveAttribute('role', 'slider')
|
|
await expect(slider).toHaveAttribute('aria-label', 'Progress')
|
|
await expect(slider).toHaveAttribute('aria-disabled', 'false')
|
|
await page.evaluate(() => {
|
|
window.art.currentTime = 1
|
|
})
|
|
await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeCloseTo(1, 1)
|
|
await expect.poll(() => page.evaluate(() => window.art.video.seeking)).toBe(false)
|
|
await expect.poll(() => page.evaluate(() => Math.abs(Number(document.querySelector('.art-control-progress').getAttribute('aria-valuenow')) - window.art.currentTime))).toBeLessThan(0.001)
|
|
const start = await page.evaluate(() => window.art.currentTime)
|
|
await page.evaluate(() => {
|
|
window.sliderEvents.length = 0
|
|
})
|
|
await page.keyboard.press('ArrowRight')
|
|
await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeCloseTo(start + 0.5, 1)
|
|
await expect.poll(() => page.evaluate(() => Math.abs(Number(document.querySelector('.art-control-progress').getAttribute('aria-valuenow')) - window.art.currentTime))).toBeLessThan(0.001)
|
|
const events = await page.evaluate(() => window.sliderEvents)
|
|
expect(events.slice(0, 2)).toEqual([['setBar', (start + 0.5) / await page.evaluate(() => window.art.duration), null], ['seek', start + 0.5]])
|
|
await page.keyboard.press('ArrowUp')
|
|
await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeCloseTo(2, 1)
|
|
expect(await page.evaluate(() => window.art.volume)).toBe(0.7)
|
|
await page.keyboard.press('Home')
|
|
await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeCloseTo(0, 1)
|
|
await page.keyboard.press('End')
|
|
await expect.poll(() => page.evaluate(() => Math.abs(window.art.currentTime - window.art.duration))).toBeLessThan(0.1)
|
|
await page.keyboard.press('PageDown')
|
|
try {
|
|
await expect.poll(() => page.evaluate(() => Math.abs(window.art.currentTime - Math.max(0, window.art.duration - 5)))).toBeLessThan(0.1)
|
|
}
|
|
finally {
|
|
await test.info().attach('slider-after-pagedown', { contentType: 'application/json', body: JSON.stringify(await page.evaluate(() => ({
|
|
events: window.sliderEvents,
|
|
focus: document.activeElement?.className,
|
|
currentTime: window.art.currentTime,
|
|
duration: window.art.duration,
|
|
seeking: window.art.video.seeking,
|
|
ended: window.art.video.ended,
|
|
paused: window.art.video.paused,
|
|
}))) })
|
|
}
|
|
expect(await page.evaluate(() => window.sliderEvents.filter(event => event[0] === 'hotkey'))).toEqual([])
|
|
await expect(slider).toBeFocused()
|
|
await page.keyboard.press('Tab')
|
|
await expect(page.locator('.art-control-playAndPause')).toBeFocused()
|
|
})
|
|
|
|
test('candidate: volume panel opens from keyboard focus and the slider unmutes without seeking', async ({ page }) => {
|
|
await setup(page)
|
|
await page.keyboard.press('Tab')
|
|
await page.keyboard.press('Tab')
|
|
await expect(page.locator('.art-icon-volumeClose')).toBeFocused()
|
|
const slider = page.locator('.art-volume-slider')
|
|
await expect(slider).toBeVisible()
|
|
await expect.poll(() => page.locator('.art-volume-panel').evaluate(element => getComputedStyle(element).opacity)).toBe('1')
|
|
await page.keyboard.press('Tab')
|
|
await expect(slider).toBeFocused()
|
|
await expect(slider).toHaveAttribute('aria-label', 'Volume')
|
|
await expect(slider).toHaveAttribute('aria-orientation', 'vertical')
|
|
await expect(slider).toHaveAttribute('aria-valuenow', '0')
|
|
await page.keyboard.press('ArrowUp')
|
|
await expect.poll(() => page.evaluate(() => window.art.volume)).toBeCloseTo(0.05, 5)
|
|
expect(await page.evaluate(() => window.art.muted)).toBe(false)
|
|
await expect(slider).toHaveAttribute('aria-valuetext', '5%')
|
|
await page.keyboard.press('PageUp')
|
|
await expect.poll(() => page.evaluate(() => window.art.volume)).toBeCloseTo(0.55, 5)
|
|
await page.keyboard.press('End')
|
|
await expect.poll(() => page.evaluate(() => window.art.volume)).toBe(1)
|
|
await page.keyboard.press('Home')
|
|
await expect.poll(() => page.evaluate(() => window.art.volume)).toBe(0)
|
|
expect(await page.evaluate(() => window.art.currentTime)).toBe(0)
|
|
expect(await page.evaluate(() => window.sliderEvents.filter(event => ['seek', 'hotkey'].includes(event[0])))).toEqual([])
|
|
await expect(slider).toBeFocused()
|
|
await page.locator('#before-player').focus()
|
|
await expect.poll(() => page.locator('.art-volume-panel').evaluate(element => getComputedStyle(element).visibility)).toBe('hidden')
|
|
})
|
|
|
|
test('candidate: unknown duration disables progress until metadata returns and labels use i18n', async ({ page }) => {
|
|
await setup(page, { lang: 'zh-cn' })
|
|
const slider = page.locator('.art-control-progress')
|
|
await expect(slider).toHaveAttribute('aria-label', '播放进度')
|
|
await page.evaluate(() => {
|
|
Object.defineProperty(window.art.video, 'duration', { configurable: true, value: Infinity })
|
|
window.art.video.dispatchEvent(new Event('durationchange'))
|
|
window.sliderEvents.length = 0
|
|
})
|
|
await expect(slider).toHaveAttribute('aria-disabled', 'true')
|
|
await expect(slider).toHaveAttribute('aria-valuemax', '0')
|
|
await page.keyboard.press('End')
|
|
await page.keyboard.press('ArrowRight')
|
|
expect(await page.evaluate(() => window.sliderEvents)).toEqual([])
|
|
await page.evaluate(() => {
|
|
delete window.art.video.duration
|
|
window.art.video.dispatchEvent(new Event('durationchange'))
|
|
})
|
|
await expect(slider).toHaveAttribute('aria-disabled', 'false')
|
|
await page.keyboard.press('ArrowRight')
|
|
await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeCloseTo(0.5, 1)
|
|
})
|
|
|
|
test('candidate: progress removal and volume destruction inside callbacks cancel pending writes', async ({ page }) => {
|
|
await setup(page)
|
|
await page.evaluate(() => {
|
|
const remove = (kind, ratio) => {
|
|
if (kind === 'played' && ratio > 0) {
|
|
window.art.off('setBar', remove)
|
|
window.art.controls.remove('progress')
|
|
}
|
|
}
|
|
window.art.on('setBar', remove)
|
|
window.sliderEvents.length = 0
|
|
})
|
|
await page.keyboard.press('ArrowRight')
|
|
expect(await page.evaluate(() => window.art.currentTime)).toBe(0)
|
|
expect(await page.evaluate(() => window.sliderEvents.filter(event => event[0] === 'seek'))).toEqual([])
|
|
await page.locator('.art-icon-volumeClose').focus()
|
|
await page.keyboard.press('Tab')
|
|
await expect(page.locator('.art-volume-slider')).toBeFocused()
|
|
await page.evaluate(() => {
|
|
window.savedVideo = window.art.video
|
|
window.art.once('muted', () => window.art.destroy(false))
|
|
})
|
|
await page.keyboard.press('ArrowUp')
|
|
expect(await page.evaluate(() => window.savedVideo.volume)).toBe(0.7)
|
|
})
|