Files
ArtPlayer/test/facade-properties.test.js
T

93 lines
3.7 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 { attrMix, cssVarMix, typeMix, themeMix, posterMix } = await loadModules(Object.fromEntries(
['attrMix', 'cssVarMix', 'typeMix', 'themeMix', 'posterMix'].map(name => [name, `packages/artplayer/src/player/${name}`]),
))
test('attr retains dynamic keys, captured media, undefined reads and native receiver errors', () => {
const symbol = Symbol('plugin')
const video = { volume: 0.5, [symbol]: 1 }
const error = new Error('native property')
Object.defineProperty(video, 'throwing', {
get() { return undefined },
set() {
throw error
},
})
const art = { template: { $video: video } }
attrMix(art)
const attr = art.attr
art.template.$video = { volume: 1 }
assert.equal(attr('volume'), 0.5)
assert.equal(attr('volume', undefined), 0.5)
assert.equal(attr(symbol, 2), undefined)
assert.equal(video[symbol], 2)
assert.equal(attr('volume', null), undefined)
assert.equal(video.volume, null)
assert.throws(() => attr('throwing', 1), e => e === error)
assert.deepEqual(Object.getOwnPropertyDescriptor(art, 'attr'), { value: attr, configurable: false, enumerable: false, writable: false })
})
test('cssVar retains falsy reads and passes truthy values to the captured native style', (t) => {
const saved = Object.getOwnPropertyDescriptor(globalThis, 'getComputedStyle')
t.after(() => saved ? Object.defineProperty(globalThis, 'getComputedStyle', saved) : delete globalThis.getComputedStyle)
const writes = []
const player = { style: { setProperty: (...args) => {
writes.push(args)
} } }
globalThis.getComputedStyle = (element) => {
assert.equal(element, player)
return { getPropertyValue: key => `value:${key}` }
}
const art = { template: { $player: player } }
cssVarMix(art)
const cssVar = art.cssVar
art.template.$player = {}
for (const value of [undefined, null, false, 0, '', Number.NaN])
assert.equal(cssVar('--custom', value), 'value:--custom')
const object = { toString: () => 'native coercion' }
assert.equal(cssVar('--custom', object), undefined)
assert.equal(writes[0][1], object)
assert.equal(Object.getOwnPropertyDescriptor(art, 'cssVar').enumerable, false)
})
test('type and theme preserve forwarding and immutable accessor descriptors', () => {
const calls = []
const option = { type: 'mp4' }
const art = { option, cssVar(...args) {
calls.push(args)
return 'computed-theme'
} }
typeMix(art)
themeMix(art)
art.type = 'custom'
assert.equal(option.type, 'custom')
assert.equal(art.type, 'custom')
assert.equal(art.theme, 'computed-theme')
art.theme = ''
assert.deepEqual(calls, [['--art-theme'], ['--art-theme', '']])
for (const name of ['type', 'theme']) {
const descriptor = Object.getOwnPropertyDescriptor(art, name)
assert.equal(descriptor.enumerable, false)
assert.equal(descriptor.configurable, false)
assert.equal(typeof descriptor.get, 'function')
assert.equal(typeof descriptor.set, 'function')
}
})
test('poster keeps historical quoted extraction, empty fallback and original target', () => {
const poster = { style: { backgroundImage: 'url("first.png")' } }
const art = { template: { $poster: poster } }
posterMix(art)
assert.equal(art.poster, 'first.png')
poster.style.backgroundImage = 'url(unquoted.png)'
assert.equal(art.poster, '')
art.template.$poster = { style: {} }
art.poster = 'new.png'
assert.equal(poster.style.backgroundImage, 'url(new.png)')
assert.equal(Object.getOwnPropertyDescriptor(art, 'poster').configurable, false)
})