diff --git a/src/v1/bandwidthRtc.test.ts b/src/v1/bandwidthRtc.test.ts index fb860fc..a11e44d 100644 --- a/src/v1/bandwidthRtc.test.ts +++ b/src/v1/bandwidthRtc.test.ts @@ -272,6 +272,42 @@ describe("bandwidthRtcV1 addStreamToPublishingPeerConnection", () => { }); }); +describe("bandwidthRtcV1 init reconnect replay", () => { + function stubSetupPeerConnection(brtc: BandwidthRtc) { + // init() only needs a stand-in RTCPeerConnection; the real + // negotiation performed by setupPeerConnection is exercised elsewhere. + (brtc as any).setupPeerConnection = jest.fn().mockResolvedValue({}); + } + + test("does not replay when no streams were previously published (first connect)", async () => { + const brtc = new BandwidthRtc(); + stubSetupPeerConnection(brtc); + const addSpy = jest.spyOn(brtc as any, "addStreamToPublishingPeerConnection"); + const offerSpy = jest.spyOn(brtc as any, "offerPublishSdp").mockResolvedValue(undefined); + + await brtc.init({ publishSdpOffer: {}, subscribeSdpOffer: {} } as any); + + expect(addSpy).not.toHaveBeenCalled(); + expect(offerSpy).not.toHaveBeenCalled(); + }); + + test("re-attaches previously published streams to the new publishing peer connection on reconnect", async () => { + const brtc = new BandwidthRtc(); + stubSetupPeerConnection(brtc); + const addSpy = jest.spyOn(brtc as any, "addStreamToPublishingPeerConnection").mockImplementation(() => {}); + const offerSpy = jest.spyOn(brtc as any, "offerPublishSdp").mockResolvedValue(undefined); + + const mediaStream = { id: "stream-1" } as any; + (brtc as any).publishedStreams.set(mediaStream.id, { mediaStream }); + + // Simulate the websocket "open" handler re-emitting "init" after a reconnect. + await brtc.init({ publishSdpOffer: {}, subscribeSdpOffer: {} } as any); + + expect(addSpy).toHaveBeenCalledWith(mediaStream); + expect(offerSpy).toHaveBeenCalledTimes(1); + }); +}); + describe("bandwidthRtcV1 connect method", () => { beforeAll(() => { setupNavigatorMocks(); diff --git a/src/v1/bandwidthRtc.ts b/src/v1/bandwidthRtc.ts index 5b441f2..c7b6882 100644 --- a/src/v1/bandwidthRtc.ts +++ b/src/v1/bandwidthRtc.ts @@ -603,6 +603,17 @@ export class BandwidthRtc { subscriptionOnTrackHandler, setMediaPreferencesResponse.subscribeSdpOffer.sdpOffer, ); + + // On a fresh connect, publishedStreams is empty and this is a no-op. On a + // reconnect (the websocket re-opened and re-emitted "init"), the new + // publishingPeerConnection above is trackless, so re-attach every + // previously published stream and renegotiate to carry them over. + if (this.publishedStreams.size > 0) { + for (const { mediaStream } of this.publishedStreams.values()) { + this.addStreamToPublishingPeerConnection(mediaStream); + } + await this.offerPublishSdp(); + } } private async setupPeerConnection(