From 58246827522de47d4608adad4e0a267fbeb09c82 Mon Sep 17 00:00:00 2001 From: Mustafa BOLEKEN Date: Mon, 12 Feb 2024 13:09:35 +0300 Subject: [PATCH 1/4] Prevent init new peer coneection, in case of it already established --- src/main/js/webrtc_adaptor.js | 77 +++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/src/main/js/webrtc_adaptor.js b/src/main/js/webrtc_adaptor.js index c8628956..845aa669 100644 --- a/src/main/js/webrtc_adaptor.js +++ b/src/main/js/webrtc_adaptor.js @@ -236,7 +236,7 @@ export class WebRTCAdaptor { /** * Degradation Preference - * + * * maintain-framerate, maintain-resolution, or balanced */ this.degradationPreference = "maintain-resolution"; @@ -650,8 +650,8 @@ export class WebRTCAdaptor { this.stop(this.publishStreamId); setTimeout(() => { - //publish about some time later because server may not drop the connection yet - //it may trigger already publishing error + //publish about some time later because server may not drop the connection yet + //it may trigger already publishing error Logger.log("Trying publish again for stream: " + this.publishStreamId); this.publish(this.publishStreamId, this.publishToken, this.publishSubscriberId, this.publishSubscriberCode, this.publishStreamName, this.publishMainTrack, this.publishMetaData); }, 500); @@ -673,8 +673,8 @@ export class WebRTCAdaptor { Logger.log("It will try to play again for stream: " + this.publishStreamId + " because it is not stopped on purpose") this.stop(streamId); setTimeout(() => { - //play about some time later because server may not drop the connection yet - //it may trigger already playing error + //play about some time later because server may not drop the connection yet + //it may trigger already playing error Logger.log("Trying play again for stream: " + streamId); this.play(streamId, this.playToken, this.playRoomId, this.playEnableTracks, this.playSubscriberId, this.playSubscriberCode, this.playMetaData); }, 500); @@ -948,7 +948,7 @@ export class WebRTCAdaptor { */ sanitizeHTML(text) { if(text.includes("script")) - return text.replace(//g, ">"); + return text.replace(//g, ">"); return text } @@ -1043,10 +1043,10 @@ export class WebRTCAdaptor { this.iceCandidateList[streamId] = new Array(); if (!this.playStreamId.includes(streamId)) { if (this.mediaManager.localStream != null) { - this.mediaManager.localStream.getTracks().forEach(track => { - + this.mediaManager.localStream.getTracks().forEach(track => { + let rtpSender = this.remotePeerConnection[streamId].addTrack(track, this.mediaManager.localStream); - if (track.kind == 'video') + if (track.kind == 'video') { let parameters = rtpSender.getParameters(); parameters.degradationPreference = this.degradationPreference; @@ -1130,7 +1130,7 @@ export class WebRTCAdaptor { } } - + return this.remotePeerConnection[streamId]; } @@ -1376,6 +1376,15 @@ export class WebRTCAdaptor { startPublishing(idOfStream) { let streamId = idOfStream; + if (typeof this.remotePeerConnection[streamId] !== 'undefined' + && this.remotePeerConnection[streamId] !== null + && (this.remotePeerConnection[streamId].iceConnectionState !== "new" + || this.remotePeerConnection[streamId].iceConnectionState !== "failed" + || this.remotePeerConnection[streamId].iceConnectionState !== "disconnected")) { + Logger.debug("We already established peer connection, no need to create offer"); + return; + } + let peerConnection = this.initPeerConnection(streamId, "publish"); //this.remotePeerConnection[streamId] @@ -1544,8 +1553,8 @@ export class WebRTCAdaptor { if (typeof value.jitterBufferDelay != "undefined" && typeof value.jitterBufferEmittedCount != "undefined") { videoJitterAverageDelay = value.jitterBufferDelay / value.jitterBufferEmittedCount; } - } - + } + else if (value.type == "remote-inbound-rtp" && typeof value.kind != "undefined") { //this is coming when webrtc publishing @@ -1922,27 +1931,27 @@ export class WebRTCAdaptor { this.webSocketAdaptor.send(JSON.stringify(jsCmd)); } - + /** * Register user push notification token to Ant Media Server according to subscriberId and authToken * @param {string} subscriberId: subscriber id it can be anything that defines the user - * @param {string} authToken: JWT token with the issuer field is the subscriberId and secret is the application's subscriberAuthenticationKey, + * @param {string} authToken: JWT token with the issuer field is the subscriberId and secret is the application's subscriberAuthenticationKey, * It's used to authenticate the user - token should be obtained from Ant Media Server Push Notification REST Service * or can be generated with JWT by using the secret and issuer fields - * + * * @param {string} pushNotificationToken: Push Notification Token that is obtained from the Firebase or APN * @param {string} tokenType: It can be "fcm" or "apn" for Firebase Cloud Messaging or Apple Push Notification - * + * * @returns Server responds this message with a result. - * Result message is something like + * Result message is something like * { * "command":"notification", * "success":true or false * "definition":"If success is false, it gives the error message", * "information":"If succeess is false, it gives more information to debug if available" - * - * } - * + * + * } + * */ registerPushNotificationToken(subscriberId, authToken, pushNotificationToken, tokenType) { let jsCmd = { @@ -1954,8 +1963,8 @@ export class WebRTCAdaptor { }; this.webSocketAdaptor.send(JSON.stringify(jsCmd)); } - - + + /** * Send push notification to subscribers * @param {string} subscriberId: subscriber id it can be anything(email, username, id) that defines the user in your applicaiton @@ -1964,31 +1973,31 @@ export class WebRTCAdaptor { * or can be generated with JWT by using the secret and issuer fields * @param {string} pushNotificationContent: JSON Format - Push Notification Content. If it's not JSON, it will not parsed * @param {Array} subscriberIdsToNotify: Array of subscriber ids to notify - * + * * @returns Server responds this message with a result. - * Result message is something like + * Result message is something like * { * "command":"notification", * "success":true or false * "definition":"If success is false, it gives the error message", * "information":"If succeess is false, it gives more information to debug if available" - * - * } + * + * } */ sendPushNotification(subscriberId, authToken, pushNotificationContent, subscriberIdsToNotify) { - + //type check for pushNotificationContent if json if (typeof pushNotificationContent !== "object") { Logger.error("Push Notification Content is not JSON format"); throw new Error("Push Notification Content is not JSON format"); } - + //type check if subscriberIdsToNotify is array if (!Array.isArray(subscriberIdsToNotify)) { Logger.error("subscriberIdsToNotify is not an array. Please put the subscriber ids to notify in an array such as [user1], [user1, user2]"); throw new Error("subscriberIdsToNotify is not an array. Please put the subscriber ids to notify in an array such as [user1], [user1, user2]"); } - + let jsCmd = { command: "sendPushNotification", subscriberId: subscriberId, @@ -1998,16 +2007,16 @@ export class WebRTCAdaptor { }; this.webSocketAdaptor.send(JSON.stringify(jsCmd)); } - + /** * Send push notification to topic * @param {string} subscriberId: subscriber id it can be anything(email, username, id) that defines the user in your applicaiton - * @param {string} authToken: JWT token with the issuer field is the subscriberId and secret is the application's subscriberAuthenticationKey, + * @param {string} authToken: JWT token with the issuer field is the subscriberId and secret is the application's subscriberAuthenticationKey, * It's used to authenticate the user - token should be obtained from Ant Media Server Push Notification REST Service * or can be generated with JWT by using the secret and issuer fields * @param {string} pushNotificationContent:JSON Format - Push Notification Content. If it's not JSON, it will not parsed * @param {string} topic: Topic to send push notification - * + * * @returns Server responds this message with a result. * Result message is something like * { @@ -2016,7 +2025,7 @@ export class WebRTCAdaptor { * "definition":"If success is false, it gives the error message", * "information":"If succeess is false, it gives more information to debug if available" * } - * + * */ sendPushNotificationToTopic(subscriberId, authToken, pushNotificationContent, topic) { //type check for pushNotificationContent if json @@ -2024,7 +2033,7 @@ export class WebRTCAdaptor { Logger.error("Push Notification Content is not JSON format"); throw new Error("Push Notification Content is not JSON format"); } - + let jsCmd = { command: "sendPushNotification", subscriberId: subscriberId, From 86143a6bc2c505ec26cc16afdffafe35de02aada Mon Sep 17 00:00:00 2001 From: Mustafa BOLEKEN Date: Mon, 18 Mar 2024 12:41:02 +0300 Subject: [PATCH 2/4] Add unit test for startPublishing with different oeer connection states --- src/test/js/webrtc_adaptor.test.js | 355 ++++++++++++++++++----------- 1 file changed, 223 insertions(+), 132 deletions(-) diff --git a/src/test/js/webrtc_adaptor.test.js b/src/test/js/webrtc_adaptor.test.js index dc1317fb..10635467 100644 --- a/src/test/js/webrtc_adaptor.test.js +++ b/src/test/js/webrtc_adaptor.test.js @@ -21,6 +21,19 @@ describe("WebRTCAdaptor", function() { sinon.restore(); clock.restore(); sandbox.restore(); + mockRTCPeerConnection.restore(); + }); + + // Create a mock for the RTCPeerConnection + const mockRTCPeerConnection = sinon.stub(window, 'RTCPeerConnection'); + +// Define the behavior of the mock object + mockRTCPeerConnection.returns({ + createOffer: sinon.stub().returns(Promise.resolve()), + setLocalDescription: sinon.stub().returns(Promise.resolve()), + addIceCandidate: sinon.stub().returns(Promise.resolve()), + close: sinon.stub(), + // Add any other methods you want to mock }); @@ -135,36 +148,36 @@ describe("WebRTCAdaptor", function() { expect(adaptor.remotePeerConnection[streamId]).to.not.be.undefined; //Add extra delay because publish is called a few seconds later the stop in tryAgain method - + clock.tick(1500); sendExpectation.verify(); }); - + it("toggleVideo", async function() { let adaptor = new WebRTCAdaptor({ websocketURL: "ws://example.com", isPlayMode: true }); - + let webSocketAdaptor = sinon.mock(adaptor.webSocketAdaptor); let streamId = "stream1"; let trackId = "trackId"; let enabled = true; - + let jsCmd = { command: "toggleVideo", streamId: streamId, trackId: trackId, enabled: enabled, }; - + let sendExpectation = webSocketAdaptor.expects("send").once().withArgs(JSON.stringify(jsCmd)); - + adaptor.toggleVideo(streamId, trackId, enabled); - + sendExpectation.verify() }) @@ -306,7 +319,7 @@ describe("WebRTCAdaptor", function() { var message = adaptor.sanitizeHTML(text) assert.strictEqual(text,message) }) - + it("Reconnection for publish", async function() { var adaptor = new WebRTCAdaptor({ @@ -338,43 +351,43 @@ describe("WebRTCAdaptor", function() { clock.tick(1500); assert(fakeSendPublish.calledOnce); assert(fakeStop.calledOnce); - + clock.tick(2500); assert(fakeSendPublish.calledTwice); }); - + it("EnableStats - DisableStats", async function() { - + var adaptor = new WebRTCAdaptor({ websocketURL: "ws://example.com", isPlayMode: true }); - + const streamId = "test"+Math.floor(Math.random() * 100); adaptor.publishStreamId = streamId; var mockPC = sinon.mock(RTCPeerConnection); adaptor.remotePeerConnection[streamId] = mockPC - + expect(adaptor.remotePeerConnectionStats[streamId]).to.be.undefined; - + adaptor.enableStats(streamId); expect(adaptor.remotePeerConnectionStats[streamId].timerId).to.be.not.undefined; - - adaptor.disableStats(streamId); + + adaptor.disableStats(streamId); expect(adaptor.remotePeerConnectionStats[streamId]).to.be.undefined; - - + + adaptor.enableStats(streamId); expect(adaptor.remotePeerConnectionStats[streamId].timerId).to.be.not.undefined; - - - adaptor.disableStats(streamId); + + + adaptor.disableStats(streamId); expect(adaptor.remotePeerConnectionStats[streamId]).to.be.undefined; - - + + }); it("Websocket send try catch", async function() @@ -636,7 +649,7 @@ describe("WebRTCAdaptor", function() { var mediaStreamTrack = mediaStreamSource.stream.getAudioTracks()[0]; oscillator.start(); - + adaptor.mediaManager.mutedAudioStream = new MediaStream([mediaStreamTrack]) adaptor.mediaManager.localStream = new MediaStream([mediaStreamTrack]) adaptor.mediaManager.audioContext = audioContext; @@ -659,7 +672,7 @@ describe("WebRTCAdaptor", function() { navigator.mediaDevices.getUserMedia = async () => { return Promise.resolve(new MediaStream([mediaStreamTrack])); }; - + adaptor.initialize().then(async () => { adaptor.mediaManager.callback = (info) => { console.log("callback ", info); @@ -672,7 +685,7 @@ describe("WebRTCAdaptor", function() { }); }); }); - + var soundMeteraddModuleFailed = speakingButMuted.then(() => { adaptor.mediaManager.mutedSoundMeter.context.audioWorklet.addModule = async () => { return Promise.reject("error"); @@ -681,37 +694,37 @@ describe("WebRTCAdaptor", function() { adaptor.enableAudioLevelWhenMuted().catch((e)=>{resolve()}) }); }); - + return soundMeteraddModuleFailed; }); - - + + it("startPublishing", async function(){ let adaptor = new WebRTCAdaptor({ websocketURL: "ws://example.com", isPlayMode: true }); - + let peerConnection = new RTCPeerConnection(); let initPeerConnection = sinon.replace(adaptor, "initPeerConnection", sinon.fake.returns(peerConnection)); - + let createOfferFake = sinon.replace(peerConnection, "createOffer", sinon.fake.returns(Promise.reject("this is on purpose"))); adaptor.startPublishing("stream123"); - + expect(initPeerConnection.calledWithExactly("stream123", "publish")).to.be.true; }); - + it("join", async function() { - + let adaptor = new WebRTCAdaptor({ websocketURL: "ws://example.com", isPlayMode: true }); - + let streamId = "stream123"; let jsCmd = { command: "join", @@ -719,72 +732,72 @@ describe("WebRTCAdaptor", function() { multiPeer: false, mode: "play" }; - + let webSocketAdaptor = sinon.mock(adaptor.webSocketAdaptor); - + let sendExpectation = webSocketAdaptor.expects("send").once().withArgs(JSON.stringify(jsCmd)); - + adaptor.join(streamId); - + sendExpectation.verify() }) - + it("joinRoom", async function() { - + let adaptor = new WebRTCAdaptor({ websocketURL: "ws://example.com", isPlayMode: true }); - + let streamId = "stream123"; let roomId = "roomId"; - + let jsCmd = { command: "joinRoom", room: roomId, streamId: streamId, mode: "multitrack", } - + let webSocketAdaptor = sinon.mock(adaptor.webSocketAdaptor); - + let sendExpectation = webSocketAdaptor.expects("send").once().withArgs(JSON.stringify(jsCmd)); - + adaptor.joinRoom(roomId, streamId, "multitrack"); - + sendExpectation.verify() - + }); - + it("eventListeners", async function() { let adaptor = new WebRTCAdaptor({ websocketURL: "ws://example.com", isPlayMode: true }); - - + + var eventListenerCalled = false; adaptor.addEventListener((info, obj) => { eventListenerCalled = true; }); - + var errorListenerCalled = false; adaptor.addErrorEventListener((error, message) => { errorListenerCalled = true; }); - - + + adaptor.mediaManager.callback("info", "obj"); - - adaptor.mediaManager.callbackError("info", "obj"); - + + adaptor.mediaManager.callbackError("info", "obj"); + expect(eventListenerCalled).to.be.true; expect(errorListenerCalled).to.be.true; }); - + it("onTrack", async function() { - + { var videoElement = document.createElement("video"); let adaptor = new WebRTCAdaptor({ @@ -792,33 +805,33 @@ describe("WebRTCAdaptor", function() { isPlayMode: true, remoteVideoElement: videoElement }); - + var mediaStream = new MediaStream(); var event = { streams:[ mediaStream ] } - + expect(videoElement.srcObject).to.be.null; - + adaptor.onTrack(event, "stream1"); - + expect(videoElement.srcObject).to.not.be.null; } - - + + { let adaptor = new WebRTCAdaptor({ websocketURL: "ws://example.com", isPlayMode: true, }); - + var eventListenerCalled = false; adaptor.addEventListener((info, obj) => { if (info == "newTrackAvailable") { eventListenerCalled = true; } }) - + var mediaStream = new MediaStream(); var event = { streams:[ mediaStream ], @@ -826,97 +839,175 @@ describe("WebRTCAdaptor", function() { id: "anyid" } } - + adaptor.idMapping["stream1"] = "anything"; - + adaptor.onTrack(event, "stream1"); - + expect(eventListenerCalled).to.be.true; - + } }); - + it("getStreamInfo", async function(){ let adaptor = new WebRTCAdaptor({ websocketURL: "ws://example.com", isPlayMode: true }); - + let streamId = "stream123"; let jsCmd = { command: "getStreamInfo", streamId: streamId, }; - + let webSocketAdaptor = sinon.mock(adaptor.webSocketAdaptor); - + let sendExpectation = webSocketAdaptor.expects("send").once().withArgs(JSON.stringify(jsCmd)); - + adaptor.getStreamInfo(streamId); - + sendExpectation.verify() }); - - + it("startPublishing with existing peer connection", async function() { + let adaptor = new WebRTCAdaptor({ + websocketURL: "ws://example.com", + isPlayMode: true + }); + + let streamId = "stream123"; + let peerConnection = new RTCPeerConnection(); + peerConnection.iceConnectionState = "connected"; + adaptor.remotePeerConnection[streamId] = peerConnection; + + let initPeerConnection = sinon.replace(adaptor, "initPeerConnection", sinon.fake.returns(peerConnection)); + let createOfferFake = sinon.replace(peerConnection, "createOffer", sinon.fake.returns(Promise.reject("this is on purpose"))); + + adaptor.startPublishing(streamId); + + expect(initPeerConnection.called).to.be.false; + expect(createOfferFake.called).to.be.false; + }); + + it("startPublishing with new peer connection", async function() { + let adaptor = new WebRTCAdaptor({ + websocketURL: "ws://example.com", + isPlayMode: true + }); + + let streamId = "stream123"; + let peerConnection = new RTCPeerConnection(); + peerConnection.iceConnectionState = "new"; + adaptor.remotePeerConnection[streamId] = peerConnection; + + let initPeerConnection = sinon.replace(adaptor, "initPeerConnection", sinon.fake.returns(peerConnection)); + let createOfferFake = sinon.replace(peerConnection, "createOffer", sinon.fake.returns(Promise.resolve())); + + adaptor.startPublishing(streamId); + + expect(initPeerConnection.calledWithExactly(streamId, "publish")).to.be.false; + expect(createOfferFake.called).to.be.false; + }); + + it("startPublishing with failed peer connection", async function() { + let adaptor = new WebRTCAdaptor({ + websocketURL: "ws://example.com", + isPlayMode: true + }); + + let streamId = "stream123"; + let peerConnection = new RTCPeerConnection(); + peerConnection.iceConnectionState = "failed"; + adaptor.remotePeerConnection[streamId] = peerConnection; + + let initPeerConnection = sinon.replace(adaptor, "initPeerConnection", sinon.fake.returns(peerConnection)); + let createOfferFake = sinon.replace(peerConnection, "createOffer", sinon.fake.returns(Promise.resolve())); + + adaptor.startPublishing(streamId); + + expect(initPeerConnection.calledWithExactly(streamId, "publish")).to.be.false; + expect(createOfferFake.called).to.be.false; + }); + + it("startPublishing with disconnected peer connection", async function() { + let adaptor = new WebRTCAdaptor({ + websocketURL: "ws://example.com", + isPlayMode: true + }); + + let streamId = "stream123"; + let peerConnection = new RTCPeerConnection(); + peerConnection.iceConnectionState = "disconnected"; + adaptor.remotePeerConnection[streamId] = peerConnection; + + let initPeerConnection = sinon.replace(adaptor, "initPeerConnection", sinon.fake.returns(peerConnection)); + let createOfferFake = sinon.replace(peerConnection, "createOffer", sinon.fake.returns(Promise.resolve())); + + adaptor.startPublishing(streamId); + + expect(initPeerConnection.calledWithExactly(streamId, "publish")).to.be.false; + expect(createOfferFake.called).to.be.false; + }); + it("getBroadcastObject", async function(){ let adaptor = new WebRTCAdaptor({ websocketURL: "ws://example.com", isPlayMode: true }); - + let streamId = "stream123"; let jsCmd = { command: "getBroadcastObject", streamId: streamId, }; - + let webSocketAdaptor = sinon.mock(adaptor.webSocketAdaptor); - + let sendExpectation = webSocketAdaptor.expects("send").once().withArgs(JSON.stringify(jsCmd)); - + adaptor.getBroadcastObject(streamId); - + sendExpectation.verify() }); - + it("requestVideoTrackAssignments", async function() { - + let adaptor = new WebRTCAdaptor({ websocketURL: "ws://example.com", isPlayMode: true }); - + let streamId = "stream123"; - + let jsCmd = { command: "getVideoTrackAssignmentsCommand", streamId: streamId, }; - + let webSocketAdaptor = sinon.mock(adaptor.webSocketAdaptor); - + let sendExpectation = webSocketAdaptor.expects("send").once().withArgs(JSON.stringify(jsCmd)); - + adaptor.requestVideoTrackAssignments(streamId); - + sendExpectation.verify() - + }) - - + + it("registerPushNotificationToken",async function() { let adaptor = new WebRTCAdaptor({ websocketURL: "ws://example.com", isPlayMode: true }); - + let subscriberId = "subscriberId"; let authToken = "autotokenkdnkf"; let pnsRegistrationToken = "pnsRegistrationTokenpnsRegistrationTokenpnsRegistrationTokenpnsRegistrationToken"; let pnstype = "fcm"; - + let jsCmd = { command: "registerPushNotificationToken", subscriberId: subscriberId, @@ -924,39 +1015,39 @@ describe("WebRTCAdaptor", function() { pnsRegistrationToken: pnsRegistrationToken, pnsType: pnstype }; - + let webSocketAdaptor = sinon.mock(adaptor.webSocketAdaptor); - + let sendExpectation = webSocketAdaptor.expects("send").once().withArgs(JSON.stringify(jsCmd)); - + adaptor.registerPushNotificationToken(subscriberId, authToken, pnsRegistrationToken, pnstype); - + sendExpectation.verify() - + }); - - + + it("sendPushNotification",async function() { let adaptor = new WebRTCAdaptor({ websocketURL: "ws://example.com", isPlayMode: true }); - + let subscriberId = "subscriberId"; let authToken = "autotokenkdnkf"; let pushNotificationContent = "pnsRegistrationTokenpnsRegistrationTokenpnsRegistrationTokenpnsRegistrationToken"; let subscriberIdsToNotify = "string1"; - - - + + + try { adaptor.sendPushNotification(subscriberId, authToken, pushNotificationContent, subscriberIdsToNotify); assert.fail("It should throw exception because pushNotificationContent is not json"); } catch (e) { //pass } - - + + pushNotificationContent = {title:"title", body:"body"}; let jsCmd = { command: "sendPushNotification", @@ -965,14 +1056,14 @@ describe("WebRTCAdaptor", function() { pushNotificationContent: pushNotificationContent, subscriberIdsToNotify: subscriberIdsToNotify }; - + try { adaptor.sendPushNotification(subscriberId, authToken, pushNotificationContent, subscriberIdsToNotify); assert.fail("It should throw exception because subscriberIdsToNotify is not array"); } catch (e) { //pass } - + jsCmd = { command: "sendPushNotification", subscriberId: subscriberId, @@ -980,9 +1071,9 @@ describe("WebRTCAdaptor", function() { pushNotificationContent: pushNotificationContent, subscriberIdsToNotify: subscriberIdsToNotify }; - + subscriberIdsToNotify = ["string1"]; - + jsCmd = { command: "sendPushNotification", subscriberId: subscriberId, @@ -991,28 +1082,28 @@ describe("WebRTCAdaptor", function() { subscriberIdsToNotify: subscriberIdsToNotify }; let webSocketAdaptor = sinon.mock(adaptor.webSocketAdaptor); - + let sendExpectation = webSocketAdaptor.expects("send").once().withArgs(JSON.stringify(jsCmd)); - - adaptor.sendPushNotification(subscriberId, authToken, pushNotificationContent, subscriberIdsToNotify); - + + adaptor.sendPushNotification(subscriberId, authToken, pushNotificationContent, subscriberIdsToNotify); + sendExpectation.verify() - + }); - - + + it("sendPushNotificationToTopic", async function(){ - + let adaptor = new WebRTCAdaptor({ websocketURL: "ws://example.com", isPlayMode: true }); - + let subscriberId = "subscriberId"; let authToken = "autotokenkdnkf"; let pushNotificationContent = "text"; let topic = "topic"; - + let jsCmd = { command: "sendPushNotification", subscriberId: subscriberId, @@ -1020,14 +1111,14 @@ describe("WebRTCAdaptor", function() { pushNotificationContent: pushNotificationContent, topic: topic }; - + try { adaptor.sendPushNotificationToTopic(subscriberId, authToken, pushNotificationContent, topic); assert.fail("It should throw exception because pushNotificationContent is not json"); } catch (error) { //pass } - + pushNotificationContent = {title:"title", body:"body"}; jsCmd = { command: "sendPushNotification", @@ -1036,16 +1127,16 @@ describe("WebRTCAdaptor", function() { pushNotificationContent: pushNotificationContent, topic: topic }; - + let webSocketAdaptor = sinon.mock(adaptor.webSocketAdaptor); - + let sendExpectation = webSocketAdaptor.expects("send").once().withArgs(JSON.stringify(jsCmd)); - + adaptor.sendPushNotificationToTopic(subscriberId, authToken, pushNotificationContent, topic); - + sendExpectation.verify() - + }); - + }); From 39c56962ec268cff3b3ed32c3c6711201fb11bf4 Mon Sep 17 00:00:00 2001 From: Mustafa BOLEKEN Date: Sun, 23 Jun 2024 00:55:19 +0300 Subject: [PATCH 3/4] Update webrtc_adaptor.test.js --- src/test/js/webrtc_adaptor.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/js/webrtc_adaptor.test.js b/src/test/js/webrtc_adaptor.test.js index 1b29ef31..28e4ad07 100644 --- a/src/test/js/webrtc_adaptor.test.js +++ b/src/test/js/webrtc_adaptor.test.js @@ -844,6 +844,8 @@ describe("WebRTCAdaptor", function () { adaptor.startPublishing(streamId); + expect(Logger.debug.calledWithExactly("We already established peer connection, no need to create offer")).to.be.true; + expect(initPeerConnection.calledWithExactly(streamId, "publish")).to.be.false; expect(createOfferFake.called).to.be.false; }); From 0df14f42d49a032b9b746b99c1ef2aac139b40e1 Mon Sep 17 00:00:00 2001 From: Mustafa BOLEKEN Date: Sun, 23 Jun 2024 01:08:50 +0300 Subject: [PATCH 4/4] Update webrtc_adaptor.test.js --- src/test/js/webrtc_adaptor.test.js | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/test/js/webrtc_adaptor.test.js b/src/test/js/webrtc_adaptor.test.js index 28e4ad07..adb4d5d8 100644 --- a/src/test/js/webrtc_adaptor.test.js +++ b/src/test/js/webrtc_adaptor.test.js @@ -795,9 +795,9 @@ describe("WebRTCAdaptor", function () { }); let streamId = "stream123"; - let peerConnection = new RTCPeerConnection(); - peerConnection.iceConnectionState = "connected"; - adaptor.remotePeerConnection[streamId] = peerConnection; + let peerConnection = new RTCPeerConnection(); + sandbox.replaceGetter(peerConnection,"iceConnectionState", sinon.fake.returns("connected")); + adaptor.remotePeerConnection[streamId] = peerConnection; let initPeerConnection = sinon.replace(adaptor, "initPeerConnection", sinon.fake.returns(peerConnection)); let createOfferFake = sinon.replace(peerConnection, "createOffer", sinon.fake.returns(Promise.reject("this is on purpose"))); @@ -815,9 +815,9 @@ describe("WebRTCAdaptor", function () { }); let streamId = "stream123"; - let peerConnection = new RTCPeerConnection(); - peerConnection.iceConnectionState = "new"; - adaptor.remotePeerConnection[streamId] = peerConnection; + let peerConnection = new RTCPeerConnection(); + sandbox.replaceGetter(peerConnection,"iceConnectionState", sinon.fake.returns("new")); + adaptor.remotePeerConnection[streamId] = peerConnection; let initPeerConnection = sinon.replace(adaptor, "initPeerConnection", sinon.fake.returns(peerConnection)); let createOfferFake = sinon.replace(peerConnection, "createOffer", sinon.fake.returns(Promise.resolve())); @@ -835,17 +835,15 @@ describe("WebRTCAdaptor", function () { }); let streamId = "stream123"; - let peerConnection = new RTCPeerConnection(); - peerConnection.iceConnectionState = "failed"; - adaptor.remotePeerConnection[streamId] = peerConnection; + let peerConnection = new RTCPeerConnection(); + sandbox.replaceGetter(peerConnection,"iceConnectionState", sinon.fake.returns("failed")); + adaptor.remotePeerConnection[streamId] = peerConnection; let initPeerConnection = sinon.replace(adaptor, "initPeerConnection", sinon.fake.returns(peerConnection)); let createOfferFake = sinon.replace(peerConnection, "createOffer", sinon.fake.returns(Promise.resolve())); adaptor.startPublishing(streamId); - expect(Logger.debug.calledWithExactly("We already established peer connection, no need to create offer")).to.be.true; - expect(initPeerConnection.calledWithExactly(streamId, "publish")).to.be.false; expect(createOfferFake.called).to.be.false; }); @@ -857,9 +855,9 @@ describe("WebRTCAdaptor", function () { }); let streamId = "stream123"; - let peerConnection = new RTCPeerConnection(); - peerConnection.iceConnectionState = "disconnected"; - adaptor.remotePeerConnection[streamId] = peerConnection; + let peerConnection = new RTCPeerConnection(); + sandbox.replaceGetter(peerConnection,"iceConnectionState", sinon.fake.returns("disconnected")); + adaptor.remotePeerConnection[streamId] = peerConnection; let initPeerConnection = sinon.replace(adaptor, "initPeerConnection", sinon.fake.returns(peerConnection)); let createOfferFake = sinon.replace(peerConnection, "createOffer", sinon.fake.returns(Promise.resolve()));