From 762cc634312a524f6d68a954c8c165319ed2151e Mon Sep 17 00:00:00 2001 From: Harvey Zhao Date: Sat, 12 Sep 2026 04:42:16 +0800 Subject: [PATCH] test(dash): [PKG-DASH-02] cover released contracts and real menu interactions --- package.json | 4 +- refactor/baselines/dash-validation.json | 1846 +++++++++++++++++ .../changes/2026-09-12-PKG-DASH-02-tests.md | 22 + refactor/dash-validation.md | 45 + refactor/plan.md | 5 +- refactor/progress.md | 13 + refactor/risk-table.md | 6 +- refactor/risks.json | 18 +- refactor/tasks.json | 8 +- test/browser/dash-control.spec.js | 171 ++ test/dash-contract.test.js | 263 +++ test/helpers/dash-control.js | 194 ++ 12 files changed, 2580 insertions(+), 15 deletions(-) create mode 100644 refactor/baselines/dash-validation.json create mode 100644 refactor/changes/2026-09-12-PKG-DASH-02-tests.md create mode 100644 refactor/dash-validation.md create mode 100644 test/browser/dash-control.spec.js create mode 100644 test/dash-contract.test.js create mode 100644 test/helpers/dash-control.js diff --git a/package.json b/package.json index b343c6dfc..c893adf41 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "test:playback": "node --test test/playback.test.js", "trans:docs": "node ./scripts/trans-docs.js", "create:plugin": "node ./scripts/plugin/create.js", - "test:dash-control": "node --test test/dash-control.test.js", + "test:dash-control": "node --test test/dash-control.test.js test/dash-contract.test.js", "dev": "npx cross-env NODE_ENV=development node ./scripts/dev.js", "build": "npx cross-env NODE_ENV=production node ./scripts/build.js", "lint": "eslint \"packages/*/{src,public,types,package.json}\" \"scripts/*.{js,mjs}\" \"test/*\" \"docs/assets/ts/*\" \"types/*.d.ts\" \"playwright*.config.js\" --no-fix", @@ -50,7 +50,7 @@ "ci:build": "yarn build:types && yarn build all && yarn build:i18n && yarn build:ts && yarn build:docs && yarn test:imports", "test:imports": "node --test test/esm.test.js test/i18n.test.js test/ssr.test.js", "typecheck": "node scripts/typecheck.mjs", - "test:unit": "node --test test/playback.test.js test/dash-control.test.js test/hls-control.test.js test/audio-track.test.js test/public-behavior.test.js test/helpers.test.js test/chapter.test.js test/utils.test.js test/resource-scope.test.js test/instance-lifecycle.test.js test/options.test.js test/media-hosts.test.js test/plugins.test.js test/source.test.js test/playback-properties.test.js test/media-events.test.js test/template-resources.test.js test/core-vendor.test.js test/component-resources.test.js test/setting-model.test.js test/setting-layout.test.js test/setting-resources.test.js test/subtitle.test.js test/display-native.test.js test/display-video-fullscreen.test.js test/display-pip.test.js test/display-mini.test.js test/display-sizing.test.js test/display-orientation.test.js test/hotkey.test.js test/listener-registry.test.js test/global-events.test.js test/pointer-events.test.js test/gesture.test.js test/event-scheduling.test.js test/notice.test.js test/fast-forward.test.js test/auto-playback.test.js test/builtin-layers.test.js test/prompt-components.test.js test/screenshot.test.js test/thumbnails.test.js test/progress.test.js test/environment.test.js test/storage.test.js test/facade-properties.test.js test/dom-boundaries.test.js test/initialization.test.js test/entry.test.js test/accessibility-button.test.js test/accessibility-focus.test.js test/accessibility-slider.test.js", + "test:unit": "node --test test/playback.test.js test/dash-control.test.js test/dash-contract.test.js test/hls-control.test.js test/audio-track.test.js test/public-behavior.test.js test/helpers.test.js test/chapter.test.js test/utils.test.js test/resource-scope.test.js test/instance-lifecycle.test.js test/options.test.js test/media-hosts.test.js test/plugins.test.js test/source.test.js test/playback-properties.test.js test/media-events.test.js test/template-resources.test.js test/core-vendor.test.js test/component-resources.test.js test/setting-model.test.js test/setting-layout.test.js test/setting-resources.test.js test/subtitle.test.js test/display-native.test.js test/display-video-fullscreen.test.js test/display-pip.test.js test/display-mini.test.js test/display-sizing.test.js test/display-orientation.test.js test/hotkey.test.js test/listener-registry.test.js test/global-events.test.js test/pointer-events.test.js test/gesture.test.js test/event-scheduling.test.js test/notice.test.js test/fast-forward.test.js test/auto-playback.test.js test/builtin-layers.test.js test/prompt-components.test.js test/screenshot.test.js test/thumbnails.test.js test/progress.test.js test/environment.test.js test/storage.test.js test/facade-properties.test.js test/dom-boundaries.test.js test/initialization.test.js test/entry.test.js test/accessibility-button.test.js test/accessibility-focus.test.js test/accessibility-slider.test.js", "test:coverage": "node --test test/coverage.test.js && node scripts/coverage.mjs", "test": "yarn test:node && yarn test:baseline", "test:browser": "playwright test", diff --git a/refactor/baselines/dash-validation.json b/refactor/baselines/dash-validation.json new file mode 100644 index 000000000..f72f66a52 --- /dev/null +++ b/refactor/baselines/dash-validation.json @@ -0,0 +1,1846 @@ +{ + "schemaVersion": 1, + "task": "PKG-DASH-02", + "baseCommit": "3d4c6361", + "scope": "Controlled SDK contract tests, real core/plugin DOM and native MP4 playback. No actual dash.js instance, MPD, ABR, physical device or installed candidate package acceptance.", + "inputs": [ + { + "file": "test/helpers/dash-control.js", + "sha256LF": "0aceb5a2f7c775ea05807fe8b76b77ce0ca7dd37637053a6383e1a8656edaba1" + }, + { + "file": "test/dash-contract.test.js", + "sha256LF": "4477b48fc53224890a7eb22ed5f1554b57fd6265c864fb4039393978e63ceb31" + }, + { + "file": "test/dash-control.test.js", + "sha256LF": "2a123bbd93659c053ab206f09ab489d04380b222885179203c0bfb401590b35d" + }, + { + "file": "test/browser/dash-control.spec.js", + "sha256LF": "eebdd42357eb5084ae5cf84c04193dd8dfb5dcbdfdf227809876683036a304c3" + }, + { + "file": "packages/artplayer-plugin-dash-control/src/index.js", + "sha256LF": "aaa7975115a6d2677f4c8d71182954edbf69a12f9ffe8bee86afa94f6b5615e8" + } + ], + "reports": [ + { + "file": "refactor/.cache/dash02-first/report.json", + "sha256": "3b5237ecaa4a2eb653af8e0daf9ae0d079fe9a23661214250c34777d6305c129", + "bytes": 5671528, + "resultDir": "refactor/.cache/dash02-first/results", + "stats": { + "startTime": "2026-09-11T20:31:54.035Z", + "duration": 227299.818, + "expected": 24, + "skipped": 0, + "unexpected": 24, + "flaky": 0 + }, + "resultFiles": [ + { + "file": "refactor/.cache/dash02-first/results/.last-run.json", + "sha256": "7d2379952fc78cef3d06336abb8f3bdf274c696eb3826ea572db35a718fdc539", + "bytes": 1223 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-02bec-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "d5f36833338ef79468736e4199533f8024e29f212d0dbdf3ea8743f7a19c95ef", + "bytes": 820526 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-02bec-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "33179828c23d5f3804415c64d3da04cac81216357717b12739334855a545f8b6", + "bytes": 835423 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-02bec-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "ac70929db771e60a346d00d634b65713c9c95d50a8da5af38fa13aef77d55641", + "bytes": 548071 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-1333a-on-through-real-setting-DOM-chromium/error-context.md", + "sha256": "b6af89b4cbb0b439fc5965834d4c54c29f5cac915b9482d6729084a26dedab6e", + "bytes": 8488 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-1333a-on-through-real-setting-DOM-chromium/test-failed-1.png", + "sha256": "54e61b1d1c78d9695c029b5fa221c143aa898a1c52dce6f9c1365dc723e568c9", + "bytes": 70983 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-1333a-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "878602a8b38d16d521a214464be223b15ab8afd457afbc11ac43d18d9460c46f", + "bytes": 592717 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-1333a-on-through-real-setting-DOM-firefox/error-context.md", + "sha256": "b6af89b4cbb0b439fc5965834d4c54c29f5cac915b9482d6729084a26dedab6e", + "bytes": 8488 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-1333a-on-through-real-setting-DOM-firefox/test-failed-1.png", + "sha256": "2638cc1f8f44caf219b3e59d5fb4ed0fe7b17fb531c0079587ca3c5db3dbf95a", + "bytes": 105250 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-1333a-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "5fd577fa95e61fc406bcc5f619b241282f4d152364969cd862a3648ddc9cbfad", + "bytes": 1970424 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-1333a-on-through-real-setting-DOM-webkit/error-context.md", + "sha256": "b6af89b4cbb0b439fc5965834d4c54c29f5cac915b9482d6729084a26dedab6e", + "bytes": 8488 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-1333a-on-through-real-setting-DOM-webkit/test-failed-1.png", + "sha256": "cf95efa44d8328a73a1d9e636ed3084dd06bf4adea0ddf9a8838fa49c1786b95", + "bytes": 268752 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-1333a-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "ac2ae066b26d9f1381171778933c4c61a8249ff81ac83391866773ef461d3842", + "bytes": 525890 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-3300d-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "948272af50cdb12b690ee4586778152d8b5b852bee40aa561ef6ba71a4811d3a", + "bytes": 825612 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-3300d-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "48e77be2d95db091d1dfcdc0e4303be5407c22c1fe4c994aa4f0d694f23324c6", + "bytes": 828719 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-3300d-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "5a5d35534008c16f0880ce210cb226a80b8d9dcd31a11cc4346caeb5fef0fb41", + "bytes": 568850 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-39df1-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "899421b48d3c7db8c99fb5bacb3ae6bd2645a895757cb44d183419d6a2d0464c", + "bytes": 803722 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-39df1-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "d316885f1c866423ddc74818bc90b876129fb35de453f4dcc4d1283cd4812df6", + "bytes": 888624 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-39df1-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "66ba09932878734f3304cf5771f204d018315b5303a0d94ee4295d2a1c922896", + "bytes": 475841 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-5af40-on-through-real-setting-DOM-chromium/error-context.md", + "sha256": "de4e5bf11bc96ab4c0670e37e5d371732687f5696282010f8e7fbc2424ae8380", + "bytes": 8488 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-5af40-on-through-real-setting-DOM-chromium/test-failed-1.png", + "sha256": "54e61b1d1c78d9695c029b5fa221c143aa898a1c52dce6f9c1365dc723e568c9", + "bytes": 70983 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-5af40-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "b712cb6a749edaec55ec6d2ac3123e4f1987d7ce687a77dff359529e9bad452d", + "bytes": 569286 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-5af40-on-through-real-setting-DOM-firefox/error-context.md", + "sha256": "de4e5bf11bc96ab4c0670e37e5d371732687f5696282010f8e7fbc2424ae8380", + "bytes": 8488 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-5af40-on-through-real-setting-DOM-firefox/test-failed-1.png", + "sha256": "9b2113757b61c27886d4aaa80275a1a6cb0ece8c7f7daaaac393f8d4603d0561", + "bytes": 105194 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-5af40-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "3d8eecd2655ec1739a850622462d663243806e32b0bfb98abd9c23a147df2611", + "bytes": 2238550 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-5af40-on-through-real-setting-DOM-webkit/error-context.md", + "sha256": "de4e5bf11bc96ab4c0670e37e5d371732687f5696282010f8e7fbc2424ae8380", + "bytes": 8488 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-5af40-on-through-real-setting-DOM-webkit/test-failed-1.png", + "sha256": "211749c5258be5e4a740926d0f1a283b34a84d59601a8cfdca82512eeb683310", + "bytes": 267746 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-5af40-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "c4315f48b50b80bcd711aa39f85adea7f6b83a8703178c9750ffa66e2872a447", + "bytes": 542364 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-8e292-on-through-real-setting-DOM-chromium/error-context.md", + "sha256": "caf67f8eca905132bafbe730c671ad76d1e2a45065e081bead2dff9f8ccaa596", + "bytes": 8492 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-8e292-on-through-real-setting-DOM-chromium/test-failed-1.png", + "sha256": "74c0e6214a99c99b0b215bf33ae6bdf3040f2aeed1b57817a84f7bcb2d9cbb2a", + "bytes": 74856 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-8e292-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "d8842697464b37f9e2b900cb5e3f02a1dd7e98352f0a5f25280295105923bb96", + "bytes": 480643 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-8e292-on-through-real-setting-DOM-firefox/error-context.md", + "sha256": "caf67f8eca905132bafbe730c671ad76d1e2a45065e081bead2dff9f8ccaa596", + "bytes": 8492 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-8e292-on-through-real-setting-DOM-firefox/test-failed-1.png", + "sha256": "9e31b23f94e98fa8424b086a9d09270a99b635b795976f904f612da9a6bf27aa", + "bytes": 106313 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-8e292-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "6399bc8d025ab7688c8cb62ba1d6b156af7dfc2303cdd644a6d4ac530da83328", + "bytes": 2380746 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-8e292-on-through-real-setting-DOM-webkit/error-context.md", + "sha256": "caf67f8eca905132bafbe730c671ad76d1e2a45065e081bead2dff9f8ccaa596", + "bytes": 8492 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-8e292-on-through-real-setting-DOM-webkit/test-failed-1.png", + "sha256": "e5dd307087f487a8c0937bb9b6254cecb6998aa9c4a8e3313a3e022661c84952", + "bytes": 266754 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-8e292-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "8507a97bbe73a7280f74ee0bc65bf474674f4835db48cca64875e3f7f10bc470", + "bytes": 507595 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-9124e-on-through-real-setting-DOM-chromium/error-context.md", + "sha256": "d8491a61b50afce51cc8204b4d125f4b399a63bd95e49d326150b2ae12ab4528", + "bytes": 8492 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-9124e-on-through-real-setting-DOM-chromium/test-failed-1.png", + "sha256": "74c0e6214a99c99b0b215bf33ae6bdf3040f2aeed1b57817a84f7bcb2d9cbb2a", + "bytes": 74856 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-9124e-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "bd28891c89f18f073369056120ec031566da3fd1b5ee1a50af078228c1313918", + "bytes": 480525 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-9124e-on-through-real-setting-DOM-firefox/error-context.md", + "sha256": "d8491a61b50afce51cc8204b4d125f4b399a63bd95e49d326150b2ae12ab4528", + "bytes": 8492 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-9124e-on-through-real-setting-DOM-firefox/test-failed-1.png", + "sha256": "9e31b23f94e98fa8424b086a9d09270a99b635b795976f904f612da9a6bf27aa", + "bytes": 106313 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-9124e-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "519b7825c1b4daf2cd3974eaabddcadefe50492645b1f99d748b082773a32419", + "bytes": 2346134 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-9124e-on-through-real-setting-DOM-webkit/error-context.md", + "sha256": "d8491a61b50afce51cc8204b4d125f4b399a63bd95e49d326150b2ae12ab4528", + "bytes": 8492 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-9124e-on-through-real-setting-DOM-webkit/test-failed-1.png", + "sha256": "e5dd307087f487a8c0937bb9b6254cecb6998aa9c4a8e3313a3e022661c84952", + "bytes": 266754 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-9124e-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "9f6b7ef5e1cc0830baa36562c2d69c1fd0da7fa5a51484658b7c0c67a7cf768c", + "bytes": 524874 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-945b5-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "50b27e9a1eae3ae14167626dec1562a2a00521ace81c08f10e568f5a604084a8", + "bytes": 838008 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-945b5-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "36236d0f06b04a7117a56638b27878b598f14a0c9367afa65e78523305d97996", + "bytes": 878236 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-candidate-cor-945b5-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "787e76457f33ffd96112dc5fe569fe5b86ca724cc32f6ab2f1399441096a9aeb", + "bytes": 548972 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-3457b-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "f692e0d5581c863c370c647150e67b464ae9065ca4370b9b073b56396f0752db", + "bytes": 819573 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-3457b-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "7254a93fcf9235c90346f18d0906f350e3f418beef96d39e8c946d4c497bc8df", + "bytes": 847930 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-3457b-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "32417de357299ee57a0f6a704cde6bddb668b4bea9986a80dd4b4a0391cc09fe", + "bytes": 562223 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-3c6d1-on-through-real-setting-DOM-chromium/error-context.md", + "sha256": "2d6b23f1d32cefe801b1bdd07de54a6f6b15fb767033e46443eae688cc1d7749", + "bytes": 8492 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-3c6d1-on-through-real-setting-DOM-chromium/test-failed-1.png", + "sha256": "21d1e0d10cbba44fa5f850aebd192f8e84155637193fd8d62b14a81b9d62245a", + "bytes": 74918 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-3c6d1-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "0884a6c0cd3d4668132791dfc96783aa66c75a6ab44d4f9632bf509b4a60d83e", + "bytes": 613928 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-3c6d1-on-through-real-setting-DOM-firefox/error-context.md", + "sha256": "2d6b23f1d32cefe801b1bdd07de54a6f6b15fb767033e46443eae688cc1d7749", + "bytes": 8492 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-3c6d1-on-through-real-setting-DOM-firefox/test-failed-1.png", + "sha256": "f48e049531eec2efcd9619b061cded8e3397a9d7bef605a9d5e320b832086379", + "bytes": 106299 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-3c6d1-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "4f2ab2f3a7bbcf57b15cedcb82361b231596eddb03cd5edb82ba093b78c216d9", + "bytes": 2378428 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-3c6d1-on-through-real-setting-DOM-webkit/error-context.md", + "sha256": "2d6b23f1d32cefe801b1bdd07de54a6f6b15fb767033e46443eae688cc1d7749", + "bytes": 8492 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-3c6d1-on-through-real-setting-DOM-webkit/test-failed-1.png", + "sha256": "52d9aa537ec65038b45b0619c97eba0067c14393de6a40a60242bebbcf61a504", + "bytes": 266830 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-3c6d1-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "ba20154ee8ebc9ec8dab41189bbc81da738e0e02ee543592d6203b5b33d60a2b", + "bytes": 500365 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-4c264-on-through-real-setting-DOM-chromium/error-context.md", + "sha256": "3b50564cf0dd21ffde6ccb18537a9459adf006ce6284d11e8f3109f44b18afee", + "bytes": 8488 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-4c264-on-through-real-setting-DOM-chromium/test-failed-1.png", + "sha256": "be61d892603a9db8a3eb36db371c8c8ea066f6732081df5bb80923af54e03b1e", + "bytes": 71047 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-4c264-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "f66132d763789d51d955828c27deda27506ceb518ea5d0299a56b13e14327f35", + "bytes": 585021 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-4c264-on-through-real-setting-DOM-firefox/error-context.md", + "sha256": "3b50564cf0dd21ffde6ccb18537a9459adf006ce6284d11e8f3109f44b18afee", + "bytes": 8488 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-4c264-on-through-real-setting-DOM-firefox/test-failed-1.png", + "sha256": "4187f5a77408823299e0ff6cd1ba4152a0018769a60d889eaf2836a8ecbf9b2e", + "bytes": 105222 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-4c264-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "982880329df99f1141b0643503e07e06d27818bd332d4b5d8bb8a238b2128885", + "bytes": 2211971 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-4c264-on-through-real-setting-DOM-webkit/error-context.md", + "sha256": "3b50564cf0dd21ffde6ccb18537a9459adf006ce6284d11e8f3109f44b18afee", + "bytes": 8488 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-4c264-on-through-real-setting-DOM-webkit/test-failed-1.png", + "sha256": "73cb3bbf618ff3c96182198e57dd23f9a8c70257c8b1cebbb332bf891cae02d5", + "bytes": 267819 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-4c264-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "3dc371118e29a0ad35fd7804e398e3dea49235057b5ebe224c9ba7d9424cb0d8", + "bytes": 542129 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-541e9-on-through-real-setting-DOM-chromium/error-context.md", + "sha256": "fb81aa74cb2adda651ee7272777204149f284694fb8c9a1272bb2c6f393dee40", + "bytes": 8492 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-541e9-on-through-real-setting-DOM-chromium/test-failed-1.png", + "sha256": "21d1e0d10cbba44fa5f850aebd192f8e84155637193fd8d62b14a81b9d62245a", + "bytes": 74918 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-541e9-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "63eb7c2484f591c6aacf8a212702e37184cdfdb708b9e811f6308bef9fe06f73", + "bytes": 614033 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-541e9-on-through-real-setting-DOM-firefox/error-context.md", + "sha256": "fb81aa74cb2adda651ee7272777204149f284694fb8c9a1272bb2c6f393dee40", + "bytes": 8492 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-541e9-on-through-real-setting-DOM-firefox/test-failed-1.png", + "sha256": "f48e049531eec2efcd9619b061cded8e3397a9d7bef605a9d5e320b832086379", + "bytes": 106299 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-541e9-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "5cef8c8b8a9a39c00179ad07cdc7790ddcc1855b79b4742a6771d5541e9fd9cd", + "bytes": 2274507 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-541e9-on-through-real-setting-DOM-webkit/error-context.md", + "sha256": "fb81aa74cb2adda651ee7272777204149f284694fb8c9a1272bb2c6f393dee40", + "bytes": 8492 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-541e9-on-through-real-setting-DOM-webkit/test-failed-1.png", + "sha256": "52d9aa537ec65038b45b0619c97eba0067c14393de6a40a60242bebbcf61a504", + "bytes": 266830 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-541e9-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "782c28cdef64ddc38ddd215fe787cc078d14f396b9e8d387feff77c9b393d65e", + "bytes": 502493 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-7dd29-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "c03b924c82e14ede7677a1375a8d1a49e9303b4bcab248931d1a07f486f8702c", + "bytes": 785936 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-7dd29-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "6f24bbfb26d8248fb0c2c6eafe9ee1fd323721b802183d5b427d7c2735ce2021", + "bytes": 831061 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-7dd29-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "cf3e80fddd83fa34993529eda2a4e737024405d6d6be823d85fc1418eb4e5fb4", + "bytes": 552984 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-b39ba-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "6fa0feda8dfa6be78d66410012eb65bab2de513ebe127f01265a33dc15b8ba9f", + "bytes": 825595 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-b39ba-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "28381a37929154ad9bb30941a96bc104c67e29cfc17d99ad1ecbae9e6ee9d24b", + "bytes": 874412 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-b39ba-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "4149f0bf51ef5086574dd7ce76a26d970ee21502c5fa24384497fc5557594f57", + "bytes": 525777 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-ba411-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "6b9cc09ed82e6312147a083f3b60977e457db994572b333ba1528ede2b7aa17f", + "bytes": 857549 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-ba411-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "dca7084c411b270da3c26d0e955cfc766fc9c64d6eb57572fc99ad56fa3a8d8d", + "bytes": 812094 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-ba411-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "996e109cb35087174e920f77ff09bf4030d5f3fb37668853fde89bf8393bab6f", + "bytes": 532791 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-f0528-on-through-real-setting-DOM-chromium/error-context.md", + "sha256": "7d7e482aaa8209be463607a09251ad497e98d16680d3f3c28476bd770f110da4", + "bytes": 8488 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-f0528-on-through-real-setting-DOM-chromium/test-failed-1.png", + "sha256": "be61d892603a9db8a3eb36db371c8c8ea066f6732081df5bb80923af54e03b1e", + "bytes": 71047 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-f0528-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "1e680d223d703486b11b812fc52a720c65b21a36ddef256f31d22b821709f46d", + "bytes": 583975 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-f0528-on-through-real-setting-DOM-firefox/error-context.md", + "sha256": "7d7e482aaa8209be463607a09251ad497e98d16680d3f3c28476bd770f110da4", + "bytes": 8488 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-f0528-on-through-real-setting-DOM-firefox/test-failed-1.png", + "sha256": "4187f5a77408823299e0ff6cd1ba4152a0018769a60d889eaf2836a8ecbf9b2e", + "bytes": 105222 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-f0528-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "63c67bd382fd5d3bf2730828c9eefe4595ff2e9c88b55bbd8763da8b645bbfed", + "bytes": 2213990 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-f0528-on-through-real-setting-DOM-webkit/error-context.md", + "sha256": "7d7e482aaa8209be463607a09251ad497e98d16680d3f3c28476bd770f110da4", + "bytes": 8488 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-f0528-on-through-real-setting-DOM-webkit/test-failed-1.png", + "sha256": "73cb3bbf618ff3c96182198e57dd23f9a8c70257c8b1cebbb332bf891cae02d5", + "bytes": 267819 + }, + { + "file": "refactor/.cache/dash02-first/results/dash-control-published-cor-f0528-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "a4562dbe941c388e2f87bf8f602e9e8749fdc3b5e0874bd8e87d16737cd21b1a", + "bytes": 522735 + } + ], + "inputs": { + "published": { + "name": "artplayer-plugin-dash-control", + "version": "1.1.0", + "metadataUrl": "https://registry.npmjs.org/artplayer-plugin-dash-control/1.1.0", + "tarball": "https://registry.npmjs.org/artplayer-plugin-dash-control/-/artplayer-plugin-dash-control-1.1.0.tgz", + "integrity": "sha512-EssRkzYXWcln3a6nAzi4ESacBhzMih8s0bzdjXuvBBCh2UFmvK99ITD5E+0cuU8i5ZzIQGQSdce1/gANTrX0BQ==", + "sha256": "f4047a569d99b6a7de57b3719b7ad40109f2a1d360566a840f50ab32aacefcd9", + "archiveBytes": 3385, + "registryGitHead": "daf133b22630b4a0eecfa3336bbddab0e9119d96", + "files": { + "package/README.md": "98982f1123ff9a11f5d3d9a52da6e8fea9cd0989f7465605c27b0f9a46f2dbcd", + "package/dist/artplayer-plugin-dash-control.js": "f0cbbcf8badeaca13c05ae178932818cb52fbce37ed504ac0e62160b9c7e1145", + "package/dist/artplayer-plugin-dash-control.legacy.js": "f0cbbcf8badeaca13c05ae178932818cb52fbce37ed504ac0e62160b9c7e1145", + "package/dist/artplayer-plugin-dash-control.mjs": "e32bf08c33a481781883067dcc639f0495c9dcb8a88b91be13736370f4932fc4", + "package/package.json": "556e2adc479bab36c5973de617c0b57c5d86aa8425643a1952ab04738e9ce927", + "package/types/artplayer-plugin-dash-control.d.ts": "e15ef683e0c335d81531587828593325e037efe7ed29c022477cd14fe71aebba" + }, + "manifest": { + "name": "artplayer-plugin-dash-control", + "version": "1.1.0", + "description": "Dash control plugin for ArtPlayer", + "author": "Harvey Zhao ", + "license": "MIT", + "homepage": "https://artplayer.org", + "repository": { + "type": "git", + "url": "git+https://github.com/zhw2590582/ArtPlayer.git" + }, + "bugs": { + "url": "https://github.com/zhw2590582/ArtPlayer/issues" + }, + "keywords": [ + "html5", + "video", + "player" + ], + "exports": { + ".": { + "types": "./types/artplayer-plugin-dash-control.d.ts", + "import": "./dist/artplayer-plugin-dash-control.mjs", + "require": "./dist/artplayer-plugin-dash-control.js" + }, + "./legacy": { + "types": "./types/artplayer-plugin-dash-control.d.ts", + "import": "./dist/artplayer-plugin-dash-control.legacy.js", + "require": "./dist/artplayer-plugin-dash-control.legacy.js" + } + }, + "main": "./dist/artplayer-plugin-dash-control.js", + "module": "./dist/artplayer-plugin-dash-control.mjs", + "types": "./types/artplayer-plugin-dash-control.d.ts", + "legacy": "./dist/artplayer-plugin-dash-control.legacy.js", + "browserslist": "last 1 Chrome version" + } + }, + "sourceSHA256": "e7a64a47310374888b3b0deab445a15df3875fe2b8307fce70277e094520047b", + "candidate": "workspace source build", + "scope": "Real ArtPlayer DOM and native MP4 with controlled SDK methods. No dash.js instance, MPD, ABR or adaptive media validation." + }, + "browsers": [ + { + "project": "chromium", + "version": "153.0.8010.12", + "platform": "win32", + "manifest": { + "kind": "artplayer-browser-test", + "resources": { + "/candidate/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040 + }, + "/compiled/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040, + "aliasOf": "/candidate/artplayer.js" + }, + "/uncompiled/artplayer/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040, + "aliasOf": "/candidate/artplayer.js" + }, + "/candidate/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529 + }, + "/compiled/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/uncompiled/artplayer-plugin-chapter/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/published/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "/published/artplayer-plugin-chapter.js": { + "source": { + "kind": "npm-release", + "version": "1.1.0", + "integrity": "sha512-ji66Lr2K2S+OjFMuMby3yq+pefWlOC51Sbpop/DIr2N6w3F0smrF+YZbshN1Dy8/Tx1TYpT7N6WkkZWy5Jix1w==", + "member": "package/dist/artplayer-plugin-chapter.js" + }, + "sha256": "c2aaee11bf1db765433b01d9f8dd3978e41fa4d39655db00ebd03fc0be3e35e0", + "bytes": 4973 + }, + "/test/pattern.mp4": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.mp4" + }, + "sha256": "0ad1d7ad286aec6e0fa9e27fc1e487e7277df2e603e30040fb942365763d0233", + "bytes": 251538 + }, + "/test/pattern.webm": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.webm" + }, + "sha256": "9d3c2b3dec9581a599de2d6732992ef7846790e0d1368e6e131bd339b39e984f", + "bytes": 162073 + }, + "/test/audio-tone.m4a": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/audio-tone.m4a" + }, + "sha256": "83e6672b880b5d1c97093b1e26bdc40221c0b279615f40e99dbf9d2ade7b4d56", + "bytes": 132436 + }, + "/test/declaration-cues.vtt": { + "source": { + "kind": "test-subtitles", + "file": "test/browser/media/declaration-cues.vtt" + }, + "sha256": "5d149d4e641ce41cbb83376835c03daf1fb89f3b9f568fa59e064d51e2b57704", + "bytes": 54 + }, + "/test/thumbnail-grid.svg": { + "source": { + "kind": "test-thumbnail-grid", + "file": "test/browser/media/thumbnail-grid.svg" + }, + "sha256": "bb3f1ec9895d37def77ca4b192d3cd73577a2668558cc99de1588f511d65d3e6", + "bytes": 14969 + }, + "/test/legacy-safe-area.js": { + "source": { + "kind": "frozen-own-source", + "file": "test/helpers/legacy-safe-area.js", + "commit": "ccf77c4e" + }, + "sha256": "ce0368618ef6363b78271b8bcc7973abd0478e797cc464ddd912929e6dfa501a", + "bytes": 795 + }, + "/assets/sample/video.mp4": { + "source": { + "kind": "docs-media", + "file": "docs/assets/sample/video.mp4" + }, + "sha256": "30a2de667ba267b6bc605edcee1c4bd728c048ed76f500ea0e73d1f1a6f8f980", + "bytes": 5818706 + }, + "/test/performance.js": { + "source": { + "kind": "adapted-baseline-fixture", + "file": "refactor/fixtures/performance.js" + }, + "sha256": "2318f39bdb5f3a3348d755cb4335907ae4adc944be3a435839c1bba201e81500", + "bytes": 8994 + } + } + } + }, + { + "project": "firefox", + "version": "155.0", + "platform": "win32", + "manifest": { + "kind": "artplayer-browser-test", + "resources": { + "/candidate/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040 + }, + "/compiled/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040, + "aliasOf": "/candidate/artplayer.js" + }, + "/uncompiled/artplayer/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040, + "aliasOf": "/candidate/artplayer.js" + }, + "/candidate/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529 + }, + "/compiled/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/uncompiled/artplayer-plugin-chapter/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/published/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "/published/artplayer-plugin-chapter.js": { + "source": { + "kind": "npm-release", + "version": "1.1.0", + "integrity": "sha512-ji66Lr2K2S+OjFMuMby3yq+pefWlOC51Sbpop/DIr2N6w3F0smrF+YZbshN1Dy8/Tx1TYpT7N6WkkZWy5Jix1w==", + "member": "package/dist/artplayer-plugin-chapter.js" + }, + "sha256": "c2aaee11bf1db765433b01d9f8dd3978e41fa4d39655db00ebd03fc0be3e35e0", + "bytes": 4973 + }, + "/test/pattern.mp4": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.mp4" + }, + "sha256": "0ad1d7ad286aec6e0fa9e27fc1e487e7277df2e603e30040fb942365763d0233", + "bytes": 251538 + }, + "/test/pattern.webm": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.webm" + }, + "sha256": "9d3c2b3dec9581a599de2d6732992ef7846790e0d1368e6e131bd339b39e984f", + "bytes": 162073 + }, + "/test/audio-tone.m4a": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/audio-tone.m4a" + }, + "sha256": "83e6672b880b5d1c97093b1e26bdc40221c0b279615f40e99dbf9d2ade7b4d56", + "bytes": 132436 + }, + "/test/declaration-cues.vtt": { + "source": { + "kind": "test-subtitles", + "file": "test/browser/media/declaration-cues.vtt" + }, + "sha256": "5d149d4e641ce41cbb83376835c03daf1fb89f3b9f568fa59e064d51e2b57704", + "bytes": 54 + }, + "/test/thumbnail-grid.svg": { + "source": { + "kind": "test-thumbnail-grid", + "file": "test/browser/media/thumbnail-grid.svg" + }, + "sha256": "bb3f1ec9895d37def77ca4b192d3cd73577a2668558cc99de1588f511d65d3e6", + "bytes": 14969 + }, + "/test/legacy-safe-area.js": { + "source": { + "kind": "frozen-own-source", + "file": "test/helpers/legacy-safe-area.js", + "commit": "ccf77c4e" + }, + "sha256": "ce0368618ef6363b78271b8bcc7973abd0478e797cc464ddd912929e6dfa501a", + "bytes": 795 + }, + "/assets/sample/video.mp4": { + "source": { + "kind": "docs-media", + "file": "docs/assets/sample/video.mp4" + }, + "sha256": "30a2de667ba267b6bc605edcee1c4bd728c048ed76f500ea0e73d1f1a6f8f980", + "bytes": 5818706 + }, + "/test/performance.js": { + "source": { + "kind": "adapted-baseline-fixture", + "file": "refactor/fixtures/performance.js" + }, + "sha256": "2318f39bdb5f3a3348d755cb4335907ae4adc944be3a435839c1bba201e81500", + "bytes": 8994 + } + } + } + }, + { + "project": "webkit", + "version": "26.6", + "platform": "win32", + "manifest": { + "kind": "artplayer-browser-test", + "resources": { + "/candidate/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040 + }, + "/compiled/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040, + "aliasOf": "/candidate/artplayer.js" + }, + "/uncompiled/artplayer/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040, + "aliasOf": "/candidate/artplayer.js" + }, + "/candidate/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529 + }, + "/compiled/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/uncompiled/artplayer-plugin-chapter/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/published/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "/published/artplayer-plugin-chapter.js": { + "source": { + "kind": "npm-release", + "version": "1.1.0", + "integrity": "sha512-ji66Lr2K2S+OjFMuMby3yq+pefWlOC51Sbpop/DIr2N6w3F0smrF+YZbshN1Dy8/Tx1TYpT7N6WkkZWy5Jix1w==", + "member": "package/dist/artplayer-plugin-chapter.js" + }, + "sha256": "c2aaee11bf1db765433b01d9f8dd3978e41fa4d39655db00ebd03fc0be3e35e0", + "bytes": 4973 + }, + "/test/pattern.mp4": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.mp4" + }, + "sha256": "0ad1d7ad286aec6e0fa9e27fc1e487e7277df2e603e30040fb942365763d0233", + "bytes": 251538 + }, + "/test/pattern.webm": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.webm" + }, + "sha256": "9d3c2b3dec9581a599de2d6732992ef7846790e0d1368e6e131bd339b39e984f", + "bytes": 162073 + }, + "/test/audio-tone.m4a": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/audio-tone.m4a" + }, + "sha256": "83e6672b880b5d1c97093b1e26bdc40221c0b279615f40e99dbf9d2ade7b4d56", + "bytes": 132436 + }, + "/test/declaration-cues.vtt": { + "source": { + "kind": "test-subtitles", + "file": "test/browser/media/declaration-cues.vtt" + }, + "sha256": "5d149d4e641ce41cbb83376835c03daf1fb89f3b9f568fa59e064d51e2b57704", + "bytes": 54 + }, + "/test/thumbnail-grid.svg": { + "source": { + "kind": "test-thumbnail-grid", + "file": "test/browser/media/thumbnail-grid.svg" + }, + "sha256": "bb3f1ec9895d37def77ca4b192d3cd73577a2668558cc99de1588f511d65d3e6", + "bytes": 14969 + }, + "/test/legacy-safe-area.js": { + "source": { + "kind": "frozen-own-source", + "file": "test/helpers/legacy-safe-area.js", + "commit": "ccf77c4e" + }, + "sha256": "ce0368618ef6363b78271b8bcc7973abd0478e797cc464ddd912929e6dfa501a", + "bytes": 795 + }, + "/assets/sample/video.mp4": { + "source": { + "kind": "docs-media", + "file": "docs/assets/sample/video.mp4" + }, + "sha256": "30a2de667ba267b6bc605edcee1c4bd728c048ed76f500ea0e73d1f1a6f8f980", + "bytes": 5818706 + }, + "/test/performance.js": { + "source": { + "kind": "adapted-baseline-fixture", + "file": "refactor/fixtures/performance.js" + }, + "sha256": "2318f39bdb5f3a3348d755cb4335907ae4adc944be3a435839c1bba201e81500", + "bytes": 8994 + } + } + } + } + ], + "errors": [ + "Test timeout of 20000ms exceeded.", + "Error: locator.click: Test timeout of 20000ms exceeded.\nCall log:\n - waiting for locator('.art-setting-item').filter({ hasText: /^720p$/ })\n\n\n 97 | await page.locator('.art-control-setting').click()\n 98 | await page.locator(`[data-name=\"dash-${type}\"]`).click()\n> 99 | await page.locator('.art-setting-item').filter({ hasText: new RegExp(`^${text}$`) }).click()\n | ^\n 100 | }\n 101 | const expected = type === 'quality'\n 102 | ? [['auto', false], plugin === 'published' ? ['qualityIndex', 'video', 1] : ['representationId', 'video', 'high']]\n at D:\\github\\ArtPlayer\\test\\browser\\dash-control.spec.js:99:98", + "Error: locator.click: Test timeout of 20000ms exceeded.\nCall log:\n - waiting for locator('.art-setting-item').filter({ hasText: /^fr$/ })\n\n\n 97 | await page.locator('.art-control-setting').click()\n 98 | await page.locator(`[data-name=\"dash-${type}\"]`).click()\n> 99 | await page.locator('.art-setting-item').filter({ hasText: new RegExp(`^${text}$`) }).click()\n | ^\n 100 | }\n 101 | const expected = type === 'quality'\n 102 | ? [['auto', false], plugin === 'published' ? ['qualityIndex', 'video', 1] : ['representationId', 'video', 'high']]\n at D:\\github\\ArtPlayer\\test\\browser\\dash-control.spec.js:99:98" + ] + }, + { + "file": "refactor/.cache/dash02-final/report.json", + "sha256": "f58572c74e94cf3c7436288ac2b7b4452dac203e8636b5aaaf900644d6f5a810", + "bytes": 10450993, + "resultDir": "refactor/.cache/dash02-final/results", + "stats": { + "startTime": "2026-09-11T20:38:05.407Z", + "duration": 43695.555, + "expected": 48, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "resultFiles": [ + { + "file": "refactor/.cache/dash02-final/results/.last-run.json", + "sha256": "91d1c43004802cd49950d78eb11c8fa7d05da8ffffe219a8b13b2f561bc00903", + "bytes": 45 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-02bec-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "18444db8769ef6a8e7249ad953dd8662e5b85fce6fd1d90aaef2dfdcfd362384", + "bytes": 805248 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-02bec-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "be6593249dd5371a008e4425c9ee05d8a34a1a2105e99f28d267a1511f0d27a0", + "bytes": 855250 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-02bec-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "f3bb83673cf7ff033f6a09a1e91fb0062e113772a89a911414c02d3ffb229524", + "bytes": 498870 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-1333a-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "9ab27e2471f731c0ea373ea4ae62e6c32221eb461a9377da0e0cd2fb7bfc6014", + "bytes": 1042667 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-1333a-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "7e55c466317e4afc9da93b9691e590c16f5a21f7dab91f7e2a266be652b37568", + "bytes": 902778 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-1333a-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "2240eab8c15737a22ee055391048bdb747e791b10acded551728dbb825a3e1b2", + "bytes": 753246 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-3300d-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "9326228e7f6c4c27883f1f7685ced045f2ecdcf19a061900e444b3e23bb380cd", + "bytes": 845443 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-3300d-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "a74f12414b25688043483266237b45f6e7cebddcbb5289399cf8d3bd6b19865c", + "bytes": 900811 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-3300d-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "8651a100cdbd182b668e102afb5bd45c29799d5550f525f7c7358ee22f674c71", + "bytes": 516369 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-39df1-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "880cf50027ca5b52546ce7f6f08878ef5f41e2cb9e0500088187f6de09d82e2f", + "bytes": 803932 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-39df1-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "e2685476a800232822dcd98cf0840bbbb07a59a5462e69235fdccae9395899e8", + "bytes": 829579 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-39df1-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "d7a6ba24738cec0dc91b28ca2438841048b8dca2c8fcdce324e9aa3d4b4d4f85", + "bytes": 570691 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-5af40-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "4f9dfa13dce4863ca75549cf4164256ca00f3e2acaeeb427dab41d160e9a0698", + "bytes": 1063500 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-5af40-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "446fe423f92ebe3876f0f8dd0207e56f05214bf6727fa59eebab35bb1efa1378", + "bytes": 926027 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-5af40-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "6c337fc38e56f43712aa4c3dbc613103a01278a945dbb62bd349b7c6c15d21db", + "bytes": 731694 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-8e292-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "d17215fdafa3ccf8a780e8deb95c1890baa5bc63491513f94353439489d4283f", + "bytes": 979438 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-8e292-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "9aa3c23b69de83e0e4eae109c64d1420c60a3c1e8cc977bfdd6e2b9835b651ae", + "bytes": 869288 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-8e292-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "cef295b96dfab09abcabae384325e75fe1012226297eae9eff4c5dada7e8c136", + "bytes": 722407 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-9124e-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "06af38dc70a0eb2f5de3cd6e40ed39f2df5b8e80ce04314b4f86cde20400ff6d", + "bytes": 935910 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-9124e-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "9f3fcb1bd8fb270dffdc42fc5b8f7a2e2a232d8a31616eb154d26710a4be94d7", + "bytes": 908230 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-9124e-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "79951e185a1dd3fd796a59395601c82daa91d2ac363af221982c9f057c7cdf53", + "bytes": 760621 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-945b5-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "268bf06808ccfaacb9116d416a53669e7fb23c6b4d2461ac5a89c167b720bfa8", + "bytes": 800692 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-945b5-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "3524ead429acd988f17783fe2c0134741d85cab3e2a4826d77f3d5cc01896de0", + "bytes": 800871 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-candidate-cor-945b5-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "08268078c772e728d17aef9675b4347c473978cdf0cac61c7830b4c89a16701d", + "bytes": 531436 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-3457b-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "ff1f0f322a38d1fb6630e3752033b137d1f393c996eb4294e2835baa7e5404d6", + "bytes": 839699 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-3457b-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "4e219a43423a319b6c73f81b64d9b160957e692d4c79a1fcc2c4a2173c8260fc", + "bytes": 825265 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-3457b-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "d248226a971e68d87a9305af87c3a35a0932cee10eb30217d9506e5adf679d90", + "bytes": 549651 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-3c6d1-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "e104ee947b835da6ac02fb48b2970cf80fa77f91ea60fb23abdd1533d5fb2f52", + "bytes": 1048521 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-3c6d1-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "8c9d5b2d80bb0d7c5cc18e49d3b9a9e78710c4ec305bcb8f4a168e84aa37644c", + "bytes": 864264 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-3c6d1-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "318e8bca1d67f3e8e64755117e466aa36eec203f116208743bd80a9b832bfb64", + "bytes": 717480 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-4c264-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "4afa75914a400910edfb350d70a2795f900f4cc65b1e5c9f5087d9a20dc7aa9b", + "bytes": 1043432 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-4c264-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "f20708549e5991a8aeaf66428bd23a5255d0184c0f92ecb43f20a514f01e6410", + "bytes": 861620 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-4c264-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "0bc1e99b083193738036c6c7bc57afe31ee42dc9abf2ad63968cac524fc76a53", + "bytes": 714214 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-541e9-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "ff6e2151a35d34c74b22aee059ea2471b4efec59706ce5ae0ffd91f86eddea92", + "bytes": 1054795 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-541e9-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "0a53ce06a97902699083edee6ff4e7a12aa98577c1ba7640a468a3526b4b888a", + "bytes": 912997 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-541e9-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "e5a7480202aad0dd20aafeaf865788b2edcee86ef28abb695478c568fb313114", + "bytes": 736877 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-7dd29-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "7eeb94f6340e8ed17992f228081a25fa01419d6756a6eb174f5ed01b0d05e45b", + "bytes": 823746 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-7dd29-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "0427841cca8f45027c9b8a2881e8b68b27def769ea60fb87ab7a7b1296bbc74a", + "bytes": 936208 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-7dd29-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "7589b13cae1c2a7680f5f47763761c8af2b64cf151db1601baa4ebbb2146d608", + "bytes": 541092 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-b39ba-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "924894558503f61c186a63156468e45dc2210019e2d5500861c904e2d94086b9", + "bytes": 841167 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-b39ba-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "34f1ab0bc72927c3ae43ea2cbf01bdc09d43bf2f9a53d8d1cda95968778aeb6c", + "bytes": 1067532 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-b39ba-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "303977dcf3f95aff456d7e2cd91963f5675fd6fcac6b7c78aa3298eda256db2e", + "bytes": 495700 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-ba411-on-through-real-control-DOM-chromium/trace.zip", + "sha256": "e054b3be79701bbed0ba315382a270700e45ebd55403bc33758af185aa2e54ad", + "bytes": 799869 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-ba411-on-through-real-control-DOM-firefox/trace.zip", + "sha256": "78f08804bd12e59725da872e2a3a4c50b87dea1565bc455e5a3d42ea1d74bacc", + "bytes": 780849 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-ba411-on-through-real-control-DOM-webkit/trace.zip", + "sha256": "bbfb2d7b91a5a4af5644166b1d1d73e37b1490b5376faab482502dd7302dfb75", + "bytes": 550670 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-f0528-on-through-real-setting-DOM-chromium/trace.zip", + "sha256": "c44fcf3105c6ede5bd6aa52eccae243a3262b27ea976f9738ec256f556c24fbe", + "bytes": 1042334 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-f0528-on-through-real-setting-DOM-firefox/trace.zip", + "sha256": "5f3014a008a11eef716ccfd7d69dbb6c06168d56fc18eeada9a9562cef99f1b3", + "bytes": 881022 + }, + { + "file": "refactor/.cache/dash02-final/results/dash-control-published-cor-f0528-on-through-real-setting-DOM-webkit/trace.zip", + "sha256": "bf4af268ad2fc50739766f142581a93d274d848440457b37187a5e29ca37f978", + "bytes": 712287 + } + ], + "inputs": { + "published": { + "name": "artplayer-plugin-dash-control", + "version": "1.1.0", + "metadataUrl": "https://registry.npmjs.org/artplayer-plugin-dash-control/1.1.0", + "tarball": "https://registry.npmjs.org/artplayer-plugin-dash-control/-/artplayer-plugin-dash-control-1.1.0.tgz", + "integrity": "sha512-EssRkzYXWcln3a6nAzi4ESacBhzMih8s0bzdjXuvBBCh2UFmvK99ITD5E+0cuU8i5ZzIQGQSdce1/gANTrX0BQ==", + "sha256": "f4047a569d99b6a7de57b3719b7ad40109f2a1d360566a840f50ab32aacefcd9", + "archiveBytes": 3385, + "registryGitHead": "daf133b22630b4a0eecfa3336bbddab0e9119d96", + "files": { + "package/README.md": "98982f1123ff9a11f5d3d9a52da6e8fea9cd0989f7465605c27b0f9a46f2dbcd", + "package/dist/artplayer-plugin-dash-control.js": "f0cbbcf8badeaca13c05ae178932818cb52fbce37ed504ac0e62160b9c7e1145", + "package/dist/artplayer-plugin-dash-control.legacy.js": "f0cbbcf8badeaca13c05ae178932818cb52fbce37ed504ac0e62160b9c7e1145", + "package/dist/artplayer-plugin-dash-control.mjs": "e32bf08c33a481781883067dcc639f0495c9dcb8a88b91be13736370f4932fc4", + "package/package.json": "556e2adc479bab36c5973de617c0b57c5d86aa8425643a1952ab04738e9ce927", + "package/types/artplayer-plugin-dash-control.d.ts": "e15ef683e0c335d81531587828593325e037efe7ed29c022477cd14fe71aebba" + }, + "manifest": { + "name": "artplayer-plugin-dash-control", + "version": "1.1.0", + "description": "Dash control plugin for ArtPlayer", + "author": "Harvey Zhao ", + "license": "MIT", + "homepage": "https://artplayer.org", + "repository": { + "type": "git", + "url": "git+https://github.com/zhw2590582/ArtPlayer.git" + }, + "bugs": { + "url": "https://github.com/zhw2590582/ArtPlayer/issues" + }, + "keywords": [ + "html5", + "video", + "player" + ], + "exports": { + ".": { + "types": "./types/artplayer-plugin-dash-control.d.ts", + "import": "./dist/artplayer-plugin-dash-control.mjs", + "require": "./dist/artplayer-plugin-dash-control.js" + }, + "./legacy": { + "types": "./types/artplayer-plugin-dash-control.d.ts", + "import": "./dist/artplayer-plugin-dash-control.legacy.js", + "require": "./dist/artplayer-plugin-dash-control.legacy.js" + } + }, + "main": "./dist/artplayer-plugin-dash-control.js", + "module": "./dist/artplayer-plugin-dash-control.mjs", + "types": "./types/artplayer-plugin-dash-control.d.ts", + "legacy": "./dist/artplayer-plugin-dash-control.legacy.js", + "browserslist": "last 1 Chrome version" + } + }, + "sourceSHA256": "e7a64a47310374888b3b0deab445a15df3875fe2b8307fce70277e094520047b", + "candidate": "workspace source build", + "scope": "Real ArtPlayer DOM and native MP4 with controlled SDK methods. No dash.js instance, MPD, ABR or adaptive media validation." + }, + "browsers": [ + { + "project": "chromium", + "version": "153.0.8010.12", + "platform": "win32", + "manifest": { + "kind": "artplayer-browser-test", + "resources": { + "/candidate/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040 + }, + "/compiled/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040, + "aliasOf": "/candidate/artplayer.js" + }, + "/uncompiled/artplayer/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040, + "aliasOf": "/candidate/artplayer.js" + }, + "/candidate/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529 + }, + "/compiled/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/uncompiled/artplayer-plugin-chapter/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/published/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "/published/artplayer-plugin-chapter.js": { + "source": { + "kind": "npm-release", + "version": "1.1.0", + "integrity": "sha512-ji66Lr2K2S+OjFMuMby3yq+pefWlOC51Sbpop/DIr2N6w3F0smrF+YZbshN1Dy8/Tx1TYpT7N6WkkZWy5Jix1w==", + "member": "package/dist/artplayer-plugin-chapter.js" + }, + "sha256": "c2aaee11bf1db765433b01d9f8dd3978e41fa4d39655db00ebd03fc0be3e35e0", + "bytes": 4973 + }, + "/test/pattern.mp4": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.mp4" + }, + "sha256": "0ad1d7ad286aec6e0fa9e27fc1e487e7277df2e603e30040fb942365763d0233", + "bytes": 251538 + }, + "/test/pattern.webm": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.webm" + }, + "sha256": "9d3c2b3dec9581a599de2d6732992ef7846790e0d1368e6e131bd339b39e984f", + "bytes": 162073 + }, + "/test/audio-tone.m4a": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/audio-tone.m4a" + }, + "sha256": "83e6672b880b5d1c97093b1e26bdc40221c0b279615f40e99dbf9d2ade7b4d56", + "bytes": 132436 + }, + "/test/declaration-cues.vtt": { + "source": { + "kind": "test-subtitles", + "file": "test/browser/media/declaration-cues.vtt" + }, + "sha256": "5d149d4e641ce41cbb83376835c03daf1fb89f3b9f568fa59e064d51e2b57704", + "bytes": 54 + }, + "/test/thumbnail-grid.svg": { + "source": { + "kind": "test-thumbnail-grid", + "file": "test/browser/media/thumbnail-grid.svg" + }, + "sha256": "bb3f1ec9895d37def77ca4b192d3cd73577a2668558cc99de1588f511d65d3e6", + "bytes": 14969 + }, + "/test/legacy-safe-area.js": { + "source": { + "kind": "frozen-own-source", + "file": "test/helpers/legacy-safe-area.js", + "commit": "ccf77c4e" + }, + "sha256": "ce0368618ef6363b78271b8bcc7973abd0478e797cc464ddd912929e6dfa501a", + "bytes": 795 + }, + "/assets/sample/video.mp4": { + "source": { + "kind": "docs-media", + "file": "docs/assets/sample/video.mp4" + }, + "sha256": "30a2de667ba267b6bc605edcee1c4bd728c048ed76f500ea0e73d1f1a6f8f980", + "bytes": 5818706 + }, + "/test/performance.js": { + "source": { + "kind": "adapted-baseline-fixture", + "file": "refactor/fixtures/performance.js" + }, + "sha256": "2318f39bdb5f3a3348d755cb4335907ae4adc944be3a435839c1bba201e81500", + "bytes": 8994 + } + } + } + }, + { + "project": "firefox", + "version": "155.0", + "platform": "win32", + "manifest": { + "kind": "artplayer-browser-test", + "resources": { + "/candidate/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040 + }, + "/compiled/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040, + "aliasOf": "/candidate/artplayer.js" + }, + "/uncompiled/artplayer/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040, + "aliasOf": "/candidate/artplayer.js" + }, + "/candidate/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529 + }, + "/compiled/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/uncompiled/artplayer-plugin-chapter/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/published/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "/published/artplayer-plugin-chapter.js": { + "source": { + "kind": "npm-release", + "version": "1.1.0", + "integrity": "sha512-ji66Lr2K2S+OjFMuMby3yq+pefWlOC51Sbpop/DIr2N6w3F0smrF+YZbshN1Dy8/Tx1TYpT7N6WkkZWy5Jix1w==", + "member": "package/dist/artplayer-plugin-chapter.js" + }, + "sha256": "c2aaee11bf1db765433b01d9f8dd3978e41fa4d39655db00ebd03fc0be3e35e0", + "bytes": 4973 + }, + "/test/pattern.mp4": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.mp4" + }, + "sha256": "0ad1d7ad286aec6e0fa9e27fc1e487e7277df2e603e30040fb942365763d0233", + "bytes": 251538 + }, + "/test/pattern.webm": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.webm" + }, + "sha256": "9d3c2b3dec9581a599de2d6732992ef7846790e0d1368e6e131bd339b39e984f", + "bytes": 162073 + }, + "/test/audio-tone.m4a": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/audio-tone.m4a" + }, + "sha256": "83e6672b880b5d1c97093b1e26bdc40221c0b279615f40e99dbf9d2ade7b4d56", + "bytes": 132436 + }, + "/test/declaration-cues.vtt": { + "source": { + "kind": "test-subtitles", + "file": "test/browser/media/declaration-cues.vtt" + }, + "sha256": "5d149d4e641ce41cbb83376835c03daf1fb89f3b9f568fa59e064d51e2b57704", + "bytes": 54 + }, + "/test/thumbnail-grid.svg": { + "source": { + "kind": "test-thumbnail-grid", + "file": "test/browser/media/thumbnail-grid.svg" + }, + "sha256": "bb3f1ec9895d37def77ca4b192d3cd73577a2668558cc99de1588f511d65d3e6", + "bytes": 14969 + }, + "/test/legacy-safe-area.js": { + "source": { + "kind": "frozen-own-source", + "file": "test/helpers/legacy-safe-area.js", + "commit": "ccf77c4e" + }, + "sha256": "ce0368618ef6363b78271b8bcc7973abd0478e797cc464ddd912929e6dfa501a", + "bytes": 795 + }, + "/assets/sample/video.mp4": { + "source": { + "kind": "docs-media", + "file": "docs/assets/sample/video.mp4" + }, + "sha256": "30a2de667ba267b6bc605edcee1c4bd728c048ed76f500ea0e73d1f1a6f8f980", + "bytes": 5818706 + }, + "/test/performance.js": { + "source": { + "kind": "adapted-baseline-fixture", + "file": "refactor/fixtures/performance.js" + }, + "sha256": "2318f39bdb5f3a3348d755cb4335907ae4adc944be3a435839c1bba201e81500", + "bytes": 8994 + } + } + } + }, + { + "project": "webkit", + "version": "26.6", + "platform": "win32", + "manifest": { + "kind": "artplayer-browser-test", + "resources": { + "/candidate/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040 + }, + "/compiled/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040, + "aliasOf": "/candidate/artplayer.js" + }, + "/uncompiled/artplayer/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "df495dd386d32ea96be5006e1bbfda1ea91cfeb32aa21758197b46a155ebe0dc", + "bytes": 378040, + "aliasOf": "/candidate/artplayer.js" + }, + "/candidate/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529 + }, + "/compiled/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/uncompiled/artplayer-plugin-chapter/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "1a8eb891d3690e2526e78a2e53183a25367b1d02a5fd349d821548edb731ee3a", + "bytes": 8529, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/published/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "/published/artplayer-plugin-chapter.js": { + "source": { + "kind": "npm-release", + "version": "1.1.0", + "integrity": "sha512-ji66Lr2K2S+OjFMuMby3yq+pefWlOC51Sbpop/DIr2N6w3F0smrF+YZbshN1Dy8/Tx1TYpT7N6WkkZWy5Jix1w==", + "member": "package/dist/artplayer-plugin-chapter.js" + }, + "sha256": "c2aaee11bf1db765433b01d9f8dd3978e41fa4d39655db00ebd03fc0be3e35e0", + "bytes": 4973 + }, + "/test/pattern.mp4": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.mp4" + }, + "sha256": "0ad1d7ad286aec6e0fa9e27fc1e487e7277df2e603e30040fb942365763d0233", + "bytes": 251538 + }, + "/test/pattern.webm": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.webm" + }, + "sha256": "9d3c2b3dec9581a599de2d6732992ef7846790e0d1368e6e131bd339b39e984f", + "bytes": 162073 + }, + "/test/audio-tone.m4a": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/audio-tone.m4a" + }, + "sha256": "83e6672b880b5d1c97093b1e26bdc40221c0b279615f40e99dbf9d2ade7b4d56", + "bytes": 132436 + }, + "/test/declaration-cues.vtt": { + "source": { + "kind": "test-subtitles", + "file": "test/browser/media/declaration-cues.vtt" + }, + "sha256": "5d149d4e641ce41cbb83376835c03daf1fb89f3b9f568fa59e064d51e2b57704", + "bytes": 54 + }, + "/test/thumbnail-grid.svg": { + "source": { + "kind": "test-thumbnail-grid", + "file": "test/browser/media/thumbnail-grid.svg" + }, + "sha256": "bb3f1ec9895d37def77ca4b192d3cd73577a2668558cc99de1588f511d65d3e6", + "bytes": 14969 + }, + "/test/legacy-safe-area.js": { + "source": { + "kind": "frozen-own-source", + "file": "test/helpers/legacy-safe-area.js", + "commit": "ccf77c4e" + }, + "sha256": "ce0368618ef6363b78271b8bcc7973abd0478e797cc464ddd912929e6dfa501a", + "bytes": 795 + }, + "/assets/sample/video.mp4": { + "source": { + "kind": "docs-media", + "file": "docs/assets/sample/video.mp4" + }, + "sha256": "30a2de667ba267b6bc605edcee1c4bd728c048ed76f500ea0e73d1f1a6f8f980", + "bytes": 5818706 + }, + "/test/performance.js": { + "source": { + "kind": "adapted-baseline-fixture", + "file": "refactor/fixtures/performance.js" + }, + "sha256": "2318f39bdb5f3a3348d755cb4335907ae4adc944be3a435839c1bba201e81500", + "bytes": 8994 + } + } + } + } + ], + "errors": [] + } + ], + "logs": [ + { + "file": "refactor/.cache/dash02-node-first.log", + "sha256": "b422bb3184fedccfde1e80513f8d32e8058e7763ca15217eba911c3276f96d2b", + "bytes": 7368 + }, + { + "file": "refactor/.cache/dash02-node-final.log", + "sha256": "5abea1ebfacd12ed6420e25a4f182da84ecd2ed54a7065537fba459771def596", + "bytes": 7367 + }, + { + "file": "refactor/.cache/dash02-browser-first.log", + "sha256": "3f225a798c1b24da4dd0aecc1fec6f24c926a3f8ded59bd3a410e60d19dc68ca", + "bytes": 78961 + }, + { + "file": "refactor/.cache/dash02-browser-final.log", + "sha256": "e66a1ada79b7129055191f39d324150f74fce0a14b3b42d6eeab4a85269c78c1", + "bytes": 9624 + }, + { + "file": "refactor/.cache/dash02-ci.log", + "sha256": "cc4e02ab21074455bfd184bd9bf6dd596a14494c8c8d19e5b71e9b5e2bb674b3", + "bytes": 70378 + } + ], + "totals": { + "nodeFocused": 74, + "ciUnit": 619, + "ciEngineering": 14, + "ciBaseline": 37, + "browserFirst": { + "passed": 24, + "failed": 24 + }, + "browserFinal": { + "passed": 48, + "failed": 0 + } + }, + "limitation": "Raw reports/traces are local cache, not committed/uploaded. First failures preserve the whole-row text locator error; final assertions retain SDK selection, both UI surfaces and native playback checks." +} diff --git a/refactor/changes/2026-09-12-PKG-DASH-02-tests.md b/refactor/changes/2026-09-12-PKG-DASH-02-tests.md new file mode 100644 index 000000000..bf7fce3b4 --- /dev/null +++ b/refactor/changes/2026-09-12-PKG-DASH-02-tests.md @@ -0,0 +1,22 @@ +# PKG-DASH-02:DASH 特有行为与错误测试 + +起点 `3d4c6361`,新增源码/冻结工作区/真实 npm 三格式行为测试和三引擎真实 DOM 交互测试。 +保留原有 5 项稳定 ID 回归,补全音轨、默认参数、排序去重、ABR、原始对象/调用身份、 +同步异常、换 SDK、多实例、空拓扑、销毁后引用与历史高亮问题。 + +维护入口及范围见 [验证说明](../dash-validation.md),输入/报告指纹见 +[执行证据](../baselines/dash-validation.json)。本步只建立测试,不改生产源码、公开类型、 +README、demo、构建产物或依赖。测试脚本接入已有 `test:unit` 和 `test:dash-control`。 +生产模块图将在 03/04 随实际拆分交付,不能提前描述尚未实现的结构。 + +定向 Node 74 项通过。浏览器首轮 24 通过/24 定位失败,trace 证明 SVG 换行使整行精确 +匹配失效;修正为专用文字节点,原有断言不变,最终 48 项通过、无重试/跳过。 +实际 SDK/MPD 解码不在这 48 项证据内,05 仍须验证两代固定 SDK。 + +完整 CI 670 项通过(619 单元、14 工程、37 基线),包括严格类型、声明漂移和 lint。 +最终任务/风险校验通过,217 项任务为 72 done、3 doing、142 todo。 +本步复现的 DASH-SDK-01、DASH-LIFE-01、DASH-STATE-01 +均保持 open,明确由 03/05 接续。没有以历史缺陷观察替代候选修复断言。 + +本任务独立本地 commit;回退本提交撤回新增测试、脚本接入和记录,生产行为不变。 +未 push/tag/publish/merge;全项目目标未完成。下一任务 PKG-DASH-03。 diff --git a/refactor/dash-validation.md b/refactor/dash-validation.md new file mode 100644 index 000000000..2cc60f621 --- /dev/null +++ b/refactor/dash-validation.md @@ -0,0 +1,45 @@ +# DASH Control 验证与维护入口 + +PKG-DASH-02 保护真实 npm 1.1.0 的既有调用契约,以及重构前工作区的 SDK 5.x 稳定 ID +修正。版本来源见 [发布契约](baselines/dash-control-contract.md)。本步没有更改生产实现。 + +## 可重跑的测试 + +- `yarn test:dash-control`:原有 5 项过滤/稳定 ID 回归和新增 69 项行为测试,共 74 项。 + 该脚本和 `test:unit` 都保留旧测试,完整 CI 自动执行。 +- `yarn test:browser test/browser/dash-control.spec.js --trace on`:48 项,两个核心、两个插件、 + 两类菜单、两种选择、Chromium/Firefox/WebKit。浏览器套件串行运行,避免共享端口和报告覆盖。 +- `yarn ci:check`:工具链、计划、lint、声明漂移、严格类型和 Node/基线测试。 + +Node helper 分别加载当前源码、固定 Git 提交的旧工作区 UMD、实际 npm main/legacy/module。 +Git 内容以 LF 指纹核对,发布归档与成员以原始字节指纹核对。`ARTPLAYER_TEST_DASH` 可指定 +待测产物,以系统路径分隔符连接;未设置时不会把源码测试冒充三种候选产物验证。 + +`test/helpers/dash-control.js` 只提供可控 SDK 方法和组件注册表,检查 this、类型参数、 +原始轨道身份、调用顺序、错误身份、ABR 配置保留、换 SDK、多实例和关闭后的引用。 +真实旧实现的缺陷观察保持冻结;03 修复时为候选实现新增正确行为断言,不把历史缺陷当作兼容要求。 + +浏览器使用真实发布/候选 ArtPlayer DOM、真实发布/候选插件和本地原生 MP4。SDK 方法可控, +断言真实点击触发的参数及控制栏/设置同步,再通过真实播放按钮验证视频时钟推进、无媒体错误。 +**没有加载 dash.js,没有验证 MPD、ABR 自动切换或自适应流解码。** 这些仍是 05 必须完成的 +固定 dash.js 4.5.2 / 5.2.1 集成验证。`ARTPLAYER_DASH_ARTIFACT` 可替换插件脚本;本次没有使用。 + +## 首次失败与证据 + +首次浏览器运行 24 通过、24 失败;全部失败位于设置选项文字定位。trace 中选项确实已渲染, +整行文本包含图标 SVG 的换行,`^fr$`/`^720p$` 不能匹配。改为当前面板内专用 +`.art-setting-item-left-text` 的精确文本定位;保持原有调用、同步和播放断言,没有增大超时或跳过。 +补充清理前行文本诊断,最终 48 项通过;候选设置选择的截图已人工查看,文字与控制栏一致。 + +首轮与最终报告、全部结果/trace 目录都保留在本地缓存;输入和证据指纹见 +[本步执行记录](baselines/dash-validation.json)。缓存不入 Git,永久保存的是测试、来源和结果摘要; +换机器应按上述命令重新取得执行证据,不能声称本地 trace 已上传。 + +## 下一步缺陷与边界 + +- DASH-SDK-01:两代旧实现分别在另一代 SDK 方法表上失败。03 通过能力适配恢复旧用法。 +- DASH-LIFE-01:空列表/禁用后 UI 残留,旧回调仍写旧 SDK,销毁后 update 和订阅仍有效。 +- DASH-STATE-01:克隆当前轨道、重复标签、数字零 representation ID 会丢失高亮。 + +这些受控复现仍是 open,不能以本步绿色测试关闭。03 处理结构、清理与正确当前项,04 完成公开 +类型兼容,05 完成真实 SDK/媒体/组合验证,06 完成包分发验收。物理设备和 npm 发布准入仍待完成。 diff --git a/refactor/plan.md b/refactor/plan.md index 4ec126eb7..ba8b69941 100644 --- a/refactor/plan.md +++ b/refactor/plan.md @@ -4,7 +4,7 @@ 基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 217 项,范围 22 个包及工作区/示例。 -状态:todo 143 / doing 3 / blocked 0 / done 71 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 +状态:todo 142 / doing 3 / blocked 0 / done 72 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。 @@ -202,7 +202,7 @@ | ID | 范围 / 步骤 | 前置依赖 | 交付物 | 验收条件 | 风险 | 状态 | | --- | --- | --- | --- | --- | --- | --- | | PKG-DASH-01 | artplayer-plugin-dash-control
核对包契约与历史用法 | BASE-05 | quality/audio、representation ID/Auto、getName 和 update | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结 | H | done | -| PKG-DASH-02 | artplayer-plugin-dash-control
建立特有行为与错误测试 | PKG-DASH-01, ENG-03, ENG-05 | 保留已有 5 项稳定 ID 回归,补发布版 SDK 4.x/当前 5.x、音轨/空列表/过滤/换源与关闭引用 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | todo | +| PKG-DASH-02 | artplayer-plugin-dash-control
建立特有行为与错误测试 | PKG-DASH-01, ENG-03, ENG-05 | 保留已有 5 项稳定 ID 回归,补发布版 SDK 4.x/当前 5.x、音轨/空列表/过滤/换源与关闭引用 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | done | | PKG-DASH-03 | artplayer-plugin-dash-control
整理内部职责与资源 | PKG-DASH-02, CORE-11, CORE-14 | 能力适配保留 SDK 4.x 与 5.x,稳定 ID 映射、ABR 状态、UI 清理和生命周期职责分离 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | todo | | PKG-DASH-04 | artplayer-plugin-dash-control
迁移自有源码和公开类型 | PKG-DASH-03, ENG-04, ENG-06, CORE-07 | dash.js adapter、selector 和回调类型 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | todo | | PKG-DASH-05 | artplayer-plugin-dash-control
验证新旧核心和组合 | PKG-DASH-04, CORE-22 | 固定 dash.js 4.5.2/5.2.1 与本地 DASH 实际清晰度/音轨、高亮、Auto 和换源组合 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | todo | @@ -480,3 +480,4 @@ - PKG-HLS-04: [记录](changes/2026-09-12-PKG-HLS-04-types.md) [记录](baselines/hls-types-validation.json) [记录](hls-validation.md) - PKG-HLS-SDK-01: [记录](changes/2026-09-12-PKG-HLS-SDK-01-integration.md) [记录](baselines/hls-sdk-validation.json) [记录](baselines/hls-sdk-diagnostics.json) - PKG-DASH-01: [记录](changes/2026-09-12-PKG-DASH-01-contract.md) [记录](baselines/dash-control-contract.md) [记录](baselines/dash-control-release.json) +- PKG-DASH-02: [记录](changes/2026-09-12-PKG-DASH-02-tests.md) [记录](dash-validation.md) [记录](baselines/dash-validation.json) diff --git a/refactor/progress.md b/refactor/progress.md index 0924db3fc..ebcfa9d4b 100644 --- a/refactor/progress.md +++ b/refactor/progress.md @@ -1,5 +1,18 @@ # 进度与证据 +## 最新完成:DASH-02 行为测试与真实 DOM 交互 + +保留原有 5 项稳定 ID 回归,新增发布三格式/冻结工作区/候选源码契约测试,定向 74 项通过。 +完整 CI 670 项通过(619 单元、14 工程、37 基线),未修改生产源码、声明、依赖或产物。 +新旧核心/插件、控制栏/设置、质量/音轨三引擎最终 48 项通过。首轮 24 通过/24 失败的报告 +及全部 trace 已保留;失败原因是 SVG 换行使整行精确定位失效,改为专用文本节点,未放宽断言。 + +浏览器使用真实 DOM 和原生 MP4,SDK 方法受控;不代表 dash.js/MPD/ABR 实际集成通过。 +SDK 两代不兼容、过期 UI/引用、当前项高亮问题已受控复现,仍保持 open,03/05 接续修复验证。 +当前 217 项:72 done、3 doing、142 todo。下一步 DASH-03 开始源码职责和 SDK 适配改造。 +详见 [本次变更](changes/2026-09-12-PKG-DASH-02-tests.md) 与 [验证维护入口](dash-validation.md)。 +本任务独立本地提交,不推送/发布;其他媒体和设备风险、全包发布准入仍未完成。 + ## 最新完成:DASH-01 发布版与 SDK 兼容契约 已校验 DASH Control 1.1.0 的实际 npm 归档及 6 个成员。发现发布版使用 dash.js 4.x diff --git a/refactor/risk-table.md b/refactor/risk-table.md index 5d06aa8c0..af2d04f3d 100644 --- a/refactor/risk-table.md +++ b/refactor/risk-table.md @@ -135,8 +135,8 @@ | AUDIO-BUFFER-01 | open / 已复现 | Windows WebKit 原生媒体无法在受限响应下推进至真实缓冲 | PKG-AUDIO-05 | | CHAPTER-LAYOUT-01 | resolved / 已复现 | 长章节标题超出窄播放器进度条宽度 | PKG-CHAPTER-05 | | CHAPTER-TIMING-01 | open / 已复现 | Windows WebKit 清晰度切换曾在等待窗口内未见 restart,稍后状态恢复 | PKG-CHAPTER-05 | -| DASH-SDK-01 | open / 源码/产物事实 | npm 发布版 4.x 与工作区仅 5.x 的 SDK 接口不兼容 | PKG-DASH-02, PKG-DASH-03, PKG-DASH-05 | -| DASH-LIFE-01 | open / 源码/产物事实 | DASH 空拓扑残留 UI,监听和旧选择回调缺乏关闭守卫 | PKG-DASH-02, PKG-DASH-03 | -| DASH-STATE-01 | open / 源码/产物事实 | DASH 当前项高亮使用真值 ID、音轨身份和标签去重,边界待核实 | PKG-DASH-02, PKG-DASH-03, PKG-DASH-05 | +| DASH-SDK-01 | open / 已复现 | npm 发布版 4.x 与工作区仅 5.x 的 SDK 接口不兼容 | PKG-DASH-02, PKG-DASH-03, PKG-DASH-05 | +| DASH-LIFE-01 | open / 已复现 | DASH 空拓扑残留 UI,监听和旧选择回调缺乏关闭守卫 | PKG-DASH-02, PKG-DASH-03 | +| DASH-STATE-01 | open / 已复现 | DASH 当前项高亮使用真值 ID、音轨身份和标签去重,边界待核实 | PKG-DASH-02, PKG-DASH-03, PKG-DASH-05 | | DASH-TYPE-01 | open / 源码/产物事实 | DASH 类型未表达默认工厂参数、SDK 回调对象和现代模块入口 | PKG-DASH-04 | | DASH-DEMO-01 | open / 源码/产物事实 | DASH 示例仅新 SDK 且重复安装会累积销毁回调 | PKG-DASH-06 | diff --git a/refactor/risks.json b/refactor/risks.json index 0516fd3cd..861bf99a1 100644 --- a/refactor/risks.json +++ b/refactor/risks.json @@ -2834,7 +2834,7 @@ { "id": "DASH-SDK-01", "title": "npm 发布版 4.x 与工作区仅 5.x 的 SDK 接口不兼容", - "confirmation": "source-observed", + "confirmation": "reproduced", "status": "open", "owners": [ "PKG-DASH-02", @@ -2846,7 +2846,9 @@ "refactor/baselines/dash-control-release.json", "packages/artplayer-plugin-dash-control/src/index.js", "packages/artplayer-plugin-dash-control/types/artplayer-plugin-dash-control.d.ts", - "docs/assets/example/dash.control.js" + "docs/assets/example/dash.control.js", + "test/dash-contract.test.js", + "refactor/dash-validation.md" ], "compatibleResolution": "按方法能力适配两代已存在用法,保留 v5 稳定 ID,不能要求旧消费者改用新 SDK。", "closureCriteria": "归档旧用法、v4/v5 受控及实际媒体矩阵通过,清晰度键不混用。" @@ -2854,7 +2856,7 @@ { "id": "DASH-LIFE-01", "title": "DASH 空拓扑残留 UI,监听和旧选择回调缺乏关闭守卫", - "confirmation": "source-observed", + "confirmation": "reproduced", "status": "open", "owners": [ "PKG-DASH-02", @@ -2865,7 +2867,9 @@ "refactor/baselines/dash-control-release.json", "packages/artplayer-plugin-dash-control/src/index.js", "packages/artplayer-plugin-dash-control/types/artplayer-plugin-dash-control.d.ts", - "docs/assets/example/dash.control.js" + "docs/assets/example/dash.control.js", + "test/dash-contract.test.js", + "refactor/dash-validation.md" ], "compatibleResolution": "仅释放插件自有 ready/restart/destroy 订阅和 UI,SDK 仍由调用方拥有;替换后旧回调不写旧实例。", "closureCriteria": "空列表、换源/SDK、销毁后引用、安装异常有回归,其他实例与 SDK 不被误释放。" @@ -2873,7 +2877,7 @@ { "id": "DASH-STATE-01", "title": "DASH 当前项高亮使用真值 ID、音轨身份和标签去重,边界待核实", - "confirmation": "source-observed", + "confirmation": "reproduced", "status": "open", "owners": [ "PKG-DASH-02", @@ -2885,7 +2889,9 @@ "refactor/baselines/dash-control-release.json", "packages/artplayer-plugin-dash-control/src/index.js", "packages/artplayer-plugin-dash-control/types/artplayer-plugin-dash-control.d.ts", - "docs/assets/example/dash.control.js" + "docs/assets/example/dash.control.js", + "test/dash-contract.test.js", + "refactor/dash-validation.md" ], "compatibleResolution": "验证零 ID、重复标签和克隆音轨当前项,在保持原展示语义时按实际可选项定位高亮。", "closureCriteria": "有受控和真实 SDK 证据说明选中的 representation/track 与 UI 一致。" diff --git a/refactor/tasks.json b/refactor/tasks.json index 9939cadde..777e2919f 100644 --- a/refactor/tasks.json +++ b/refactor/tasks.json @@ -1992,11 +1992,15 @@ "ENG-03", "ENG-05" ], - "status": "todo", + "status": "done", "risk": "H", "deliverable": "保留已有 5 项稳定 ID 回归,补发布版 SDK 4.x/当前 5.x、音轨/空列表/过滤/换源与关闭引用", "acceptance": "旧版本行为可重跑,成功/失败/切源/销毁有必要断言", - "evidence": [] + "evidence": [ + "changes/2026-09-12-PKG-DASH-02-tests.md", + "dash-validation.md", + "baselines/dash-validation.json" + ] }, { "id": "PKG-DASH-03", diff --git a/test/browser/dash-control.spec.js b/test/browser/dash-control.spec.js new file mode 100644 index 000000000..e986a0669 --- /dev/null +++ b/test/browser/dash-control.spec.js @@ -0,0 +1,171 @@ +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 { expect, test } from './fixtures.js' + +let publishedCode +let sourceCode +let evidence +test.beforeAll(async () => { + const { release } = JSON.parse(fs.readFileSync(new URL('../../refactor/baselines/dash-control-release.json', import.meta.url))) + + const member = 'package/dist/artplayer-plugin-dash-control.js' + + 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.' } +}) + +test.afterEach(async ({ page }, testInfo) => { + const state = await page.evaluate(() => ({ + calls: window.dashCalls, + ready: window.art?.isReady, + time: window.art?.currentTime, + videoError: window.art?.video.error?.code || null, + quality: window.art?.controls['dash-quality']?.textContent, + audio: window.art?.controls['dash-audio']?.textContent, + settingRows: [...document.querySelectorAll('.art-setting-panel.art-current .art-setting-item')].map(row => ({ text: row.textContent, label: row.querySelector('.art-setting-item-left-text')?.textContent })), + })).catch(error => ({ error: error.message })) + + await testInfo.attach('controlled-dash-state', { contentType: 'application/json', body: JSON.stringify(state) }) + + if (!page.isClosed()) + await page.evaluate(() => window.art?.destroy()) +}) + +async function openDash(page, core, plugin, testInfo) { + await testInfo.attach('controlled-dash-inputs', { contentType: 'application/json', body: JSON.stringify(evidence) }) + + await page.goto(`/test/player.html?core=${core}`) + + await page.addScriptTag({ content: plugin === 'published' ? publishedCode : sourceCode }) + + await page.evaluate((sdk) => { + window.dashCalls = [] + + window.art = new window.Artplayer({ + container: '.player', + url: '/test/pattern.mp4', + muted: true, + setting: true, + plugins: [(art) => { + const levels = sdk === 4 + ? [{ qualityIndex: 0, height: 360 }, { qualityIndex: 1, height: 720 }] + : [{ id: 'low', height: 360 }, { id: 'high', height: 720 }] + + const tracks = [{ id: 'en', lang: 'en' }, { id: 'fr', lang: 'fr' }] + + window.dashState = { levels, tracks, track: tracks[0], current: levels[0], quality: 0, settings: { streaming: { abr: { autoSwitchBitrate: { video: true } } } } } + + const state = window.dashState + + art.dash = { + getVideoElement: () => art.template.$video, + getSettings: () => state.settings, + updateSettings(update) { + state.settings.streaming.abr.autoSwitchBitrate.video = update.streaming.abr.autoSwitchBitrate.video + window.dashCalls.push(['auto', state.settings.streaming.abr.autoSwitchBitrate.video]) + }, + getTracksFor: () => state.tracks, + getCurrentTrackFor: () => state.track, + setCurrentTrack(track) { + state.track = track + window.dashCalls.push(['track', track.id, tracks.includes(track)]) + }, + } + + if (sdk === 4) { + Object.assign(art.dash, { + getBitrateInfoListFor: () => levels, + getQualityFor: () => state.quality, + setQualityFor(type, index) { + state.quality = index + window.dashCalls.push(['qualityIndex', type, index]) + }, + }) + } + else { + Object.assign(art.dash, { + getRepresentationsByType: () => levels, + getCurrentRepresentationForType: () => state.current, + setRepresentationForTypeById(type, id) { + state.current = levels.find(level => level.id === id) + window.dashCalls.push(['representationId', type, id]) + }, + }) + } + + return window.artplayerPluginDashControl({ quality: { control: true, setting: true }, audio: { control: true, setting: true } })(art) + }], + }) + + document.querySelector('#play').onclick = () => window.art.play() + + document.querySelector('#pause').onclick = () => window.art.pause() + }, plugin === 'published' ? 4 : 5) + + await expect.poll(() => page.evaluate(() => window.art.isReady)).toBe(true) + + await expect(page.locator('.art-control-dash-quality .art-selector-value')).toHaveText('Auto') + + await expect(page.locator('.art-control-dash-audio .art-selector-value')).toHaveText('en') +} + +for (const core of ['published', 'candidate']) { + for (const plugin of ['published', 'candidate']) { + for (const surface of ['control', 'setting']) { + for (const type of ['quality', 'audio']) { + test(`${core} core + ${plugin} DASH: controlled SDK ${type} selection through real ${surface} DOM`, async ({ page }, testInfo) => { + await openDash(page, core, plugin, testInfo) + + const text = type === 'quality' ? '720p' : 'fr' + + if (surface === 'control') { + const control = page.locator(`.art-control-dash-${type}`) + + await control.hover() + + await expect(control.locator('.art-selector-list')).toHaveCSS('opacity', '1') + + await control.locator('.art-selector-item').filter({ hasText: new RegExp(`^${text}$`) }).click() + } + else { + await page.locator('.art-control-setting').click() + + await page.locator(`[data-name="dash-${type}"]`).click() + + await page.locator('.art-setting-panel.art-current .art-setting-item-left-text').filter({ hasText: new RegExp(`^${text}$`) }).click() + } + + const expected = type === 'quality' + ? [['auto', false], plugin === 'published' ? ['qualityIndex', 'video', 1] : ['representationId', 'video', 'high']] + : [['track', 'fr', true]] + + await expect.poll(() => page.evaluate(() => window.dashCalls)).toEqual(expected) + + await expect(page.locator(`.art-control-dash-${type} .art-selector-value`)).toHaveText(text) + + expect(await page.evaluate(type => window.art.setting.find(`dash-${type}`).tooltip, type)).toBe(text) + + await testInfo.attach('controlled-dash-selection', { contentType: 'image/png', body: await page.screenshot() }) + + await page.locator('#play').click() + + await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeGreaterThan(0.2) + + expect(await page.evaluate(() => window.art.video.error)).toBeNull() + }) + } + } + } +} diff --git a/test/dash-contract.test.js b/test/dash-contract.test.js new file mode 100644 index 000000000..934189376 --- /dev/null +++ b/test/dash-contract.test.js @@ -0,0 +1,263 @@ +import assert from 'node:assert/strict' +// eslint-disable-next-line test/no-import-node-test -- Controlled plugin contracts use Node's built-in runner. +import test from 'node:test' +import { bothMenus, dashHost, dashImplementations } from './helpers/dash-control.js' + +const implementations = await dashImplementations() +const abr = video => ({ streaming: { abr: { autoSwitchBitrate: { video } } } }) +for (const { name, factory, sdk } of implementations) { + test(`${name}: optional factory, deferred SDK binding and synchronous update shape`, () => { + const host = dashHost(sdk) + delete host.art.dash + const result = factory()(host.art) + assert.deepEqual(Object.keys(result).sort(), ['name', 'update']) + assert.equal(result.name, 'artplayerPluginDashControl') + assert.equal(host.calls.length, 0) + host.art.dash = host.dash + assert.equal(result.update(), undefined) + assert.equal(host.controls.size, 0) + assert.equal(host.settings.size, 0) + }) + test(`${name}: ready/restart render named surfaces and preserve default Auto/audio behavior`, () => { + const host = dashHost(sdk) + factory(bothMenus())(host.art) + assert.equal(host.controls.size, 0) + host.art.emit('ready') + assert.deepEqual([...host.controls.keys()], ['dash-quality', 'dash-audio']) + assert.deepEqual([...host.settings.keys()], ['dash-quality', 'dash-audio']) + const quality = host.controls.get('dash-quality') + const audio = host.controls.get('dash-audio') + assert.equal(quality.html, 'Auto') + assert.deepEqual(Array.from(quality.selector, item => item.html), ['1080p', '720p', '360p', 'Auto']) + assert.deepEqual(Array.from(quality.selector).filter(item => item.default).map(item => item.value), ['auto']) + assert.equal(audio.html, 'en') + assert.deepEqual(Array.from(audio.selector, item => item.value), host.state.tracks) + assert.equal(audio.selector[0].default, true) + assert.equal(audio.selector.length, 2, 'Audio has no synthetic Auto item') + for (const key of ['dash-quality', 'dash-audio']) { + assert.equal(host.controls.get(key).position, 'right') + assert.equal(host.controls.get(key).style.padding, '0 10px') + assert.equal(host.settings.get(key).width, 200) + assert.match(host.settings.get(key).icon, / call[0]), ['controls.update', 'setting.update', 'controls.update', 'setting.update']) + }) + test(`${name}: selectors preserve SDK/check identities, notice order and sync return values`, () => { + for (const surface of ['controls', 'settings']) { + const host = dashHost(sdk) + factory(bothMenus())(host.art).update() + const menu = host[surface].get('dash-quality') + const item = menu.selector[0] + host.calls.length = 0 + assert.equal(menu.onSelect(item), '1080p') + assert.deepEqual(host.calls, [ + ['updateSettings', abr(false)], + sdk === 4 ? ['setQualityFor', 'video', 2] : ['setRepresentationForTypeById', 'video', 'top'], + ['notice', 'Quality: 1080p'], + ['controls.check', item], + ['setting.check', item], + ]) + assert.equal(host.state.settings.streaming.abr.autoSwitchBitrate.audio, false) + assert.equal(host.state.settings.streaming.abr.minBitrate.video, -1) + host.calls.length = 0 + const auto = menu.selector.at(-1) + assert.equal(menu.onSelect(auto), 'Auto') + assert.deepEqual(host.calls, [['updateSettings', abr(true)], ['notice', 'Quality: Auto'], ['controls.check', auto], ['setting.check', auto]]) + const audio = host[surface].get('dash-audio') + const track = audio.selector[1] + host.calls.length = 0 + assert.equal(audio.onSelect(track), 'fr') + assert.equal(host.state.currentTrack, host.state.tracks[1]) + assert.deepEqual(host.calls, [['setCurrentTrack', host.state.tracks[1]], ['notice', 'Audio: fr'], ['controls.check', track], ['setting.check', track]]) + } + }) + test(`${name}: getName sees original objects, one argument and no receiver binding`, () => { + const host = dashHost(sdk) + host.state.settings.streaming.abr.autoSwitchBitrate.video = false + const qualityCalls = [] + const audioCalls = [] + const options = bothMenus() + options.quality.getName = function (...args) { + qualityCalls.push([this, args]) + return `Q${args[0].height}` + } + options.audio.getName = function (...args) { + audioCalls.push([this, args]) + return `A${args[0].lang}` + } + factory(options)(host.art).update() + assert.deepEqual(qualityCalls.map(([receiver, args]) => [receiver, args.length, args[0]]), [host.state.levels[1], ...host.state.levels].map(item => [undefined, 1, item])) + assert.deepEqual(audioCalls.map(([receiver, args]) => [receiver, args.length, args[0]]), [host.state.tracks[0], ...host.state.tracks].map(item => [undefined, 1, item])) + assert.equal(host.controls.get('dash-quality').html, 'Q720') + assert.equal(host.controls.get('dash-audio').html, 'Aen') + }) + test(`${name}: labels deduplicate without mutating caller SDK arrays`, () => { + const host = dashHost(sdk) + host.state.levels[1].height = 360 + host.state.tracks[1].lang = 'en' + const levels = [...host.state.levels] + const tracks = [...host.state.tracks] + const before = JSON.stringify({ levels, tracks }) + factory(bothMenus())(host.art).update() + assert.deepEqual(Array.from(host.controls.get('dash-quality').selector, item => item.html), ['1080p', '360p', 'Auto']) + assert.equal(host.controls.get('dash-audio').selector.length, 1) + assert.equal(host.controls.get('dash-audio').selector[0].value, tracks[0]) + assert.equal(JSON.stringify({ levels: host.state.levels, tracks: host.state.tracks }), before) + assert.deepEqual(host.state.levels, levels) + }) + test(`${name}: explicit quality keys survive noncontiguous SDK metadata`, () => { + const host = dashHost(sdk) + host.state.levels.forEach((level, index) => { + level[sdk === 4 ? 'qualityIndex' : 'absoluteIndex'] = 10 + index * 20 + }) + factory(bothMenus())(host.art).update() + const menu = host.controls.get('dash-quality') + const item = menu.selector.find(item => item.html === '720p') + host.calls.length = 0 + menu.onSelect(item) + assert.deepEqual(host.calls[1], sdk === 4 ? ['setQualityFor', 'video', 30] : ['setRepresentationForTypeById', 'video', 'high']) + }) + test(`${name}: empty topology has no UI and later ready data can render`, () => { + const host = dashHost(sdk) + const { levels, tracks } = host.state + host.state.levels = [] + host.state.tracks = null + const plugin = factory(bothMenus())(host.art) + plugin.update() + assert.equal(host.calls.length, 0) + host.state.levels = levels + host.state.tracks = tracks + host.art.emit('ready') + assert.equal(host.controls.size, 2) + }) + test(`${name}: truthy label defaults and per-surface enablement remain unchanged`, () => { + const host = dashHost(sdk) + factory({ quality: { control: true, title: '', auto: '' }, audio: { setting: true, title: '' } })(host.art).update() + assert.deepEqual([...host.controls.keys()], ['dash-quality']) + assert.deepEqual([...host.settings.keys()], ['dash-audio']) + assert.equal(host.controls.get('dash-quality').html, 'Auto') + assert.equal(host.settings.get('dash-audio').html, 'Audio') + host.calls.length = 0 + const audio = host.settings.get('dash-audio') + audio.onSelect(audio.selector[1]) + assert.equal(host.calls.some(call => call[0] === 'controls.check'), false) + }) + test(`${name}: missing and wrong media ownership fails synchronously`, () => { + const host = dashHost(sdk) + const plugin = factory(bothMenus())(host.art) + host.state.video = {} + assert.throws(plugin.update, { message: 'Cannot find instance of DASH from "art.dash"' }) + assert.equal(host.controls.size, 0) + delete host.art.dash + assert.throws(plugin.update, { name: 'TypeError' }) + host.art.dash = host.dash + host.state.video = host.video + plugin.update() + assert.equal(host.controls.size, 2) + }) + test(`${name}: caller getName and SDK setter failures preserve error identity`, () => { + const host = dashHost(sdk) + const failure = new Error('caller failure') + const options = bothMenus() + options.quality.getName = () => { + throw failure + } + const plugin = factory(options)(host.art) + assert.throws(plugin.update, error => error === failure) + assert.equal(host.controls.size, 0) + delete options.quality.getName + plugin.update() + host.dash[sdk === 4 ? 'setQualityFor' : 'setRepresentationForTypeById'] = () => { + throw failure + } + host.calls.length = 0 + const menu = host.controls.get('dash-quality') + assert.throws(() => menu.onSelect(menu.selector[0]), error => error === failure) + assert.deepEqual(host.calls, [['updateSettings', abr(false)]]) + }) + test(`${name}: SDK replacement and multiple hosts retain independent selections`, () => { + const left = dashHost(sdk) + const right = dashHost(sdk) + factory(bothMenus())(left.art).update() + factory(bothMenus())(right.art).update() + right.state.video = left.video + left.art.dash = right.dash + left.art.emit('restart') + left.calls.length = 0 + right.calls.length = 0 + const menu = left.controls.get('dash-audio') + menu.onSelect(menu.selector[1]) + assert.equal(right.state.currentTrack, right.state.tracks[1]) + assert.equal(left.state.currentTrack, left.state.tracks[0]) + assert.equal(left.calls.some(call => call[0] === 'setCurrentTrack'), false) + assert.equal(right.calls[0][0], 'setCurrentTrack') + }) +} +// These historical factories stay frozen when the live source is repaired. +for (const { name, factory, sdk } of implementations.filter(item => item.name.startsWith('published') || item.name === 'pre-refactor-v5')) { + test(`${name} observation DASH-LIFE-01: empty/disabled surfaces remain registered`, () => { + const host = dashHost(sdk) + const options = bothMenus() + const plugin = factory(options)(host.art) + plugin.update() + const previous = host.controls.get('dash-quality') + host.state.levels = [] + host.state.tracks = [] + plugin.update() + assert.equal(host.controls.get('dash-quality'), previous) + options.quality.control = options.quality.setting = false + options.audio.control = options.audio.setting = false + plugin.update() + assert.equal(host.controls.size, 2) + assert.equal(host.settings.size, 2) + }) + test(`${name} observation DASH-LIFE-01: retained callbacks outlive destruction and SDK replacement`, () => { + const host = dashHost(sdk) + const plugin = factory(bothMenus())(host.art) + plugin.update() + const menu = host.controls.get('dash-quality') + const next = dashHost(sdk) + next.state.video = host.video + host.art.dash = next.dash + plugin.update() + host.art.destroy() + host.calls.length = 0 + menu.onSelect(menu.selector[0]) + assert.equal(host.calls[1][0], sdk === 4 ? 'setQualityFor' : 'setRepresentationForTypeById') + assert.equal(host.listeners.get('ready').size, 1) + assert.equal(host.listeners.get('restart').size, 1) + host.calls.length = 0 + plugin.update() + assert.equal(host.calls.filter(call => call[0].endsWith('.update')).length, 4) + assert.equal(host.calls.some(call => call[0] === 'dash.destroy'), false) + }) + test(`${name} observation DASH-STATE-01: cloned current track and duplicate current label lose highlighting`, () => { + const host = dashHost(sdk) + host.state.currentTrack = { ...host.state.tracks[1] } + host.state.settings.streaming.abr.autoSwitchBitrate.video = false + host.state.levels[1].height = 360 + factory(bothMenus())(host.art).update() + assert.equal(host.controls.get('dash-audio').html, 'fr') + assert.equal(Array.from(host.controls.get('dash-audio').selector).filter(item => item.default).length, 0) + assert.equal(host.controls.get('dash-quality').html, '360p') + assert.equal(Array.from(host.controls.get('dash-quality').selector).filter(item => item.default).length, 0) + }) +} +test('pre-refactor v5 observation: numeric zero representation ID loses manual highlighting', () => { + const { factory } = implementations.find(item => item.name === 'pre-refactor-v5') + const host = dashHost(5) + host.state.levels[1].id = 0 + host.state.settings.streaming.abr.autoSwitchBitrate.video = false + factory(bothMenus())(host.art).update() + const menu = host.controls.get('dash-quality') + assert.equal(menu.html, '720p') + assert.equal(Array.from(menu.selector).filter(item => item.default).length, 0) +}) +test('frozen SDK generations demonstrate the two incompatible quality method surfaces', () => { + const published = implementations.find(item => item.name === 'published-main').factory + const historical = implementations.find(item => item.name === 'pre-refactor-v5').factory + assert.throws(() => published(bothMenus())(dashHost(5).art).update(), /getBitrateInfoListFor/) + assert.throws(() => historical(bothMenus())(dashHost(4).art).update(), /getRepresentationsByType/) +}) diff --git a/test/helpers/dash-control.js b/test/helpers/dash-control.js new file mode 100644 index 000000000..6dffe4307 --- /dev/null +++ b/test/helpers/dash-control.js @@ -0,0 +1,194 @@ +import assert from 'node:assert/strict' +import { Buffer } from 'node:buffer' +import { execFileSync } from 'node:child_process' +import fs from 'node:fs' +import path from 'node:path' +import process from 'node:process' +import vm from 'node:vm' +import { ensureArchive, hash, readMember } from '../../refactor/scripts/releases.mjs' +import { loadPackage } from './load.js' + +async function factoryFromBytes(bytes, module) { + if (module) + return (await import(`data:text/javascript;base64,${Buffer.from(bytes).toString('base64')}`)).default + const context = { module: { exports: {} } } + context.exports = context.module.exports + vm.runInNewContext(bytes.toString(), context, { timeout: 5000 }) + assert.equal(typeof context.module.exports, 'function') + return context.module.exports +} +export async function dashImplementations() { + const baseline = JSON.parse(fs.readFileSync(new URL('../../refactor/baselines/dash-control-release.json', import.meta.url))) + const { release } = baseline + const archive = await ensureArchive(release) + const implementations = [{ name: 'source', sdk: 5, factory: (await loadPackage(release.name)).default }] + const historicalFile = `packages/${release.name}/dist/artplayer-plugin-dash-control.js` + const historical = execFileSync('git', ['show', `${baseline.sourceCommit}:${historicalFile}`]) + assert.equal(hash(historical.toString().replace(/\r\n/g, '\n')), baseline.source[historicalFile]) + implementations.push({ name: 'pre-refactor-v5', sdk: 5, factory: await factoryFromBytes(historical, false) }) + for (const format of ['main', 'legacy', 'module']) { + const member = `package/${release.manifest[format].replace(/^\.\//, '')}` + const bytes = readMember(archive, member) + assert.equal(hash(bytes), release.files[member]) + implementations.push({ name: `published-${format}`, sdk: 4, factory: await factoryFromBytes(bytes, format === 'module') }) + } + for (const filename of (process.env.ARTPLAYER_TEST_DASH || '').split(path.delimiter).filter(Boolean)) { + const bytes = fs.readFileSync(filename) + implementations.push({ name: `artifact-${path.basename(filename)}`, sdk: 5, factory: await factoryFromBytes(bytes, filename.endsWith('.mjs')) }) + } + return implementations +} +// A controlled SDK surface and registry. It does not decode media or simulate ABR. +export function dashHost(version = 5) { + const calls = [] + const controls = new Map() + const settings = new Map() + const listeners = new Map() + const video = {} + const levels = [ + { id: 'low', qualityIndex: 0, height: 360, bitrateInKbit: 400 }, + { id: 'high', qualityIndex: 1, height: 720, bitrateInKbit: 1200 }, + { id: 'top', qualityIndex: 2, height: 1080, bitrateInKbit: 2400 }, + ] + for (const level of levels) { + if (version === 4) + delete level.id + else + delete level.qualityIndex + } + const tracks = [{ id: 'en', lang: 'en', index: 0 }, { id: 'fr', lang: 'fr', index: 1 }] + const state = { + video, + levels, + tracks, + currentRepresentation: levels[1], + currentQuality: 1, + currentTrack: tracks[0], + settings: { streaming: { abr: { autoSwitchBitrate: { video: true, audio: false }, minBitrate: { video: -1 } } } }, + } + const art = { + template: { $video: video }, + isDestroy: false, + constructor: { utils: { errorHandle(condition, message) { + if (!condition) + throw new Error(message) + } } }, + notice: {}, + on(name, callback) { + if (!listeners.has(name)) + listeners.set(name, new Set()) + listeners.get(name).add(callback) + return art + }, + off(name, callback) { + listeners.get(name)?.delete(callback) + return art + }, + emit(name, ...args) { + for (const callback of [...(listeners.get(name) || [])]) + callback(...args) + return art + }, + destroy() { + art.isDestroy = true + art.emit('destroy') + }, + } + let notice = '' + Object.defineProperty(art.notice, 'show', { + get: () => notice, + set(value) { + notice = value + calls.push(['notice', value]) + }, + }) + for (const [name, entries] of [['controls', controls], ['setting', settings]]) { + art[name] = { + update(option) { + entries.set(option.name, option) + calls.push([`${name}.update`, option.name]) + }, + remove(key) { + entries.delete(key) + calls.push([`${name}.remove`, key]) + }, + check(item) { + calls.push([`${name}.check`, item]) + }, + } + } + const dash = { + getVideoElement() { + assert.equal(this, dash) + return state.video + }, + getSettings() { + assert.equal(this, dash) + return state.settings + }, + updateSettings(update) { + assert.equal(this, dash) + calls.push(['updateSettings', JSON.parse(JSON.stringify(update))]) + Object.assign(state.settings.streaming.abr.autoSwitchBitrate, update.streaming.abr.autoSwitchBitrate) + }, + getTracksFor(type) { + assert.equal(this, dash) + assert.equal(type, 'audio') + return state.tracks + }, + getCurrentTrackFor(type) { + assert.equal(this, dash) + assert.equal(type, 'audio') + return state.currentTrack + }, + setCurrentTrack(track) { + assert.equal(this, dash) + state.currentTrack = track + calls.push(['setCurrentTrack', track]) + }, + destroy() { + calls.push(['dash.destroy']) + }, + } + if (version === 4) { + Object.assign(dash, { + getBitrateInfoListFor(type) { + assert.equal(this, dash) + assert.equal(type, 'video') + return state.levels + }, + getQualityFor(type) { + assert.equal(this, dash) + assert.equal(type, 'video') + return state.currentQuality + }, + setQualityFor(type, index) { + assert.equal(this, dash) + state.currentQuality = index + calls.push(['setQualityFor', type, index]) + }, + }) + } + else { + Object.assign(dash, { + getRepresentationsByType(type) { + assert.equal(this, dash) + assert.equal(type, 'video') + return state.levels + }, + getCurrentRepresentationForType(type) { + assert.equal(this, dash) + assert.equal(type, 'video') + return state.currentRepresentation + }, + setRepresentationForTypeById(type, id) { + assert.equal(this, dash) + state.currentRepresentation = state.levels?.find(level => level.id === id) + calls.push(['setRepresentationForTypeById', type, id]) + }, + }) + } + art.dash = dash + return { art, dash, state, calls, controls, settings, listeners, video } +} +export const bothMenus = () => ({ quality: { control: true, setting: true }, audio: { control: true, setting: true } })