mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-27 17:51:20 -08:00
refactor(core): CORE-18 type builtins and own prompt lifetimes
This commit is contained in:
1 parent
a842058136
commit
98a1800032
55 files changed
+26511
-650
No files matched your search
@@ -0,0 +1,163 @@
|
||||
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 { Notice, Emitter, beginLifecycle, getScope } = await loadModules({
|
||||
Notice: 'packages/artplayer/src/notice',
|
||||
Emitter: 'packages/artplayer/src/utils/emitter',
|
||||
beginLifecycle: { file: 'packages/artplayer/src/lifecycle/instance', name: 'beginLifecycle' },
|
||||
getScope: { file: 'packages/artplayer/src/lifecycle/instance', name: 'getScope' },
|
||||
})
|
||||
|
||||
function fixture(t) {
|
||||
const timers = new Map()
|
||||
let id = 0
|
||||
t.mock.method(globalThis, 'setTimeout', (callback, delay) => {
|
||||
const key = ++id
|
||||
timers.set(key, { callback, delay })
|
||||
return key
|
||||
})
|
||||
t.mock.method(globalThis, 'clearTimeout', key => timers.delete(key))
|
||||
const classes = new Set()
|
||||
const classList = {
|
||||
add: value => classes.add(value),
|
||||
remove: value => classes.delete(value),
|
||||
contains: value => classes.has(value),
|
||||
}
|
||||
const inner = { textContent: '' }
|
||||
const art = Object.assign(new Emitter(), {
|
||||
template: { $player: { classList }, $noticeInner: inner },
|
||||
constructor: { NOTICE_TIME: 100 },
|
||||
})
|
||||
beginLifecycle(art)
|
||||
const scope = getScope(art)
|
||||
const notice = new Notice(art)
|
||||
return { art, scope, notice, inner, classList, timers }
|
||||
}
|
||||
|
||||
test('notice preserves fields, descriptors, text, live delay and hide semantics', (t) => {
|
||||
const f = fixture(t)
|
||||
assert.deepEqual(Object.keys(f.notice), ['art', 'timer'])
|
||||
assert.deepEqual(Object.getOwnPropertyNames(Object.getPrototypeOf(f.notice)), ['constructor', 'destroy', 'show'])
|
||||
assert.equal(f.notice.show, false)
|
||||
assert.equal(f.notice.timer, null)
|
||||
f.notice.show = new Error(' example ')
|
||||
assert.equal(f.inner.textContent, 'example')
|
||||
assert.equal(f.notice.show, true)
|
||||
assert.equal(f.timers.get(f.notice.timer).delay, 100)
|
||||
f.art.constructor.NOTICE_TIME = 200
|
||||
f.notice.show = ' next '
|
||||
assert.equal(f.inner.textContent, ' next ')
|
||||
assert.equal(f.timers.size, 1)
|
||||
assert.equal(f.timers.get(f.notice.timer).delay, 200)
|
||||
f.notice.show = ''
|
||||
assert.equal(f.notice.show, false)
|
||||
assert.equal(f.inner.textContent, ' next ')
|
||||
assert.equal(f.timers.size, 1)
|
||||
f.timers.get(f.notice.timer).callback()
|
||||
assert.equal(f.inner.textContent, '')
|
||||
})
|
||||
|
||||
test('manual notice destroy cancels its timer and permits reuse while alive', (t) => {
|
||||
const f = fixture(t)
|
||||
f.notice.show = 'visible'
|
||||
assert.equal(f.notice.destroy(), undefined)
|
||||
assert.equal(f.notice.timer, null)
|
||||
assert.equal(f.timers.size, 0)
|
||||
assert.equal(f.notice.show, true)
|
||||
assert.equal(f.inner.textContent, 'visible')
|
||||
f.notice.destroy()
|
||||
f.notice.show = 'reused'
|
||||
assert.equal(f.timers.size, 1)
|
||||
f.art.emit('destroy')
|
||||
assert.equal(f.timers.size, 0)
|
||||
f.notice.show = 'again'
|
||||
assert.equal(f.timers.size, 1)
|
||||
f.scope.dispose()
|
||||
f.notice.show = 'ignored'
|
||||
assert.equal(f.timers.size, 0)
|
||||
assert.equal(f.inner.textContent, 'again')
|
||||
})
|
||||
|
||||
test('notice does not allocate a timer after destruction during DOM text writes', (t) => {
|
||||
const f = fixture(t)
|
||||
Object.defineProperty(f.inner, 'textContent', {
|
||||
get: () => '',
|
||||
set() {
|
||||
f.scope.dispose()
|
||||
},
|
||||
})
|
||||
f.notice.show = 'destroy during setter'
|
||||
assert.equal(f.notice.timer, null)
|
||||
assert.equal(f.timers.size, 0)
|
||||
assert.equal(f.notice.show, false)
|
||||
})
|
||||
|
||||
test('obsolete notice timer callbacks cannot erase a newer message', (t) => {
|
||||
const f = fixture(t)
|
||||
f.notice.show = 'old'
|
||||
const stale = f.timers.get(f.notice.timer).callback
|
||||
f.notice.show = 'new'
|
||||
stale()
|
||||
assert.equal(f.inner.textContent, 'new')
|
||||
assert.equal(f.notice.show, true)
|
||||
f.scope.dispose()
|
||||
stale()
|
||||
assert.equal(f.inner.textContent, 'new')
|
||||
})
|
||||
|
||||
test('notice expiry does not hide a message installed by a nested DOM write', (t) => {
|
||||
const f = fixture(t)
|
||||
f.notice.show = 'old'
|
||||
const expire = f.timers.get(f.notice.timer).callback
|
||||
let value = 'old'
|
||||
Object.defineProperty(f.inner, 'textContent', {
|
||||
get: () => value,
|
||||
set(next) {
|
||||
value = next
|
||||
if (next === '')
|
||||
f.notice.show = 'nested'
|
||||
},
|
||||
})
|
||||
expire()
|
||||
assert.equal(f.inner.textContent, 'nested')
|
||||
assert.equal(f.notice.show, true)
|
||||
assert.equal(f.timers.size, 1)
|
||||
})
|
||||
|
||||
test('nested notice writes keep only the newest timer', (t) => {
|
||||
const f = fixture(t)
|
||||
let value = ''
|
||||
Object.defineProperty(f.inner, 'textContent', {
|
||||
get: () => value,
|
||||
set(next) {
|
||||
value = next
|
||||
if (next === 'outer')
|
||||
f.notice.show = 'inner'
|
||||
},
|
||||
})
|
||||
f.notice.show = 'outer'
|
||||
assert.equal(f.inner.textContent, 'inner')
|
||||
assert.equal(f.notice.show, true)
|
||||
assert.equal(f.timers.size, 1)
|
||||
f.scope.dispose()
|
||||
assert.equal(f.timers.size, 0)
|
||||
})
|
||||
|
||||
test('notice message updates do not invoke a consumer override of the public destroy method', (t) => {
|
||||
const f = fixture(t)
|
||||
let calls = 0
|
||||
const original = f.notice.destroy
|
||||
f.notice.destroy = function () {
|
||||
calls++
|
||||
return original.call(this)
|
||||
}
|
||||
f.notice.show = 'first'
|
||||
f.notice.show = 'second'
|
||||
assert.equal(calls, 0)
|
||||
assert.equal(f.inner.textContent, 'second')
|
||||
f.notice.destroy()
|
||||
assert.equal(calls, 1)
|
||||
f.scope.dispose()
|
||||
})
|
||||
Reference in new issue
Block a user