mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-08 19:06:15 -08:00
test(chapter): [PKG-CHAPTER-05] correlate restart event and observation timing
This commit is contained in:
1 parent
814bdc11db
commit
e93d3cbb67
8 files changed
+2880
-6
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,49 @@
|
||||
# PKG-CHAPTER-05 历史超时与事件观测
|
||||
|
||||
任务仍为 doing。本轮接续已提交的组合检查点,未修改生产源码、类型、产物或依赖。
|
||||
没有把已通过的桌面模拟宣称为物理设备验收。
|
||||
|
||||
## 历史 trace 的新发现
|
||||
|
||||
读取原 `chapter05-quality-ready-results` 中 candidate core + candidate chapter 的
|
||||
WebKit 失败 trace,核对实际 before/after 调用,而非只看测试错误摘要:
|
||||
|
||||
| 操作 | 耗时 | 返回值 |
|
||||
| --- | --- | --- |
|
||||
| 选择 Quality A | 582.473 ms | 点击完成 |
|
||||
| 检查当前 URL | 38.196 ms | true |
|
||||
| 第一次读取 restart 数组 | 3.373 ms | 空数组 |
|
||||
| 第二次读取 restart 数组 | 9956.244 ms | 目标 URL 已在数组中 |
|
||||
|
||||
最后一次 evaluate 超过原 7000 ms 轮询期限,之后的 afterEach 才得到恢复位置和
|
||||
readyState=4。这不是持续快速轮询七秒都得到空数组。旧 trace 没有为 restart
|
||||
和原生媒体事件记录页面时钟,仍无法判断事件发生在该调用的哪一时刻,或区分
|
||||
媒体驱动、页面主线程、协议传输、trace 快照开销。不能据此关闭风险,更不能仅
|
||||
凭类似十秒停顿把它和 JASSUB 的 Firefox 问题认定为同一根因。
|
||||
|
||||
原 trace ZIP/member hash、准确时点和序列化返回值保存在
|
||||
[机器记录](../baselines/chapter-timing-observations.json)。原始 ZIP 未改写。
|
||||
|
||||
## 测试改进与本轮验证
|
||||
|
||||
`chapter-combinations.spec.js` 现在记录公共事件与原生事件的 performance.now,
|
||||
清晰度选择前的时间点,以及每次完成的 restart 读取的 Node 起点、往返耗时、
|
||||
页面时间和 performance.timeOrigin。future trace 可以对齐两端时钟,分离已发生
|
||||
但晚观察到的事件和真正晚发生的事件。原目标 URL、恢复位置、菜单、章节及
|
||||
缩略图断言不变,超时没有增加,测试未启用重试。
|
||||
|
||||
固定 Node 24.21.0 / Yarn 1.22.22,执行:
|
||||
|
||||
```sh
|
||||
yarn test:browser test/browser/chapter-combinations.spec.js --grep 'quality switch' --workers=1
|
||||
```
|
||||
|
||||
三浏览器、四组新旧核心/章节组合共 12 项通过。两个已发布核心的 WebKit 用例
|
||||
仍是历史位置归零观察,候选核心仍要求恢复原位置;不能将这两项统计为修复。
|
||||
本轮使用浏览器服务的源码构建,报告保存实际资源 hash。定向只读 ESLint 通过。
|
||||
没有重新运行章节全量、fullscreen/touch 全部矩阵或 tarball 安装验收。
|
||||
|
||||
本轮通过仅验证新增观测没有破坏既有组合断言,不解释历史停顿。CHAPTER-TIMING-01
|
||||
保持 open,05/06 和物理设备门槛仍未完成。下一步可继续独立插件实施;若再次出现
|
||||
停顿,先对照页面事件时点和往返耗时,避免直接修改核心或用更长等待掩盖它。
|
||||
回退本提交只移除观测及记录;不 push/publish。
|
||||
+1
-1
@@ -500,7 +500,7 @@
|
||||
- PKG-CHAPTER-02: [记录](changes/2026-09-10-PKG-CHAPTER-02-tests.md) [记录](baselines/chapter-validation.json)
|
||||
- PKG-CHAPTER-03: [记录](changes/2026-09-10-PKG-CHAPTER-03-typescript-modules.md) [记录](baselines/chapter-migration-validation.json)
|
||||
- PKG-CHAPTER-04: [记录](changes/2026-09-10-PKG-CHAPTER-04-public-types.md) [记录](baselines/chapter-types-validation.json)
|
||||
- PKG-CHAPTER-05: [记录](changes/2026-09-12-PKG-CHAPTER-05-combinations.md) [记录](baselines/chapter-combinations-checkpoint.json)
|
||||
- PKG-CHAPTER-05: [记录](changes/2026-09-12-PKG-CHAPTER-05-combinations.md) [记录](baselines/chapter-combinations-checkpoint.json) [记录](changes/2026-09-14-PKG-CHAPTER-05-timing.md) [记录](baselines/chapter-timing-observations.json)
|
||||
- PKG-AMBILIGHT-01: [记录](changes/2026-09-12-PKG-AMBILIGHT-01-contract.md) [记录](baselines/ambilight-contract.md) [记录](baselines/ambilight-release.json) [记录](baselines/ambilight-contract-validation.json)
|
||||
- PKG-AMBILIGHT-02: [记录](changes/2026-09-12-PKG-AMBILIGHT-02-tests.md) [记录](baselines/ambilight-behavior-validation.json) [记录](ambilight-validation.md)
|
||||
- PKG-AMBILIGHT-03: [记录](changes/2026-09-12-PKG-AMBILIGHT-03-lifecycle.md) [记录](ambilight-validation.md) [记录](baselines/ambilight-lifecycle-validation.json)
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# 进度与证据
|
||||
|
||||
## PKG-CHAPTER-05 时序取证继续(doing)
|
||||
|
||||
复核旧失败 ZIP:一次 restart 数组读取耗时 9956.244 ms,返回时已含目标 URL;
|
||||
不能只凭原超时文本认定七秒都未触发 restart。新增公共/原生事件页面时点与
|
||||
restart 读取往返耗时,三浏览器四组质量/章节/缩略图组合十二项通过,保留两项
|
||||
已发布核心 WebKit 位置归零观察。无生产或依赖变更,CHAPTER-TIMING-01 和物理
|
||||
设备缺口保持未关闭,05/06 未完成。详见[记录](changes/2026-09-14-PKG-CHAPTER-05-timing.md)
|
||||
及[trace 摘要](baselines/chapter-timing-observations.json)。VAST 的初始化兼容
|
||||
选择已再次列为待答复事项,尚未变更默认行为;其他独立实施继续。
|
||||
|
||||
## PKG-JASSUB-09 合成截图验证(doing)
|
||||
|
||||
新增显式截图模式,由 Node pngjs@7.0.0 解码实际页面 PNG,不复制转移画布。
|
||||
|
||||
+3
-1
@@ -2874,7 +2874,9 @@
|
||||
"evidence": [
|
||||
"refactor/baselines/chapter-combinations-checkpoint.json",
|
||||
"test/browser/chapter-combinations.spec.js",
|
||||
"refactor/changes/2026-09-12-PKG-CHAPTER-05-combinations.md"
|
||||
"refactor/changes/2026-09-12-PKG-CHAPTER-05-combinations.md",
|
||||
"refactor/changes/2026-09-14-PKG-CHAPTER-05-timing.md",
|
||||
"refactor/baselines/chapter-timing-observations.json"
|
||||
],
|
||||
"compatibleResolution": "记录原生事件和绝对/相对时序,进一步区分媒体驱动耗时、夹具和核心源操作;未证明原因前不改核心、不扩大超时或重复到绿灯。",
|
||||
"closureCriteria": "确认先前超时的来源并有对应可靠回归;后续单次通过不足以关闭。"
|
||||
|
||||
+3
-1
@@ -1434,7 +1434,9 @@
|
||||
"acceptance": "最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成",
|
||||
"evidence": [
|
||||
"changes/2026-09-12-PKG-CHAPTER-05-combinations.md",
|
||||
"baselines/chapter-combinations-checkpoint.json"
|
||||
"baselines/chapter-combinations-checkpoint.json",
|
||||
"changes/2026-09-14-PKG-CHAPTER-05-timing.md",
|
||||
"baselines/chapter-timing-observations.json"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -217,3 +217,11 @@ hashes identify the actual selected ASS, not the white baseline. Screenshots are
|
||||
attached at named phases; errors from individual polling attempts are retained.
|
||||
The fixture's automatic failure screenshot runs after cleanup and may show an
|
||||
empty player; use the named pre-cleanup screenshots for visual claims.
|
||||
|
||||
Chapter quality combinations attach `chapter-restart-observations`: completed
|
||||
read calls include host wall time/elapsed time and browser monotonic time/origin.
|
||||
Public/native chapter events also carry browser timestamps. Preserve those clocks
|
||||
when diagnosing a timeout: the historical failure includes a single ~10-second
|
||||
evaluate returning an already-recorded restart, not seven seconds of fast empty
|
||||
reads. These observations do not expand the timeout or waive the open timing and
|
||||
physical-device acceptance in PKG-CHAPTER-05.
|
||||
@@ -26,9 +26,9 @@ async function openChapter(page, core, chapter) {
|
||||
] })],
|
||||
})
|
||||
for (const name of ['restart', 'seek', 'fullscreen', 'fullscreenWeb'])
|
||||
window.art.on(name, value => window.chapterEvents.push({ name, value }))
|
||||
window.art.on(name, value => window.chapterEvents.push({ name, value, at: performance.now() }))
|
||||
for (const name of ['loadedmetadata', 'loadeddata', 'canplay', 'seeking', 'seeked', 'playing', 'pause', 'error'])
|
||||
window.art.video.addEventListener(name, () => window.chapterMediaEvents.push({ name, time: window.art.currentTime, source: window.art.video.currentSrc, paused: window.art.video.paused, readyState: window.art.video.readyState }))
|
||||
window.art.video.addEventListener(name, () => window.chapterMediaEvents.push({ name, at: performance.now(), time: window.art.currentTime, source: window.art.video.currentSrc, paused: window.art.video.paused, readyState: window.art.video.readyState }))
|
||||
document.querySelector('#play').onclick = () => window.art.play()
|
||||
document.querySelector('#pause').onclick = () => window.art.pause()
|
||||
})
|
||||
@@ -62,8 +62,30 @@ async function hoverChapter(page, percentage, text) {
|
||||
return { box, x, layout }
|
||||
}
|
||||
|
||||
async function waitForChapterRestart(page, testInfo) {
|
||||
const calls = []
|
||||
try {
|
||||
await expect.poll(async () => {
|
||||
const started = Date.now()
|
||||
const state = await page.evaluate(() => ({
|
||||
at: performance.now(),
|
||||
timeOrigin: performance.timeOrigin,
|
||||
events: window.chapterEvents.filter(event => event.name === 'restart').map(event => event.value),
|
||||
}))
|
||||
calls.push({ started, elapsed: Date.now() - started, ...state })
|
||||
return state.events
|
||||
}).toEqual(['/test/pattern.mp4?quality=A'])
|
||||
}
|
||||
finally {
|
||||
await testInfo.attach('chapter-restart-observations', { contentType: 'application/json', body: JSON.stringify(calls) })
|
||||
}
|
||||
}
|
||||
|
||||
test.afterEach(async ({ page }, testInfo) => {
|
||||
const state = await page.evaluate(() => ({
|
||||
at: performance.now(),
|
||||
timeOrigin: performance.timeOrigin,
|
||||
qualitySelectedAt: window.chapterQualitySelectedAt,
|
||||
events: window.chapterEvents,
|
||||
nativeEvents: window.chapterMediaEvents,
|
||||
time: window.art?.currentTime,
|
||||
@@ -121,9 +143,10 @@ for (const core of ['published', 'candidate']) {
|
||||
expect(await page.locator('.art-chapter .art-progress-played').evaluateAll(nodes => [nodes[0].style.width, nodes[2].style.width])).toEqual(['100%', '0px'])
|
||||
await page.locator('.art-control-quality').hover()
|
||||
await expect(page.locator('.art-control-quality .art-selector-list')).toHaveCSS('opacity', '1')
|
||||
await page.evaluate(() => window.chapterQualitySelectedAt = performance.now())
|
||||
await page.locator('.art-control-quality .art-selector-item').filter({ hasText: 'Quality A' }).click()
|
||||
await expect.poll(() => page.evaluate(() => window.art.url.includes('quality=A'))).toBe(true)
|
||||
await expect.poll(() => page.evaluate(() => window.chapterEvents.filter(event => event.name === 'restart').map(event => event.value))).toEqual(['/test/pattern.mp4?quality=A'])
|
||||
await waitForChapterRestart(page, testInfo)
|
||||
await expect.poll(() => page.evaluate(() => !window.art.video.seeking && window.art.video.readyState >= 2)).toBe(true)
|
||||
const restoredTime = await page.evaluate(() => window.art.currentTime)
|
||||
const historicalReset = core === 'published' && browserName === 'webkit'
|
||||
|
||||
Reference in new issue
Block a user