diff --git a/src/app-bridge.test.ts b/src/app-bridge.test.ts index a87b0e7db..c85d73864 100644 --- a/src/app-bridge.test.ts +++ b/src/app-bridge.test.ts @@ -71,6 +71,56 @@ describe("App <-> AppBridge integration", () => { await bridgeTransport.close(); }); + describe("host context lifecycle", () => { + it("retains context set before connection for the initialization handshake", async () => { + const errors: Error[] = []; + bridge.onerror = (error) => errors.push(error); + + bridge.setHostContext({ theme: "dark", locale: "en-US" }); + await flush(); + await bridge.connect(bridgeTransport); + await app.connect(appTransport); + + expect(app.getHostContext()).toEqual({ theme: "dark", locale: "en-US" }); + expect(errors).toEqual([]); + }); + + it("retains context set after disconnect for the next view", async () => { + const errors: Error[] = []; + bridge.onerror = (error) => errors.push(error); + await bridge.connect(bridgeTransport); + await app.connect(appTransport); + await app.close(); + + bridge.setHostContext({ theme: "light" }); + await flush(); + + [appTransport, bridgeTransport] = InMemoryTransport.createLinkedPair(); + app = new App(testAppInfo, {}, { autoResize: false }); + await bridge.connect(bridgeTransport); + await app.connect(appTransport); + + expect(app.getHostContext()).toEqual({ theme: "light" }); + expect(errors).toEqual([]); + }); + + it("reports a context notification send failure through onerror", async () => { + const errors: Error[] = []; + bridge.onerror = (error) => errors.push(error); + await bridge.connect(bridgeTransport); + await app.connect(appTransport); + const failure = new Error("Context transport failed"); + const send = spyOn(bridgeTransport, "send").mockRejectedValue(failure); + try { + bridge.setHostContext({ theme: "dark" }); + await flush(); + expect(errors).toEqual([failure]); + } finally { + send.mockRestore(); + } + }); + }); + describe("initialization handshake", () => { it("App.connect() triggers bridge.oninitialized", async () => { let initializedFired = false; diff --git a/src/app-bridge.ts b/src/app-bridge.ts index 1ac4db485..108346fee 100644 --- a/src/app-bridge.ts +++ b/src/app-bridge.ts @@ -1658,6 +1658,8 @@ export class AppBridge extends Protocol { * `ui/notifications/host-context-changed` notification containing only fields * that have been added or modified. If no fields have changed, no notification is sent. * The new context fully replaces the internal state. + * While disconnected, the context is saved for the next initialization handshake. + * Notification failures are reported through {@link onerror `onerror`}. * * Common use cases include notifying the view when: * - Theme changes (light/dark mode toggle) @@ -1699,7 +1701,11 @@ export class AppBridge extends Protocol { } if (hasChanges) { this._hostContext = hostContext; - this.sendHostContextChange(changes); + if (this.transport) { + Promise.resolve(this.sendHostContextChange(changes)).catch((error) => { + this.onerror?.(error); + }); + } } }