mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-09 20:26:16 -08:00
test(ci): [CI-01] checkpoint installed adaptive and thumbnail coverage
This commit is contained in:
1 parent
7094cf6f9c
commit
b90de99bc2
25 files changed
+10494
-45
No files matched your search
@@ -108,7 +108,9 @@ for (const variant of ['destroy', 'restart', 'complete', 'frame-destroy', 'frame
|
||||
throw new Error('No owned encoding deadline')
|
||||
probe.encodingDeadline.callback()
|
||||
}
|
||||
else probe.art.emit(scenario.replace('frame-', ''))
|
||||
else {
|
||||
probe.art.emit(scenario.replace('frame-', ''))
|
||||
}
|
||||
if (probe.blobs[0]) {
|
||||
probe.blobs[0].callback(probe.blobs[0].blob)
|
||||
probe.blobs[0].callback(probe.blobs[0].blob)
|
||||
@@ -136,14 +138,16 @@ for (const variant of ['destroy', 'restart', 'complete', 'frame-destroy', 'frame
|
||||
probe.restore()
|
||||
return { before, after, video, canvasDimensions, publishedImage, final, blobs, pendingDeadlines: probe.timers.size, warnings: probe.warnings, heldFrames: probe.frames.length, frameSupport: probe.frameSupport, result: probe.result }
|
||||
}, scenario)
|
||||
await testInfo.attach('auto-thumbnail-candidate-native-lifecycle', { contentType: 'application/json', body: JSON.stringify({ scenario, useDefault, sha256: hash(implementation.code), scope: 'Actual HTTP decoding/seek/JPEG and held native presentation callback lifecycle with a stub player host. Frame scenarios use a held Blob fallback only when native frame callbacks are absent. Pixel acceptance is separate; AUTO-THUMB-PIXEL-01 remains open.', ...state }) })
|
||||
await testInfo.attach('auto-thumbnail-candidate-native-lifecycle', { contentType: 'application/json', body: JSON.stringify({ scenario, useDefault, sha256: hash(implementation.code), provenance: implementation.provenance, scope: 'Actual HTTP decoding/seek/JPEG and held native presentation callback lifecycle with a stub player host. Frame scenarios use a held Blob fallback only when native frame callbacks are absent. Pixel acceptance is separate; AUTO-THUMB-PIXEL-01 remains open.', ...state }) })
|
||||
expect(state.result).toEqual({ name: 'artplayerPluginAutoThumbnail' })
|
||||
expect(state.pendingDeadlines).toBe(0)
|
||||
if (scenario === 'encoding-timeout') {
|
||||
expect(state.warnings).toHaveLength(1)
|
||||
expect(state.warnings[0][1]).toContain('encoding timed out')
|
||||
}
|
||||
else expect(state.warnings).toEqual([])
|
||||
else {
|
||||
expect(state.warnings).toEqual([])
|
||||
}
|
||||
expect(state.before).toEqual(scenario === 'complete' ? { urls: 1, updates: 2 } : { urls: 0, updates: 0 })
|
||||
expect(state.after).toEqual(state.before)
|
||||
expect(state.video).toEqual({ connected: false, src: null, readyState: 0, paused: true, handlers: [true, true, true, true] })
|
||||
|
||||
@@ -91,6 +91,7 @@ for (const media of ['auto-thumbnail-timeline', 'pattern']) {
|
||||
})
|
||||
await testInfo.attach('auto-thumbnail-candidate-hidden-pixels', { contentType: 'application/json', body: JSON.stringify({
|
||||
sha256: hash(implementation.code),
|
||||
provenance: implementation.provenance,
|
||||
media,
|
||||
scope: 'All five cells are asserted where native frame presentation callbacks are available. Without that capability only cells 2-4 are asserted, with cells 0-1 recorded as unresolved diagnostics under AUTO-THUMB-PIXEL-01. Native HTTP/JPEG and a stub player host, not a core integration.',
|
||||
...state,
|
||||
|
||||
@@ -2,7 +2,7 @@ import assert from 'node:assert/strict'
|
||||
import fs from 'node:fs'
|
||||
import process from 'node:process'
|
||||
import { ensureArchive, hash, readMember } from '../../refactor/scripts/releases.mjs'
|
||||
import { compilePackage } from '../helpers/load.js'
|
||||
import { browserCandidate } from '../helpers/browser-candidate.js'
|
||||
import { expect, test } from './fixtures.js'
|
||||
|
||||
let publishedCode
|
||||
@@ -14,9 +14,9 @@ test.beforeAll(async () => {
|
||||
const bytes = readMember(await ensureArchive(release), member)
|
||||
assert.equal(hash(bytes), release.files[member])
|
||||
publishedCode = bytes.toString()
|
||||
assert(!process.env.ARTPLAYER_BROWSER_ARTIFACTS, 'Controlled DASH source tests do not represent installed SDK/package acceptance')
|
||||
sourceCode = process.env.ARTPLAYER_DASH_ARTIFACT ? fs.readFileSync(process.env.ARTPLAYER_DASH_ARTIFACT, 'utf8') : await compilePackage(release.name, 'umd')
|
||||
evidence = { published: release, sourceSHA256: hash(sourceCode), candidate: process.env.ARTPLAYER_DASH_ARTIFACT || 'workspace source build', scope: 'Real ArtPlayer DOM and native MP4 with controlled SDK methods. No dash.js instance, MPD, ABR or adaptive media validation.' }
|
||||
const candidate = await browserCandidate(release.name, process.env.ARTPLAYER_DASH_ARTIFACT)
|
||||
sourceCode = candidate.code
|
||||
evidence = { published: release, sourceSHA256: hash(sourceCode), candidate: candidate.provenance, scope: 'Real ArtPlayer DOM and native MP4 with controlled SDK methods. No dash.js instance, MPD, ABR or adaptive media validation.' }
|
||||
})
|
||||
test.afterEach(async ({ page }, testInfo) => {
|
||||
const state = await page.evaluate(() => ({
|
||||
@@ -37,7 +37,7 @@ test.afterEach(async ({ page }, testInfo) => {
|
||||
}
|
||||
})
|
||||
async function openDash(page, core, plugin, sdk, testInfo) {
|
||||
await testInfo.attach('controlled-dash-inputs', { contentType: 'application/json', body: JSON.stringify(evidence) })
|
||||
await testInfo.attach('controlled-dash-inputs', { contentType: 'application/json', body: JSON.stringify({ ...evidence, core, plugin, selected: plugin === 'published' ? { kind: 'published', sha256: hash(publishedCode) } : evidence.candidate }) })
|
||||
await page.goto(`/test/player.html?core=${core}`)
|
||||
await page.addScriptTag({ content: plugin === 'published' ? publishedCode : sourceCode })
|
||||
await page.evaluate((sdk) => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import assert from 'node:assert/strict'
|
||||
import fs from 'node:fs'
|
||||
import process from 'node:process'
|
||||
import { ensureArchive, hash, readMember } from '../../refactor/scripts/releases.mjs'
|
||||
import { compilePackage } from '../helpers/load.js'
|
||||
import { browserCandidate } from '../helpers/browser-candidate.js'
|
||||
import { observeDashBuffers } from './dash-buffer-observer.js'
|
||||
import { probeBufferGetter, probeBufferMetric } from './dash-seek-diagnostics.js'
|
||||
import { expect, test } from './fixtures.js'
|
||||
@@ -10,6 +10,7 @@ import { expect, test } from './fixtures.js'
|
||||
const sdks = new Map()
|
||||
const media = new Map()
|
||||
let candidate
|
||||
let candidateProvenance
|
||||
let published
|
||||
let mediaManifest
|
||||
let pluginRelease
|
||||
@@ -18,6 +19,7 @@ assert(['none', 'upstream4', 'bufferlevel4'].includes(diagnosticSDK), 'Unknown d
|
||||
const recoveryModes = ['ARTPLAYER_DASH_DIAGNOSE_STALL', 'ARTPLAYER_DASH_DIAGNOSE_GETTER', 'ARTPLAYER_DASH_DIAGNOSE_METRICS'].filter(name => process.env[name] === '1')
|
||||
assert(recoveryModes.length <= 1, 'Choose only one DASH recovery diagnostic')
|
||||
assert(!recoveryModes.length || diagnosticSDK === 'none', 'Recovery diagnostics require the unchanged published SDK')
|
||||
assert(!process.env.ARTPLAYER_BROWSER_ARTIFACTS || (diagnosticSDK === 'none' && recoveryModes.length === 0), 'Installed DASH checks cannot use SDK or recovery diagnostics')
|
||||
|
||||
test.beforeAll(async () => {
|
||||
const baseline = JSON.parse(fs.readFileSync(new URL('../../refactor/baselines/dash-sdk.json', import.meta.url)))
|
||||
@@ -44,7 +46,9 @@ test.beforeAll(async () => {
|
||||
const bytes = readMember(await ensureArchive(pluginRelease), 'package/dist/artplayer-plugin-dash-control.js')
|
||||
assert.equal(hash(bytes), pluginRelease.files['package/dist/artplayer-plugin-dash-control.js'])
|
||||
published = bytes.toString()
|
||||
candidate = process.env.ARTPLAYER_DASH_ARTIFACT ? fs.readFileSync(process.env.ARTPLAYER_DASH_ARTIFACT, 'utf8') : await compilePackage('artplayer-plugin-dash-control', 'umd')
|
||||
const input = await browserCandidate('artplayer-plugin-dash-control', process.env.ARTPLAYER_DASH_ARTIFACT)
|
||||
candidate = input.code
|
||||
candidateProvenance = input.provenance
|
||||
mediaManifest = JSON.parse(fs.readFileSync(new URL('./media/dash/manifest.json', import.meta.url)))
|
||||
for (const [name, expected] of Object.entries(mediaManifest.files)) {
|
||||
assert(/^[\w.-]+$/.test(name))
|
||||
@@ -116,7 +120,7 @@ async function loadSDK(page, version, core, testInfo) {
|
||||
await page.evaluate(observeDashBuffers)
|
||||
await page.addScriptTag({ content: sdk.code })
|
||||
const capability = await page.evaluate(() => ({ sdk: window.dashjs.supportsMediaSource(), mse: typeof window.MediaSource, managed: typeof window.ManagedMediaSource, avc: Boolean(window.MediaSource?.isTypeSupported('video/mp4; codecs="avc1.42c01e"')), aac: Boolean(window.MediaSource?.isTypeSupported('audio/mp4; codecs="mp4a.40.2"')) }))
|
||||
await testInfo.attach('dash-sdk-inputs', { contentType: 'application/json', body: JSON.stringify({ sdk: sdk.release, codeMember: sdk.diagnostic?.member || sdk.codeMember, diagnostic: sdk.diagnostic, pluginRelease, candidateSHA256: hash(candidate), candidate: process.env.ARTPLAYER_DASH_ARTIFACT || 'workspace source build', media: mediaManifest, capability }) })
|
||||
await testInfo.attach('dash-sdk-inputs', { contentType: 'application/json', body: JSON.stringify({ sdk: sdk.release, codeMember: sdk.diagnostic?.member || sdk.codeMember, diagnostic: sdk.diagnostic, pluginRelease, candidateSHA256: hash(candidate), availableCandidate: candidateProvenance, pluginLoaded: false, media: mediaManifest, capability }) })
|
||||
return capability
|
||||
}
|
||||
|
||||
@@ -124,6 +128,7 @@ async function openDash(page, version, core, plugin, testInfo) {
|
||||
const capability = await loadSDK(page, version, core, testInfo)
|
||||
test.skip(!capability.sdk, 'Actual SDK reports no MediaSource support; this engine has no DASH playback acceptance')
|
||||
await routeMedia(page)
|
||||
await testInfo.attach('dash-plugin-inputs', { contentType: 'application/json', body: JSON.stringify({ version, core, plugin, selected: plugin === 'published' ? { kind: 'published', sha256: hash(published) } : candidateProvenance }) })
|
||||
await page.addScriptTag({ content: plugin === 'published' ? published : candidate })
|
||||
await page.evaluate(() => {
|
||||
window.sdkErrors = []
|
||||
|
||||
@@ -2,7 +2,7 @@ import assert from 'node:assert/strict'
|
||||
import fs from 'node:fs'
|
||||
import process from 'node:process'
|
||||
import { ensureArchive, hash, readMember } from '../../refactor/scripts/releases.mjs'
|
||||
import { compilePackage } from '../helpers/load.js'
|
||||
import { browserCandidate } from '../helpers/browser-candidate.js'
|
||||
import { expect, test } from './fixtures.js'
|
||||
|
||||
let sdkCode
|
||||
@@ -38,11 +38,8 @@ test.beforeAll(async () => {
|
||||
}
|
||||
sdkCode = await code(sdk.release, 'package/dist/hls.min.js')
|
||||
publishedCode = await code(plugin.release, 'package/dist/artplayer-plugin-hls-control.js')
|
||||
// This task exercises source builds. Installed artifacts are a separate HLS-06 gate.
|
||||
assert(!process.env.ARTPLAYER_BROWSER_ARTIFACTS, 'HLS source fixture cannot masquerade as an installed plugin')
|
||||
sourceCode = process.env.ARTPLAYER_HLS_ARTIFACT
|
||||
? fs.readFileSync(process.env.ARTPLAYER_HLS_ARTIFACT, 'utf8')
|
||||
: await compilePackage('artplayer-plugin-hls-control', 'umd')
|
||||
const candidate = await browserCandidate('artplayer-plugin-hls-control', process.env.ARTPLAYER_HLS_ARTIFACT)
|
||||
sourceCode = candidate.code
|
||||
const manifest = JSON.parse(fs.readFileSync(new URL('./media/hls/manifest.json', import.meta.url)))
|
||||
media = new Map()
|
||||
for (const [name, expected] of Object.entries(manifest.files)) {
|
||||
@@ -52,11 +49,11 @@ test.beforeAll(async () => {
|
||||
assert.equal(bytes.length, expected.bytes)
|
||||
media.set(name, bytes)
|
||||
}
|
||||
evidence = { sdk: sdk.release, plugin: plugin.release, sourceSHA256: hash(sourceCode), candidate: process.env.ARTPLAYER_HLS_ARTIFACT || 'workspace source build', media: manifest, limitations: ['SDK worker disabled', 'local deterministic media', 'not an isolated installed package', 'no physical device certification'] }
|
||||
evidence = { sdk: sdk.release, plugin: plugin.release, sourceSHA256: hash(sourceCode), candidate: candidate.provenance, media: manifest, limitations: ['SDK worker disabled', 'local deterministic media', 'no physical device certification'] }
|
||||
})
|
||||
|
||||
async function openHls(page, core, plugin, testInfo, manifest = 'master.m3u8') {
|
||||
await testInfo.attach('hls-inputs', { contentType: 'application/json', body: JSON.stringify(evidence) })
|
||||
await testInfo.attach('hls-inputs', { contentType: 'application/json', body: JSON.stringify({ ...evidence, core, plugin, selected: plugin === 'published' ? { kind: 'published', sha256: hash(publishedCode) } : evidence.candidate }) })
|
||||
await page.route('**/hls-fixture/**', async (route) => {
|
||||
const name = new URL(route.request().url()).pathname.split('/').at(-1)
|
||||
const bytes = media.get(name)
|
||||
|
||||
@@ -3,22 +3,22 @@ import { Buffer } from 'node:buffer'
|
||||
import fs from 'node:fs'
|
||||
import process from 'node:process'
|
||||
import { ensureArchive, hash, readMember } from '../../refactor/scripts/releases.mjs'
|
||||
import { compilePackage } from '../helpers/load.js'
|
||||
import { browserCandidate } from '../helpers/browser-candidate.js'
|
||||
import { observeWorkers } from '../helpers/worker-observer.js'
|
||||
import { expect, test } from './fixtures.js'
|
||||
|
||||
const matrix = JSON.parse(fs.readFileSync(new URL('../../refactor/baselines/hls-sdk-matrix.json', import.meta.url)))
|
||||
const grouped = fs.readFileSync(new URL('./fixtures/hls-grouped.m3u8', import.meta.url), 'utf8')
|
||||
let candidate
|
||||
let candidateProvenance
|
||||
let published
|
||||
const sdks = new Map()
|
||||
const media = new Map()
|
||||
|
||||
test.beforeAll(async () => {
|
||||
assert(!process.env.ARTPLAYER_BROWSER_ARTIFACTS, 'HLS installed artifact map remains a separate HLS-06 gate')
|
||||
candidate = process.env.ARTPLAYER_HLS_ARTIFACT
|
||||
? fs.readFileSync(process.env.ARTPLAYER_HLS_ARTIFACT, 'utf8')
|
||||
: await compilePackage('artplayer-plugin-hls-control', 'umd')
|
||||
const input = await browserCandidate('artplayer-plugin-hls-control', process.env.ARTPLAYER_HLS_ARTIFACT)
|
||||
candidate = input.code
|
||||
candidateProvenance = input.provenance
|
||||
const baseline = JSON.parse(fs.readFileSync(new URL('../../refactor/baselines/hls-control-release.json', import.meta.url)))
|
||||
const bytes = readMember(await ensureArchive(baseline.release), 'package/dist/artplayer-plugin-hls-control.js')
|
||||
assert.equal(hash(bytes), baseline.release.files['package/dist/artplayer-plugin-hls-control.js'])
|
||||
@@ -55,7 +55,7 @@ test.afterEach(async ({ page }, testInfo) => {
|
||||
})
|
||||
|
||||
async function open(page, testInfo, release, core, plugin = 'candidate', manifest = 'master.m3u8') {
|
||||
await testInfo.attach('hls-sdk-inputs', { contentType: 'application/json', body: JSON.stringify({ sdk: release, core, plugin, pluginSHA256: hash(plugin === 'candidate' ? candidate : published), candidate: process.env.ARTPLAYER_HLS_ARTIFACT || 'workspace source build', media: Object.fromEntries([...media].map(([name, bytes]) => [name, hash(bytes)])), enableWorker: true }) })
|
||||
await testInfo.attach('hls-sdk-inputs', { contentType: 'application/json', body: JSON.stringify({ sdk: release, core, plugin, pluginSHA256: hash(plugin === 'candidate' ? candidate : published), selected: plugin === 'candidate' ? candidateProvenance : { kind: 'published', sha256: hash(published) }, media: Object.fromEntries([...media].map(([name, bytes]) => [name, hash(bytes)])), enableWorker: true }) })
|
||||
await page.route('**/hls-sdk-fixture/**', async (route) => {
|
||||
const name = new URL(route.request().url()).pathname.split('/').at(-1)
|
||||
const bytes = media.get(name)
|
||||
|
||||
Reference in new issue
Block a user