mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-09 03:46:16 -08:00
100 lines
4.2 KiB
JavaScript
100 lines
4.2 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
// eslint-disable-next-line test/no-import-node-test -- Use the built-in runner without adding a test framework.
|
|
import { mock, test } from 'node:test'
|
|
import { setImmediate } from 'node:timers/promises'
|
|
import { loadModules } from './helpers/load.js'
|
|
import { playbackFactory } from './helpers/playback.js'
|
|
|
|
const modules = await loadModules({
|
|
silencePromise: { file: 'packages/artplayer/src/utils/error', name: 'silencePromise' },
|
|
Emitter: 'packages/artplayer/src/utils/emitter',
|
|
Hotkey: 'packages/artplayer/src/hotkey',
|
|
playMix: 'packages/artplayer/src/player/playMix',
|
|
pauseMix: 'packages/artplayer/src/player/pauseMix',
|
|
toggleMix: 'packages/artplayer/src/player/toggleMix',
|
|
switchMix: 'packages/artplayer/src/player/switchMix',
|
|
beginLifecycle: { file: 'packages/artplayer/src/lifecycle/instance', name: 'beginLifecycle' },
|
|
getScope: { file: 'packages/artplayer/src/lifecycle/instance', name: 'getScope' },
|
|
})
|
|
const { silencePromise, Hotkey } = modules
|
|
const createArt = playbackFactory(modules)
|
|
|
|
test('silencePromise preserves fulfilled values and handles rejected promises', async () => {
|
|
assert.equal(await silencePromise(Promise.resolve(42)), 42)
|
|
assert.equal(await silencePromise(Promise.reject(new Error('interrupted'))), undefined)
|
|
})
|
|
|
|
test('silencePromise passes through synchronous values and catch-less thenables', () => {
|
|
const thenable = { then: (resolve, reject) => Promise.resolve(42).then(resolve, reject) }
|
|
for (const value of [undefined, null, false, 42, thenable]) {
|
|
assert.equal(silencePromise(value), value)
|
|
}
|
|
assert.equal(createArt(undefined, true).toggle(), undefined)
|
|
})
|
|
|
|
for (const name of ['AbortError', 'NotAllowedError', 'NotSupportedError']) {
|
|
test(`public play/toggle still reject with ${name}`, async () => {
|
|
const error = new DOMException('Playback failed', name)
|
|
const art = createArt(() => Promise.reject(error))
|
|
const onPlay = mock.fn()
|
|
art.on('play', onPlay)
|
|
await assert.rejects(art.play(), actual => actual === error)
|
|
await assert.rejects(art.toggle(), actual => actual === error)
|
|
assert.equal(onPlay.mock.callCount(), 0)
|
|
})
|
|
|
|
for (const method of ['switchUrl', 'switchQuality']) {
|
|
test(`${method} settles when resume rejects with ${name}`, { timeout: 1000 }, async () => {
|
|
const art = createArt(() => Promise.reject(new DOMException('Playback failed', name)), true)
|
|
const switching = art[method]('new.mp4')
|
|
art.currentTime = 0
|
|
art.playbackRate = 1
|
|
art.aspectRatio = 'default'
|
|
art.emit('video:loadedmetadata')
|
|
art.emit('video:canplay')
|
|
await switching
|
|
assert.equal(art.currentTime, method === 'switchQuality' ? 37 : 0)
|
|
assert.equal(art.playbackRate, 1.5)
|
|
assert.equal(art.aspectRatio, '16:9')
|
|
assert.equal(art.notice.show, '')
|
|
assert.equal(art.template.$video.play.mock.callCount(), 1)
|
|
assert.deepEqual(Object.keys(art.e), [])
|
|
})
|
|
}
|
|
}
|
|
|
|
test('Space handles an interrupted pending play without an unhandled rejection', async () => {
|
|
let rejectPlay
|
|
const art = createArt(() => new Promise((resolve, reject) => {
|
|
rejectPlay = reject
|
|
}))
|
|
const hotkey = new Hotkey(art)
|
|
hotkey.keys.Space[0]()
|
|
art.pause()
|
|
rejectPlay(new DOMException('Interrupted by pause', 'AbortError'))
|
|
// node:test fails on unhandled rejections, including those from event callbacks.
|
|
await setImmediate()
|
|
assert.equal(art.playing, false)
|
|
})
|
|
|
|
test('switch resumes successfully and remains paused when previously paused', async () => {
|
|
for (const playing of [true, false]) {
|
|
const art = createArt(undefined, playing)
|
|
const switching = art.switchUrl('new.mp4')
|
|
art.emit('video:loadedmetadata')
|
|
art.emit('video:canplay')
|
|
await switching
|
|
assert.equal(art.template.$video.play.mock.callCount(), playing ? 1 : 0)
|
|
}
|
|
})
|
|
|
|
test('source errors still reject switches and clean up listeners', async () => {
|
|
const art = createArt()
|
|
const error = new Error('Source failed to load')
|
|
const rejected = assert.rejects(art.switchUrl('bad.mp4'), actual => actual === error)
|
|
art.emit('video:error', error)
|
|
await rejected
|
|
assert.deepEqual(Object.keys(art.e), [])
|
|
assert.equal(art.template.$video.play.mock.callCount(), 0)
|
|
})
|