mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-14 16:36:18 -08:00
test(vast): [PKG-VAST-01] freeze published and workspace contracts
This commit is contained in:
1 parent
29692d2815
commit
4f39d6f2b9
11 files changed
+797
-17
No files matched your search
@@ -0,0 +1,43 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { execFileSync } from 'node:child_process'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { archiveFiles, ensureArchive, hash, readMember, refactorDir } from './releases.mjs'
|
||||
|
||||
export async function verifyVastContract() {
|
||||
const baseline = JSON.parse(fs.readFileSync(path.join(refactorDir, 'baselines/vast-release.json')))
|
||||
const archives = new Map()
|
||||
for (const release of [baseline.release, ...baseline.sdk]) {
|
||||
const archive = await ensureArchive(release)
|
||||
assert.deepEqual(archiveFiles(archive), Object.keys(release.files).sort())
|
||||
for (const [member, expected] of Object.entries(release.files))
|
||||
assert.equal(hash(readMember(archive, member)), expected, `${release.name}@${release.version}/${member}`)
|
||||
assert.deepEqual(JSON.parse(readMember(archive, 'package/package.json')), release.manifest)
|
||||
for (const field of ['main', 'module', 'types', 'legacy']) {
|
||||
const target = release.manifest[field]
|
||||
if (target)
|
||||
assert(Object.hasOwn(release.files, `package/${target.replace(/^\.\//, '')}`))
|
||||
}
|
||||
archives.set(`${release.name}@${release.version}`, archive)
|
||||
}
|
||||
const sources = new Map()
|
||||
assert(/^[a-f\d]{40}$/.test(baseline.sourceCommit))
|
||||
for (const [file, expected] of Object.entries(baseline.source)) {
|
||||
const content = execFileSync('git', ['show', `${baseline.sourceCommit}:${file}`]).toString().replaceAll('\r\n', '\n')
|
||||
assert.equal(hash(content), expected, `Historical source changed: ${file}`)
|
||||
sources.set(file, content)
|
||||
}
|
||||
const core = baseline.historicalCore
|
||||
const manifest = execFileSync('git', ['show', `${core.commit}:${core.file}`]).toString().replaceAll('\r\n', '\n')
|
||||
assert.equal(hash(manifest), core.sha256LF)
|
||||
assert.equal(JSON.parse(manifest).version, core.version)
|
||||
assert.equal(baseline.registryObservation.workspaceVersionPublished, false)
|
||||
assert.deepEqual(baseline.registryObservation.versions, ['1.0.0'])
|
||||
console.log('Verified VAST: published 1.0.0, two SDK archives, 60 members and frozen workspace/core association')
|
||||
return { baseline, archives, sources }
|
||||
}
|
||||
|
||||
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url))
|
||||
await verifyVastContract()
|
||||
@@ -0,0 +1,137 @@
|
||||
import assert from 'node:assert/strict'
|
||||
// eslint-disable-next-line test/no-import-node-test -- Verify immutable releases and wrapper contracts without external ad requests.
|
||||
import test from 'node:test'
|
||||
import vm from 'node:vm'
|
||||
import { transform } from 'esbuild'
|
||||
import { readMember } from './releases.mjs'
|
||||
import { verifyVastContract } from './vast-contract.mjs'
|
||||
|
||||
const contract = await verifyVastContract()
|
||||
const archive = contract.archives.get('artplayer-plugin-vast@1.0.0')
|
||||
|
||||
test('VAST published artifacts expose a CommonJS default namespace and browser global', () => {
|
||||
for (const member of ['package/dist/artplayer-plugin-vast.js', 'package/dist/artplayer-plugin-vast.legacy.js']) {
|
||||
const module = { exports: {} }
|
||||
const window = {}
|
||||
vm.runInNewContext(readMember(archive, member).toString(), { module, exports: module.exports, window, CustomEvent }, { timeout: 5000 })
|
||||
assert.equal(typeof module.exports, 'object')
|
||||
assert.deepEqual(Object.keys(module.exports), ['default'])
|
||||
assert.equal(typeof module.exports.default, 'function')
|
||||
assert.equal(window.artplayerPluginVast, module.exports.default)
|
||||
assert.equal(typeof module.exports.default(), 'function')
|
||||
}
|
||||
})
|
||||
|
||||
function sdkFixture() {
|
||||
const players = []
|
||||
const ima = { AdsRenderingSettings: class {}, AdsRequest: class {} }
|
||||
const sdk = {
|
||||
loadImaSdk: async () => ima,
|
||||
PlayerOptions: class {},
|
||||
Player: class {
|
||||
constructor(...args) {
|
||||
this.args = args
|
||||
this.requests = []
|
||||
this.events = new Map()
|
||||
players.push(this)
|
||||
}
|
||||
|
||||
addEventListener(name, callback) { this.events.set(name, callback) }
|
||||
playAds(request) { this.requests.push(request) }
|
||||
destroy() { this.destroyed = true }
|
||||
},
|
||||
}
|
||||
const node = () => ({ style: {}, parentNode: null })
|
||||
const parent = {
|
||||
children: [],
|
||||
appendChild(child) {
|
||||
child.parentNode = this
|
||||
this.children.push(child)
|
||||
return child
|
||||
},
|
||||
removeChild(child) {
|
||||
child.parentNode = null
|
||||
this.children.splice(this.children.indexOf(child), 1)
|
||||
},
|
||||
}
|
||||
const art = { template: { $player: parent, $video: {} }, constructor: { utils: { createElement: node, setStyles: (target, styles) => Object.assign(target.style, styles), append: (target, child) => target.appendChild(child) } } }
|
||||
return { players, ima, sdk, art }
|
||||
}
|
||||
|
||||
async function loadSource(source, fixture) {
|
||||
const module = { exports: {} }
|
||||
const result = await transform(source, { loader: 'js', format: 'cjs', target: 'es2020' })
|
||||
vm.runInNewContext(result.code, { module, exports: module.exports, window: { google: { ima: fixture.ima } }, console, require(name) {
|
||||
assert.equal(name, '@glomex/vast-ima-player')
|
||||
return fixture.sdk
|
||||
} }, { timeout: 5000 })
|
||||
return module.exports.default
|
||||
}
|
||||
|
||||
for (const family of ['published', 'workspace']) {
|
||||
test(`VAST ${family}: frozen source shows async callback timing and its exact context/initialization contract`, async () => {
|
||||
const fixture = sdkFixture()
|
||||
const source = family === 'published' ? readMember(archive, 'package/src/index.js').toString() : contract.sources.get('packages/artplayer-plugin-vast/src/index.js')
|
||||
const factory = await loadSource(source, fixture)
|
||||
let release
|
||||
let callbackStarted
|
||||
const ready = new Promise((resolve) => {
|
||||
callbackStarted = resolve
|
||||
})
|
||||
const gate = new Promise((resolve) => {
|
||||
release = resolve
|
||||
})
|
||||
const attaching = factory(async (value) => {
|
||||
callbackStarted(value)
|
||||
await gate
|
||||
})(fixture.art)
|
||||
assert.equal(typeof attaching.then, 'function', 'The historical synchronous declaration is inaccurate')
|
||||
const context = await ready
|
||||
assert(context)
|
||||
assert.equal(context.art, fixture.art)
|
||||
if (family === 'published') {
|
||||
assert.deepEqual(Object.keys(context), ['art', 'id', 'ima', 'imaPlayer', '$container', 'playUrl', 'playRes'])
|
||||
assert.equal(fixture.players.length, 1)
|
||||
assert.equal(context.imaPlayer, fixture.players[0])
|
||||
assert.equal(context.$container, fixture.art.template.$player.children[0])
|
||||
assert.equal(context.id, context.$container.id)
|
||||
assert.match(context.id, /^art-\d+$/)
|
||||
}
|
||||
else {
|
||||
assert.deepEqual(Object.keys(context), ['art', 'playUrl', 'playRes', 'init', 'ima', 'adsRenderingSettings', 'playerOptions', 'imaPlayer', 'container'])
|
||||
assert.equal(fixture.players.length, 0)
|
||||
assert.equal(context.imaPlayer, null)
|
||||
assert.equal(context.container, null)
|
||||
assert.equal(context.id, undefined)
|
||||
assert.equal(context.$container, undefined)
|
||||
assert.equal(context.init(), context.init())
|
||||
assert.equal(context.imaPlayer, fixture.players[0])
|
||||
assert.equal(context.container, fixture.art.template.$player.children[0])
|
||||
assert.equal(context.adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete, true)
|
||||
assert.equal(context.adsRenderingSettings.enablePreloading, true)
|
||||
}
|
||||
assert.equal(context.playUrl('/ad.xml', { adTagUrl: '/override.xml', extra: 1 }), undefined)
|
||||
assert.equal(fixture.players[0].requests[0].adTagUrl, family === 'published' ? '/ad.xml' : '/override.xml')
|
||||
assert.equal(context.playRes('<VAST/>'), undefined)
|
||||
assert.equal(fixture.players[0].requests[1].adsResponse, '<VAST/>')
|
||||
release()
|
||||
const result = await attaching
|
||||
assert.deepEqual(Object.keys(result), family === 'published' ? ['name'] : ['name', 'destroy'])
|
||||
assert.equal(result.name, 'artplayerPluginVast')
|
||||
if (family === 'workspace') {
|
||||
result.destroy()
|
||||
assert.equal(fixture.players[0].destroyed, true)
|
||||
assert.equal(context.container, null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
test('VAST wrapper SDK public declarations import a development-only dependency', () => {
|
||||
for (const release of contract.baseline.sdk) {
|
||||
assert.equal(release.manifest.dependencies?.['@alugha/ima'], undefined)
|
||||
assert.equal(typeof release.manifest.devDependencies['@alugha/ima'], 'string')
|
||||
const archive = contract.archives.get(`${release.name}@${release.version}`)
|
||||
assert.match(readMember(archive, 'package/dist/index.d.ts').toString(), /from ['"]@alugha\/ima['"]/)
|
||||
assert.match(readMember(archive, 'package/dist/vast-ima-player.d.ts').toString(), /from ['"]@alugha\/ima['"]/)
|
||||
}
|
||||
})
|
||||
Reference in new issue
Block a user