diff --git a/openc3-cosmos-init/plugins/packages/openc3-js-common/src/services/cable.js b/openc3-cosmos-init/plugins/packages/openc3-js-common/src/services/cable.js index fc1ec780f7..4899bfb955 100644 --- a/openc3-cosmos-init/plugins/packages/openc3-js-common/src/services/cable.js +++ b/openc3-cosmos-init/plugins/packages/openc3-js-common/src/services/cable.js @@ -63,11 +63,24 @@ class ResilientSubscription { return this._subscription?.identifier } + // Once the owner has torn this subscription down (unsubscribe, or + // Cable#disconnect when its component unmounts) there's nothing to perform + // on. Callers perform from async callbacks, e.g. after the token refresh in + // a connected handler, that can land after the teardown, and anycable + // rejects those on the closed consumer with NoConnectionError. Nobody awaits + // them, so that surfaced as an unhandled rejection - e.g. a Telemetry Viewer + // screen closed right after it opened. perform(action, data) { + if (this._unsubscribed) { + return Promise.resolve() + } return this._subscription?.perform(action, data) } send(data) { + if (this._unsubscribed) { + return Promise.resolve() + } return this._subscription?.send(data) } diff --git a/playwright/tests/fixture.ts b/playwright/tests/fixture.ts index ff207f7b33..2636eb321d 100644 --- a/playwright/tests/fixture.ts +++ b/playwright/tests/fixture.ts @@ -34,6 +34,10 @@ const startCoverage = async (page: any) => { const stopCoverage = async (page: any) => { try { const coverage = await page.coverage.stopJSCoverage() + // Empty when the page never loaded a script with a URL (e.g. a blank popup) + // or profiling never started on it. MCR rejects [] with "The added coverage + // data must be Array(V8) or Object(Istanbul)", so skip it. + if (!coverage.length) return // Appends raw V8 data to coverage/.cache (safe across workers AND // separate `playwright test` invocations); generate-coverage.mjs // merges everything into one report at the end of `pnpm test`