mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-18 02:21:20 -08:00
test(ambilight): [PKG-AMBILIGHT-05] checkpoint installed canvas combinations
This commit is contained in:
1 parent
e7f31b6fc8
commit
765ddb816f
19 files changed
+1032
-85
No files matched your search
@@ -11,8 +11,20 @@ for (const core of ['published-5.1.7', 'published', 'candidate']) {
|
||||
const scenario = core === 'published-5.1.7' ? 'historical core has no proxy option and retains native Ambilight playback' : 'Ambilight samples all nine canvas proxy regions after output resizing'
|
||||
test(`${core}: ${scenario}`, async ({ page }, testInfo) => {
|
||||
await page.goto(`/test/player.html?core=${core}`)
|
||||
for (const [name, source] of [['ambilightFactory', implementation.source], ['canvasProxy', proxy]])
|
||||
await page.addScriptTag({ content: `(() => { const module = { exports: {} }; const exports = module.exports; ${source}; window.${name} = module.exports.default || module.exports; })();` })
|
||||
for (const [name, source] of [['ambilightFactory', implementation.source], ['canvasProxy', proxy]]) {
|
||||
await page.addScriptTag({ content: `(() => {
|
||||
const pending = new Set();
|
||||
const requestAnimationFrame = callback => {
|
||||
const id = window.requestAnimationFrame(time => { pending.delete(id); callback(time); });
|
||||
pending.add(id); return id;
|
||||
};
|
||||
const cancelAnimationFrame = id => { pending.delete(id); window.cancelAnimationFrame(id); };
|
||||
const module = { exports: {} }; const exports = module.exports;
|
||||
${source};
|
||||
window.${name} = module.exports.default || module.exports;
|
||||
(window.combinationFrames ||= {})['${name}'] = pending;
|
||||
})();` })
|
||||
}
|
||||
await page.evaluate(() => {
|
||||
window.palette = ['rgb(255, 0, 0)', 'rgb(0, 255, 0)', 'rgb(0, 0, 255)', 'rgb(255, 255, 0)', 'rgb(0, 255, 255)', 'rgb(255, 0, 255)', 'rgb(120, 0, 0)', 'rgb(0, 120, 0)', 'rgb(0, 0, 120)']
|
||||
window.drawCount = 0
|
||||
@@ -61,8 +73,14 @@ for (const core of ['published-5.1.7', 'published', 'candidate']) {
|
||||
expect(dimensions.canvas).not.toEqual(dimensions.video)
|
||||
await testInfo.attach('ambilight-proxy-inputs', { contentType: 'application/json', body: JSON.stringify({ core, dimensions, plugin: hash(implementation.source), proxy: hash(proxySource), media: '/test/pattern.mp4', scope: 'real video decode and proxy post-processing callback paints a nine-cell palette using native Canvas' }) })
|
||||
await expect.poll(() => page.evaluate(() => [...document.querySelectorAll('.artplayer-plugin-ambilight > div')].map(node => node.style.backgroundColor))).toEqual(await page.evaluate(() => window.palette))
|
||||
await page.evaluate(() => window.art.destroy())
|
||||
const drawsAtDestroy = await page.evaluate(async () => {
|
||||
window.art.destroy()
|
||||
const draws = window.drawCount
|
||||
await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)))
|
||||
return draws
|
||||
})
|
||||
expect(await page.locator('.artplayer-plugin-ambilight').count()).toBe(0)
|
||||
expect(await page.evaluate(() => ({ draws: window.drawCount, pluginFrames: window.combinationFrames.ambilightFactory.size, proxyFrames: window.combinationFrames.canvasProxy.size }))).toEqual({ draws: drawsAtDestroy, pluginFrames: 0, proxyFrames: 0 })
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
@@ -6,12 +7,19 @@ import vm from 'node:vm'
|
||||
import { build, transform } from 'esbuild'
|
||||
import { verifyAmbilightContract } from '../../refactor/scripts/ambilight-contract.mjs'
|
||||
import { readMember } from '../../refactor/scripts/releases.mjs'
|
||||
import { verifyInstalledArtifacts } from '../../scripts/installed-artifacts.mjs'
|
||||
import { getEntryFile } from '../../scripts/projects.js'
|
||||
|
||||
export async function ambilightCandidate() {
|
||||
const root = fileURLToPath(new URL('../../', import.meta.url))
|
||||
if (process.env.ARTPLAYER_BROWSER_ARTIFACTS) {
|
||||
assert.notEqual(process.env.ARTPLAYER_AMBILIGHT_BASELINE, '1', 'Installed candidate cannot use the frozen workspace')
|
||||
const { inputs } = verifyInstalledArtifacts(root, process.env.ARTPLAYER_BROWSER_ARTIFACTS, ['artplayer', 'artplayer-plugin-chapter', 'artplayer-plugin-ambilight'])
|
||||
const input = inputs.find(item => item.name === 'artplayer-plugin-ambilight')
|
||||
return { name: 'candidate-installed', source: fs.readFileSync(input.file, 'utf8'), format: 'artifact', provenance: input }
|
||||
}
|
||||
if (process.env.ARTPLAYER_AMBILIGHT_BASELINE === '1')
|
||||
return (await ambilightHistorical()).find(item => item.name === 'frozen-workspace')
|
||||
const root = fileURLToPath(new URL('../../', import.meta.url))
|
||||
const result = await build({ entryPoints: [getEntryFile(path.join(root, 'packages/artplayer-plugin-ambilight'))], bundle: true, write: false, platform: 'browser', format: 'cjs', target: 'es2020' })
|
||||
return { name: 'candidate-source', source: result.outputFiles[0].text, format: 'artifact' }
|
||||
}
|
||||
|
||||
+10
-1
@@ -1,3 +1,5 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
@@ -5,12 +7,19 @@ import vm from 'node:vm'
|
||||
import { build, transform } from 'esbuild'
|
||||
import { verifyCanvasContract } from '../../refactor/scripts/canvas-contract.mjs'
|
||||
import { readMember } from '../../refactor/scripts/releases.mjs'
|
||||
import { verifyInstalledArtifacts } from '../../scripts/installed-artifacts.mjs'
|
||||
import { getEntryFile } from '../../scripts/projects.js'
|
||||
|
||||
export async function canvasCandidate() {
|
||||
const root = fileURLToPath(new URL('../../', import.meta.url))
|
||||
if (process.env.ARTPLAYER_BROWSER_ARTIFACTS) {
|
||||
assert.notEqual(process.env.ARTPLAYER_CANVAS_BASELINE, '1', 'Installed candidate cannot use the frozen workspace')
|
||||
const { inputs } = verifyInstalledArtifacts(root, process.env.ARTPLAYER_BROWSER_ARTIFACTS, ['artplayer', 'artplayer-plugin-chapter', 'artplayer-proxy-canvas'])
|
||||
const input = inputs.find(item => item.name === 'artplayer-proxy-canvas')
|
||||
return { name: 'candidate-installed', source: fs.readFileSync(input.file, 'utf8'), format: 'artifact', provenance: input }
|
||||
}
|
||||
if (process.env.ARTPLAYER_CANVAS_BASELINE === '1')
|
||||
return (await canvasHistorical()).find(item => item.name === 'frozen-workspace')
|
||||
const root = fileURLToPath(new URL('../../', import.meta.url))
|
||||
const result = await build({ entryPoints: [getEntryFile(path.join(root, 'packages/artplayer-proxy-canvas'))], bundle: true, write: false, platform: 'browser', format: 'cjs', target: 'es2020' })
|
||||
return { name: 'candidate-source', source: result.outputFiles[0].text, format: 'artifact' }
|
||||
}
|
||||
|
||||
@@ -1,11 +1,42 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
// eslint-disable-next-line test/no-import-node-test -- This fixture exercises the repository's Node test runner.
|
||||
import { test } from 'node:test'
|
||||
import { checkFiles, publishedConsumer } from '../scripts/package-check.mjs'
|
||||
import { checkFiles, checkPackages, publishedConsumer } from '../scripts/package-check.mjs'
|
||||
import { removeConsumer, runtimeConsumer } from '../scripts/package-consumer.mjs'
|
||||
import { emitterContracts } from './contracts/emitter.js'
|
||||
import { ambilightCandidate } from './helpers/ambilight.js'
|
||||
import { canvasCandidate } from './helpers/canvas.js'
|
||||
|
||||
test('Additional browser packages cannot be mistaken for full release consumer acceptance', async () => {
|
||||
await assert.rejects(checkPackages({ release: true, include: ['artplayer-plugin-ambilight'] }), /not full release acceptance/)
|
||||
})
|
||||
|
||||
test('Explicit installed plugin maps never fall back to source or frozen workspace', async () => {
|
||||
const keys = ['ARTPLAYER_BROWSER_ARTIFACTS', 'ARTPLAYER_AMBILIGHT_BASELINE', 'ARTPLAYER_CANVAS_BASELINE']
|
||||
const previous = Object.fromEntries(keys.map(key => [key, process.env[key]]))
|
||||
try {
|
||||
process.env.ARTPLAYER_BROWSER_ARTIFACTS = path.resolve('refactor/.cache/absent-installed-plugin-map.json')
|
||||
assert(!fs.existsSync(process.env.ARTPLAYER_BROWSER_ARTIFACTS))
|
||||
delete process.env.ARTPLAYER_AMBILIGHT_BASELINE
|
||||
delete process.env.ARTPLAYER_CANVAS_BASELINE
|
||||
await assert.rejects(ambilightCandidate(), { code: 'ENOENT' })
|
||||
await assert.rejects(canvasCandidate(), { code: 'ENOENT' })
|
||||
process.env.ARTPLAYER_AMBILIGHT_BASELINE = '1'
|
||||
process.env.ARTPLAYER_CANVAS_BASELINE = '1'
|
||||
await assert.rejects(ambilightCandidate(), /cannot use the frozen workspace/)
|
||||
await assert.rejects(canvasCandidate(), /cannot use the frozen workspace/)
|
||||
}
|
||||
finally {
|
||||
for (const key of keys) {
|
||||
if (previous[key] === undefined)
|
||||
delete process.env[key]
|
||||
else process.env[key] = previous[key]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
test('Package checks reject missing files, missing wildcard exports and internal configuration', () => {
|
||||
const manifest = { name: 'fixture', main: './dist/main.js', module: './dist/main.mjs', types: './types/main.d.ts', legacy: './dist/legacy.js', exports: { '.': './dist/main.js', './lang/*': './dist/lang/*.js' } }
|
||||
|
||||
+15
-2
@@ -1,8 +1,14 @@
|
||||
# Installed package checks
|
||||
|
||||
Run `yarn test:package` with the pinned Node and Yarn after a frozen install. The
|
||||
initial scope is core and chapter; extend `names` in `scripts/package-consumer.mjs`
|
||||
and add package-specific consumers when migrating another package.
|
||||
default consumer scope is core and chapter. For Ambilight/Canvas browser work,
|
||||
run `yarn test:package --include=artplayer-plugin-ambilight,artplayer-proxy-canvas`.
|
||||
These two additional packages have reviewed published contracts and use the same
|
||||
source snapshot/build/pack/offline-install/frozen-reinstall pipeline. Installed
|
||||
files are copied only after archive hash checks. The report explicitly separates
|
||||
the core/chapter runtime/type scope from the additional browser package scope;
|
||||
`--release` rejects additional packages until complete consumer coverage exists.
|
||||
Other packages need a reviewed contract and their own consumers before inclusion.
|
||||
|
||||
`scripts/package-check.mjs` copies source into an ignored build snapshot, rebuilds
|
||||
all three formats and core languages using repository scripts, and runs Yarn pack.
|
||||
@@ -72,6 +78,13 @@ and run `yarn test:browser`. The service then uses installed package bytes witho
|
||||
falling back to source. CI performs this sequence and uploads only reports and
|
||||
artifacts, excluding the build snapshot's node_modules link.
|
||||
|
||||
`scripts/installed-artifacts.mjs` verifies selected packages against the installed
|
||||
report and the current source/build inputs; performance retains its existing
|
||||
two-package wrapper. Ambilight and Canvas browser helpers use this verifier when
|
||||
an artifact map is supplied, including optional legacy maps pointing to checked
|
||||
legacy members in the same installation. Missing packages, stale source, modified
|
||||
bundles or contradictory frozen-workspace flags fail instead of rebuilding source.
|
||||
|
||||
`test/package-check.test.js` verifies missing targets, leaked configuration and
|
||||
removed historical files, then deliberately removes an actual published default
|
||||
export and required entry in an isolated consumer to prove runtime failures are
|
||||
|
||||
@@ -6,6 +6,7 @@ import process from 'node:process'
|
||||
import { test } from 'node:test'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { hash } from '../refactor/scripts/releases.mjs'
|
||||
import { verifyInstalledArtifacts } from '../scripts/installed-artifacts.mjs'
|
||||
import { verifyPerformanceArtifacts } from '../scripts/performance-artifacts.mjs'
|
||||
import { performanceHtml, performanceScript, waitForObservation } from '../scripts/performance-fixture.mjs'
|
||||
import { validatePairedPerformance } from '../scripts/performance-report.mjs'
|
||||
@@ -128,7 +129,7 @@ test('performance refuses stale sources, build tools and altered installed bundl
|
||||
write(path.join(root, file), content)
|
||||
write(path.join(snapshot, file), content)
|
||||
}
|
||||
const names = ['artplayer', 'artplayer-plugin-chapter']
|
||||
const names = ['artplayer', 'artplayer-plugin-chapter', 'artplayer-plugin-ambilight']
|
||||
const packages = names.map((name) => {
|
||||
const entry = `packages/${name}/src/index.ts`
|
||||
write(path.join(root, entry), 'export default 1\n')
|
||||
@@ -144,6 +145,13 @@ test('performance refuses stale sources, build tools and altered installed bundl
|
||||
write(map, JSON.stringify(Object.fromEntries(names.map(name => [name, `artifacts/${name}/dist/${name}.js`]))))
|
||||
write(path.join(output, 'report.json'), JSON.stringify({ task: 'ENG-07', knownTypeBlockers: 0, node: process.versions.node, packages }))
|
||||
assert.equal(verifyPerformanceArtifacts(root, map).inputs.length, 2)
|
||||
assert.equal(verifyPerformanceArtifacts(root, map).packages.length, 2)
|
||||
assert.equal(verifyInstalledArtifacts(root, map, names).inputs.length, 3)
|
||||
assert.throws(() => verifyInstalledArtifacts(root, map, [...names, 'artplayer-proxy-canvas']), /Missing installed package/)
|
||||
const pluginSource = path.join(root, 'packages/artplayer-plugin-ambilight/src/index.ts')
|
||||
write(pluginSource, 'export default 2\n')
|
||||
assert.throws(() => verifyInstalledArtifacts(root, map, names), /Stale package source/)
|
||||
write(pluginSource, 'export default 1\n')
|
||||
const source = path.join(root, 'packages/artplayer/src/index.ts')
|
||||
write(source, 'export default 2\n')
|
||||
assert.throws(() => verifyPerformanceArtifacts(root, map), /Stale package source/)
|
||||
@@ -158,5 +166,5 @@ test('performance refuses stale sources, build tools and altered installed bundl
|
||||
assert.throws(() => verifyPerformanceArtifacts(root, map), /Stale library build inputs/)
|
||||
fs.unlinkSync(path.join(snapshot, 'scripts/library/removed.ts'))
|
||||
write(path.join(output, 'artifacts/artplayer/dist/artplayer.js'), 'changed bundle\n')
|
||||
assert.throws(() => verifyPerformanceArtifacts(root, map), /Installed performance artifact changed/)
|
||||
assert.throws(() => verifyPerformanceArtifacts(root, map), /Installed browser artifact changed/)
|
||||
})
|
||||
Reference in new issue
Block a user