mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-09 03:27:43 -08:00
135 lines
5.6 KiB
JavaScript
135 lines
5.6 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
// eslint-disable-next-line test/no-import-node-test -- Use the repository Node test runner.
|
|
import { test } from 'node:test'
|
|
import { loadModules } from './helpers/load.js'
|
|
|
|
const { Emitter, installProgressInteractions, getPosFromEvent, beginLifecycle, getScope, beginSource, ownEntry, releaseEntry } = await loadModules({
|
|
Emitter: 'packages/artplayer/src/utils/emitter',
|
|
installProgressInteractions: { file: 'packages/artplayer/src/control/progress/interactions', name: 'installProgressInteractions' },
|
|
getPosFromEvent: { file: 'packages/artplayer/src/control/progress/position', name: 'getPosFromEvent' },
|
|
beginLifecycle: { file: 'packages/artplayer/src/lifecycle/instance', name: 'beginLifecycle' },
|
|
getScope: { file: 'packages/artplayer/src/lifecycle/instance', name: 'getScope' },
|
|
beginSource: { file: 'packages/artplayer/src/source/operation', name: 'beginSource' },
|
|
ownEntry: { file: 'packages/artplayer/src/component/resources', name: 'ownEntry' },
|
|
releaseEntry: { file: 'packages/artplayer/src/component/resources', name: 'releaseEntry' },
|
|
})
|
|
|
|
function mouse(name, clientX = 60, button = 0) {
|
|
return Object.assign(new Event(name), { clientX, button })
|
|
}
|
|
|
|
function fixture() {
|
|
const progress = Object.assign(new EventTarget(), { clientWidth: 100, getBoundingClientRect: () => ({ left: 10 }) })
|
|
const indicator = new EventTarget()
|
|
const control = Object.assign(new EventTarget(), { querySelector: () => indicator })
|
|
const effects = []
|
|
const art = Object.assign(new Emitter(), {
|
|
template: { $progress: progress },
|
|
duration: 200,
|
|
isRotate: false,
|
|
events: {
|
|
proxy(target, name, callback) {
|
|
target.addEventListener(name, callback)
|
|
return () => target.removeEventListener(name, callback)
|
|
},
|
|
remove: cleanup => cleanup(),
|
|
},
|
|
})
|
|
Object.defineProperty(art, 'seek', { get: () => 0, set: value => effects.push(['seek', value]) })
|
|
art.on('setBar', (kind, percentage) => effects.push(['setBar', kind, percentage]))
|
|
beginLifecycle(art)
|
|
ownEntry(art, control)
|
|
installProgressInteractions(art, control)
|
|
return { art, progress, control, indicator, effects }
|
|
}
|
|
|
|
test('progress position clamps outside edges and retains its time and percentage calculations', () => {
|
|
const f = fixture()
|
|
assert.deepEqual(getPosFromEvent(f.art, mouse('click', 60)), { second: 100, time: '01:40', width: 50, percentage: 0.5 })
|
|
assert.equal(getPosFromEvent(f.art, mouse('click', -100)).percentage, 0)
|
|
assert.equal(getPosFromEvent(f.art, mouse('click', 1000)).percentage, 1)
|
|
f.progress.clientWidth = 0
|
|
assert(Number.isNaN(getPosFromEvent(f.art, mouse('click', 10)).percentage))
|
|
})
|
|
|
|
test('live progress clicks and drags preserve setBar before seek and mouseup stops dragging', () => {
|
|
const f = fixture()
|
|
f.progress.dispatchEvent(mouse('click'))
|
|
assert.deepEqual(f.effects, [['setBar', 'played', 0.5], ['seek', 100]])
|
|
f.effects.length = 0
|
|
f.progress.dispatchEvent(mouse('mousedown'))
|
|
f.art.emit('document:mousemove', mouse('mousemove', 85))
|
|
f.art.emit('document:mouseup', mouse('mouseup'))
|
|
f.art.emit('document:mousemove', mouse('mousemove', 100))
|
|
assert.deepEqual(f.effects, [['setBar', 'played', 0.75], ['seek', 150]])
|
|
})
|
|
|
|
for (const mode of ['control removal', 'destruction', 'source replacement']) {
|
|
test(`progress click does not seek after ${mode} inside setBar`, () => {
|
|
const f = fixture()
|
|
f.art.on('setBar', () => {
|
|
if (mode === 'control removal')
|
|
releaseEntry(f.control)
|
|
else if (mode === 'destruction')
|
|
getScope(f.art).dispose()
|
|
else
|
|
beginSource(f.art)
|
|
})
|
|
f.progress.dispatchEvent(mouse('click'))
|
|
assert.deepEqual(f.effects, [['setBar', 'played', 0.5]])
|
|
})
|
|
}
|
|
|
|
test('progress drag loses its source when media is replaced and a new mousedown can start again', () => {
|
|
const f = fixture()
|
|
f.progress.dispatchEvent(mouse('mousedown'))
|
|
beginSource(f.art)
|
|
f.art.emit('document:mousemove', mouse('mousemove', 85))
|
|
assert.deepEqual(f.effects, [])
|
|
f.progress.dispatchEvent(mouse('mousedown'))
|
|
f.art.emit('document:mousemove', mouse('mousemove', 60))
|
|
assert.deepEqual(f.effects, [['setBar', 'played', 0.5], ['seek', 100]])
|
|
})
|
|
|
|
test('progress drag does not seek when its control is removed inside setBar', () => {
|
|
const f = fixture()
|
|
f.art.on('setBar', () => releaseEntry(f.control))
|
|
f.progress.dispatchEvent(mouse('mousedown'))
|
|
f.art.emit('document:mousemove', mouse('mousemove', 60))
|
|
assert.deepEqual(f.effects, [['setBar', 'played', 0.5]])
|
|
})
|
|
|
|
test('progress geometry reentry cannot emit or seek after disposal', () => {
|
|
const f = fixture()
|
|
f.progress.getBoundingClientRect = () => {
|
|
getScope(f.art).dispose()
|
|
return { left: 10 }
|
|
}
|
|
f.progress.dispatchEvent(mouse('click'))
|
|
assert.deepEqual(f.effects, [])
|
|
})
|
|
|
|
test('a newer nested progress click supersedes the earlier seek', () => {
|
|
const f = fixture()
|
|
let nested = false
|
|
f.art.on('setBar', () => {
|
|
if (!nested) {
|
|
nested = true
|
|
f.progress.dispatchEvent(mouse('click', 85))
|
|
}
|
|
})
|
|
f.progress.dispatchEvent(mouse('click', 60))
|
|
assert.deepEqual(f.effects, [['setBar', 'played', 0.5], ['setBar', 'played', 0.75], ['seek', 150]])
|
|
})
|
|
|
|
test('right-button mousedown and mouseup inside setBar do not continue dragging', () => {
|
|
const f = fixture()
|
|
f.progress.dispatchEvent(mouse('mousedown', 60, 2))
|
|
f.art.emit('document:mousemove', mouse('mousemove', 85))
|
|
assert.deepEqual(f.effects, [])
|
|
f.art.on('setBar', () => f.art.emit('document:mouseup', mouse('mouseup')))
|
|
f.progress.dispatchEvent(mouse('mousedown'))
|
|
f.art.emit('document:mousemove', mouse('mousemove', 60))
|
|
assert.deepEqual(f.effects, [['setBar', 'played', 0.5]])
|
|
})
|