test(ads): [PKG-ADS-01] freeze published contracts and legacy compatibility gaps

This commit is contained in:
Harvey Zhao committed 2026-09-12 07:05:00 +08:00
1 parent bafbf2c8b0
commit c6b82c3392
12 files changed
+665 -16

No files matched your search

+49
View File
@@ -0,0 +1,49 @@
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'
const root = path.resolve(refactorDir, '..')
const normalizeLF = value => value.toString().replaceAll('\r\n', '\n')
export async function verifyAdsContract() {
const baseline = JSON.parse(fs.readFileSync(path.join(refactorDir, 'baselines/ads-release.json')))
assert.equal(baseline.task, 'PKG-ADS-01')
const releases = [...baseline.olderReleases, baseline.release]
assert.deepEqual(releases.map(release => release.version), ['1.0.0', '1.0.2', '1.0.3', '1.0.4', '1.0.6'])
const archives = new Map()
for (const release of releases) {
assert.equal(release.name, 'artplayer-plugin-ads')
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, `Changed Ads release member: ${release.version}/${member}`)
assert.deepEqual(JSON.parse(readMember(archive, 'package/package.json')), release.manifest)
for (const entry of [release.manifest.main, release.manifest.types])
assert(Object.hasOwn(release.files, `package/${entry.replace(/^\.\//, '')}`))
archives.set(release.version, archive)
}
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}`], { cwd: root })
assert.equal(hash(normalizeLF(content)), expected, `Changed historical Ads source: ${file}`)
}
for (const comparison of baseline.comparisons) {
const published = hash(normalizeLF(readMember(archives.get('1.0.6'), `package/${comparison.file}`)))
assert.equal(published, comparison.publishedLF)
assert.equal(baseline.source[`packages/artplayer-plugin-ads/${comparison.file}`], comparison.workspaceLF)
assert.equal(published === comparison.workspaceLF, comparison.equal)
}
const core = baseline.historicalCore
const content = execFileSync('git', ['show', `${core.commit}:${core.file}`], { cwd: root })
assert.equal(hash(normalizeLF(content)), core.sha256LF)
assert.equal(JSON.parse(content).version, core.version)
console.log('Verified Ads: five published archives, 30 members, historical source and core-version association')
return { baseline, archives }
}
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url))
await verifyAdsContract()
+58
View File
@@ -0,0 +1,58 @@
import assert from 'node:assert/strict'
import { execFileSync } from 'node:child_process'
// eslint-disable-next-line test/no-import-node-test -- Validate frozen package provenance and actual published exports.
import test from 'node:test'
import vm from 'node:vm'
import { verifyAdsContract } from './ads-contract.mjs'
import { readMember } from './releases.mjs'
test('Ads archives and historical contract remain immutable, including the unpublished workspace version boundary', verifyAdsContract)
test('actual Ads 1.0.6 exposes a CommonJS default namespace, browser factory and deferred synchronous result', async () => {
const { baseline, archives } = await verifyAdsContract()
const module = { exports: {} }
const browser = {}
vm.runInNewContext(readMember(archives.get('1.0.6'), 'package/dist/artplayer-plugin-ads.js').toString(), { module, exports: module.exports, window: browser }, { timeout: 5000 })
assert.equal(typeof module.exports, 'object')
assert.deepEqual(Object.keys(module.exports), ['default'])
const factory = module.exports.default
assert.equal(browser.artplayerPluginAds, factory)
assert.equal(factory.version, '1.0.6')
assert.equal(factory.env, 'production')
assert.equal(typeof factory.build, 'string')
const current = { exports: {} }
vm.runInNewContext(execFileSync('git', ['show', `${baseline.sourceCommit}:packages/artplayer-plugin-ads/dist/artplayer-plugin-ads.js`]).toString(), { module: current, exports: current.exports }, { timeout: 5000 })
assert.equal(typeof current.exports, 'function')
assert.equal(current.exports.default, undefined)
let options
let schema
const subscriptions = []
const art = {
template: { $player: {} },
icons: {},
constructor: {
validator(value, rules) {
options = value
schema = rules
return value
},
utils: {},
},
on(name) { subscriptions.push(name) },
}
const result = factory({ html: '<b>ad</b>', muted: true })(art)
assert.deepEqual(Object.keys(result), ['name', 'skip', 'pause', 'play'])
assert.equal(result.name, 'artplayerPluginAds')
for (const method of ['skip', 'pause', 'play']) assert.equal(typeof result[method], 'function')
assert.deepEqual(subscriptions, ['ready'])
assert.equal(options.html, '<b>ad</b>')
assert.equal(options.video, '')
assert.equal(options.url, '')
assert.equal(options.playDuration, 5)
assert.equal(options.totalDuration, 10)
assert.equal(options.muted, true)
assert.equal(options.i18n.countdown, '%s秒')
assert.equal(schema.totalDuration, 'number')
assert(!Object.hasOwn(schema, 'source'))
assert(!Object.hasOwn(schema, 'type'))
})