Verify six app seams and record Phase 4 performance measurements

This commit is contained in:
Jonathan Sykes
2026-10-08 05:03:55 +08:00
parent 2c5003575c
commit a7473cbca2
15 changed files with 4263 additions and 12 deletions

View File

@@ -271,3 +271,43 @@ Legacy pages cannot report their selected layout. Their one-time migration block
all layouts to preserve immediate offline selection; modern pages block only the
reported layout and its shared controls. Executing groups never re-evaluate live.
See plans/phase3-staged-apply-decision.md: Phase 4 must add disposal/state handoff.
## Phase 4 seams and verification
The dependency inventory in `plans/phase4-seams.md` records Phase 3 declarations,
resolved outside references and byte/coupling rankings. Reproduce its source using
`npm install --prefix perf/.tmp/analysis --no-audit --no-fund acorn@8 eslint-scope@8`
and `node perf/analyze-app.cjs cd4a25a` (development scratch dependencies only).
Shell/shared view/Settings/section-rail definitions remain eager before app.js.
Presenter, Remote client, Watch party, Share/External and Stats view register
classic singletons on `window.YT`; synchronous playback hooks remain facades.
Executing chunks remain pinned: disposal/state handoff is still required before
any live replacement can be enabled.
```bash
node --test frontend/*.test.js
(cd server && bun install && bun run test)
node perf/hidden-timers.mjs
node perf/seams.mjs --browser all
node perf/lazy.mjs --browser all
node perf/migration.mjs --browser all --profile lossy \
--out perf/results/phase4-migration-lossy-2026-10-08.json
node perf/migration.mjs --browser all --profile unthrottled \
--out perf/results/phase4-migration-unthrottled-2026-10-08.json
node perf/baseline.mjs --runs 1 --browser all --profile lte --scenario all \
--out perf/results/phase4-final-2026-10-08.json \
--compare perf/results/after-phase0-2026-10-07.json
node perf/baseline.mjs --runs 3 --browser chromium --profile lte --scenario cold \
--out perf/results/phase4-cold-isolated-2026-10-08.json
```
`update-feature` appends one comment to presenter.js in scratch, installs the worker,
explicitly activates, then waits for the changed background chunk to be verified
in CacheStorage. It asserts that no other application JS/CSS/font/icon payload
transfers; derived index/manifest and worker script checks are included in totals.
`all` includes this scenario when the source contains presenter.js. Cold records
now include individual long-task timing without changing the aggregate metric,
plus the source frontend build tag. WebKit does not expose the long-task API.
Migration supports `--out` to preserve earlier phase evidence. Existing lazy
harness results are copied to `phase4-lazy-2026-10-08.json` after each Phase 4 run
and the Phase 3 result is restored. No production requests or deploys are needed.

View File

@@ -1,11 +1,14 @@
const fs=require('fs'), acorn=require('./.tmp/analysis/node_modules/acorn'), scope=require('./.tmp/analysis/node_modules/eslint-scope');
const src=fs.readFileSync('frontend/app.js','utf8');
const {execFileSync}=require('node:child_process');
const commit=process.argv[2];
const read=file=>commit?execFileSync('git',['show',commit+':'+file],{encoding:'utf8',maxBuffer:2000000}):fs.readFileSync(file,'utf8');
const src=read('frontend/app.js');
function parse(s){return acorn.parse(s,{ecmaVersion:2024,sourceType:'script',locations:true,ranges:true});}
const ast=parse(src), mgr=scope.analyze(ast,{ecmaVersion:2024,sourceType:'script',optimistic:true,ignoreEval:true});
const vars=mgr.globalScope.variables, names=new Set(vars.map(v=>v.name));
const rows=vars.map(v=>{const decl=v.defs[0].parent||v.defs[0].node;const stmt=ast.body.find(n=>n.start<=decl.start&&n.end>=decl.end);return {name:v.name,start:stmt.start,end:stmt.end,line:stmt.loc.start.line,bytes:Buffer.byteLength(src.slice(stmt.start,stmt.end)),outside:v.references.filter(r=>r.identifier.start<stmt.start||r.identifier.start>=stmt.end).map(r=>r.identifier.loc.start.line),imports:[]};});
for(const row of rows){const deps=new Set();for(const v of vars)if(v.name!==row.name&&v.references.some(r=>r.identifier.start>=row.start&&r.identifier.start<row.end))deps.add(v.name);row.imports=[...deps];}
for(const file of fs.readdirSync('frontend').filter(f=>f.endsWith('.js')&&!f.endsWith('.test.js')&&f!=='app.js')){try{const other=scope.analyze(parse(fs.readFileSync('frontend/'+file,'utf8')),{ecmaVersion:2024,sourceType:'script',optimistic:true,ignoreEval:true});for(const r of other.globalScope.through){if(names.has(r.identifier.name))rows.find(x=>x.name===r.identifier.name).outside.push(file+':'+r.identifier.loc.start.line);}}catch(e){if(!file.includes('entry'))console.error(file,e.message);}}
for(const file of (commit?execFileSync('git',['ls-tree','--name-only',commit+':frontend'],{encoding:'utf8'}).trim().split('\n'):fs.readdirSync('frontend')).filter(f=>f.endsWith('.js')&&!f.endsWith('.test.js')&&f!=='app.js')){try{const other=scope.analyze(parse(read('frontend/'+file)),{ecmaVersion:2024,sourceType:'script',optimistic:true,ignoreEval:true});for(const r of other.globalScope.through){if(names.has(r.identifier.name))rows.find(x=>x.name===r.identifier.name).outside.push(file+':'+r.identifier.loc.start.line);}}catch(e){if(!file.includes('entry'))console.error(file,e.message);}}
fs.writeFileSync('perf/.tmp/analysis/declarations.json',JSON.stringify(rows,null,2));
const candidates={shell:['Recommendations','renderSidebar','renderHomePlaylists','updateHomeGridScrollState','updateBottomChrome','setHomeOverPlayer','showMiniBar','updateMiniBar','hideMiniBar','setTile','updateNowPlayingActions','renderSmartSidebar'],presenter:['Presenter'],remote:['Remote'],party:['Party'],share:['Share','External'],stats:['renderStats'],notes:['Notes'],settings:['renderSettings'],service:['ServiceVisual','enterServiceMode','exitServiceMode'],editor:['openVideoEditor'],export:['exportToDevice'],sectionRail:['SectionRail'],gestures:['Gestures']};
const summary=Object.entries(candidates).map(([name,list])=>{const chosen=rows.filter(r=>list.includes(r.name));const coupling=new Set(chosen.flatMap(r=>r.imports).filter(n=>!list.includes(n)));return {name,bytes:chosen.reduce((s,r)=>s+r.bytes,0),coupling:coupling.size,ratio:Math.round(chosen.reduce((s,r)=>s+r.bytes,0)/Math.max(1,coupling.size)),imports:[...coupling],outside:chosen.flatMap(r=>r.outside),list};}).sort((a,b)=>b.ratio-a.ratio);fs.writeFileSync('perf/.tmp/analysis/candidates.json',JSON.stringify(summary,null,2));console.log(summary.map(r=>[r.name,r.bytes,r.coupling,r.ratio].join(' ')).join('\n'));

View File

@@ -25,6 +25,8 @@
* --compare <json-path> Compare results against a previous baseline JSON
*/
import assert from 'node:assert/strict';
import { createHash } from 'node:crypto';
import { spawn, spawnSync, execFileSync } from 'node:child_process';
import { existsSync, mkdirSync, rmSync, cpSync, appendFileSync, statSync, writeFileSync, readFileSync, symlinkSync, unlinkSync } from 'node:fs';
import path from 'node:path';
@@ -244,6 +246,7 @@ async function setupPageMetrics(page) {
window.__fcp = null;
window.__lcp = null;
window.__longTasksTotal = 0;
window.__longTasks = [];
// Observe boot completion landmark (#cards view set by renderList())
const markBoot = () => {
@@ -263,6 +266,7 @@ async function setupPageMetrics(page) {
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
window.__longTasksTotal += entry.duration;
window.__longTasks.push({start:Math.round(entry.startTime),duration:Math.round(entry.duration)});
}
}).observe({ type: 'longtask', buffered: true });
} catch {}
@@ -374,6 +378,7 @@ async function runColdScenario({ browserType, server, proxy, profile }) {
domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null,
bootDone: window.__bootDone ? Math.round(window.__bootDone) : null,
longTaskTotal: Math.round(window.__longTasksTotal || 0),
longTasks: window.__longTasks || [],
};
});
@@ -396,6 +401,7 @@ async function runColdScenario({ browserType, server, proxy, profile }) {
domContentLoaded: pageMetrics.domContentLoaded,
bootDone: pageMetrics.bootDone,
longTaskTotal: pageMetrics.longTaskTotal,
longTasks: pageMetrics.longTasks,
requests: stats.requests,
initialJsCss: pageMetrics.initialJsCss,
initialAssetRequests: pageMetrics.initialAssetRequests,
@@ -478,6 +484,7 @@ async function runWarmScenario({ browserType, server, proxy, profile }) {
domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null,
bootDone: window.__bootDone ? Math.round(window.__bootDone) : null,
longTaskTotal: Math.round(window.__longTasksTotal || 0),
longTasks: window.__longTasks || [],
};
});
@@ -492,6 +499,7 @@ async function runWarmScenario({ browserType, server, proxy, profile }) {
domContentLoaded: pageMetrics.domContentLoaded,
bootDone: pageMetrics.bootDone,
longTaskTotal: pageMetrics.longTaskTotal,
longTasks: pageMetrics.longTasks,
};
}
@@ -634,7 +642,7 @@ async function runUpdateScenario({ browserType, server, proxy, profile, updateKi
}
// Switch server to Tree N+1 (app.js or theme-glass.css modification)
const targetTree = updateKind === 'js' ? trees.treeUpdateJs : trees.treeUpdateCss;
const targetTree = updateKind === 'feature' ? trees.treeUpdateFeature : updateKind === 'js' ? trees.treeUpdateJs : trees.treeUpdateCss;
await server.restartWithPublic(targetTree);
// Measure wire bytes and duration from reg.update() until new SW is waiting/installed
@@ -654,10 +662,32 @@ async function runUpdateScenario({ browserType, server, proxy, profile, updateKi
await sleep(50);
}
if (updateKind === 'feature') {
// Readiness excludes background chunks. Include activation and the changed
// feature's actual idle transfer rather than reporting readiness as its cost.
const expected = createHash('sha256').update(readFileSync(path.join(targetTree,'presenter.js'))).digest('hex').slice(0,10);
await page.evaluate(async()=>{const r=await navigator.serviceWorker.getRegistration();r.waiting.postMessage({type:'SKIP_WAITING'});});
const end=Date.now()+90000;
while(true) {
const complete=await page.evaluate(async h=>{
const r=await navigator.serviceWorker.getRegistration();
if(r.waiting || r.installing)return false;
r.active?.postMessage({type:'WARM_ASSETS',saveData:false});
const c=await caches.open('ytplayer-assets'),entry=await c.match('/presenter.js?v='+h);
return entry?.headers.get('X-Asset-Hash')===h;
},expected);
if(complete)break;
if(Date.now()>end)throw Error('Changed feature was not cached after activation');
await sleep(100);
}
}
const duration = Date.now() - t0;
proxy.stopTracking();
const stats = proxy.getStats();
if(updateKind==='feature') {
const assetDownloads=stats.requests.filter(r=>r.bytes>0).map(r=>new URL(r.url,navUrl).pathname).filter(p=>/\.(?:js|css|woff2?|png|svg)$/.test(p)&&!['/sw.js','/asset-sync-core.js'].includes(p));
assert.deepEqual([...new Set(assetDownloads)],['/presenter.js'],'feature edit transfers only its chunk; no app/core/font/icon payload');
}
await browser.close();
return {
@@ -696,6 +726,7 @@ async function main() {
const treeBase = path.join(tmpRoot, 'tree-base');
const treeUpdateJs = path.join(tmpRoot, 'tree-update-js');
const treeUpdateCss = path.join(tmpRoot, 'tree-update-css');
const treeUpdateFeature = path.join(tmpRoot, 'tree-update-feature');
let frontendSource=path.join(REPO_ROOT,'frontend');
if(options.frontendCommit) {
@@ -704,14 +735,15 @@ async function main() {
execFileSync('tar',['-xf',archive,'-C',tmpRoot]);
frontendSource=path.join(tmpRoot,'frontend');
}
for(const tree of [treeBase,treeUpdateJs,treeUpdateCss])cpSync(frontendSource,tree,{recursive:true});
for(const tree of [treeBase,treeUpdateJs,treeUpdateCss,treeUpdateFeature])cpSync(frontendSource,tree,{recursive:true});
// Append 1 comment line to app.js in treeUpdateJs
appendFileSync(path.join(treeUpdateJs, 'app.js'), '\n// baseline bench: 1-line app.js comment\n');
// Append 1 rule to theme-glass.css in treeUpdateCss
appendFileSync(path.join(treeUpdateCss, 'theme-glass.css'), '\n/* baseline bench: 1-line css rule */\n.baseline-marker { opacity: 0.99; }\n');
const trees = { treeBase, treeUpdateJs, treeUpdateCss };
if(existsSync(path.join(treeUpdateFeature,'presenter.js')))appendFileSync(path.join(treeUpdateFeature,'presenter.js'),'\n// baseline bench: 1-line presenter chunk comment\n');
const trees = { treeBase, treeUpdateJs, treeUpdateCss, treeUpdateFeature };
const serverScratch = path.join(tmpRoot, 'server-run');
const server = new ServerManager(serverScratch, treeBase);
@@ -721,6 +753,7 @@ async function main() {
const results = {
date: new Date().toISOString(),
frontendCommit: options.frontendCommit,
frontendBuildTag: (await (await fetch('http://127.0.0.1:'+server.port+'/api/version')).json()).buildTag,
commit: spawnSync('git', ['rev-parse', 'HEAD'], { cwd: REPO_ROOT }).stdout.toString().trim(),
runsConfigured: options.runs,
browsers: {},
@@ -759,6 +792,7 @@ async function main() {
domContentLoaded: summarizeList(coldRuns.map((r) => r.domContentLoaded)),
bootDone: summarizeList(coldRuns.map((r) => r.bootDone)),
longTaskTotal: summarizeList(coldRuns.map((r) => r.longTaskTotal)),
longTasks: coldRuns.map(r=>r.longTasks),
swInstallDuration: summarizeList(coldRuns.map((r) => r.swInstallDuration)),
swInstallBytes: summarizeList(coldRuns.map((r) => r.swInstallBytes)),
storageEstimate: coldRuns[0]?.storageEstimate || null,
@@ -869,6 +903,16 @@ async function main() {
};
}
if ((options.scenario === 'all' || options.scenario === 'update-feature') && existsSync(path.join(treeBase,'presenter.js'))) {
console.log(` [Scenario: Update split-out presenter, including idle cache fill] running ${options.runs} iterations...`);
const runs=[];
for(let r=0;r<options.runs;r++) {
const res=await runUpdateScenario({browserType:bType,server,proxy,profile:prof,updateKind:'feature',trees});runs.push(res);
console.log(` run ${r+1}/${options.runs}: ${res.wireBytes} bytes, ${res.requestCount} reqs, dur=${res.duration}ms`);
}
results.browsers[bName][prof].updateFeature={requestCount:summarizeList(runs.map(r=>r.requestCount)),wireBytes:summarizeList(runs.map(r=>r.wireBytes)),duration:summarizeList(runs.map(r=>r.duration)),wireBytesByType:runs[0]?.wireBytesByType||{},requests:runs[0]?.requests||[]};
}
await proxy.close();
}
}

View File

@@ -234,5 +234,5 @@ async function run(name) {
try {
const results = [];
for (const name of browserName === 'all' ? ['chromium', 'webkit'] : [browserName]) results.push(await run(name));
writeFileSync(join(repo, `perf/results/phase3-migration-${profile}-2026-10-08.json`), JSON.stringify({ commit, results }, null, 2) + '\n');
writeFileSync(args.includes('--out') ? resolve(args[args.indexOf('--out')+1]) : join(repo, `perf/results/phase3-migration-${profile}-2026-10-08.json`), JSON.stringify({ commit, results }, null, 2) + '\n');
} finally { rmSync(scratch, { recursive: true, force: true }); }

View File

@@ -0,0 +1,931 @@
{
"date": "2026-10-07T20:55:14.741Z",
"frontendCommit": null,
"frontendBuildTag": "c3dbdd7039db",
"commit": "2c5003575c641fddb128c6d1d14bb5d1e3999efb",
"runsConfigured": 3,
"browsers": {
"chromium": {
"lte": {
"cold": {
"requestCount": {
"median": 115,
"min": 115,
"max": 115,
"values": [
115,
115,
115
]
},
"wireBytes": {
"median": 651012,
"min": 651012,
"max": 651012,
"values": [
651012,
651012,
651012
]
},
"fcp": {
"median": 1352,
"min": 1352,
"max": 1384,
"values": [
1384,
1352,
1352
]
},
"lcp": {
"median": 1352,
"min": 1352,
"max": 1384,
"values": [
1384,
1352,
1352
]
},
"domContentLoaded": {
"median": 6992,
"min": 6973,
"max": 7373,
"values": [
7373,
6992,
6973
]
},
"bootDone": {
"median": 7010,
"min": 6989,
"max": 7389,
"values": [
7389,
7010,
6989
]
},
"longTaskTotal": {
"median": 275,
"min": 274,
"max": 297,
"values": [
297,
274,
275
]
},
"longTasks": [
[
{
"start": 1232,
"duration": 135
},
{
"start": 7216,
"duration": 162
}
],
[
{
"start": 1223,
"duration": 109
},
{
"start": 6834,
"duration": 165
}
],
[
{
"start": 1225,
"duration": 111
},
{
"start": 6814,
"duration": 164
}
]
],
"swInstallDuration": {
"median": 36619,
"min": 36567,
"max": 36956,
"values": [
36956,
36567,
36619
]
},
"swInstallBytes": {
"median": 651012,
"min": 651012,
"max": 651012,
"values": [
651012,
651012,
651012
]
},
"storageEstimate": {
"usage": 2801669,
"quota": 5371510789
},
"mediaReady": {
"median": null,
"min": null,
"max": null,
"values": [
null,
null,
null
]
},
"autoplayBlocked": true,
"wireBytesByType": {
"html": 22882,
"js": 296653,
"css": 65916,
"fonts": 254048,
"images": 6278,
"media": 0,
"api": 4604,
"other": 631
},
"requests": [
{
"url": "http://127.0.0.1:6199/?v=benchmedia01",
"status": 200,
"bytes": 11441
},
{
"url": "http://127.0.0.1:6199/fonts/HankenGrotesk-latin.woff2",
"status": 200,
"bytes": 34704
},
{
"url": "http://127.0.0.1:6199/fonts/BricolageGrotesque-latin.woff2",
"status": 200,
"bytes": 76888
},
{
"url": "http://127.0.0.1:6199/lazy.js?v=99caff8ebd",
"status": 200,
"bytes": 2543
},
{
"url": "http://127.0.0.1:6199/theme-classic.css?v=d420fcfb12",
"status": 200,
"bytes": 3529
},
{
"url": "http://127.0.0.1:6199/fonts/fonts.css?v=dda3dfb804",
"status": 200,
"bytes": 391
},
{
"url": "http://127.0.0.1:6199/styles.css?v=9f3a5dea41",
"status": 200,
"bytes": 27364
},
{
"url": "http://127.0.0.1:6199/service-ui.css?v=b9bf96a3a8",
"status": 200,
"bytes": 3736
},
{
"url": "http://127.0.0.1:6199/refresh.css?v=62498384f1",
"status": 200,
"bytes": 5027
},
{
"url": "http://127.0.0.1:6199/layout-base.css?v=4f3307cd3b",
"status": 200,
"bytes": 278
},
{
"url": "http://127.0.0.1:6199/recommendations.css?v=055101368d",
"status": 200,
"bytes": 790
},
{
"url": "http://127.0.0.1:6199/settings-sections.css?v=055507ab85",
"status": 200,
"bytes": 873
},
{
"url": "http://127.0.0.1:6199/offline-pages.css?v=2889456261",
"status": 200,
"bytes": 859
},
{
"url": "http://127.0.0.1:6199/saved-page.css?v=3ff576a784",
"status": 200,
"bytes": 537
},
{
"url": "http://127.0.0.1:6199/fullscreen-orientation.css?v=91f2d84453",
"status": 200,
"bytes": 1415
},
{
"url": "http://127.0.0.1:6199/related-videos.css?v=5a616b1be8",
"status": 200,
"bytes": 404
},
{
"url": "http://127.0.0.1:6199/download-actions.css?v=12d3bcfe3e",
"status": 200,
"bytes": 430
},
{
"url": "http://127.0.0.1:6199/fingerprint.js?v=a635143269",
"status": 200,
"bytes": 1034
},
{
"url": "http://127.0.0.1:6199/opfs.js?v=df7a8d0391",
"status": 200,
"bytes": 3920
},
{
"url": "http://127.0.0.1:6199/lyrics-core.js?v=4dcdac2edd",
"status": 200,
"bytes": 2632
},
{
"url": "http://127.0.0.1:6199/lyrics-display.js?v=48e8550175",
"status": 200,
"bytes": 571
},
{
"url": "http://127.0.0.1:6199/flag-ui.js?v=eeae1c1d1a",
"status": 200,
"bytes": 2036
},
{
"url": "http://127.0.0.1:6199/sha256-wasm.js?v=393c50ba56",
"status": 200,
"bytes": 1521
},
{
"url": "http://127.0.0.1:6199/sha256.js?v=cd9b980e6f",
"status": 200,
"bytes": 2733
},
{
"url": "http://127.0.0.1:6199/loudness-wasm.js?v=c6102d7844",
"status": 200,
"bytes": 1130
},
{
"url": "http://127.0.0.1:6199/loudness.js?v=01b3da88dd",
"status": 200,
"bytes": 1818
},
{
"url": "http://127.0.0.1:6199/device-db.js?v=880c5cd70e",
"status": 200,
"bytes": 1050
},
{
"url": "http://127.0.0.1:6199/async-guard.js?v=e4afa1f2be",
"status": 200,
"bytes": 725
},
{
"url": "http://127.0.0.1:6199/asset-sync-core.js?v=155be9339b",
"status": 200,
"bytes": 1690
},
{
"url": "http://127.0.0.1:6199/sw-update.js?v=772c123c20",
"status": 200,
"bytes": 4411
},
{
"url": "http://127.0.0.1:6199/related-videos.js?v=3eec0ebd4c",
"status": 200,
"bytes": 545
},
{
"url": "http://127.0.0.1:6199/audio-continuity.js?v=63b5464dd5",
"status": 200,
"bytes": 583
},
{
"url": "http://127.0.0.1:6199/fullscreen-orientation.js?v=c8e44eb66b",
"status": 200,
"bytes": 2494
},
{
"url": "http://127.0.0.1:6199/settings-sections.js?v=1101425859",
"status": 200,
"bytes": 2690
},
{
"url": "http://127.0.0.1:6199/download-actions.js?v=388c7edecb",
"status": 200,
"bytes": 550
},
{
"url": "http://127.0.0.1:6199/download-errors.js?v=bb6a4c887a",
"status": 200,
"bytes": 727
},
{
"url": "http://127.0.0.1:6199/downloads.js?v=f2d3e7d212",
"status": 200,
"bytes": 1764
},
{
"url": "http://127.0.0.1:6199/downloads-page.js?v=c1a3a218c0",
"status": 200,
"bytes": 3103
},
{
"url": "http://127.0.0.1:6199/saved-page.js?v=f1518c50fb",
"status": 200,
"bytes": 652
},
{
"url": "http://127.0.0.1:6199/server-backfill.js?v=294b103023",
"status": 200,
"bytes": 918
},
{
"url": "http://127.0.0.1:6199/visible-timer.js?v=5322e86ef4",
"status": 200,
"bytes": 380
},
{
"url": "http://127.0.0.1:6199/prewarm-next.js?v=ed16a51424",
"status": 200,
"bytes": 567
},
{
"url": "http://127.0.0.1:6199/eq-parameters.js?v=dc2c6a8e8d",
"status": 200,
"bytes": 722
},
{
"url": "http://127.0.0.1:6199/feature-bootstrap.js?v=33779ecef7",
"status": 200,
"bytes": 2056
},
{
"url": "http://127.0.0.1:6199/shell-core.js?v=a04305c2ad",
"status": 200,
"bytes": 3882
},
{
"url": "http://127.0.0.1:6199/views-core.js?v=49be16274c",
"status": 200,
"bytes": 16310
},
{
"url": "http://127.0.0.1:6199/section-rail.js?v=07417c1bcc",
"status": 200,
"bytes": 3552
},
{
"url": "http://127.0.0.1:6199/app.js?v=f485286cbc",
"status": 200,
"bytes": 95477
},
{
"url": "http://127.0.0.1:6199/api/recommendations?fp=c83c12c79b483c87",
"status": 200,
"bytes": 24
},
{
"url": "http://127.0.0.1:6199/api/version",
"status": 200,
"bytes": 62
},
{
"url": "http://127.0.0.1:6199/sw.js",
"status": 200,
"bytes": 7766
},
{
"url": "http://127.0.0.1:6199/api/user/sync",
"status": 200,
"bytes": 11
},
{
"url": "http://127.0.0.1:6199/asset-sync-core.js?v=155be9339b",
"status": 304,
"bytes": 0
},
{
"url": "http://127.0.0.1:6199/api/manifest",
"status": 200,
"bytes": 3210
},
{
"url": "http://127.0.0.1:6199/assets.json?v=6f517e2aa4",
"status": 200,
"bytes": 1058
},
{
"url": "http://127.0.0.1:6199/fonts/BricolageGrotesque-latin-ext.woff2",
"status": 200,
"bytes": 30736
},
{
"url": "http://127.0.0.1:6199/fonts/HankenGrotesk-latin-ext.woff2",
"status": 200,
"bytes": 19588
},
{
"url": "http://127.0.0.1:6199/fonts/JetBrainsMono-latin-ext.woff2",
"status": 200,
"bytes": 11624
},
{
"url": "http://127.0.0.1:6199/fonts/JetBrainsMono-latin.woff2",
"status": 200,
"bytes": 31432
},
{
"url": "http://127.0.0.1:6199/fonts/fonts.css",
"status": 200,
"bytes": 391
},
{
"url": "http://127.0.0.1:6199/icons/icon-192.png",
"status": 200,
"bytes": 1669
},
{
"url": "http://127.0.0.1:6199/icons/icon-512.png",
"status": 200,
"bytes": 4609
},
{
"url": "http://127.0.0.1:6199/index.html?v=b556b50667",
"status": 200,
"bytes": 11441
},
{
"url": "http://127.0.0.1:6199/manifest.webmanifest",
"status": 200,
"bytes": 631
},
{
"url": "http://127.0.0.1:6199/opfs-worker.js?v=17cfe8fb26",
"status": 200,
"bytes": 3487
},
{
"url": "http://127.0.0.1:6199/api/recommendations?fp=c83c12c79b483c87",
"status": 200,
"bytes": 24
},
{
"url": "http://127.0.0.1:6199/resume-core.js?v=df42e94600",
"status": 200,
"bytes": 762
},
{
"url": "http://127.0.0.1:6199/sw.js",
"status": 200,
"bytes": 7766
},
{
"url": "http://127.0.0.1:6199/asset-sync-core.js?v=155be9339b",
"status": 304,
"bytes": 0
},
{
"url": "http://127.0.0.1:6199/bento-hub.js?v=c867882d7e",
"status": 200,
"bytes": 1294
},
{
"url": "http://127.0.0.1:6199/car-mode.css?v=7d421630b3",
"status": 200,
"bytes": 385
},
{
"url": "http://127.0.0.1:6199/car-mode.js?v=ebd6588f35",
"status": 200,
"bytes": 1727
},
{
"url": "http://127.0.0.1:6199/direct-media.css?v=19b8428bfd",
"status": 200,
"bytes": 291
},
{
"url": "http://127.0.0.1:6199/direct-media.js?v=035420e8fb",
"status": 200,
"bytes": 3697
},
{
"url": "http://127.0.0.1:6199/direct-protocol.js?v=87a73be90f",
"status": 200,
"bytes": 1079
},
{
"url": "http://127.0.0.1:6199/eq-core.js?v=cb6d079933",
"status": 200,
"bytes": 875
},
{
"url": "http://127.0.0.1:6199/direct-recv-worker.js?v=caa45eb981",
"status": 200,
"bytes": 1050
},
{
"url": "http://127.0.0.1:6199/direct-stream.js?v=d7f9871605",
"status": 200,
"bytes": 1249
},
{
"url": "http://127.0.0.1:6199/f7-layout.js?v=fe7e94a4a9",
"status": 200,
"bytes": 4158
},
{
"url": "http://127.0.0.1:6199/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80",
"status": 200,
"bytes": 21728
},
{
"url": "http://127.0.0.1:6199/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70",
"status": 200,
"bytes": 27348
},
{
"url": "http://127.0.0.1:6199/export.js?v=5b7cdcd7a3",
"status": 200,
"bytes": 1305
},
{
"url": "http://127.0.0.1:6199/glass-controls.js?v=a60ed1fe84",
"status": 200,
"bytes": 2763
},
{
"url": "http://127.0.0.1:6199/glass-panel-layout.js?v=d5417786d0",
"status": 200,
"bytes": 965
},
{
"url": "http://127.0.0.1:6199/hash-worker.js?v=5cccc78057",
"status": 200,
"bytes": 542
},
{
"url": "http://127.0.0.1:6199/lower-third.css?v=031f8e0ead",
"status": 200,
"bytes": 375
},
{
"url": "http://127.0.0.1:6199/lower-third.js?v=7705dcbfb4",
"status": 200,
"bytes": 927
},
{
"url": "http://127.0.0.1:6199/lyrics-window.js?v=8f333e2442",
"status": 200,
"bytes": 2048
},
{
"url": "http://127.0.0.1:6199/p2p-transfer.js?v=e508302618",
"status": 200,
"bytes": 2431
},
{
"url": "http://127.0.0.1:6199/p2p-core.js?v=168a879219",
"status": 200,
"bytes": 989
},
{
"url": "http://127.0.0.1:6199/p2p-recv-worker.js?v=9d435c6cbb",
"status": 200,
"bytes": 1267
},
{
"url": "http://127.0.0.1:6199/midi.js?v=dbecfa74e1",
"status": 200,
"bytes": 1713
},
{
"url": "http://127.0.0.1:6199/p2p-client.js?v=74fbd79661",
"status": 200,
"bytes": 3850
},
{
"url": "http://127.0.0.1:6199/piano-engine.mjs?v=2d2f29b38e",
"status": 200,
"bytes": 2580
},
{
"url": "http://127.0.0.1:6199/piano-core.js?v=77c8269761",
"status": 200,
"bytes": 756
},
{
"url": "http://127.0.0.1:6199/piano.js?v=e82bc30884",
"status": 200,
"bytes": 3453
},
{
"url": "http://127.0.0.1:6199/presenter.js?v=e5b34ff758",
"status": 200,
"bytes": 3094
},
{
"url": "http://127.0.0.1:6199/party-dj.js?v=1677c38a88",
"status": 200,
"bytes": 1184
},
{
"url": "http://127.0.0.1:6199/remote-client.js?v=a2b5acb20f",
"status": 200,
"bytes": 7926
},
{
"url": "http://127.0.0.1:6199/setlist-import.js?v=13bc5cc4a4",
"status": 200,
"bytes": 2462
},
{
"url": "http://127.0.0.1:6199/stats-core.js?v=3de0591d83",
"status": 200,
"bytes": 2336
},
{
"url": "http://127.0.0.1:6199/share-external.js?v=9de67de710",
"status": 200,
"bytes": 3653
},
{
"url": "http://127.0.0.1:6199/theme-f7.css?v=02ba226f82",
"status": 200,
"bytes": 4727
},
{
"url": "http://127.0.0.1:6199/theme-glass-controls.css?v=3354ad9631",
"status": 200,
"bytes": 1480
},
{
"url": "http://127.0.0.1:6199/theme-glass-panel.css?v=25aadb0bb7",
"status": 200,
"bytes": 848
},
{
"url": "http://127.0.0.1:6199/stats-view.js?v=beb2343b30",
"status": 200,
"bytes": 2294
},
{
"url": "http://127.0.0.1:6199/theme-bento-hub.css?v=f529dc4bb7",
"status": 200,
"bytes": 6718
},
{
"url": "http://127.0.0.1:6199/vendor/framework7-swipe.min.js?v=22b954749c",
"status": 200,
"bytes": 38592
},
{
"url": "http://127.0.0.1:6199/vocal-reducer.js?v=ddb2fc1bbe",
"status": 200,
"bytes": 1146
},
{
"url": "http://127.0.0.1:6199/video-edit.js?v=90c5dd1eb6",
"status": 200,
"bytes": 2168
},
{
"url": "http://127.0.0.1:6199/watch-party-client.js?v=0210655848",
"status": 200,
"bytes": 6513
},
{
"url": "http://127.0.0.1:6199/theme-glass.css?v=09feb15c53",
"status": 200,
"bytes": 5068
},
{
"url": "http://127.0.0.1:6199/api/p2p/config",
"status": 200,
"bytes": 40
},
{
"url": "http://127.0.0.1:6199/api/p2p/device",
"status": 200,
"bytes": 121
},
{
"url": "http://127.0.0.1:6199/api/p2p/holdings",
"status": 200,
"bytes": 54
}
],
"initialJsCss": {
"median": 210419,
"min": 210419,
"max": 210419,
"values": [
210419,
210419,
210419
]
},
"initialAssetRequests": [
{
"url": "http://127.0.0.1:6199/lazy.js?v=99caff8ebd",
"bytes": 2543
},
{
"url": "http://127.0.0.1:6199/theme-classic.css?v=d420fcfb12",
"bytes": 3529
},
{
"url": "http://127.0.0.1:6199/fonts/fonts.css?v=dda3dfb804",
"bytes": 391
},
{
"url": "http://127.0.0.1:6199/styles.css?v=9f3a5dea41",
"bytes": 27364
},
{
"url": "http://127.0.0.1:6199/service-ui.css?v=b9bf96a3a8",
"bytes": 3736
},
{
"url": "http://127.0.0.1:6199/refresh.css?v=62498384f1",
"bytes": 5027
},
{
"url": "http://127.0.0.1:6199/layout-base.css?v=4f3307cd3b",
"bytes": 278
},
{
"url": "http://127.0.0.1:6199/recommendations.css?v=055101368d",
"bytes": 790
},
{
"url": "http://127.0.0.1:6199/settings-sections.css?v=055507ab85",
"bytes": 873
},
{
"url": "http://127.0.0.1:6199/offline-pages.css?v=2889456261",
"bytes": 859
},
{
"url": "http://127.0.0.1:6199/saved-page.css?v=3ff576a784",
"bytes": 537
},
{
"url": "http://127.0.0.1:6199/fullscreen-orientation.css?v=91f2d84453",
"bytes": 1415
},
{
"url": "http://127.0.0.1:6199/related-videos.css?v=5a616b1be8",
"bytes": 404
},
{
"url": "http://127.0.0.1:6199/download-actions.css?v=12d3bcfe3e",
"bytes": 430
},
{
"url": "http://127.0.0.1:6199/fingerprint.js?v=a635143269",
"bytes": 1034
},
{
"url": "http://127.0.0.1:6199/opfs.js?v=df7a8d0391",
"bytes": 3920
},
{
"url": "http://127.0.0.1:6199/lyrics-core.js?v=4dcdac2edd",
"bytes": 2632
},
{
"url": "http://127.0.0.1:6199/lyrics-display.js?v=48e8550175",
"bytes": 571
},
{
"url": "http://127.0.0.1:6199/flag-ui.js?v=eeae1c1d1a",
"bytes": 2036
},
{
"url": "http://127.0.0.1:6199/sha256-wasm.js?v=393c50ba56",
"bytes": 1521
},
{
"url": "http://127.0.0.1:6199/sha256.js?v=cd9b980e6f",
"bytes": 2733
},
{
"url": "http://127.0.0.1:6199/loudness-wasm.js?v=c6102d7844",
"bytes": 1130
},
{
"url": "http://127.0.0.1:6199/loudness.js?v=01b3da88dd",
"bytes": 1818
},
{
"url": "http://127.0.0.1:6199/device-db.js?v=880c5cd70e",
"bytes": 1050
},
{
"url": "http://127.0.0.1:6199/async-guard.js?v=e4afa1f2be",
"bytes": 725
},
{
"url": "http://127.0.0.1:6199/asset-sync-core.js?v=155be9339b",
"bytes": 1690
},
{
"url": "http://127.0.0.1:6199/sw-update.js?v=772c123c20",
"bytes": 4411
},
{
"url": "http://127.0.0.1:6199/related-videos.js?v=3eec0ebd4c",
"bytes": 545
},
{
"url": "http://127.0.0.1:6199/audio-continuity.js?v=63b5464dd5",
"bytes": 583
},
{
"url": "http://127.0.0.1:6199/fullscreen-orientation.js?v=c8e44eb66b",
"bytes": 2494
},
{
"url": "http://127.0.0.1:6199/settings-sections.js?v=1101425859",
"bytes": 2690
},
{
"url": "http://127.0.0.1:6199/download-actions.js?v=388c7edecb",
"bytes": 550
},
{
"url": "http://127.0.0.1:6199/download-errors.js?v=bb6a4c887a",
"bytes": 727
},
{
"url": "http://127.0.0.1:6199/downloads.js?v=f2d3e7d212",
"bytes": 1764
},
{
"url": "http://127.0.0.1:6199/downloads-page.js?v=c1a3a218c0",
"bytes": 3103
},
{
"url": "http://127.0.0.1:6199/saved-page.js?v=f1518c50fb",
"bytes": 652
},
{
"url": "http://127.0.0.1:6199/server-backfill.js?v=294b103023",
"bytes": 918
},
{
"url": "http://127.0.0.1:6199/visible-timer.js?v=5322e86ef4",
"bytes": 380
},
{
"url": "http://127.0.0.1:6199/prewarm-next.js?v=ed16a51424",
"bytes": 567
},
{
"url": "http://127.0.0.1:6199/eq-parameters.js?v=dc2c6a8e8d",
"bytes": 722
},
{
"url": "http://127.0.0.1:6199/feature-bootstrap.js?v=33779ecef7",
"bytes": 2056
},
{
"url": "http://127.0.0.1:6199/shell-core.js?v=a04305c2ad",
"bytes": 3882
},
{
"url": "http://127.0.0.1:6199/views-core.js?v=49be16274c",
"bytes": 16310
},
{
"url": "http://127.0.0.1:6199/section-rail.js?v=07417c1bcc",
"bytes": 3552
},
{
"url": "http://127.0.0.1:6199/app.js?v=f485286cbc",
"bytes": 95477
}
]
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,133 @@
{
"date": "2026-10-07T21:00:01.096Z",
"frontendCommit": null,
"frontendBuildTag": "1146a2a9ceca",
"commit": "2c5003575c641fddb128c6d1d14bb5d1e3999efb",
"runsConfigured": 1,
"browsers": {
"chromium": {
"lte": {
"offline": {
"requestCount": {
"median": 0,
"min": 0,
"max": 0,
"values": [
0
]
},
"wireBytes": {
"median": 0,
"min": 0,
"max": 0,
"values": [
0
]
},
"fcp": {
"median": 48,
"min": 48,
"max": 48,
"values": [
48
]
},
"lcp": {
"median": 48,
"min": 48,
"max": 48,
"values": [
48
]
},
"domContentLoaded": {
"median": 152,
"min": 152,
"max": 152,
"values": [
152
]
},
"bootDone": {
"median": 156,
"min": 156,
"max": 156,
"values": [
156
]
},
"reloadDuration": {
"median": 173,
"min": 173,
"max": 173,
"values": [
173
]
}
}
}
},
"webkit": {
"lte": {
"offline": {
"requestCount": {
"median": 0,
"min": 0,
"max": 0,
"values": [
0
]
},
"wireBytes": {
"median": 0,
"min": 0,
"max": 0,
"values": [
0
]
},
"fcp": {
"median": 53,
"min": 53,
"max": 53,
"values": [
53
]
},
"lcp": {
"median": 81,
"min": 81,
"max": 81,
"values": [
81
]
},
"domContentLoaded": {
"median": 80,
"min": 80,
"max": 80,
"values": [
80
]
},
"bootDone": {
"median": 83,
"min": 83,
"max": 83,
"values": [
83
]
},
"reloadDuration": {
"median": 100,
"min": 100,
"max": 100,
"values": [
100
]
}
}
}
}
}
}

View File

@@ -0,0 +1,79 @@
{
"results": [
{
"browser": "chromium",
"sourceBuildTag": "09d1ee0f9c80",
"classicSharedDefaults": true,
"cssOrderPreserved": true,
"settingsSearch": true,
"carControls": 4,
"offlineFeature": true,
"firstUseNetwork": 0,
"layoutsOffline": [
"glass-stage",
"bento-hub",
"f7-swipe",
"classic"
],
"pinned": true,
"compatibleUnexecutedNewURL": true,
"incompatibleN1ReloadRequired": true,
"stagedN1": true,
"playbackGuard": true,
"prePaintLayout": true,
"offlineSettingsPanels": true,
"scriptErrors": [],
"offlineTransportErrors": []
},
{
"browser": "webkit",
"sourceBuildTag": "09d1ee0f9c80",
"classicSharedDefaults": true,
"cssOrderPreserved": true,
"settingsSearch": true,
"carControls": 4,
"offlineFeature": true,
"firstUseNetwork": 0,
"layoutsOffline": [
"glass-stage",
"bento-hub",
"f7-swipe",
"classic"
],
"pinned": true,
"compatibleUnexecutedNewURL": true,
"incompatibleN1ReloadRequired": true,
"stagedN1": true,
"playbackGuard": true,
"prePaintLayout": true,
"offlineSettingsPanels": true,
"scriptErrors": [],
"offlineTransportErrors": [
{
"message": "TypeError: Load failed",
"disconnected": true
},
{
"message": "/127.0.0.1:38295/api/version.",
"disconnected": true
},
{
"message": "TypeError: Load failed",
"disconnected": true
},
{
"message": "/127.0.0.1:38295/api/recommendations?fp=163577c02a53bc40.",
"disconnected": true
},
{
"message": "TypeError: Load failed",
"disconnected": true
},
{
"message": "/127.0.0.1:38295/api/version.",
"disconnected": true
}
]
}
]
}

View File

@@ -0,0 +1,41 @@
{
"commit": "b77938a",
"results": [
{
"browser": "chromium",
"oldTag": "1175f1a1d2c1",
"newTag": "c3dbdd7039db",
"banners": 1,
"updateReloads": 1,
"cachedFiles": 122,
"durationMs": 25699,
"wireBytes": 628797,
"offline": true,
"legacyURLs": 21,
"profile": "lossy",
"userInitiatedOnly": true,
"playbackGuard": true,
"evictionRepair": true,
"incrementalRefresh": true,
"offlineTransportErrors": 0
},
{
"browser": "webkit",
"oldTag": "1175f1a1d2c1",
"newTag": "c3dbdd7039db",
"banners": 1,
"updateReloads": 1,
"cachedFiles": 122,
"durationMs": 23376,
"wireBytes": 737972,
"offline": true,
"legacyURLs": 21,
"profile": "lossy",
"userInitiatedOnly": true,
"playbackGuard": true,
"evictionRepair": true,
"incrementalRefresh": true,
"offlineTransportErrors": 4
}
]
}

View File

@@ -0,0 +1,41 @@
{
"commit": "b77938a",
"results": [
{
"browser": "chromium",
"oldTag": "1175f1a1d2c1",
"newTag": "c3dbdd7039db",
"banners": 1,
"updateReloads": 1,
"cachedFiles": 122,
"durationMs": 9805,
"wireBytes": 646234,
"offline": true,
"legacyURLs": 21,
"profile": "unthrottled",
"userInitiatedOnly": true,
"playbackGuard": true,
"evictionRepair": true,
"incrementalRefresh": true,
"offlineTransportErrors": 0
},
{
"browser": "webkit",
"oldTag": "1175f1a1d2c1",
"newTag": "c3dbdd7039db",
"banners": 1,
"updateReloads": 1,
"cachedFiles": 122,
"durationMs": 9554,
"wireBytes": 751943,
"offline": true,
"legacyURLs": 21,
"profile": "unthrottled",
"userInitiatedOnly": true,
"playbackGuard": true,
"evictionRepair": true,
"incrementalRefresh": true,
"offlineTransportErrors": 4
}
]
}

View File

@@ -0,0 +1,28 @@
[
{
"browser": "chromium",
"checked": [
"shell",
"presenter",
"remote",
"party",
"share",
"stats"
],
"offlineNetworkRequests": 0,
"errors": []
},
{
"browser": "webkit",
"checked": [
"shell",
"presenter",
"remote",
"party",
"share",
"stats"
],
"offlineNetworkRequests": 0,
"errors": []
}
]

View File

@@ -0,0 +1,133 @@
{
"date": "2026-10-07T20:58:10.947Z",
"frontendCommit": null,
"frontendBuildTag": "9b741452f44e",
"commit": "2c5003575c641fddb128c6d1d14bb5d1e3999efb",
"runsConfigured": 1,
"browsers": {
"chromium": {
"lte": {
"offline": {
"requestCount": {
"median": 0,
"min": 0,
"max": 0,
"values": [
0
]
},
"wireBytes": {
"median": 0,
"min": 0,
"max": 0,
"values": [
0
]
},
"fcp": {
"median": 40,
"min": 40,
"max": 40,
"values": [
40
]
},
"lcp": {
"median": 40,
"min": 40,
"max": 40,
"values": [
40
]
},
"domContentLoaded": {
"median": 136,
"min": 136,
"max": 136,
"values": [
136
]
},
"bootDone": {
"median": 137,
"min": 137,
"max": 137,
"values": [
137
]
},
"reloadDuration": {
"median": 154,
"min": 154,
"max": 154,
"values": [
154
]
}
}
}
},
"webkit": {
"lte": {
"offline": {
"requestCount": {
"median": 0,
"min": 0,
"max": 0,
"values": [
0
]
},
"wireBytes": {
"median": 0,
"min": 0,
"max": 0,
"values": [
0
]
},
"fcp": {
"median": 60,
"min": 60,
"max": 60,
"values": [
60
]
},
"lcp": {
"median": 96,
"min": 96,
"max": 96,
"values": [
96
]
},
"domContentLoaded": {
"median": 94,
"min": 94,
"max": 94,
"values": [
94
]
},
"bootDone": {
"median": 98,
"min": 98,
"max": 98,
"values": [
98
]
},
"reloadDuration": {
"median": 115,
"min": 115,
"max": 115,
"values": [
115
]
}
}
}
}
}
}

View File

@@ -23,7 +23,7 @@ async function run(name){
browser=await ({chromium,webkit}[name]).launch({headless:true});const context=await browser.newContext();
await context.route('**/*',r=>r.request().url().startsWith(origin)?r.continue():r.abort());
await context.addInitScript(()=>{Object.defineProperty(navigator,'onLine',{configurable:true,get:()=>!window.__offline});});
const page=await context.newPage(),errors=[];page.on('pageerror',e=>errors.push(e.message));
const page=await context.newPage(),errors=[],failedRequests=[];page.on('pageerror',e=>errors.push(e.message));page.on('requestfailed',r=>failedRequests.push(r.url()));
await page.goto(origin);await page.waitForFunction(()=>typeof data!=='undefined'&&document.querySelector('#carModeBtn'));
await wait(page,async()=>!!(await navigator.serviceWorker.getRegistration())?.active);
await page.evaluate(()=>Lazy.warm());
@@ -39,14 +39,18 @@ async function run(name){
const checked=['shell'];
if(groups.includes('feature:presenter')) {
await page.evaluate(async()=>{history.replaceState(null,'','/?present=');await Presenter.boot();});
await page.waitForSelector('#presenterView:not(.hidden)');await page.keyboard.press('b');
await page.waitForSelector('#presenterView:not(.hidden)');
await page.locator('#pvCode').fill('x');await page.locator('#pvPairBtn').click();assert.match(await page.locator('#pvMsg').textContent(),/6-digit/);
await page.evaluate(()=>document.activeElement?.blur());await page.keyboard.press('b');
assert.equal(await page.locator('#pvBlank').evaluate(n=>!n.classList.contains('hidden')),true);
await page.evaluate(()=>{document.querySelector('#presenterView').classList.add('hidden');document.body.classList.remove('presenter-open');});checked.push('presenter');
}
if(groups.includes('feature:remote-client')) {
await page.evaluate(()=>document.querySelector('#navRemoteBtn').click());
await page.waitForSelector('#modal:not(.hidden)');assert.match(await page.locator('#modal').textContent(),/remote|screen|phone/i);
await page.evaluate(()=>closeModal());checked.push('remote');
await page.getByRole('button',{name:'Use this phone as a remote',exact:true}).click();
await page.waitForSelector('#remoteView:not(.hidden)');await page.locator('#rvCode').fill('x');await page.locator('#rvPairBtn').click();
assert.match(await page.locator('#rvPairMsg').textContent(),/6-digit/);await page.locator('#rvClose').click();checked.push('remote');
}
if(groups.includes('feature:watch-party')) {
await page.evaluate(()=>document.querySelector('#navPartyBtn').click());await page.waitForSelector('#partyPanel:not(.hidden)');
@@ -58,10 +62,14 @@ async function run(name){
await page.locator('.sm-time').fill('0:30');await page.locator('.sm-time').dispatchEvent('input');
assert.match(await page.locator('.sm-app').textContent(),/t=30/);
const m3u=await page.evaluate(async()=>{await Lazy.load('feature:share-external');return window.YT.External.m3u([{id:'benchmedia01',title:'Cached smoke'}]);});assert.match(m3u,/#EXTM3U/);assert.match(m3u,/benchmedia01/);
await page.evaluate(async()=>{closeModal();current={meta:{id:'upl_0123456789ab',title:'Cached upload'}};await External.open();});
await page.waitForSelector('.ext-panel');assert.match(await page.locator('.ext-panel').textContent(),/api\/uploads\/upl_0123456789ab/);
await page.evaluate(()=>closeModal());checked.push('share');
}
if(groups.includes('feature:stats-view')) {
await page.evaluate(async()=>{view={type:'stats'};render();});await page.waitForSelector('.stats-empty');checked.push('stats');
await page.evaluate(async()=>{view={type:'stats'};render();});await page.waitForSelector('.stats-empty');
await page.evaluate(async()=>{data.stats=StatsCore.record(null,{id:'benchmedia01',title:'Cached stats',channel:'Fixture'},600,true);await renderStats();});
await page.waitForSelector('.stats .st-tiles');assert.match(await page.locator('.st-song-text').first().textContent(),/Cached stats/);checked.push('stats');
}
if(groups.includes('feature:share-external')) {
await page.evaluate(()=>{Share.open=()=>Promise.reject(new Error('Unavailable fixture chunk'));document.querySelector('#shareMomentBtn').click();});
@@ -70,6 +78,7 @@ async function run(name){
assert.equal(proxy.getStats().requestCount,before,'all warmed seam code loads from SW without network');
// Ignore only verified disconnected version/recommendation API transports in WebKit.
const scriptErrors=errors.filter(e=>!(name==='webkit'&&(e==='TypeError: Load failed'||/\/api\/(?:recommendations\?[^\s]*|version)\.$/.test(e))));assert.deepEqual(scriptErrors,[]);
if(errors.length>scriptErrors.length)assert.ok(failedRequests.some(url=>/\/api\/(?:recommendations|version)/.test(url)),'ignored WebKit transport errors require a recorded disconnected API request');
results.push({browser:name,checked,offlineNetworkRequests:proxy.getStats().requestCount-before,errors:scriptErrors});console.log(name,JSON.stringify(results.at(-1)));
}finally{await browser?.close();await stop();await proxy?.close();}
}