mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-13 07:46:17 -08:00
docs(audio): [SITE-AUDIO-01] add bilingual track guides and browser coverage
This commit is contained in:
1 parent
6af43208af
commit
d3349e83f2
67 files changed
+6011
-1647
No files matched your search
@@ -516,3 +516,15 @@ are asserted with the original SDK initialization settings. WebKit without MSE
|
||||
checks only unsupported setup/notice/cleanup. `document-site.spec.js` also verifies
|
||||
the two guide links and Run Code libraries/source; full SDK/device acceptance stays
|
||||
separate. Unit nullable-language and repeated-cleanup cases run via test:unit.
|
||||
|
||||
## Audio Track documentation examples
|
||||
|
||||
`document-audio.spec.js` requires both guides' Run Code to match the unchanged
|
||||
`docs/assets/example/audio.track.js`. It loads the actual local plugin distribution
|
||||
with published/candidate cores, routes the demo media URLs to native Range-served
|
||||
H264/AAC fixtures, and checks decoded video pixels plus independent audio time,
|
||||
pause, offset seek, volume/rate, URL replacement, element identity and terminal
|
||||
cleanup. Pixel readiness uses the existing polling deadline, not media time alone.
|
||||
The first immediate-pixel WebKit failure remains in the refactor evidence.
|
||||
This is native desktop media playback, not physical audibility or full devices.
|
||||
`document-site.spec.js` also checks generated guide links and Run Code parameters.
|
||||
@@ -0,0 +1,85 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import fs from 'node:fs'
|
||||
import { hash } from '../../refactor/scripts/releases.mjs'
|
||||
import { extractExamples } from '../../scripts/docs-smoke/parser.ts'
|
||||
import { expect, test } from './fixtures.js'
|
||||
|
||||
const exampleSource = fs.readFileSync('docs/assets/example/audio.track.js', 'utf8').trim()
|
||||
const plugin = fs.readFileSync('packages/artplayer-plugin-audio-track/dist/artplayer-plugin-audio-track.js')
|
||||
const documents = ['plugin/audio-track.md', 'en/plugin/audio-track.md']
|
||||
const audio = fs.readFileSync('test/browser/media/audio-tone.m4a')
|
||||
const audioManifest = JSON.parse(fs.readFileSync('test/browser/media/audio-tone.json'))
|
||||
assert.equal(hash(audio), audioManifest.sha256)
|
||||
for (const document of documents) {
|
||||
const examples = extractExamples(fs.readFileSync(`packages/artplayer-vitepress/docs/${document}`, 'utf8'), document)
|
||||
assert.equal(examples.length, 1)
|
||||
assert.equal(examples[0].code, exampleSource, 'Both audio guides must execute the actual demo source')
|
||||
}
|
||||
|
||||
for (const core of ['published', 'candidate']) {
|
||||
test(`documented independent audio: playback, seek, updates and cleanup with ${core} core`, async ({ page }, testInfo) => {
|
||||
for (const [original, fixture] of [['sprite-fight.mp4', '/test/pattern.mp4'], ['sprite-fight.aac', '/test/audio-tone.m4a']]) {
|
||||
await page.route(`**/assets/sample/${original}*`, (route) => {
|
||||
const url = new URL(route.request().url())
|
||||
url.pathname = fixture
|
||||
return route.continue({ url: url.href })
|
||||
})
|
||||
}
|
||||
await page.goto(`/test/player.html?core=${core}`)
|
||||
await page.evaluate(() => document.querySelector('.player').classList.add('artplayer-app'))
|
||||
await page.addScriptTag({ content: plugin.toString() })
|
||||
await page.addScriptTag({ content: `${exampleSource}\nwindow.art = art;` })
|
||||
await page.evaluate(() => {
|
||||
window.documentedTrack = window.art.plugins.artplayerPluginAudioTrack
|
||||
window.documentedAudio = window.documentedTrack.audio
|
||||
window.art.muted = true
|
||||
document.querySelector('#play').onclick = () => window.art.play()
|
||||
})
|
||||
await testInfo.attach('documented-audio-inputs', { contentType: 'application/json', body: JSON.stringify({ documents, core, pluginSHA256: hash(plugin), sourceSHA256: hash(exampleSource), audio: audioManifest, scope: 'Original example code with local Range-served H264 pattern and AAC/MP4 tone substituted for demo URLs; native media timing, not physical audibility or full device acceptance' }) })
|
||||
try {
|
||||
await expect.poll(() => page.evaluate(() => window.art.isReady && window.documentedAudio.readyState >= 2)).toBe(true)
|
||||
await page.locator('#play').click()
|
||||
await expect.poll(() => page.evaluate(() => window.art.currentTime > 0.3 && window.documentedAudio.currentTime > 0.3 && !window.documentedAudio.paused)).toBe(true)
|
||||
await expect.poll(() => page.evaluate(() => {
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = 8
|
||||
canvas.height = 8
|
||||
const ctx = canvas.getContext('2d')
|
||||
ctx.drawImage(window.art.video, 0, 0, 8, 8)
|
||||
return [...ctx.getImageData(0, 0, 8, 8).data].some((value, index) => index % 4 !== 3 && value > 20)
|
||||
})).toBe(true)
|
||||
await page.evaluate(() => window.art.video.pause())
|
||||
await expect.poll(() => page.evaluate(() => window.documentedAudio.paused)).toBe(true)
|
||||
expect(await page.evaluate(() => window.documentedTrack.update({ offset: 0.25, sync: 0.1 }) === undefined)).toBe(true)
|
||||
await page.evaluate(() => {
|
||||
window.art.seek = 4
|
||||
window.art.volume = 0.4
|
||||
window.art.playbackRate = 1.25
|
||||
})
|
||||
await expect.poll(() => page.evaluate(() => Math.abs(window.documentedAudio.currentTime - window.art.currentTime - 0.25) < 0.1)).toBe(true)
|
||||
await expect.poll(() => page.evaluate(() => window.documentedAudio.volume)).toBeCloseTo(0.4)
|
||||
await expect.poll(() => page.evaluate(() => window.documentedAudio.playbackRate)).toBe(1.25)
|
||||
expect(await page.evaluate(() => window.documentedAudio.muted)).toBe(true)
|
||||
expect(await page.evaluate(() => window.documentedAudio.paused)).toBe(true)
|
||||
await page.evaluate(() => window.documentedTrack.update({ url: '/assets/sample/sprite-fight.aac?track=second' }))
|
||||
await expect.poll(() => page.evaluate(() => window.documentedAudio.readyState >= 2 && window.documentedAudio.currentSrc.includes('track=second'))).toBe(true)
|
||||
expect(await page.evaluate(() => window.documentedTrack.audio === window.documentedAudio)).toBe(true)
|
||||
await page.locator('#play').click()
|
||||
await expect.poll(() => page.evaluate(() => window.art.currentTime > 4.2 && window.documentedAudio.currentTime > 4.2 && !window.documentedAudio.paused)).toBe(true)
|
||||
await page.evaluate(() => window.art.destroy())
|
||||
await expect.poll(() => page.evaluate(() => window.documentedAudio.networkState)).toBe(0)
|
||||
expect(await page.evaluate(() => window.documentedAudio.getAttribute('src'))).toBeNull()
|
||||
expect(await page.evaluate(() => window.documentedAudio.paused)).toBe(true)
|
||||
expect(await page.evaluate(() => window.documentedTrack.update({ url: '/assets/sample/sprite-fight.aac?track=late' }) === undefined)).toBe(true)
|
||||
expect(await page.evaluate(() => window.documentedAudio.getAttribute('src'))).toBeNull()
|
||||
expect(await page.locator('.player').evaluate(element => element.childElementCount)).toBe(0)
|
||||
}
|
||||
finally {
|
||||
await testInfo.attach('documented-audio-state', { contentType: 'application/json', body: JSON.stringify(await page.evaluate(() => ({ time: window.documentedAudio.currentTime, paused: window.documentedAudio.paused, source: window.documentedAudio.getAttribute('src'), error: window.documentedAudio.error?.code, videoTime: window.art.currentTime, destroyed: window.art.isDestroy }))) })
|
||||
await page.evaluate(() => {
|
||||
if (!window.art.isDestroy)
|
||||
window.art.destroy()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -89,5 +89,16 @@ for (const language of ['zh', 'en']) {
|
||||
expect(dashTarget.searchParams.get('code')).toContain('art.on(\'destroy\', destroyDash)')
|
||||
expect(failedAssets).toEqual([])
|
||||
await dashExample.close()
|
||||
await page.locator(`.VPSidebar a[href="${prefix}/plugin/audio-track.html"]`).click()
|
||||
await expect(page.locator('h1')).toContainText(language === 'en' ? 'Audio Track' : '独立音轨')
|
||||
const audioPopup = context.waitForEvent('page')
|
||||
await page.locator('.run-code, [classname="run-code"]').first().click()
|
||||
const audioExample = await audioPopup
|
||||
await audioExample.waitForLoadState('domcontentloaded')
|
||||
const audioTarget = new URL(audioExample.url())
|
||||
expect(audioTarget.searchParams.get('libs')).toBe('./uncompiled/artplayer-plugin-audio-track/index.js')
|
||||
expect(audioTarget.searchParams.get('code')).toContain('artplayerPluginAudioTrack({')
|
||||
expect(failedAssets).toEqual([])
|
||||
await audioExample.close()
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user