mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-12 06:26:16 -08:00
test(iframe): [PKG-IFRAME-01] freeze historical exports and message contract
This commit is contained in:
1 parent
7e37fd4d0e
commit
a52f79a0cc
12 files changed
+505
-8
No files matched your search
@@ -0,0 +1,34 @@
|
||||
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 verifyIframeContract() {
|
||||
const baseline = JSON.parse(fs.readFileSync(path.join(refactorDir, 'baselines/iframe-release.json')))
|
||||
assert.equal(baseline.registryObservation.status, 404)
|
||||
assert.equal(baseline.release.name, 'artplayer-plugin-iframe')
|
||||
const archive = await ensureArchive(baseline.release)
|
||||
assert.deepEqual(archiveFiles(archive), Object.keys(baseline.release.files).sort())
|
||||
for (const [file, expected] of Object.entries(baseline.release.files))
|
||||
assert.equal(hash(readMember(archive, file)), expected, file)
|
||||
assert.deepEqual(JSON.parse(readMember(archive, 'package/package.json')), baseline.release.manifest)
|
||||
const core = baseline.release.historicalCore
|
||||
const coreSource = execFileSync('git', ['show', `${core.commit}:${core.file}`], { encoding: 'utf8' }).replaceAll('\r\n', '\n')
|
||||
assert.equal(hash(coreSource), core.sha256LF)
|
||||
assert.equal(JSON.parse(coreSource).version, core.version)
|
||||
const sources = new Map()
|
||||
for (const [file, expected] of Object.entries(baseline.source)) {
|
||||
const source = execFileSync('git', ['show', `${baseline.sourceCommit}:${file}`], { encoding: 'utf8' }).replaceAll('\r\n', '\n')
|
||||
assert.equal(hash(source), expected, file)
|
||||
sources.set(file, source)
|
||||
}
|
||||
return { baseline, archive, sources }
|
||||
}
|
||||
|
||||
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
||||
const { baseline } = await verifyIframeContract()
|
||||
console.log(`Iframe contract: historical ${baseline.release.name}@${baseline.release.version}, ${Object.keys(baseline.release.files).length} archive members, ${Object.keys(baseline.source).length} frozen workspace inputs; tool-name registry 404 remains an observation`)
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
import assert from 'node:assert/strict'
|
||||
// eslint-disable-next-line test/no-import-node-test -- Frozen package contract runner.
|
||||
import test from 'node:test'
|
||||
import vm from 'node:vm'
|
||||
import { iframeEnvironment, iframeHistorical } from '../../test/helpers/iframe.js'
|
||||
import { verifyIframeContract } from './iframe-contract.mjs'
|
||||
import { readMember } from './releases.mjs'
|
||||
|
||||
test('Iframe actual old-name archive and renamed workspace remain separate provenance', async () => {
|
||||
const { baseline, archive, sources } = await verifyIframeContract()
|
||||
assert.equal(Object.keys(baseline.release.files).length, 8)
|
||||
assert.equal(Object.keys(baseline.source).length, 11)
|
||||
assert.equal(baseline.release.manifest.module, undefined)
|
||||
assert.equal(baseline.registryObservation.body.error, 'Not found')
|
||||
const old = readMember(archive, 'package/types/artplayer-plugin-iframe.d.ts').toString()
|
||||
const current = sources.get('packages/artplayer-tool-iframe/types/artplayer-tool-iframe.d.ts')
|
||||
assert.match(old, /export = ArtplayerPluginIframe/)
|
||||
assert.match(old, /export as namespace ArtplayerPluginIframe/)
|
||||
assert.match(current, /export default ArtplayerToolIframe/)
|
||||
for (const source of [old, current]) {
|
||||
assert.match(source, /resove:/)
|
||||
assert.match(source, /Promise<ReturnType<T>>/)
|
||||
assert.match(source, /static onMessage\(event: MessageEvent & \{ data: Message \}\): void/)
|
||||
}
|
||||
const esm = await import(`data:text/javascript,${encodeURIComponent(sources.get('packages/artplayer-tool-iframe/dist/artplayer-tool-iframe.mjs'))}`)
|
||||
assert.equal(typeof esm.default, 'function')
|
||||
assert.deepEqual(Object.keys(esm), ['default'])
|
||||
})
|
||||
|
||||
const implementations = await iframeHistorical()
|
||||
for (const implementation of implementations.filter(item => item.global !== 'ArtplayerHelperIframe')) {
|
||||
test(`Iframe ${implementation.name}: class, CJS/script exports and constructor fields`, () => {
|
||||
const env = iframeEnvironment(implementation)
|
||||
assert.equal(typeof env.exported, implementation.namespace ? 'object' : 'function')
|
||||
const browser = {}
|
||||
browser.window = browser
|
||||
browser.self = browser
|
||||
vm.runInNewContext(implementation.code, browser)
|
||||
assert.equal(typeof browser[implementation.global], 'function')
|
||||
assert.deepEqual(Object.getOwnPropertyNames(env.Factory.prototype), ['constructor', 'onMessage', 'postMessage', 'commit', 'message', 'destroy'])
|
||||
assert.throws(() => new env.Factory({ iframe: {}, url: '/' }), error => error.name === (implementation.namespace ? 'Error' : 'TypeError') && /needs to be a HTMLIFrameElement/.test(error.message))
|
||||
assert.throws(() => new env.Factory({ iframe: new env.Frame(), url: null }), /needs to be a string/)
|
||||
const frame = new env.Frame()
|
||||
const instance = new env.Factory({ iframe: frame, url: '/iframe.html' })
|
||||
assert.deepEqual(Object.keys(instance), ['url', '$iframe', 'promises', 'injected', 'destroyed', 'messageCallback', 'onMessage'])
|
||||
assert.deepEqual(env.order, ['listen:message', 'src'])
|
||||
assert.equal(instance.$iframe, frame)
|
||||
assert.equal(instance.url, frame.url)
|
||||
assert.equal(instance.injected, false)
|
||||
assert.equal(instance.destroyed, false)
|
||||
assert.equal(instance.messageCallback(), null)
|
||||
assert.throws(() => instance.commit('return 1'), /needs to be a function/)
|
||||
assert.throws(() => instance.message(null), /needs to be a function/)
|
||||
assert.equal(instance.destroy(), undefined)
|
||||
assert.equal(env.handlers.get('message').size, 0)
|
||||
})
|
||||
|
||||
test(`Iframe ${implementation.name}: numeric envelopes, resove spelling and callback receiver`, async () => {
|
||||
const env = iframeEnvironment(implementation)
|
||||
const instance = new env.Factory({ iframe: new env.Frame(), url: '/iframe.html' })
|
||||
const observed = []
|
||||
assert.equal(instance.message(function (message) {
|
||||
observed.push({ receiver: this === instance, ...message })
|
||||
}), undefined)
|
||||
env.dispatch({ type: 'inject' })
|
||||
assert.equal(instance.injected, true)
|
||||
const pending = instance.postMessage({ type: 'query', data: 3, id: 999 })
|
||||
assert.equal(typeof pending.then, 'function')
|
||||
assert.deepEqual(JSON.parse(JSON.stringify(env.sent)), [{ packet: { type: 'query', data: 3, id: 1234 }, origin: '*' }])
|
||||
assert.deepEqual(Object.keys(instance.promises[1234]), ['resove', 'reject'])
|
||||
env.dispatch({ type: 'response', data: 4, id: 1234 })
|
||||
assert.equal(await pending, 4)
|
||||
assert.equal(Object.keys(instance.promises).length, 0)
|
||||
assert.deepEqual(observed, [{ receiver: true, type: 'inject', data: undefined }, { receiver: true, type: 'response', data: 4 }])
|
||||
instance.destroy()
|
||||
})
|
||||
|
||||
test(`Iframe ${implementation.name}: child injection and synchronous commit response contract`, async () => {
|
||||
const parent = iframeEnvironment(implementation)
|
||||
assert.equal(parent.Factory.iframe, false)
|
||||
assert.throws(() => parent.Factory.inject(), /can only be used in iframe/)
|
||||
const env = iframeEnvironment(implementation, true)
|
||||
assert.equal(env.Factory.iframe, true)
|
||||
assert.equal(env.Factory.inject(), undefined)
|
||||
assert.deepEqual(JSON.parse(JSON.stringify(env.sent)), [{ packet: { type: 'inject', id: 0 }, origin: '*' }])
|
||||
await env.Factory.onMessage({ data: { type: 'commit', data: 'return 2 + 3', id: 17 } })
|
||||
assert.deepEqual(JSON.parse(JSON.stringify(env.sent.at(-1))), { packet: { type: 'response', data: 5, id: 17 }, origin: '*' })
|
||||
})
|
||||
|
||||
test(`Iframe ${implementation.name}: commit serializes a body and resolver replies remain asynchronous`, async () => {
|
||||
const env = iframeEnvironment(implementation)
|
||||
const instance = new env.Factory({ iframe: new env.Frame(), url: '/' })
|
||||
env.dispatch({ type: 'inject' })
|
||||
const pending = instance.commit(() => {
|
||||
return 7
|
||||
})
|
||||
const packet = env.sent.at(-1).packet
|
||||
assert.equal(packet.type, 'commit')
|
||||
assert.equal(packet.data.trim(), 'return 7')
|
||||
assert.equal(packet.id, 1234)
|
||||
env.dispatch({ type: 'response', data: 7, id: packet.id })
|
||||
assert.equal(await pending, 7)
|
||||
const child = iframeEnvironment(implementation, true)
|
||||
const completion = child.Factory.onMessage({ data: { type: 'commit', data: 'resolve(8)', id: 18 } })
|
||||
assert.equal(typeof completion.then, 'function')
|
||||
await completion
|
||||
assert.deepEqual(JSON.parse(JSON.stringify(child.sent.at(-1))), { packet: { type: 'response', data: 8, id: 18 }, origin: '*' })
|
||||
instance.destroy()
|
||||
})
|
||||
}
|
||||
|
||||
for (const implementation of implementations.filter(item => item.global === 'ArtplayerHelperIframe')) {
|
||||
test(`Iframe ${implementation.name}: extra helper artifact has a distinct static destroy protocol`, async () => {
|
||||
const env = iframeEnvironment(implementation)
|
||||
assert.equal(typeof env.exported, 'object')
|
||||
assert.equal(env.Factory.iframe, undefined)
|
||||
assert.equal(typeof env.Factory.destroy, 'function')
|
||||
const browser = {}
|
||||
browser.window = browser
|
||||
browser.self = browser
|
||||
vm.runInNewContext(implementation.code, browser)
|
||||
assert.equal(typeof browser.ArtplayerHelperIframe, 'function')
|
||||
const instance = new env.Factory({ iframe: new env.Frame(), url: '/' })
|
||||
assert.equal(instance.isInject, false)
|
||||
assert.equal(instance.isDestroy, false)
|
||||
assert.equal(instance.injected, undefined)
|
||||
env.Factory.inject()
|
||||
assert.equal(env.Factory.isInject, true)
|
||||
await env.Factory.onMessage({ data: { type: 'destroy' } })
|
||||
assert.equal(env.Factory.isDestroy, true)
|
||||
assert.equal(env.Factory.isInject, false)
|
||||
assert.deepEqual(JSON.parse(JSON.stringify(env.sent)), [{ packet: { type: 'inject', id: 0 }, origin: '*' }, { packet: { type: 'destroy', id: 0 }, origin: '*' }])
|
||||
instance.destroy()
|
||||
assert.equal(instance.isDestroy, true)
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user