From a0cd642044a69e89ecb8a910c9bd63ff1ac5c18f Mon Sep 17 00:00:00 2001 From: David Novicki Date: Thu, 9 May 2019 13:08:12 -0700 Subject: [PATCH] fix: added prettier config and ran across project --- .prettierignore | 7 + .prettierrc.js | 6 + Gruntfile.js | 14 +- demo/index.html | 173 ++++++----- demo/index.js | 81 ++++-- package.json | 11 +- test/unit/connect-rtc.js | 4 +- test/unit/rtc_session.js | 311 ++++++++++++-------- test/unit/signaling.js | 160 ++++++++--- test/unit/utils.js | 606 ++++++++++++++++++++------------------- 10 files changed, 806 insertions(+), 567 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc.js diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..a2592e5 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,7 @@ +# Ignore list: +/* +# Except list: +!/src/**/*.js +!/*.js +!/demo +!/test \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..20aad76 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,6 @@ +module.exports = { + trailingComma: 'none', + tabWidth: 4, + semi: true, + singleQuote: true +}; diff --git a/Gruntfile.js b/Gruntfile.js index 0458513..af86f5d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,6 +1,6 @@ 'use strict'; -module.exports = function (grunt) { +module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { @@ -14,24 +14,20 @@ module.exports = function (grunt) { }, browserify: { connectRtcGlobalObjectDebug: { - src: [ - './src/js/connect-rtc.js' - ], + src: ['./src/js/connect-rtc.js'], dest: './out/connect-rtc-debug.js', options: { browserifyOptions: { debug: true }, - transform: [["babelify", { "presets": ["env"] }]], + transform: [['babelify', { presets: ['env'] }]] } }, connectRtcGlobalObject: { - src: [ - './src/js/connect-rtc.js' - ], + src: ['./src/js/connect-rtc.js'], dest: './out/connect-rtc.js', options: { - transform: [["babelify", { "presets": ["env"] }]], + transform: [['babelify', { presets: ['env'] }]] } } }, diff --git a/demo/index.html b/demo/index.html index c1c66c5..0a2bba7 100644 --- a/demo/index.html +++ b/demo/index.html @@ -1,69 +1,112 @@ + + connect-rtc-js demo + - - connect-rtc-js demo - - - - - - - -

Amazon Connect RTC Demo

-

See amazon-connect-streams for how to get the softphone media info

-

Note: stringify the object returned by contact.getAgentConnection().getSoftphoneMediaInfo() before pasting it - here -

- - -
- -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
- - + + + + +

Amazon Connect RTC Demo

+

+ See + amazon-connect-streams + for how to get the softphone media info +

+

+ Note: stringify the object returned by + contact.getAgentConnection().getSoftphoneMediaInfo() before + pasting it here +

+ + +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + diff --git a/demo/index.js b/demo/index.js index 8b12f60..04dbc36 100644 --- a/demo/index.js +++ b/demo/index.js @@ -1,18 +1,23 @@ -$(document).ready(function () { +$(document).ready(function() { var audioElement = $('#remoteAudio')[0]; var videoElement = $('#remoteVideo')[0]; if (window.location.hash) { - $('#softphoneMediaInfo').val(decodeURIComponent(window.location.hash.substr(1))); + $('#softphoneMediaInfo').val( + decodeURIComponent(window.location.hash.substr(1)) + ); } - $('#makeCall').click(function () { + $('#makeCall').click(function() { var mediaInfo = JSON.parse($('#softphoneMediaInfo').val()); - var rtcConfig = mediaInfo.webcallConfig || JSON.parse(mediaInfo.callConfigJson);//mediaInfo.webcallConfig is used internally by Amazon Connect team only - var session = new connect.RTCSession(rtcConfig.signalingEndpoint, + var rtcConfig = + mediaInfo.webcallConfig || JSON.parse(mediaInfo.callConfigJson); //mediaInfo.webcallConfig is used internally by Amazon Connect team only + var session = new connect.RTCSession( + rtcConfig.signalingEndpoint, rtcConfig.iceServers, mediaInfo.callContextToken, - console); + console + ); session.echoCancellation = $('#echoCancellationOption').is(':checked'); @@ -27,27 +32,41 @@ $(document).ready(function () { } if ($('#enable-video')[0].checked) { - $('#video-display')[0].style.display = 'block'; - session.remoteVideoElement = videoElement; - // enable video with 240p requested. - session.enableVideo = true; - session.maxVideoWidth = 426; - session.maxVideoHeight = 240; + $('#video-display')[0].style.display = 'block'; + session.remoteVideoElement = videoElement; + // enable video with 240p requested. + session.enableVideo = true; + session.maxVideoWidth = 426; + session.maxVideoHeight = 240; } else { - $('#video-display')[0].style.display = 'none'; - session.remoteVideoElement = null; + $('#video-display')[0].style.display = 'none'; + session.remoteVideoElement = null; } var statsCollector; session.onSessionConnected = () => { statsCollector = setInterval(() => { var collectTime = new Date(); - Promise.all([session.getUserAudioStats(), session.getRemoteAudioStats()]).then((streamStats) => { - console.log(collectTime + " Audio statistics : " + JSON.stringify(streamStats)); + Promise.all([ + session.getUserAudioStats(), + session.getRemoteAudioStats() + ]).then(streamStats => { + console.log( + collectTime + + ' Audio statistics : ' + + JSON.stringify(streamStats) + ); }); if ($('#enable-video')[0].checked) { - Promise.all([session.getUserVideoStats(), session.getRemoteVideoStats()]).then((streamStats) => { - console.log(collectTime + " Video statistics : " + JSON.stringify(streamStats)); + Promise.all([ + session.getUserVideoStats(), + session.getRemoteVideoStats() + ]).then(streamStats => { + console.log( + collectTime + + ' Video statistics : ' + + JSON.stringify(streamStats) + ); }); } }, 2000); @@ -68,7 +87,7 @@ $(document).ready(function () { $('#enable-video').prop('disabled', true); $('#disconnectCall').prop('disabled', false); - $('#disconnectCall').click(function () { + $('#disconnectCall').click(function() { if (session) { try { session.hangup(); @@ -83,9 +102,9 @@ $(document).ready(function () { } }); - $('#pause-local-video').click(function(){ - if(session) { - if($('#pause-local-video').is(':checked')) + $('#pause-local-video').click(function() { + if (session) { + if ($('#pause-local-video').is(':checked')) session.pauseLocalVideo(); else { session.resumeLocalVideo(); @@ -93,9 +112,9 @@ $(document).ready(function () { } }); - $('#pause-remote-video').click(function(){ - if(session) { - if($('#pause-remote-video').is(':checked')) + $('#pause-remote-video').click(function() { + if (session) { + if ($('#pause-remote-video').is(':checked')) session.pauseRemoteVideo(); else { session.resumeRemoteVideo(); @@ -103,9 +122,9 @@ $(document).ready(function () { } }); - $('#pause-local-audio').click(function(){ - if(session) { - if($('#pause-local-audio').is(':checked')) + $('#pause-local-audio').click(function() { + if (session) { + if ($('#pause-local-audio').is(':checked')) session.pauseLocalAudio(); else { session.resumeLocalAudio(); @@ -113,9 +132,9 @@ $(document).ready(function () { } }); - $('#pause-remote-audio').click(function(){ - if(session) { - if($('#pause-remote-audio').is(':checked')) + $('#pause-remote-audio').click(function() { + if (session) { + if ($('#pause-remote-audio').is(':checked')) session.pauseRemoteAudio(); else { session.resumeRemoteAudio(); diff --git a/package.json b/package.json index 32a6693..e0f6569 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,14 @@ "version": "", "postversion": "export GITTAG=\"echo $(git describe --abbrev=0 --tags | sed 's/^v//')\" && git push --force --set-upstream origin bumpVersion --follow-tags && git checkout gh-pages && git pull && cp out/connect-rtc-debug.js ./connect-rtc-debug-`$GITTAG`.js && cp out/connect-rtc.min.js ./connect-rtc-`$GITTAG`.min.js && ln -fs connect-rtc-debug-`$GITTAG`.js connect-rtc-debug-latest.js && ln -fs connect-rtc-`$GITTAG`.min.js connect-rtc-latest.min.js && git add connect-rtc*.js && git commit -m `$GITTAG` && git push --set-upstream origin gh-pages && git checkout master", "prepublish": "grunt build", + "pretty": "prettier --write \"**/*.*\"", "test": "grunt && mocha --compilers js:babel-core/register test/unit" }, + "husky": { + "hooks": { + "pre-commit": "pretty-quick --staged" + } + }, "dependencies": { "webrtc-adapter": "~2.0.5", "uuid": "^3.0.1" @@ -30,8 +36,8 @@ "node": ">=6.0.0" }, "devDependencies": { - "babel-polyfill": "^6.23.0", "babel-plugin-transform-runtime": "^6.23.0", + "babel-polyfill": "^6.23.0", "babel-preset-env": "^1.3.2", "babelify": "^7.3.0", "chai": "^3.5.0", @@ -49,7 +55,10 @@ "grunt-contrib-watch": "^1.1.0", "grunt-eslint": "^21.0.0", "grunt-githooks": "^0.6.0", + "husky": "^2.2.0", "mocha": "^3.2.0", + "prettier": "^1.17.0", + "pretty-quick": "^1.10.0", "selenium-webdriver": "^3.3.0", "sinon": "^2.1.0", "tape": "^4.6.3", diff --git a/test/unit/connect-rtc.js b/test/unit/connect-rtc.js index 1e15dfa..25ef837 100644 --- a/test/unit/connect-rtc.js +++ b/test/unit/connect-rtc.js @@ -8,7 +8,7 @@ * or in the "LICENSE" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import {RTCSession, RTCErrors} from '../../src/js/connect-rtc'; +import { RTCSession, RTCErrors } from '../../src/js/connect-rtc'; import chai from 'chai'; describe('Bundled JS', () => { @@ -16,4 +16,4 @@ describe('Bundled JS', () => { chai.expect(RTCSession).to.be.not.null; chai.expect(RTCErrors).to.be.not.null; }); -}); \ No newline at end of file +}); diff --git a/test/unit/rtc_session.js b/test/unit/rtc_session.js index 3474aa8..024289d 100644 --- a/test/unit/rtc_session.js +++ b/test/unit/rtc_session.js @@ -9,7 +9,19 @@ */ import RtcSession from '../../src/js/rtc_session'; -import { RTCSessionState, GrabLocalMediaState, CreateOfferState, SetLocalSessionDescriptionState, ConnectSignalingAndIceCollectionState, InviteAnswerState, AcceptState, TalkingState, CleanUpState, DisconnectedState, FailedState } from '../../src/js/rtc_session'; +import { + RTCSessionState, + GrabLocalMediaState, + CreateOfferState, + SetLocalSessionDescriptionState, + ConnectSignalingAndIceCollectionState, + InviteAnswerState, + AcceptState, + TalkingState, + CleanUpState, + DisconnectedState, + FailedState +} from '../../src/js/rtc_session'; import { RTC_ERRORS } from '../../src/js/rtc_const'; import { BusyException, CallNotFoundException } from '../../src/js/exceptions'; import chai from 'chai'; @@ -17,14 +29,19 @@ import sinon from 'sinon'; describe('RTC session', () => { describe('session object', () => { - var session = new RtcSession('wss://amazon-connect-rtc-server.amazonaws.com/', [], 'contactToken', console); + var session = new RtcSession( + 'wss://amazon-connect-rtc-server.amazonaws.com/', + [], + 'contactToken', + console + ); it('builds audio constraints by default', () => { var constraints = session._buildMediaConstraints(); chai.expect(!!constraints.audio).to.be.true; }); - it('generates contact ID when it\'s not provided through constructor', () => { + it("generates contact ID when it's not provided through constructor", () => { chai.expect(session.callId).to.match(/^[-A-Fa-f0-9]{36}$/); }); }); @@ -45,7 +62,7 @@ describe('RTC session', () => { state = new RTCSessionState(session); }); - it('executs transit only if it\'s current state', () => { + it("executs transit only if it's current state", () => { session._state = state; session.transit = sinon.spy(); var nextState = {}; @@ -54,7 +71,7 @@ describe('RTC session', () => { chai.assert(session.transit.calledWith(nextState)); }); - it('skips transit if it\'s not current state', () => { + it("skips transit if it's not current state", () => { session._state = null; session.transit = sinon.spy(); var nextState = {}; @@ -88,36 +105,39 @@ describe('RTC session', () => { chai.assert(session.transit.args[0][0] instanceof CreateOfferState); }); - it('notifies gum error and go to failed state if gUM times out', (done) => { + it('notifies gum error and go to failed state if gUM times out', done => { session._logger = console; session._gumTimeoutMillis = 0; session._sessionReport = {}; session._state = state; - session._buildMediaConstraints = () => { }; + session._buildMediaConstraints = () => {}; session._onGumError = sinon.spy(); - session.transit = (nextState) => { + session.transit = nextState => { chai.assert(session._onGumError.calledOnce); chai.assert(session._onGumError.calledWith(session)); chai.assert(nextState instanceof FailedState); done(); }; state._gUM = sinon.stub(); - state._gUM.returns(new Promise(() => { })); + state._gUM.returns(new Promise(() => {})); state.onEnter(); }); - it('notifies gum error and go to failed state if gUM fast fails', (done) => { + it('notifies gum error and go to failed state if gUM fast fails', done => { session._logger = console; session._gumTimeoutMillis = 2000; session._sessionReport = {}; session._state = state; - session._buildMediaConstraints = () => { }; + session._buildMediaConstraints = () => {}; session._onGumError = sinon.spy(); - session.transit = (nextState) => { + session.transit = nextState => { chai.assert(session._onGumError.calledOnce); chai.assert(session._onGumError.calledWith(session)); chai.assert(nextState instanceof FailedState); - chai.assert.equal(RTC_ERRORS.GUM_OTHER_FAILURE, nextState._failureReason); + chai.assert.equal( + RTC_ERRORS.GUM_OTHER_FAILURE, + nextState._failureReason + ); done(); }; state._gUM = sinon.stub(); @@ -125,14 +145,14 @@ describe('RTC session', () => { state.onEnter(); }); - it('notifies gum success and go to create offer state if gUM succeeds within time limit', (done) => { + it('notifies gum success and go to create offer state if gUM succeeds within time limit', done => { session._logger = console; session._gumTimeoutMillis = 2000; session._sessionReport = {}; session._state = state; - session._buildMediaConstraints = () => { }; + session._buildMediaConstraints = () => {}; session._onGumSuccess = sinon.spy(); - session.transit = (nextState) => { + session.transit = nextState => { chai.assert(session._onGumSuccess.calledOnce); chai.assert(session._onGumSuccess.calledWith(session)); chai.assert(nextState instanceof CreateOfferState); @@ -169,10 +189,12 @@ describe('RTC session', () => { session._state = state; }); - it('transits to set local description state when offer created', (done) => { + it('transits to set local description state when offer created', done => { session._pc.createOffer.returns(Promise.resolve('desc')); - session.transit = (nextState) => { - chai.assert(nextState instanceof SetLocalSessionDescriptionState); + session.transit = nextState => { + chai.assert( + nextState instanceof SetLocalSessionDescriptionState + ); chai.assert.equal('desc', session._localSessionDescription); done(); }; @@ -181,9 +203,9 @@ describe('RTC session', () => { chai.assert(session._pc.addStream.calledOnce); }); - it('transits to failed state when offer creation failed', (done) => { + it('transits to failed state when offer creation failed', done => { session._pc.createOffer.returns(Promise.reject('testFailure')); - session.transit = (nextState) => { + session.transit = nextState => { chai.expect(nextState).to.be.instanceof(FailedState); chai.expect(session._localSessionDescription).to.be.undefined; done(); @@ -195,42 +217,43 @@ describe('RTC session', () => { }); describe('SetLocalSessionDescriptionState', () => { - var sdp = "v=0\r\n" + - "o=- 6968650397182970779 2 IN IP4 127.0.0.1\r\n" + - "s=-\r\n" + - "t=0 0\r\n" + - "a=group:BUNDLE audio\r\n" + - "a=msid-semantic: WMS idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n" + - "m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\n" + - "c=IN IP4 0.0.0.0\r\n" + - "a=rtcp:9 IN IP4 0.0.0.0\r\n" + - "a=ice-ufrag:E4/X\r\n" + - "a=ice-pwd:34ijxBABGSaclsOpfc9E042R\r\n" + - "a=fingerprint:sha-256 26:40:A1:3C:7E:67:75:2F:1B:21:B9:54:68:07:E8:CE:E5:9C:28:2A:E8:D4:36:26:04:C5:5B:0C:04:43:37:CF\r\n" + - "a=setup:actpass\r\n" + - "a=mid:audio\r\n" + - "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" + - "a=sendrecv\r\n" + - "a=rtcp-mux\r\n" + - "a=rtpmap:111 opus/48000/2\r\n" + - "a=rtcp-fb:111 transport-cc\r\n" + - "a=fmtp:111 minptime=10;useinbandfec=1\r\n" + - "a=rtpmap:103 ISAC/16000\r\n" + - "a=rtpmap:104 ISAC/32000\r\n" + - "a=rtpmap:9 G722/8000\r\n" + - "a=rtpmap:0 PCMU/8000\r\n" + - "a=rtpmap:8 PCMA/8000\r\n" + - "a=rtpmap:106 CN/32000\r\n" + - "a=rtpmap:105 CN/16000\r\n" + - "a=rtpmap:13 CN/8000\r\n" + - "a=rtpmap:110 telephone-event/48000\r\n" + - "a=rtpmap:112 telephone-event/32000\r\n" + - "a=rtpmap:113 telephone-event/16000\r\n" + - "a=rtpmap:126 telephone-event/8000\r\n" + - "a=ssrc:2534193841 cname:NsEUa3X+NJbQmyyN\r\n" + - "a=ssrc:2534193841 msid:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n" + - "a=ssrc:2534193841 mslabel:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n" + - "a=ssrc:2534193841 label:d26be488-17a9-4f63-85b4-bdcf9754bb9b"; + var sdp = + 'v=0\r\n' + + 'o=- 6968650397182970779 2 IN IP4 127.0.0.1\r\n' + + 's=-\r\n' + + 't=0 0\r\n' + + 'a=group:BUNDLE audio\r\n' + + 'a=msid-semantic: WMS idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n' + + 'm=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\n' + + 'c=IN IP4 0.0.0.0\r\n' + + 'a=rtcp:9 IN IP4 0.0.0.0\r\n' + + 'a=ice-ufrag:E4/X\r\n' + + 'a=ice-pwd:34ijxBABGSaclsOpfc9E042R\r\n' + + 'a=fingerprint:sha-256 26:40:A1:3C:7E:67:75:2F:1B:21:B9:54:68:07:E8:CE:E5:9C:28:2A:E8:D4:36:26:04:C5:5B:0C:04:43:37:CF\r\n' + + 'a=setup:actpass\r\n' + + 'a=mid:audio\r\n' + + 'a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n' + + 'a=sendrecv\r\n' + + 'a=rtcp-mux\r\n' + + 'a=rtpmap:111 opus/48000/2\r\n' + + 'a=rtcp-fb:111 transport-cc\r\n' + + 'a=fmtp:111 minptime=10;useinbandfec=1\r\n' + + 'a=rtpmap:103 ISAC/16000\r\n' + + 'a=rtpmap:104 ISAC/32000\r\n' + + 'a=rtpmap:9 G722/8000\r\n' + + 'a=rtpmap:0 PCMU/8000\r\n' + + 'a=rtpmap:8 PCMA/8000\r\n' + + 'a=rtpmap:106 CN/32000\r\n' + + 'a=rtpmap:105 CN/16000\r\n' + + 'a=rtpmap:13 CN/8000\r\n' + + 'a=rtpmap:110 telephone-event/48000\r\n' + + 'a=rtpmap:112 telephone-event/32000\r\n' + + 'a=rtpmap:113 telephone-event/16000\r\n' + + 'a=rtpmap:126 telephone-event/8000\r\n' + + 'a=ssrc:2534193841 cname:NsEUa3X+NJbQmyyN\r\n' + + 'a=ssrc:2534193841 msid:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n' + + 'a=ssrc:2534193841 mslabel:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n' + + 'a=ssrc:2534193841 label:d26be488-17a9-4f63-85b4-bdcf9754bb9b'; /** * @type {RtcSession} @@ -258,20 +281,26 @@ describe('RTC session', () => { session._state = state; }); - it('transits to signaling state when local description is set', (done) => { + it('transits to signaling state when local description is set', done => { session._pc.setLocalDescription.returns(Promise.resolve()); - session.transit = (nextState) => { - chai.expect(session._onSessionInitialized.calledOnce).to.be.true; - chai.expect(nextState).to.be.instanceof(ConnectSignalingAndIceCollectionState); + session.transit = nextState => { + chai.expect(session._onSessionInitialized.calledOnce).to.be + .true; + chai.expect(nextState).to.be.instanceof( + ConnectSignalingAndIceCollectionState + ); done(); }; state.onEnter(); }); - it('transits to failed state when set local description failed', (done) => { - session._pc.setLocalDescription.returns(Promise.reject('testFailure')); - session.transit = (nextState) => { - chai.expect(session._onSessionInitialized.calledOnce).to.be.false; + it('transits to failed state when set local description failed', done => { + session._pc.setLocalDescription.returns( + Promise.reject('testFailure') + ); + session.transit = nextState => { + chai.expect(session._onSessionInitialized.calledOnce).to.be + .false; chai.expect(nextState).to.be.instanceof(FailedState); done(); }; @@ -296,12 +325,11 @@ describe('RTC session', () => { _createSignalingChannel: sinon.stub(), _onIceCollectionComplete: sinon.spy(), _onSignalingConnected: sinon.spy(), - _pc: { - }, + _pc: {}, _sessionReport: {} }; - state = new ConnectSignalingAndIceCollectionState(session, 2);//2 m lines - state._createLocalCandidate = (initDict) => initDict; + state = new ConnectSignalingAndIceCollectionState(session, 2); //2 m lines + state._createLocalCandidate = initDict => initDict; session._state = state; }); @@ -311,18 +339,24 @@ describe('RTC session', () => { state.onSignalingFailed(); chai.expect(session.transit.calledOnce).to.be.true; - chai.expect(session.transit.args[0][0]).to.be.instanceof(FailedState); + chai.expect(session.transit.args[0][0]).to.be.instanceof( + FailedState + ); }); - it('transits to failed state when ICE collection times out', (done) => { + it('transits to failed state when ICE collection times out', done => { var sig = { connect: sinon.spy() }; session._createSignalingChannel.returns(sig); session._iceTimeoutMillis = 1; - session.transit = (nextState) => { + session.transit = nextState => { chai.expect(sig.connect.calledOnce).to.be.true; - chai.expect(session._onIceCollectionComplete.calledOnce).to.be.true; - chai.expect(session._onIceCollectionComplete.args[0][1]).to.be.true; - chai.expect(session._onIceCollectionComplete.args[0][2]).to.eq(0); + chai.expect(session._onIceCollectionComplete.calledOnce).to.be + .true; + chai.expect(session._onIceCollectionComplete.args[0][1]).to.be + .true; + chai.expect(session._onIceCollectionComplete.args[0][2]).to.eq( + 0 + ); chai.expect(nextState).to.be.instanceof(FailedState); done(); }; @@ -335,9 +369,12 @@ describe('RTC session', () => { state.onIceCandidate({}); chai.expect(session._onIceCollectionComplete.calledOnce).to.be.true; - chai.expect(session._onIceCollectionComplete.args[0][1]).to.be.false; + chai.expect(session._onIceCollectionComplete.args[0][1]).to.be + .false; chai.expect(session._onIceCollectionComplete.args[0][2]).to.eq(0); - chai.expect(session.transit.args[0][0]).to.be.instanceof(FailedState); + chai.expect(session.transit.args[0][0]).to.be.instanceof( + FailedState + ); }); it('keeps waiting for ICE collection when signaling gets connected', () => { @@ -354,7 +391,8 @@ describe('RTC session', () => { state.onIceCandidate({ candidate: { - candidate: 'candidate:3517520453 1 udp 41885695 172.22.116.70 59345 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag dRi5 network-id 3 network-cost 50', + candidate: + 'candidate:3517520453 1 udp 41885695 172.22.116.70 59345 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag dRi5 network-id 3 network-cost 50', sdpMLineIndex: 0, sdpMid: 'audio' } @@ -362,7 +400,8 @@ describe('RTC session', () => { state.onIceCandidate({}); chai.expect(session._onIceCollectionComplete.calledOnce).to.be.true; - chai.expect(session._onIceCollectionComplete.args[0][1]).to.be.false; + chai.expect(session._onIceCollectionComplete.args[0][1]).to.be + .false; chai.expect(session._onIceCollectionComplete.args[0][2]).to.eq(1); chai.expect(session.transit.called).to.be.false; }); @@ -372,34 +411,40 @@ describe('RTC session', () => { state.onIceCandidate({ candidate: { - candidate: 'candidate:3517520453 1 udp 41885695 172.22.116.70 59345 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag dRi5 network-id 3 network-cost 50', + candidate: + 'candidate:3517520453 1 udp 41885695 172.22.116.70 59345 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag dRi5 network-id 3 network-cost 50', sdpMLineIndex: 0, sdpMid: 'audio' } }); - chai.expect(session._onIceCollectionComplete.calledOnce).to.be.false; + chai.expect(session._onIceCollectionComplete.calledOnce).to.be + .false; state.onIceCandidate({ candidate: { - candidate: 'candidate:3517520453 2 udp 41885694 172.22.116.70 56719 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag dRi5 network-id 3 network-cost 50', + candidate: + 'candidate:3517520453 2 udp 41885694 172.22.116.70 56719 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag dRi5 network-id 3 network-cost 50', sdpMLineIndex: 0, sdpMid: 'audio' } }); - chai.expect(session._onIceCollectionComplete.calledOnce).to.be.false; + chai.expect(session._onIceCollectionComplete.calledOnce).to.be + .false; state.onIceCandidate({ candidate: { - candidate: 'candidate:3517520453 1 udp 41885695 172.22.116.70 59377 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag dRi5 network-id 3 network-cost 50', + candidate: + 'candidate:3517520453 1 udp 41885695 172.22.116.70 59377 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag dRi5 network-id 3 network-cost 50', sdpMLineIndex: 1, sdpMid: 'video' } }); chai.expect(session._onIceCollectionComplete.calledOnce).to.be.true; - chai.expect(session._onIceCollectionComplete.args[0][1]).to.be.false; + chai.expect(session._onIceCollectionComplete.args[0][1]).to.be + .false; chai.expect(session._onIceCollectionComplete.args[0][2]).to.eq(3); chai.expect(session.transit.called).to.be.false; }); @@ -409,7 +454,8 @@ describe('RTC session', () => { state.onIceCandidate({ candidate: { - candidate: 'candidate:3517520453 1 udp 41885695 172.22.116.70 59345 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag dRi5 network-id 3 network-cost 50', + candidate: + 'candidate:3517520453 1 udp 41885695 172.22.116.70 59345 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag dRi5 network-id 3 network-cost 50', sdpMLineIndex: 0, sdpMid: 'audio' } @@ -420,7 +466,9 @@ describe('RTC session', () => { chai.expect(session.transit.calledOnce).to.be.true; chai.expect(session._onSignalingConnected.calledOnce).to.be.true; chai.expect(session._onIceCollectionComplete.calledOnce).to.be.true; - chai.expect(session.transit.args[0][0]).to.be.instanceof(InviteAnswerState); + chai.expect(session.transit.args[0][0]).to.be.instanceof( + InviteAnswerState + ); }); }); @@ -438,9 +486,7 @@ describe('RTC session', () => { var candidates; beforeEach(() => { - candidates = [ - 'cand1' - ]; + candidates = ['cand1']; session = { _logger: console, _localSessionDescription: { @@ -459,10 +505,17 @@ describe('RTC session', () => { it('notifies signaling started and invites on enter', () => { state.onEnter(); - chai.expect(session._onSignalingStarted.calledOnce, 'should have sent session event').to.be.true; + chai.expect( + session._onSignalingStarted.calledOnce, + 'should have sent session event' + ).to.be.true; chai.expect(session._signalingChannel.invite.calledOnce).to.be.true; - chai.expect(session._signalingChannel.invite.args[0][0]).to.be.eq('sdp'); - chai.expect(session._signalingChannel.invite.args[0][1]).to.be.eql(candidates); + chai.expect(session._signalingChannel.invite.args[0][0]).to.be.eq( + 'sdp' + ); + chai.expect(session._signalingChannel.invite.args[0][1]).to.be.eql( + candidates + ); }); it('transits to AcceptState when signaling answer is received', () => { @@ -472,9 +525,13 @@ describe('RTC session', () => { state.onSignalingAnswered('remoteSdp', remoteCandidates); chai.expect(session.transit.calledOnce).to.be.true; - chai.expect(session.transit.args[0][0]).to.be.instanceof(AcceptState); + chai.expect(session.transit.args[0][0]).to.be.instanceof( + AcceptState + ); chai.expect(session.transit.args[0][0]._sdp).to.be.eq('remoteSdp'); - chai.expect(session.transit.args[0][0]._candidates).to.be.eql(remoteCandidates); + chai.expect(session.transit.args[0][0]._candidates).to.be.eql( + remoteCandidates + ); }); it('transits to FailedState when handshaking fails', () => { @@ -483,18 +540,28 @@ describe('RTC session', () => { state.onSignalingFailed('unknown'); chai.expect(session.transit.calledOnce).to.be.true; - chai.expect(session.transit.args[0][0]).to.be.instanceof(FailedState); - chai.expect(session.transit.args[0][0]._failureReason).to.be.eql(RTC_ERRORS.SIGNALLING_HANDSHAKE_FAILURE); + chai.expect(session.transit.args[0][0]).to.be.instanceof( + FailedState + ); + chai.expect(session.transit.args[0][0]._failureReason).to.be.eql( + RTC_ERRORS.SIGNALLING_HANDSHAKE_FAILURE + ); }); it('transits to FailedState with USER_BUSY error code when handshaking fails with BusyException', () => { session.transit = sinon.spy(); - state.onSignalingFailed(new BusyException('Agent already connected')); + state.onSignalingFailed( + new BusyException('Agent already connected') + ); chai.expect(session.transit.calledOnce).to.be.true; - chai.expect(session.transit.args[0][0]).to.be.instanceof(FailedState); - chai.expect(session.transit.args[0][0]._failureReason).to.be.eql(RTC_ERRORS.USER_BUSY); + chai.expect(session.transit.args[0][0]).to.be.instanceof( + FailedState + ); + chai.expect(session.transit.args[0][0]._failureReason).to.be.eql( + RTC_ERRORS.USER_BUSY + ); }); it('transits to FailedState with CALL_NOT_FOUND error code when handshaking fails with CallNotFoundException', () => { @@ -503,8 +570,12 @@ describe('RTC session', () => { state.onSignalingFailed(new CallNotFoundException('No such call')); chai.expect(session.transit.calledOnce).to.be.true; - chai.expect(session.transit.args[0][0]).to.be.instanceof(FailedState); - chai.expect(session.transit.args[0][0]._failureReason).to.be.eql(RTC_ERRORS.CALL_NOT_FOUND); + chai.expect(session.transit.args[0][0]).to.be.instanceof( + FailedState + ); + chai.expect(session.transit.args[0][0]._failureReason).to.be.eql( + RTC_ERRORS.CALL_NOT_FOUND + ); }); }); @@ -522,9 +593,7 @@ describe('RTC session', () => { var candidates; beforeEach(() => { - candidates = [ - 'cand1' - ]; + candidates = ['cand1']; session = { _logger: console, _stopSession: sinon.spy(), @@ -537,8 +606,8 @@ describe('RTC session', () => { state = new AcceptState(session, 'remoteSdp', candidates); session._state = state; - state._createSessionDescription = (initDict) => initDict; - state._createRemoteCandidate = (initDict) => initDict; + state._createSessionDescription = initDict => initDict; + state._createRemoteCandidate = initDict => initDict; }); it('transits to FailedState if invalid remote SDP is received', () => { @@ -549,7 +618,9 @@ describe('RTC session', () => { state.onEnter(); chai.expect(session.transit.calledOnce).to.be.true; - chai.expect(session.transit.args[0][0]).to.be.instanceof(FailedState); + chai.expect(session.transit.args[0][0]).to.be.instanceof( + FailedState + ); }); it('transits to FailedState if no valid candidate is received', () => { @@ -560,11 +631,13 @@ describe('RTC session', () => { state.onEnter(); chai.expect(session.transit.calledOnce).to.be.true; - chai.expect(session.transit.args[0][0]).to.be.instanceof(FailedState); + chai.expect(session.transit.args[0][0]).to.be.instanceof( + FailedState + ); }); - it('transits to FailedState if setRemoteDescription fails', (done) => { - session.transit = (nextState) => { + it('transits to FailedState if setRemoteDescription fails', done => { + session.transit = nextState => { chai.expect(session._stopSession.calledOnce).to.be.true; chai.expect(nextState).to.be.instanceof(FailedState); done(); @@ -574,8 +647,8 @@ describe('RTC session', () => { state.onEnter(); }); - it('transits to FailedState if addIceCandidate fails', (done) => { - session.transit = (nextState) => { + it('transits to FailedState if addIceCandidate fails', done => { + session.transit = nextState => { chai.expect(session._stopSession.calledOnce).to.be.true; chai.expect(nextState).to.be.instanceof(FailedState); done(); @@ -596,7 +669,7 @@ describe('RTC session', () => { chai.expect(session.transit.called).to.be.false; }); - it('waits for setting remote info after handshake completes', (done) => { + it('waits for setting remote info after handshake completes', done => { session.transit = sinon.spy(); session._pc.setRemoteDescription.returns(Promise.resolve('Good')); session._pc.addIceCandidate.returns(Promise.resolve('Good')); @@ -605,7 +678,7 @@ describe('RTC session', () => { chai.expect(session.transit.called).to.be.false; - session.transit = (nextState) => { + session.transit = nextState => { chai.expect(nextState).to.be.instanceof(TalkingState); done(); }; @@ -652,7 +725,9 @@ describe('RTC session', () => { chai.expect(session._signalingChannel.hangup.calledOnce).to.be.true; chai.expect(session.transit.calledOnce).to.be.true; - chai.expect(session.transit.args[0][0]).to.be.instanceof(DisconnectedState); + chai.expect(session.transit.args[0][0]).to.be.instanceof( + DisconnectedState + ); }); it('hangs up signaling when hangup is requested by client', () => { @@ -660,7 +735,9 @@ describe('RTC session', () => { chai.expect(session._signalingChannel.hangup.calledOnce).to.be.true; chai.expect(session.transit.calledOnce).to.be.true; - chai.expect(session.transit.args[0][0]).to.be.instanceof(DisconnectedState); + chai.expect(session.transit.args[0][0]).to.be.instanceof( + DisconnectedState + ); }); it('detachs media and reports session end on exit', () => { diff --git a/test/unit/signaling.js b/test/unit/signaling.js index fea09dd..1ed74f1 100644 --- a/test/unit/signaling.js +++ b/test/unit/signaling.js @@ -9,20 +9,45 @@ */ import RtcSignaling from '../../src/js/signaling'; -import { SignalingState, FailOnTimeoutState, PendingConnectState, PendingInviteState, PendingAnswerState, PendingAcceptState, PendingAcceptAckState, TalkingState, PendingReconnectState, PendingRemoteHangupState, PendingLocalHangupState, DisconnectedState, FailedState } from '../../src/js/signaling'; // eslint-disable-line no-unused-vars -import { TimeoutExceptionName, UnknownSignalingErrorName } from '../../src/js/exceptions'; +import { + SignalingState, + FailOnTimeoutState, + PendingConnectState, + PendingInviteState, + PendingAnswerState, + PendingAcceptState, + PendingAcceptAckState, + TalkingState, + PendingReconnectState, + PendingRemoteHangupState, + PendingLocalHangupState, + DisconnectedState, + FailedState +} from '../../src/js/signaling'; // eslint-disable-line no-unused-vars +import { + TimeoutExceptionName, + UnknownSignalingErrorName +} from '../../src/js/exceptions'; import chai from 'chai'; import sinon from 'sinon'; describe('signalingTest', () => { describe('signalingObject', () => { - var signaling = new RtcSignaling('call Id', 'https://myserver.com/rtc', 'co{n"t=a:c,t&T"ok}en', console, 4000); + var signaling = new RtcSignaling( + 'call Id', + 'https://myserver.com/rtc', + 'co{n"t=a:c,t&T"ok}en', + console, + 4000 + ); it('can be created and initialized', () => { chai.expect(signaling.callId).to.equal('call Id'); }); it('builds correct WSS URL with escaping', () => { - chai.expect(signaling._buildInviteUri()).to.equal('https://myserver.com/rtc?callId=call%20Id&contactCtx=co%7Bn%22t%3Da%3Ac%2Ct%26T%22ok%7Den'); + chai.expect(signaling._buildInviteUri()).to.equal( + 'https://myserver.com/rtc?callId=call%20Id&contactCtx=co%7Bn%22t%3Da%3Ac%2Ct%26T%22ok%7Den' + ); }); it('throws exit exception after calling enter on state transition', () => { @@ -31,9 +56,11 @@ describe('signalingTest', () => { onExit: initStateExit }); var nextStateEnter = sinon.stub.throws(2); - chai.expect(() => signaling.transit({ - onEnter: nextStateEnter - })).to.throw(1); + chai.expect(() => + signaling.transit({ + onEnter: nextStateEnter + }) + ).to.throw(1); }); }); @@ -52,31 +79,37 @@ describe('signalingTest', () => { signalingState = new SignalingState(signaling); }); - it('could tell it\'s not current state', () => { + it("could tell it's not current state", () => { signaling.state = null; chai.expect(signalingState.isCurrentState).to.equal(false); }); - it('could tell it\'s current state', () => { + it("could tell it's current state", () => { signaling.state = signalingState; chai.expect(signalingState.isCurrentState).to.equal(true); }); - it('calls timeout handler if it\'s current state', () => { + it("calls timeout handler if it's current state", () => { signaling.state = signalingState; signalingState.onTimeout = sinon.spy(); signalingState._onTimeoutChecked(); - chai.assert(signalingState.onTimeout.called, 'onTimeout should have been called'); + chai.assert( + signalingState.onTimeout.called, + 'onTimeout should have been called' + ); }); - it('skips calling timeout handler if it\'s not current state', () => { + it("skips calling timeout handler if it's not current state", () => { signaling.state = null; signalingState.onTimeout = sinon.spy(); signalingState._onTimeoutChecked(); - chai.assert(!signalingState.onTimeout.called, 'onTimeout should have not been called'); + chai.assert( + !signalingState.onTimeout.called, + 'onTimeout should have not been called' + ); }); - it('could schedule timeout', (done) => { + it('could schedule timeout', done => { signaling.state = signalingState; signalingState.onTimeout = done; signalingState.setStateTimeout(1); @@ -98,10 +131,15 @@ describe('signalingTest', () => { state = new FailOnTimeoutState(signaling, 1); }); - it('transit to Failed state with Timeout exception', (done) => { - signaling.transit = (nextState) => { - chai.assert(nextState instanceof FailedState, 'next state should be FailedState'); - chai.expect(nextState.exception.name).to.equal(TimeoutExceptionName); + it('transit to Failed state with Timeout exception', done => { + signaling.transit = nextState => { + chai.assert( + nextState instanceof FailedState, + 'next state should be FailedState' + ); + chai.expect(nextState.exception.name).to.equal( + TimeoutExceptionName + ); done(); }; signaling.state = state; @@ -121,8 +159,8 @@ describe('signalingTest', () => { beforeEach(() => { signaling = { - transit: sinon.spy(), - _connect: sinon.spy() + transit: sinon.spy(), + _connect: sinon.spy() }; state = new PendingConnectState(signaling, 500); }); @@ -130,22 +168,30 @@ describe('signalingTest', () => { it('transit to pending invite once WSS is open', () => { state.onOpen(); chai.expect(signaling.transit.calledOnce).to.be.true; - chai.expect(signaling.transit.args[0][0]).to.be.instanceof(PendingInviteState); + chai.expect(signaling.transit.args[0][0]).to.be.instanceof( + PendingInviteState + ); }); it('retries three times if channelDown occurs before timeout', () => { state.channelDown(); state.channelDown(); state.channelDown(); - + chai.expect(signaling.transit.calledThrice).to.be.true; chai.expect(signaling._connect.calledTwice).to.be.true; - chai.expect(signaling.transit.args[0][0]).to.be.instanceof(PendingConnectState); - chai.expect(signaling.transit.args[1][0]).to.be.instanceof(PendingConnectState); - chai.expect(signaling.transit.args[2][0]).to.be.instanceof(FailedState); - }); - - it('doesn\'t attempt to retry if the timeout has elapsed', (done) => { + chai.expect(signaling.transit.args[0][0]).to.be.instanceof( + PendingConnectState + ); + chai.expect(signaling.transit.args[1][0]).to.be.instanceof( + PendingConnectState + ); + chai.expect(signaling.transit.args[2][0]).to.be.instanceof( + FailedState + ); + }); + + it("doesn't attempt to retry if the timeout has elapsed", done => { state.channelDown(); setTimeout(function() { @@ -153,10 +199,13 @@ describe('signalingTest', () => { chai.expect(signaling.transit.calledTwice).to.be.true; chai.expect(signaling._connect.calledOnce).to.be.true; - chai.expect(signaling.transit.args[0][0]).to.be.instanceof(PendingConnectState); - chai.expect(signaling.transit.args[1][0]).to.be.instanceof(FailedState); + chai.expect(signaling.transit.args[0][0]).to.be.instanceof( + PendingConnectState + ); + chai.expect(signaling.transit.args[1][0]).to.be.instanceof( + FailedState + ); done(); - }, 1000); }); }); @@ -176,7 +225,7 @@ describe('signalingTest', () => { state = new PendingInviteState(signaling); }); - it('sends connected event to signaling object on enter', (done) => { + it('sends connected event to signaling object on enter', done => { signaling._connectedHandler = done; state.onEnter(); }); @@ -197,7 +246,9 @@ describe('signalingTest', () => { chai.assert.equal(1, inviteRequest.params.candidates.length); chai.assert.equal('cand1', inviteRequest.params.candidates[0]); chai.assert.isNotNull(inviteRequest.id); - chai.assert(signaling.transit.args[0][0] instanceof PendingAnswerState); + chai.assert( + signaling.transit.args[0][0] instanceof PendingAnswerState + ); }); }); @@ -233,10 +284,12 @@ describe('signalingTest', () => { chai.assert(signaling.transit.calledOnce); var nextState = signaling.transit.args[0][0]; chai.assert(nextState instanceof FailedState); - chai.expect(nextState.exception.name).to.eq(UnknownSignalingErrorName); + chai.expect(nextState.exception.name).to.eq( + UnknownSignalingErrorName + ); }); - it('notifies and goes to pending accept state upon receiving success response', (done) => { + it('notifies and goes to pending accept state upon receiving success response', done => { signaling._logger = { log: sinon.spy() }; @@ -255,7 +308,9 @@ describe('signalingTest', () => { } }); chai.assert(signaling.transit.calledOnce); - chai.assert(signaling.transit.args[0][0] instanceof PendingAcceptState); + chai.assert( + signaling.transit.args[0][0] instanceof PendingAcceptState + ); }); }); @@ -287,7 +342,9 @@ describe('signalingTest', () => { chai.assert.isNotNull(acceptReq.params); chai.assert.isNotNull(acceptReq.id); chai.assert(signaling.transit.calledOnce); - chai.assert(signaling.transit.args[0][0] instanceof PendingAcceptAckState); + chai.assert( + signaling.transit.args[0][0] instanceof PendingAcceptAckState + ); }); }); @@ -353,7 +410,7 @@ describe('signalingTest', () => { state = new TalkingState(signaling); }); - it('notify handshake completion on enter', (done) => { + it('notify handshake completion on enter', done => { signaling._handshakedHandler = done; state.onEnter(); }); @@ -371,7 +428,9 @@ describe('signalingTest', () => { chai.assert.isNotNull(hangupReq.params); chai.assert.isNotNull(hangupReq.id); chai.assert(signaling.transit.calledOnce); - chai.assert(signaling.transit.args[0][0] instanceof PendingRemoteHangupState); + chai.assert( + signaling.transit.args[0][0] instanceof PendingRemoteHangupState + ); }); it('responds to server hangup', () => { @@ -383,7 +442,9 @@ describe('signalingTest', () => { id: 10 }); chai.assert(signaling.transit.calledOnce); - chai.assert(signaling.transit.args[0][0] instanceof PendingLocalHangupState); + chai.assert( + signaling.transit.args[0][0] instanceof PendingLocalHangupState + ); }); it('responds to token renewal', () => { @@ -404,7 +465,9 @@ describe('signalingTest', () => { state.channelDown(); chai.assert(signaling._reconnect.calledOnce); chai.assert(signaling.transit.calledOnce); - chai.assert(signaling.transit.args[0][0] instanceof PendingReconnectState); + chai.assert( + signaling.transit.args[0][0] instanceof PendingReconnectState + ); }); }); @@ -454,7 +517,9 @@ describe('signalingTest', () => { result: {} }); chai.assert(signaling.transit.calledOnce); - chai.assert(signaling.transit.args[0][0] instanceof DisconnectedState); + chai.assert( + signaling.transit.args[0][0] instanceof DisconnectedState + ); }); }); @@ -473,7 +538,7 @@ describe('signalingTest', () => { state = new PendingLocalHangupState(signaling, 8); }); - it('notifies remote hangup on enter', (done) => { + it('notifies remote hangup on enter', done => { signaling._remoteHungupHandler = done; state.onEnter(); }); @@ -490,11 +555,12 @@ describe('signalingTest', () => { chai.assert.equal(8, hangupResp.id); chai.assert.isNotNull(hangupResp.result); chai.assert(signaling.transit.calledOnce); - chai.assert(signaling.transit.args[0][0] instanceof DisconnectedState); + chai.assert( + signaling.transit.args[0][0] instanceof DisconnectedState + ); }); }); - describe('DisconnectedState', () => { /** * @type {RtcSignaling} @@ -510,7 +576,7 @@ describe('signalingTest', () => { state = new DisconnectedState(signaling); }); - it('notifies disconnected on enter', (done) => { + it('notifies disconnected on enter', done => { signaling._wss = { close: sinon.spy() }; @@ -535,7 +601,7 @@ describe('signalingTest', () => { state = new FailedState(signaling); }); - it('notifies failure on enter', (done) => { + it('notifies failure on enter', done => { signaling._wss = { close: sinon.spy() }; diff --git a/test/unit/utils.js b/test/unit/utils.js index b26674f..b0163db 100644 --- a/test/unit/utils.js +++ b/test/unit/utils.js @@ -11,119 +11,124 @@ import { transformSdp, SdpOptions } from '../../src/js/utils'; import chai from 'chai'; - describe('transformSdp', () => { - var inputSdp = "v=0\r\n" + - "o=- 6968650397182970779 2 IN IP4 127.0.0.1\r\n" + - "s=-\r\n" + - "t=0 0\r\n" + - "a=group:BUNDLE audio\r\n" + - "a=msid-semantic: WMS idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n" + - "m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\n" + - "c=IN IP4 0.0.0.0\r\n" + - "a=rtcp:9 IN IP4 0.0.0.0\r\n" + - "a=ice-ufrag:E4/X\r\n" + - "a=ice-pwd:34ijxBABGSaclsOpfc9E042R\r\n" + - "a=fingerprint:sha-256 26:40:A1:3C:7E:67:75:2F:1B:21:B9:54:68:07:E8:CE:E5:9C:28:2A:E8:D4:36:26:04:C5:5B:0C:04:43:37:CF\r\n" + - "a=setup:actpass\r\n" + - "a=mid:audio\r\n" + - "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" + - "a=sendrecv\r\n" + - "a=rtcp-mux\r\n" + - "a=rtpmap:111 opus/48000/2\r\n" + - "a=rtcp-fb:111 transport-cc\r\n" + - "a=fmtp:111 minptime=10;useinbandfec=1\r\n" + - "a=rtpmap:103 ISAC/16000\r\n" + - "a=rtpmap:104 ISAC/32000\r\n" + - "a=rtpmap:9 G722/8000\r\n" + - "a=rtpmap:0 PCMU/8000\r\n" + - "a=rtpmap:8 PCMA/8000\r\n" + - "a=rtpmap:106 CN/32000\r\n" + - "a=rtpmap:105 CN/16000\r\n" + - "a=rtpmap:13 CN/8000\r\n" + - "a=rtpmap:110 telephone-event/48000\r\n" + - "a=rtpmap:112 telephone-event/32000\r\n" + - "a=rtpmap:113 telephone-event/16000\r\n" + - "a=rtpmap:126 telephone-event/8000\r\n" + - "a=ssrc:2534193841 cname:NsEUa3X+NJbQmyyN\r\n" + - "a=ssrc:2534193841 msid:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n" + - "a=ssrc:2534193841 mslabel:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n" + - "a=ssrc:2534193841 label:d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n"; - + var inputSdp = + 'v=0\r\n' + + 'o=- 6968650397182970779 2 IN IP4 127.0.0.1\r\n' + + 's=-\r\n' + + 't=0 0\r\n' + + 'a=group:BUNDLE audio\r\n' + + 'a=msid-semantic: WMS idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n' + + 'm=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\n' + + 'c=IN IP4 0.0.0.0\r\n' + + 'a=rtcp:9 IN IP4 0.0.0.0\r\n' + + 'a=ice-ufrag:E4/X\r\n' + + 'a=ice-pwd:34ijxBABGSaclsOpfc9E042R\r\n' + + 'a=fingerprint:sha-256 26:40:A1:3C:7E:67:75:2F:1B:21:B9:54:68:07:E8:CE:E5:9C:28:2A:E8:D4:36:26:04:C5:5B:0C:04:43:37:CF\r\n' + + 'a=setup:actpass\r\n' + + 'a=mid:audio\r\n' + + 'a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n' + + 'a=sendrecv\r\n' + + 'a=rtcp-mux\r\n' + + 'a=rtpmap:111 opus/48000/2\r\n' + + 'a=rtcp-fb:111 transport-cc\r\n' + + 'a=fmtp:111 minptime=10;useinbandfec=1\r\n' + + 'a=rtpmap:103 ISAC/16000\r\n' + + 'a=rtpmap:104 ISAC/32000\r\n' + + 'a=rtpmap:9 G722/8000\r\n' + + 'a=rtpmap:0 PCMU/8000\r\n' + + 'a=rtpmap:8 PCMA/8000\r\n' + + 'a=rtpmap:106 CN/32000\r\n' + + 'a=rtpmap:105 CN/16000\r\n' + + 'a=rtpmap:13 CN/8000\r\n' + + 'a=rtpmap:110 telephone-event/48000\r\n' + + 'a=rtpmap:112 telephone-event/32000\r\n' + + 'a=rtpmap:113 telephone-event/16000\r\n' + + 'a=rtpmap:126 telephone-event/8000\r\n' + + 'a=ssrc:2534193841 cname:NsEUa3X+NJbQmyyN\r\n' + + 'a=ssrc:2534193841 msid:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n' + + 'a=ssrc:2534193841 mslabel:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n' + + 'a=ssrc:2534193841 label:d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n'; // transformed with default SdpOptions - var defaultOutput = "v=0\r\n" + - "o=- 6968650397182970779 2 IN IP4 127.0.0.1\r\n" + - "s=-\r\n" + - "t=0 0\r\n" + - "a=group:BUNDLE audio\r\n" + - "a=msid-semantic: WMS idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n" + - "m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\n" + - "c=IN IP4 0.0.0.0\r\n" + - "a=rtcp:9 IN IP4 0.0.0.0\r\n" + - "a=ice-ufrag:E4/X\r\n" + - "a=ice-pwd:34ijxBABGSaclsOpfc9E042R\r\n" + - "a=fingerprint:sha-256 26:40:A1:3C:7E:67:75:2F:1B:21:B9:54:68:07:E8:CE:E5:9C:28:2A:E8:D4:36:26:04:C5:5B:0C:04:43:37:CF\r\n" + - "a=setup:actpass\r\n" + - "a=mid:audio\r\n" + - "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" + - "a=sendrecv\r\n" + - "a=rtcp-mux\r\n" + - "a=rtpmap:111 opus/48000/2\r\n" + - "a=fmtp:111 minptime=10;useinbandfec=1;usedtx=0\r\n" + - "a=rtcp-fb:111 transport-cc\r\n" + - "a=rtpmap:103 ISAC/16000\r\n" + - "a=rtpmap:104 ISAC/32000\r\n" + - "a=rtpmap:9 G722/8000\r\n" + - "a=rtpmap:0 PCMU/8000\r\n" + - "a=rtpmap:8 PCMA/8000\r\n" + - "a=rtpmap:106 CN/32000\r\n" + - "a=rtpmap:105 CN/16000\r\n" + - "a=rtpmap:13 CN/8000\r\n" + - "a=rtpmap:110 telephone-event/48000\r\n" + - "a=rtpmap:112 telephone-event/32000\r\n" + - "a=rtpmap:113 telephone-event/16000\r\n" + - "a=rtpmap:126 telephone-event/8000\r\n" + - "a=ssrc:2534193841 cname:NsEUa3X+NJbQmyyN\r\n" + - "a=ssrc:2534193841 msid:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n" + - "a=ssrc:2534193841 mslabel:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n" + - "a=ssrc:2534193841 label:d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n"; + var defaultOutput = + 'v=0\r\n' + + 'o=- 6968650397182970779 2 IN IP4 127.0.0.1\r\n' + + 's=-\r\n' + + 't=0 0\r\n' + + 'a=group:BUNDLE audio\r\n' + + 'a=msid-semantic: WMS idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n' + + 'm=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\n' + + 'c=IN IP4 0.0.0.0\r\n' + + 'a=rtcp:9 IN IP4 0.0.0.0\r\n' + + 'a=ice-ufrag:E4/X\r\n' + + 'a=ice-pwd:34ijxBABGSaclsOpfc9E042R\r\n' + + 'a=fingerprint:sha-256 26:40:A1:3C:7E:67:75:2F:1B:21:B9:54:68:07:E8:CE:E5:9C:28:2A:E8:D4:36:26:04:C5:5B:0C:04:43:37:CF\r\n' + + 'a=setup:actpass\r\n' + + 'a=mid:audio\r\n' + + 'a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n' + + 'a=sendrecv\r\n' + + 'a=rtcp-mux\r\n' + + 'a=rtpmap:111 opus/48000/2\r\n' + + 'a=fmtp:111 minptime=10;useinbandfec=1;usedtx=0\r\n' + + 'a=rtcp-fb:111 transport-cc\r\n' + + 'a=rtpmap:103 ISAC/16000\r\n' + + 'a=rtpmap:104 ISAC/32000\r\n' + + 'a=rtpmap:9 G722/8000\r\n' + + 'a=rtpmap:0 PCMU/8000\r\n' + + 'a=rtpmap:8 PCMA/8000\r\n' + + 'a=rtpmap:106 CN/32000\r\n' + + 'a=rtpmap:105 CN/16000\r\n' + + 'a=rtpmap:13 CN/8000\r\n' + + 'a=rtpmap:110 telephone-event/48000\r\n' + + 'a=rtpmap:112 telephone-event/32000\r\n' + + 'a=rtpmap:113 telephone-event/16000\r\n' + + 'a=rtpmap:126 telephone-event/8000\r\n' + + 'a=ssrc:2534193841 cname:NsEUa3X+NJbQmyyN\r\n' + + 'a=ssrc:2534193841 msid:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n' + + 'a=ssrc:2534193841 mslabel:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n' + + 'a=ssrc:2534193841 label:d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n'; - var expectedSdpWithOnlyOpus = "v=0\r\n" + - "o=- 6968650397182970779 2 IN IP4 127.0.0.1\r\n" + - "s=-\r\n" + - "t=0 0\r\n" + - "a=group:BUNDLE audio\r\n" + - "a=msid-semantic: WMS idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n" + - "m=audio 9 UDP/TLS/RTP/SAVPF 110 111 112 113 126\r\n" + - "c=IN IP4 0.0.0.0\r\n" + - "a=rtcp:9 IN IP4 0.0.0.0\r\n" + - "a=ice-ufrag:E4/X\r\n" + - "a=ice-pwd:34ijxBABGSaclsOpfc9E042R\r\n" + - "a=fingerprint:sha-256 26:40:A1:3C:7E:67:75:2F:1B:21:B9:54:68:07:E8:CE:E5:9C:28:2A:E8:D4:36:26:04:C5:5B:0C:04:43:37:CF\r\n" + - "a=setup:actpass\r\n" + - "a=mid:audio\r\n" + - "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" + - "a=sendrecv\r\n" + - "a=rtcp-mux\r\n" + - "a=rtpmap:111 opus/48000/2\r\n" + - "a=fmtp:111 minptime=10;useinbandfec=1;usedtx=0\r\n" + - "a=rtcp-fb:111 transport-cc\r\n" + - "a=rtpmap:110 telephone-event/48000\r\n" + - "a=rtpmap:112 telephone-event/32000\r\n" + - "a=rtpmap:113 telephone-event/16000\r\n" + - "a=rtpmap:126 telephone-event/8000\r\n" + - "a=ssrc:2534193841 cname:NsEUa3X+NJbQmyyN\r\n" + - "a=ssrc:2534193841 msid:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n" + - "a=ssrc:2534193841 mslabel:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n" + - "a=ssrc:2534193841 label:d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n"; + var expectedSdpWithOnlyOpus = + 'v=0\r\n' + + 'o=- 6968650397182970779 2 IN IP4 127.0.0.1\r\n' + + 's=-\r\n' + + 't=0 0\r\n' + + 'a=group:BUNDLE audio\r\n' + + 'a=msid-semantic: WMS idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n' + + 'm=audio 9 UDP/TLS/RTP/SAVPF 110 111 112 113 126\r\n' + + 'c=IN IP4 0.0.0.0\r\n' + + 'a=rtcp:9 IN IP4 0.0.0.0\r\n' + + 'a=ice-ufrag:E4/X\r\n' + + 'a=ice-pwd:34ijxBABGSaclsOpfc9E042R\r\n' + + 'a=fingerprint:sha-256 26:40:A1:3C:7E:67:75:2F:1B:21:B9:54:68:07:E8:CE:E5:9C:28:2A:E8:D4:36:26:04:C5:5B:0C:04:43:37:CF\r\n' + + 'a=setup:actpass\r\n' + + 'a=mid:audio\r\n' + + 'a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n' + + 'a=sendrecv\r\n' + + 'a=rtcp-mux\r\n' + + 'a=rtpmap:111 opus/48000/2\r\n' + + 'a=fmtp:111 minptime=10;useinbandfec=1;usedtx=0\r\n' + + 'a=rtcp-fb:111 transport-cc\r\n' + + 'a=rtpmap:110 telephone-event/48000\r\n' + + 'a=rtpmap:112 telephone-event/32000\r\n' + + 'a=rtpmap:113 telephone-event/16000\r\n' + + 'a=rtpmap:126 telephone-event/8000\r\n' + + 'a=ssrc:2534193841 cname:NsEUa3X+NJbQmyyN\r\n' + + 'a=ssrc:2534193841 msid:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n' + + 'a=ssrc:2534193841 mslabel:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n' + + 'a=ssrc:2534193841 label:d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n'; it('Override audio codec to opus', () => { var sdpOptions = new SdpOptions(); sdpOptions.forceCodec['audio'] = 'opus'; - chai.expect(transformSdp(inputSdp, sdpOptions).sdp).to.eq(expectedSdpWithOnlyOpus); + chai.expect(transformSdp(inputSdp, sdpOptions).sdp).to.eq( + expectedSdpWithOnlyOpus + ); sdpOptions.forceCodec['audio'] = 'OPUS'; - chai.expect(transformSdp(inputSdp, sdpOptions).sdp).to.eq(expectedSdpWithOnlyOpus); + chai.expect(transformSdp(inputSdp, sdpOptions).sdp).to.eq( + expectedSdpWithOnlyOpus + ); }); it('Removes nothing without matching media type', () => { @@ -134,155 +139,165 @@ describe('transformSdp', () => { chai.expect(result.mLines).to.eq(1); }); - var expectedPcmuSdp = "v=0\r\n" + - "o=- 6968650397182970779 2 IN IP4 127.0.0.1\r\n" + - "s=-\r\n" + - "t=0 0\r\n" + - "a=group:BUNDLE audio\r\n" + - "a=msid-semantic: WMS idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n" + - "m=audio 9 UDP/TLS/RTP/SAVPF 0 110 112 113 126\r\n" + - "c=IN IP4 0.0.0.0\r\n" + - "a=rtcp:9 IN IP4 0.0.0.0\r\n" + - "a=ice-ufrag:E4/X\r\n" + - "a=ice-pwd:34ijxBABGSaclsOpfc9E042R\r\n" + - "a=fingerprint:sha-256 26:40:A1:3C:7E:67:75:2F:1B:21:B9:54:68:07:E8:CE:E5:9C:28:2A:E8:D4:36:26:04:C5:5B:0C:04:43:37:CF\r\n" + - "a=setup:actpass\r\n" + - "a=mid:audio\r\n" + - "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" + - "a=sendrecv\r\n" + - "a=rtcp-mux\r\n" + - "a=rtpmap:0 PCMU/8000\r\n" + - "a=rtpmap:110 telephone-event/48000\r\n" + - "a=rtpmap:112 telephone-event/32000\r\n" + - "a=rtpmap:113 telephone-event/16000\r\n" + - "a=rtpmap:126 telephone-event/8000\r\n" + - "a=ssrc:2534193841 cname:NsEUa3X+NJbQmyyN\r\n" + - "a=ssrc:2534193841 msid:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n" + - "a=ssrc:2534193841 mslabel:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n" + - "a=ssrc:2534193841 label:d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n"; + var expectedPcmuSdp = + 'v=0\r\n' + + 'o=- 6968650397182970779 2 IN IP4 127.0.0.1\r\n' + + 's=-\r\n' + + 't=0 0\r\n' + + 'a=group:BUNDLE audio\r\n' + + 'a=msid-semantic: WMS idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n' + + 'm=audio 9 UDP/TLS/RTP/SAVPF 0 110 112 113 126\r\n' + + 'c=IN IP4 0.0.0.0\r\n' + + 'a=rtcp:9 IN IP4 0.0.0.0\r\n' + + 'a=ice-ufrag:E4/X\r\n' + + 'a=ice-pwd:34ijxBABGSaclsOpfc9E042R\r\n' + + 'a=fingerprint:sha-256 26:40:A1:3C:7E:67:75:2F:1B:21:B9:54:68:07:E8:CE:E5:9C:28:2A:E8:D4:36:26:04:C5:5B:0C:04:43:37:CF\r\n' + + 'a=setup:actpass\r\n' + + 'a=mid:audio\r\n' + + 'a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n' + + 'a=sendrecv\r\n' + + 'a=rtcp-mux\r\n' + + 'a=rtpmap:0 PCMU/8000\r\n' + + 'a=rtpmap:110 telephone-event/48000\r\n' + + 'a=rtpmap:112 telephone-event/32000\r\n' + + 'a=rtpmap:113 telephone-event/16000\r\n' + + 'a=rtpmap:126 telephone-event/8000\r\n' + + 'a=ssrc:2534193841 cname:NsEUa3X+NJbQmyyN\r\n' + + 'a=ssrc:2534193841 msid:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n' + + 'a=ssrc:2534193841 mslabel:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n' + + 'a=ssrc:2534193841 label:d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n'; it('Override audio codec to pcmu', () => { var sdpOptions = new SdpOptions(); sdpOptions.forceCodec['audio'] = 'pcmu'; - chai.expect(transformSdp(inputSdp, sdpOptions).sdp).to.eq(expectedPcmuSdp); + chai.expect(transformSdp(inputSdp, sdpOptions).sdp).to.eq( + expectedPcmuSdp + ); }); - var expectedSdpWithDtx = "v=0\r\n" + - "o=- 6968650397182970779 2 IN IP4 127.0.0.1\r\n" + - "s=-\r\n" + - "t=0 0\r\n" + - "a=group:BUNDLE audio\r\n" + - "a=msid-semantic: WMS idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n" + - "m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\n" + - "c=IN IP4 0.0.0.0\r\n" + - "a=rtcp:9 IN IP4 0.0.0.0\r\n" + - "a=ice-ufrag:E4/X\r\n" + - "a=ice-pwd:34ijxBABGSaclsOpfc9E042R\r\n" + - "a=fingerprint:sha-256 26:40:A1:3C:7E:67:75:2F:1B:21:B9:54:68:07:E8:CE:E5:9C:28:2A:E8:D4:36:26:04:C5:5B:0C:04:43:37:CF\r\n" + - "a=setup:actpass\r\n" + - "a=mid:audio\r\n" + - "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" + - "a=sendrecv\r\n" + - "a=rtcp-mux\r\n" + - "a=rtpmap:111 opus/48000/2\r\n" + - "a=fmtp:111 minptime=10;useinbandfec=1;usedtx=1\r\n" + - "a=rtcp-fb:111 transport-cc\r\n" + - "a=rtpmap:103 ISAC/16000\r\n" + - "a=rtpmap:104 ISAC/32000\r\n" + - "a=rtpmap:9 G722/8000\r\n" + - "a=rtpmap:0 PCMU/8000\r\n" + - "a=rtpmap:8 PCMA/8000\r\n" + - "a=rtpmap:106 CN/32000\r\n" + - "a=rtpmap:105 CN/16000\r\n" + - "a=rtpmap:13 CN/8000\r\n" + - "a=rtpmap:110 telephone-event/48000\r\n" + - "a=rtpmap:112 telephone-event/32000\r\n" + - "a=rtpmap:113 telephone-event/16000\r\n" + - "a=rtpmap:126 telephone-event/8000\r\n" + - "a=ssrc:2534193841 cname:NsEUa3X+NJbQmyyN\r\n" + - "a=ssrc:2534193841 msid:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n" + - "a=ssrc:2534193841 mslabel:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n" + - "a=ssrc:2534193841 label:d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n"; - + var expectedSdpWithDtx = + 'v=0\r\n' + + 'o=- 6968650397182970779 2 IN IP4 127.0.0.1\r\n' + + 's=-\r\n' + + 't=0 0\r\n' + + 'a=group:BUNDLE audio\r\n' + + 'a=msid-semantic: WMS idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n' + + 'm=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\n' + + 'c=IN IP4 0.0.0.0\r\n' + + 'a=rtcp:9 IN IP4 0.0.0.0\r\n' + + 'a=ice-ufrag:E4/X\r\n' + + 'a=ice-pwd:34ijxBABGSaclsOpfc9E042R\r\n' + + 'a=fingerprint:sha-256 26:40:A1:3C:7E:67:75:2F:1B:21:B9:54:68:07:E8:CE:E5:9C:28:2A:E8:D4:36:26:04:C5:5B:0C:04:43:37:CF\r\n' + + 'a=setup:actpass\r\n' + + 'a=mid:audio\r\n' + + 'a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n' + + 'a=sendrecv\r\n' + + 'a=rtcp-mux\r\n' + + 'a=rtpmap:111 opus/48000/2\r\n' + + 'a=fmtp:111 minptime=10;useinbandfec=1;usedtx=1\r\n' + + 'a=rtcp-fb:111 transport-cc\r\n' + + 'a=rtpmap:103 ISAC/16000\r\n' + + 'a=rtpmap:104 ISAC/32000\r\n' + + 'a=rtpmap:9 G722/8000\r\n' + + 'a=rtpmap:0 PCMU/8000\r\n' + + 'a=rtpmap:8 PCMA/8000\r\n' + + 'a=rtpmap:106 CN/32000\r\n' + + 'a=rtpmap:105 CN/16000\r\n' + + 'a=rtpmap:13 CN/8000\r\n' + + 'a=rtpmap:110 telephone-event/48000\r\n' + + 'a=rtpmap:112 telephone-event/32000\r\n' + + 'a=rtpmap:113 telephone-event/16000\r\n' + + 'a=rtpmap:126 telephone-event/8000\r\n' + + 'a=ssrc:2534193841 cname:NsEUa3X+NJbQmyyN\r\n' + + 'a=ssrc:2534193841 msid:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n' + + 'a=ssrc:2534193841 mslabel:idv6kIIdFJ9x3alklN0n3uNGmI8xgFecIJkt\r\n' + + 'a=ssrc:2534193841 label:d26be488-17a9-4f63-85b4-bdcf9754bb9b\r\n'; it('Adds usedtx=1 if enableDtx is true', () => { var sdpOptions = new SdpOptions(); sdpOptions.enableOpusDtx = true; - chai.expect(transformSdp(inputSdp, sdpOptions).sdp).to.eq(expectedSdpWithDtx); + chai.expect(transformSdp(inputSdp, sdpOptions).sdp).to.eq( + expectedSdpWithDtx + ); }); it('Adds usedtx=0 if enableDtx is false', () => { var sdpOptions = new SdpOptions(); sdpOptions.enableOpusDtx = false; - chai.expect(transformSdp(inputSdp, sdpOptions).sdp).to.eq(defaultOutput); + chai.expect(transformSdp(inputSdp, sdpOptions).sdp).to.eq( + defaultOutput + ); }); it('Adds usedtx=0 if enableDtx is not set', () => { var sdpOptions = new SdpOptions(); - chai.expect(transformSdp(inputSdp, sdpOptions).sdp).to.eq(defaultOutput); + chai.expect(transformSdp(inputSdp, sdpOptions).sdp).to.eq( + defaultOutput + ); }); - var audioVideoSdp = "v=0\n" + - "o=mozilla...THIS_IS_SDPARTA-59.0.2 204502799607324848 0 IN IP4 0.0.0.0\r\n" + - "s=-\r\n" + - "t=0 0\r\n" + - "a=fingerprint:sha-256 18:78:9C:01:6D:89:69:06:84:AE:1F:D1:B9:10:96:54:97:4C:FA:8D:40:9F:A1:B1:99:4D:70:2B:88:A4:8A:20\r\n" + - "a=group:BUNDLE sdparta_0 sdparta_1\r\n" + - "a=ice-options:trickle\r\n" + - "a=msid-semantic:WMS *\r\n" + - "m=audio 9 UDP/TLS/RTP/SAVPF 101 109\r\n" + - "c=IN IP4 0.0.0.0\r\n" + - "a=sendrecv\r\n" + - "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" + - "a=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid\r\n" + - "a=fmtp:101 0-15\r\n" + - "a=ice-pwd:24e9d315b24ee847d5844c5f7313c42b\r\n" + - "a=ice-ufrag:25047267\r\n" + - "a=mid:sdparta_0\r\n" + - "a=msid:{910b0af4-424f-41c3-8d46-c61f5d21516b} {ed11b922-7eea-4551-ad47-24270c902094}\r\n" + - "a=rtcp-mux\r\n" + - "a=rtpmap:109 opus/48000/2\r\n" + - "a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1;usedtx=0\r\n" + - "a=rtpmap:101 telephone-event/8000/1\r\n" + - "a=setup:actpass\r\n" + - "a=ssrc:3604426642 cname:{2fe325fe-1578-41b9-b8c1-d92e46b5d514}\r\n" + - "m=video 9 UDP/TLS/RTP/SAVPF 120 121 126 97\r\n" + - "c=IN IP4 0.0.0.0\r\n" + - "a=sendrecv\r\n" + - "a=extmap:1 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n" + - "a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\n" + - "a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid\r\n" + - "a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1\r\n" + - "a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1\r\n" + - "a=fmtp:120 max-fs=12288;max-fr=60\r\n" + - "a=fmtp:121 max-fs=12288;max-fr=60\r\n" + - "a=ice-pwd:24e9d315b24ee847d5844c5f7313c42b\r\n" + - "a=ice-ufrag:25047267\r\n" + - "a=mid:sdparta_1\r\n" + - "a=msid:{910b0af4-424f-41c3-8d46-c61f5d21516b} {5d086e46-9b16-4870-810d-0059a015528a}\r\n" + - "a=rtcp-fb:120 nack\r\n" + - "a=rtcp-fb:120 nack pli\r\n" + - "a=rtcp-fb:120 ccm fir\r\n" + - "a=rtcp-fb:120 goog-remb\r\n" + - "a=rtcp-fb:121 nack\r\n" + - "a=rtcp-fb:121 nack pli\r\n" + - "a=rtcp-fb:121 ccm fir\r\n" + - "a=rtcp-fb:121 goog-remb\r\n" + - "a=rtcp-fb:126 nack\r\n" + - "a=rtcp-fb:126 nack pli\r\n" + - "a=rtcp-fb:126 ccm fir\r\n" + - "a=rtcp-fb:126 goog-remb\r\n" + - "a=rtcp-fb:97 nack\r\n" + - "a=rtcp-fb:97 nack pli\r\n" + - "a=rtcp-fb:97 ccm fir\r\n" + - "a=rtcp-fb:97 goog-remb\r\n" + - "a=rtcp-mux\r\n" + - "a=rtpmap:120 VP8/90000\r\n" + - "a=rtpmap:121 VP9/90000\r\n" + - "a=rtpmap:126 H264/90000\r\n" + - "a=rtpmap:97 H264/90000\r\n" + - "a=setup:actpass\r\n" + - "a=ssrc:2521847393 cname:{2fe325fe-1578-41b9-b8c1-d92e46b5d514}\r\n"; + var audioVideoSdp = + 'v=0\n' + + 'o=mozilla...THIS_IS_SDPARTA-59.0.2 204502799607324848 0 IN IP4 0.0.0.0\r\n' + + 's=-\r\n' + + 't=0 0\r\n' + + 'a=fingerprint:sha-256 18:78:9C:01:6D:89:69:06:84:AE:1F:D1:B9:10:96:54:97:4C:FA:8D:40:9F:A1:B1:99:4D:70:2B:88:A4:8A:20\r\n' + + 'a=group:BUNDLE sdparta_0 sdparta_1\r\n' + + 'a=ice-options:trickle\r\n' + + 'a=msid-semantic:WMS *\r\n' + + 'm=audio 9 UDP/TLS/RTP/SAVPF 101 109\r\n' + + 'c=IN IP4 0.0.0.0\r\n' + + 'a=sendrecv\r\n' + + 'a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n' + + 'a=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid\r\n' + + 'a=fmtp:101 0-15\r\n' + + 'a=ice-pwd:24e9d315b24ee847d5844c5f7313c42b\r\n' + + 'a=ice-ufrag:25047267\r\n' + + 'a=mid:sdparta_0\r\n' + + 'a=msid:{910b0af4-424f-41c3-8d46-c61f5d21516b} {ed11b922-7eea-4551-ad47-24270c902094}\r\n' + + 'a=rtcp-mux\r\n' + + 'a=rtpmap:109 opus/48000/2\r\n' + + 'a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1;usedtx=0\r\n' + + 'a=rtpmap:101 telephone-event/8000/1\r\n' + + 'a=setup:actpass\r\n' + + 'a=ssrc:3604426642 cname:{2fe325fe-1578-41b9-b8c1-d92e46b5d514}\r\n' + + 'm=video 9 UDP/TLS/RTP/SAVPF 120 121 126 97\r\n' + + 'c=IN IP4 0.0.0.0\r\n' + + 'a=sendrecv\r\n' + + 'a=extmap:1 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n' + + 'a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\n' + + 'a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid\r\n' + + 'a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1\r\n' + + 'a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1\r\n' + + 'a=fmtp:120 max-fs=12288;max-fr=60\r\n' + + 'a=fmtp:121 max-fs=12288;max-fr=60\r\n' + + 'a=ice-pwd:24e9d315b24ee847d5844c5f7313c42b\r\n' + + 'a=ice-ufrag:25047267\r\n' + + 'a=mid:sdparta_1\r\n' + + 'a=msid:{910b0af4-424f-41c3-8d46-c61f5d21516b} {5d086e46-9b16-4870-810d-0059a015528a}\r\n' + + 'a=rtcp-fb:120 nack\r\n' + + 'a=rtcp-fb:120 nack pli\r\n' + + 'a=rtcp-fb:120 ccm fir\r\n' + + 'a=rtcp-fb:120 goog-remb\r\n' + + 'a=rtcp-fb:121 nack\r\n' + + 'a=rtcp-fb:121 nack pli\r\n' + + 'a=rtcp-fb:121 ccm fir\r\n' + + 'a=rtcp-fb:121 goog-remb\r\n' + + 'a=rtcp-fb:126 nack\r\n' + + 'a=rtcp-fb:126 nack pli\r\n' + + 'a=rtcp-fb:126 ccm fir\r\n' + + 'a=rtcp-fb:126 goog-remb\r\n' + + 'a=rtcp-fb:97 nack\r\n' + + 'a=rtcp-fb:97 nack pli\r\n' + + 'a=rtcp-fb:97 ccm fir\r\n' + + 'a=rtcp-fb:97 goog-remb\r\n' + + 'a=rtcp-mux\r\n' + + 'a=rtpmap:120 VP8/90000\r\n' + + 'a=rtpmap:121 VP9/90000\r\n' + + 'a=rtpmap:126 H264/90000\r\n' + + 'a=rtpmap:97 H264/90000\r\n' + + 'a=setup:actpass\r\n' + + 'a=ssrc:2521847393 cname:{2fe325fe-1578-41b9-b8c1-d92e46b5d514}\r\n'; it('Discovers 2 M lines of audio and video', () => { var sdpOptions = new SdpOptions(); @@ -290,70 +305,71 @@ describe('transformSdp', () => { chai.expect(result.mLines).to.eq(2); }); + var inputSdpUnencrypted = + 'v=0\r\n' + + 'o=- 6620764343933944878 2 IN IP4 127.0.0.1\r\n' + + 's=-\r\n' + + 't=0 0\r\n' + + 'a=group:BUNDLE audio\r\n' + + 'a=msid-semantic: WMS epPgfieKqbbeLwL2l9ulykxiVs3EMcKcvtnu\r\n' + + 'm=audio 9 RTP/AVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\n' + + 'c=IN IP4 0.0.0.0\r\n' + + 'a=rtcp:9 IN IP4 0.0.0.0\r\n' + + 'a=ice-ufrag:Y3ri\r\n' + + 'a=ice-pwd:G95asCJENMnUeWx2dMhpi/ht\r\n' + + 'a=ice-options:trickle\r\n' + + 'a=mid:audio\r\n' + + 'a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n' + + 'a=sendrecv\r\n' + + 'a=rtcp-mux\r\n' + + 'a=rtpmap:111 opus/48000/2\r\n' + + 'a=fmtp:111 minptime=10;useinbandfec=1;usedtx=0\r\n' + + 'a=rtcp-fb:111 transport-cc\r\n' + + 'a=rtpmap:103 ISAC/16000\r\n' + + 'a=rtpmap:104 ISAC/32000\r\n' + + 'a=rtpmap:9 G722/8000\r\n' + + 'a=rtpmap:0 PCMU/8000\r\n' + + 'a=rtpmap:8 PCMA/8000\r\n' + + 'a=rtpmap:106 CN/32000\r\n' + + 'a=rtpmap:105 CN/16000\r\n' + + 'a=rtpmap:13 CN/8000\r\n' + + 'a=rtpmap:110 telephone-event/48000\r\n' + + 'a=rtpmap:112 telephone-event/32000\r\n' + + 'a=rtpmap:113 telephone-event/16000\r\n' + + 'a=rtpmap:126 telephone-event/8000\r\n' + + 'a=ssrc:2494980608 cname:5kX24X9Mu/D2Pcca\r\n' + + 'a=ssrc:2494980608 msid:epPgfieKqbbeLwL2l9ulykxiVs3EMcKcvtnu b8c6be2c-1869-4fb6-b05e-ceefefcb6d2c\r\n' + + 'a=ssrc:2494980608 mslabel:epPgfieKqbbeLwL2l9ulykxiVs3EMcKcvtnu\r\n' + + 'a=ssrc:2494980608 label:b8c6be2c-1869-4fb6-b05e-ceefefcb6d2c\r\n'; - var inputSdpUnencrypted = "v=0\r\n" + - "o=- 6620764343933944878 2 IN IP4 127.0.0.1\r\n" + - "s=-\r\n" + - "t=0 0\r\n" + - "a=group:BUNDLE audio\r\n" + - "a=msid-semantic: WMS epPgfieKqbbeLwL2l9ulykxiVs3EMcKcvtnu\r\n" + - "m=audio 9 RTP/AVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\n" + - "c=IN IP4 0.0.0.0\r\n" + - "a=rtcp:9 IN IP4 0.0.0.0\r\n" + - "a=ice-ufrag:Y3ri\r\n" + - "a=ice-pwd:G95asCJENMnUeWx2dMhpi/ht\r\n" + - "a=ice-options:trickle\r\n" + - "a=mid:audio\r\n" + - "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" + - "a=sendrecv\r\n" + - "a=rtcp-mux\r\n" + - "a=rtpmap:111 opus/48000/2\r\n" + - "a=fmtp:111 minptime=10;useinbandfec=1;usedtx=0\r\n" + - "a=rtcp-fb:111 transport-cc\r\n" + - "a=rtpmap:103 ISAC/16000\r\n" + - "a=rtpmap:104 ISAC/32000\r\n" + - "a=rtpmap:9 G722/8000\r\n" + - "a=rtpmap:0 PCMU/8000\r\n" + - "a=rtpmap:8 PCMA/8000\r\n" + - "a=rtpmap:106 CN/32000\r\n" + - "a=rtpmap:105 CN/16000\r\n" + - "a=rtpmap:13 CN/8000\r\n" + - "a=rtpmap:110 telephone-event/48000\r\n" + - "a=rtpmap:112 telephone-event/32000\r\n" + - "a=rtpmap:113 telephone-event/16000\r\n" + - "a=rtpmap:126 telephone-event/8000\r\n" + - "a=ssrc:2494980608 cname:5kX24X9Mu/D2Pcca\r\n" + - "a=ssrc:2494980608 msid:epPgfieKqbbeLwL2l9ulykxiVs3EMcKcvtnu b8c6be2c-1869-4fb6-b05e-ceefefcb6d2c\r\n" + - "a=ssrc:2494980608 mslabel:epPgfieKqbbeLwL2l9ulykxiVs3EMcKcvtnu\r\n" + - "a=ssrc:2494980608 label:b8c6be2c-1869-4fb6-b05e-ceefefcb6d2c\r\n"; - - var outputSdpUnencryptedOpusOnly = "v=0\r\n" + - "o=- 6620764343933944878 2 IN IP4 127.0.0.1\r\n" + - "s=-\r\n" + - "t=0 0\r\n" + - "a=group:BUNDLE audio\r\n" + - "a=msid-semantic: WMS epPgfieKqbbeLwL2l9ulykxiVs3EMcKcvtnu\r\n" + - "m=audio 9 RTP/AVPF 110 111 112 113 126\r\n" + - "c=IN IP4 0.0.0.0\r\n" + - "a=rtcp:9 IN IP4 0.0.0.0\r\n" + - "a=ice-ufrag:Y3ri\r\n" + - "a=ice-pwd:G95asCJENMnUeWx2dMhpi/ht\r\n" + - "a=ice-options:trickle\r\n" + - "a=mid:audio\r\n" + - "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" + - "a=sendrecv\r\n" + - "a=rtcp-mux\r\n" + - "a=rtpmap:111 opus/48000/2\r\n" + - "a=fmtp:111 minptime=10;useinbandfec=1;usedtx=0\r\n" + - "a=rtcp-fb:111 transport-cc\r\n" + - "a=rtpmap:110 telephone-event/48000\r\n" + - "a=rtpmap:112 telephone-event/32000\r\n" + - "a=rtpmap:113 telephone-event/16000\r\n" + - "a=rtpmap:126 telephone-event/8000\r\n" + - "a=ssrc:2494980608 cname:5kX24X9Mu/D2Pcca\r\n" + - "a=ssrc:2494980608 msid:epPgfieKqbbeLwL2l9ulykxiVs3EMcKcvtnu b8c6be2c-1869-4fb6-b05e-ceefefcb6d2c\r\n" + - "a=ssrc:2494980608 mslabel:epPgfieKqbbeLwL2l9ulykxiVs3EMcKcvtnu\r\n" + - "a=ssrc:2494980608 label:b8c6be2c-1869-4fb6-b05e-ceefefcb6d2c\r\n"; + var outputSdpUnencryptedOpusOnly = + 'v=0\r\n' + + 'o=- 6620764343933944878 2 IN IP4 127.0.0.1\r\n' + + 's=-\r\n' + + 't=0 0\r\n' + + 'a=group:BUNDLE audio\r\n' + + 'a=msid-semantic: WMS epPgfieKqbbeLwL2l9ulykxiVs3EMcKcvtnu\r\n' + + 'm=audio 9 RTP/AVPF 110 111 112 113 126\r\n' + + 'c=IN IP4 0.0.0.0\r\n' + + 'a=rtcp:9 IN IP4 0.0.0.0\r\n' + + 'a=ice-ufrag:Y3ri\r\n' + + 'a=ice-pwd:G95asCJENMnUeWx2dMhpi/ht\r\n' + + 'a=ice-options:trickle\r\n' + + 'a=mid:audio\r\n' + + 'a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n' + + 'a=sendrecv\r\n' + + 'a=rtcp-mux\r\n' + + 'a=rtpmap:111 opus/48000/2\r\n' + + 'a=fmtp:111 minptime=10;useinbandfec=1;usedtx=0\r\n' + + 'a=rtcp-fb:111 transport-cc\r\n' + + 'a=rtpmap:110 telephone-event/48000\r\n' + + 'a=rtpmap:112 telephone-event/32000\r\n' + + 'a=rtpmap:113 telephone-event/16000\r\n' + + 'a=rtpmap:126 telephone-event/8000\r\n' + + 'a=ssrc:2494980608 cname:5kX24X9Mu/D2Pcca\r\n' + + 'a=ssrc:2494980608 msid:epPgfieKqbbeLwL2l9ulykxiVs3EMcKcvtnu b8c6be2c-1869-4fb6-b05e-ceefefcb6d2c\r\n' + + 'a=ssrc:2494980608 mslabel:epPgfieKqbbeLwL2l9ulykxiVs3EMcKcvtnu\r\n' + + 'a=ssrc:2494980608 label:b8c6be2c-1869-4fb6-b05e-ceefefcb6d2c\r\n'; it('Properly handles SDP with unencrypted RTP', () => { var sdpOptions = new SdpOptions();