@webex/plugin-meetings 3.1.0-next.1 → 3.1.0-next.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/common/errors/{reconnection-in-progress.js → reconnection-not-started.js} +27 -15
- package/dist/common/errors/reconnection-not-started.js.map +1 -0
- package/dist/constants.js +10 -2
- package/dist/constants.js.map +1 -1
- package/dist/index.js +15 -3
- package/dist/index.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +7 -1
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +10 -0
- package/dist/locus-info/index.js.map +1 -1
- package/dist/media/properties.js +102 -57
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +6 -0
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +474 -433
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/util.js +9 -0
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +1 -23
- package/dist/meetings/index.js.map +1 -1
- package/dist/reconnection-manager/index.js +138 -109
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/statsAnalyzer/index.js +4 -0
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +3 -0
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/types/common/errors/reconnection-not-started.d.ts +13 -0
- package/dist/types/constants.d.ts +10 -2
- package/dist/types/index.d.ts +3 -2
- package/dist/types/media/properties.d.ts +26 -2
- package/dist/types/meeting/in-meeting-actions.d.ts +6 -0
- package/dist/types/meeting/index.d.ts +3 -5
- package/dist/types/meeting/util.d.ts +3 -0
- package/dist/types/meetings/index.d.ts +1 -16
- package/dist/types/reconnection-manager/index.d.ts +4 -14
- package/dist/webinar/index.js +1 -1
- package/package.json +21 -21
- package/src/common/errors/reconnection-not-started.ts +25 -0
- package/src/constants.ts +11 -3
- package/src/index.ts +4 -1
- package/src/locus-info/controlsUtils.ts +11 -0
- package/src/locus-info/index.ts +16 -0
- package/src/media/properties.ts +67 -15
- package/src/meeting/in-meeting-actions.ts +12 -0
- package/src/meeting/index.ts +71 -77
- package/src/meeting/util.ts +8 -0
- package/src/meetings/index.ts +2 -24
- package/src/reconnection-manager/index.ts +128 -105
- package/src/statsAnalyzer/index.ts +4 -0
- package/src/statsAnalyzer/mqaUtil.ts +5 -0
- package/test/unit/spec/locus-info/controlsUtils.js +20 -0
- package/test/unit/spec/locus-info/index.js +21 -0
- package/test/unit/spec/media/properties.ts +145 -140
- package/test/unit/spec/meeting/in-meeting-actions.ts +6 -0
- package/test/unit/spec/meeting/index.js +201 -72
- package/test/unit/spec/meeting/utils.js +3 -0
- package/test/unit/spec/meetings/index.js +1 -6
- package/test/unit/spec/reconnection-manager/index.js +127 -39
- package/test/unit/spec/stats-analyzer/index.js +11 -0
- package/dist/common/errors/reconnection-in-progress.js.map +0 -1
- package/dist/types/common/errors/reconnection-in-progress.d.ts +0 -9
- package/src/common/errors/reconnection-in-progress.ts +0 -8
|
@@ -12,6 +12,7 @@ import {Credentials, Token, WebexPlugin} from '@webex/webex-core';
|
|
|
12
12
|
import Support from '@webex/internal-plugin-support';
|
|
13
13
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
14
14
|
import StaticConfig from '@webex/plugin-meetings/src/common/config';
|
|
15
|
+
import ReconnectionNotStartedError from '@webex/plugin-meetings/src/common/errors/reconnection-not-started';
|
|
15
16
|
import {Defer} from '@webex/common';
|
|
16
17
|
import {
|
|
17
18
|
FLOOR_ACTION,
|
|
@@ -658,6 +659,9 @@ describe('plugin-meetings', () => {
|
|
|
658
659
|
assert.calledOnceWithExactly(meeting.addMedia, mediaOptions, fakeTurnServerInfo);
|
|
659
660
|
|
|
660
661
|
assert.deepEqual(result, {join: fakeJoinResult, media: test4});
|
|
662
|
+
|
|
663
|
+
// resets joinWithMediaRetryInfo
|
|
664
|
+
assert.deepEqual(meeting.joinWithMediaRetryInfo, {isRetry: false, prevJoinResponse: undefined});
|
|
661
665
|
});
|
|
662
666
|
|
|
663
667
|
it("should not call handleTurnDiscoveryHttpResponse if we don't send a TURN discovery request with join", async () => {
|
|
@@ -719,8 +723,24 @@ describe('plugin-meetings', () => {
|
|
|
719
723
|
|
|
720
724
|
await assert.isRejected(meeting.joinWithMedia({mediaOptions: {allowMediaInLobby: true}}));
|
|
721
725
|
|
|
722
|
-
assert.
|
|
726
|
+
assert.calledTwice(abortTurnDiscoveryStub);
|
|
723
727
|
|
|
728
|
+
assert.calledTwice(Metrics.sendBehavioralMetric);
|
|
729
|
+
assert.calledWith(
|
|
730
|
+
Metrics.sendBehavioralMetric,
|
|
731
|
+
BEHAVIORAL_METRICS.JOIN_WITH_MEDIA_FAILURE,
|
|
732
|
+
{
|
|
733
|
+
correlation_id: meeting.correlationId,
|
|
734
|
+
locus_id: undefined,
|
|
735
|
+
reason: error.message,
|
|
736
|
+
stack: error.stack,
|
|
737
|
+
leaveErrorReason: undefined,
|
|
738
|
+
isRetry: false,
|
|
739
|
+
},
|
|
740
|
+
{
|
|
741
|
+
type: error.name,
|
|
742
|
+
}
|
|
743
|
+
);
|
|
724
744
|
assert.calledWith(
|
|
725
745
|
Metrics.sendBehavioralMetric,
|
|
726
746
|
BEHAVIORAL_METRICS.JOIN_WITH_MEDIA_FAILURE,
|
|
@@ -730,11 +750,52 @@ describe('plugin-meetings', () => {
|
|
|
730
750
|
reason: error.message,
|
|
731
751
|
stack: error.stack,
|
|
732
752
|
leaveErrorReason: undefined,
|
|
753
|
+
isRetry: true,
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
type: error.name,
|
|
757
|
+
}
|
|
758
|
+
);
|
|
759
|
+
|
|
760
|
+
// resets joinWithMediaRetryInfo
|
|
761
|
+
assert.deepEqual(meeting.joinWithMediaRetryInfo, {isRetry: false, prevJoinResponse: undefined});
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
it('should resolve if join() fails the first time but succeeds the second time', async () => {
|
|
765
|
+
const error = new Error('fake');
|
|
766
|
+
meeting.join = sinon.stub().onFirstCall().returns(Promise.reject(error)).onSecondCall().returns(Promise.resolve(fakeJoinResult));
|
|
767
|
+
const leaveStub = sinon.stub(meeting, 'leave').resolves();
|
|
768
|
+
|
|
769
|
+
const result = await meeting.joinWithMedia({
|
|
770
|
+
joinOptions,
|
|
771
|
+
mediaOptions,
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
assert.calledOnce(abortTurnDiscoveryStub);
|
|
775
|
+
assert.calledTwice(meeting.join);
|
|
776
|
+
assert.notCalled(leaveStub);
|
|
777
|
+
|
|
778
|
+
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
779
|
+
assert.calledWith(
|
|
780
|
+
Metrics.sendBehavioralMetric.firstCall,
|
|
781
|
+
BEHAVIORAL_METRICS.JOIN_WITH_MEDIA_FAILURE,
|
|
782
|
+
{
|
|
783
|
+
correlation_id: meeting.correlationId,
|
|
784
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
785
|
+
reason: error.message,
|
|
786
|
+
stack: error.stack,
|
|
787
|
+
leaveErrorReason: undefined,
|
|
788
|
+
isRetry: false,
|
|
733
789
|
},
|
|
734
790
|
{
|
|
735
791
|
type: error.name,
|
|
736
792
|
}
|
|
737
793
|
);
|
|
794
|
+
|
|
795
|
+
assert.deepEqual(result, {join: fakeJoinResult, media: test4});
|
|
796
|
+
|
|
797
|
+
// resets joinWithMediaRetryInfo
|
|
798
|
+
assert.deepEqual(meeting.joinWithMediaRetryInfo, {isRetry: false, prevJoinResponse: undefined});
|
|
738
799
|
});
|
|
739
800
|
|
|
740
801
|
it('should fail if called with allowMediaInLobby:false', async () => {
|
|
@@ -767,8 +828,26 @@ describe('plugin-meetings', () => {
|
|
|
767
828
|
reason: 'joinWithMedia failure',
|
|
768
829
|
});
|
|
769
830
|
|
|
831
|
+
|
|
832
|
+
// Behavioral metric is sent on both calls of joinWithMedia
|
|
833
|
+
assert.calledTwice(Metrics.sendBehavioralMetric);
|
|
770
834
|
assert.calledWith(
|
|
771
|
-
Metrics.sendBehavioralMetric,
|
|
835
|
+
Metrics.sendBehavioralMetric.firstCall,
|
|
836
|
+
BEHAVIORAL_METRICS.JOIN_WITH_MEDIA_FAILURE,
|
|
837
|
+
{
|
|
838
|
+
correlation_id: meeting.correlationId,
|
|
839
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
840
|
+
reason: addMediaError.message,
|
|
841
|
+
stack: addMediaError.stack,
|
|
842
|
+
leaveErrorReason: undefined,
|
|
843
|
+
isRetry: false,
|
|
844
|
+
},
|
|
845
|
+
{
|
|
846
|
+
type: addMediaError.name,
|
|
847
|
+
}
|
|
848
|
+
);
|
|
849
|
+
assert.calledWith(
|
|
850
|
+
Metrics.sendBehavioralMetric.secondCall,
|
|
772
851
|
BEHAVIORAL_METRICS.JOIN_WITH_MEDIA_FAILURE,
|
|
773
852
|
{
|
|
774
853
|
correlation_id: meeting.correlationId,
|
|
@@ -776,6 +855,47 @@ describe('plugin-meetings', () => {
|
|
|
776
855
|
reason: addMediaError.message,
|
|
777
856
|
stack: addMediaError.stack,
|
|
778
857
|
leaveErrorReason: leaveError.message,
|
|
858
|
+
isRetry: true,
|
|
859
|
+
},
|
|
860
|
+
{
|
|
861
|
+
type: addMediaError.name,
|
|
862
|
+
}
|
|
863
|
+
);
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
it('should not call leave() if addMedia fails the first time and succeeds the second time and should only call join() once', async () => {
|
|
867
|
+
const addMediaError = new Error('fake addMedia error');
|
|
868
|
+
const leaveError = new Error('leave error');
|
|
869
|
+
const leaveStub = sinon.stub(meeting, 'leave').rejects(leaveError);
|
|
870
|
+
|
|
871
|
+
meeting.addMedia = sinon
|
|
872
|
+
.stub()
|
|
873
|
+
.onFirstCall()
|
|
874
|
+
.rejects(addMediaError)
|
|
875
|
+
.onSecondCall()
|
|
876
|
+
.resolves(test4);
|
|
877
|
+
|
|
878
|
+
const result = await meeting.joinWithMedia({
|
|
879
|
+
joinOptions,
|
|
880
|
+
mediaOptions,
|
|
881
|
+
});
|
|
882
|
+
|
|
883
|
+
assert.deepEqual(result, {join: fakeJoinResult, media: test4});
|
|
884
|
+
|
|
885
|
+
assert.calledOnce(meeting.join);
|
|
886
|
+
assert.notCalled(leaveStub);
|
|
887
|
+
|
|
888
|
+
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
889
|
+
assert.calledWith(
|
|
890
|
+
Metrics.sendBehavioralMetric.firstCall,
|
|
891
|
+
BEHAVIORAL_METRICS.JOIN_WITH_MEDIA_FAILURE,
|
|
892
|
+
{
|
|
893
|
+
correlation_id: meeting.correlationId,
|
|
894
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
895
|
+
reason: addMediaError.message,
|
|
896
|
+
stack: addMediaError.stack,
|
|
897
|
+
leaveErrorReason: undefined,
|
|
898
|
+
isRetry: false,
|
|
779
899
|
},
|
|
780
900
|
{
|
|
781
901
|
type: addMediaError.name,
|
|
@@ -802,7 +922,7 @@ describe('plugin-meetings', () => {
|
|
|
802
922
|
webex.internal.voicea.on = sinon.stub();
|
|
803
923
|
webex.internal.voicea.off = sinon.stub();
|
|
804
924
|
webex.internal.voicea.listenToEvents = sinon.stub();
|
|
805
|
-
webex.internal.voicea.
|
|
925
|
+
webex.internal.voicea.turnOnCaptions = sinon.stub();
|
|
806
926
|
});
|
|
807
927
|
|
|
808
928
|
it('should subscribe to events for the first time and avoid subscribing for future transcription starts', async () => {
|
|
@@ -817,17 +937,16 @@ describe('plugin-meetings', () => {
|
|
|
817
937
|
assert.equal(webex.internal.voicea.on.callCount, 4);
|
|
818
938
|
assert.equal(meeting.areVoiceaEventsSetup, true);
|
|
819
939
|
assert.equal(webex.internal.voicea.listenToEvents.callCount, 1);
|
|
820
|
-
assert.
|
|
940
|
+
assert.called(webex.internal.voicea.turnOnCaptions);
|
|
821
941
|
|
|
822
942
|
await meeting.startTranscription();
|
|
823
943
|
assert.equal(webex.internal.voicea.on.callCount, 4);
|
|
824
944
|
assert.equal(meeting.areVoiceaEventsSetup, true);
|
|
825
945
|
assert.equal(webex.internal.voicea.listenToEvents.callCount, 1);
|
|
826
|
-
assert.calledTwice(webex.internal.voicea.
|
|
827
|
-
assert.calledWith(webex.internal.voicea.toggleTranscribing, true);
|
|
946
|
+
assert.calledTwice(webex.internal.voicea.turnOnCaptions);
|
|
828
947
|
});
|
|
829
948
|
|
|
830
|
-
it('should listen to events and not
|
|
949
|
+
it('should listen to events and not turnOnCaptions if the user is not a host', async () => {
|
|
831
950
|
meeting.joinedWith = {
|
|
832
951
|
state: 'JOINED',
|
|
833
952
|
};
|
|
@@ -839,7 +958,7 @@ describe('plugin-meetings', () => {
|
|
|
839
958
|
assert.equal(webex.internal.voicea.on.callCount, 4);
|
|
840
959
|
assert.equal(meeting.areVoiceaEventsSetup, true);
|
|
841
960
|
assert.equal(webex.internal.voicea.listenToEvents.callCount, 1);
|
|
842
|
-
assert.notCalled(webex.internal.voicea.
|
|
961
|
+
assert.notCalled(webex.internal.voicea.turnOnCaptions);
|
|
843
962
|
});
|
|
844
963
|
|
|
845
964
|
it("should throw error if request doesn't work", async () => {
|
|
@@ -858,7 +977,7 @@ describe('plugin-meetings', () => {
|
|
|
858
977
|
webex.internal.voicea.on = sinon.stub();
|
|
859
978
|
webex.internal.voicea.off = sinon.stub();
|
|
860
979
|
webex.internal.voicea.listenToEvents = sinon.stub();
|
|
861
|
-
webex.internal.voicea.
|
|
980
|
+
webex.internal.voicea.turnOnCaptions = sinon.stub();
|
|
862
981
|
});
|
|
863
982
|
|
|
864
983
|
it('should stop listening to voicea events and also trigger a stop event', () => {
|
|
@@ -1531,7 +1650,7 @@ describe('plugin-meetings', () => {
|
|
|
1531
1650
|
};
|
|
1532
1651
|
meeting.mediaProperties.setMediaDirection = sinon.stub().returns(true);
|
|
1533
1652
|
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
|
|
1534
|
-
meeting.mediaProperties.
|
|
1653
|
+
meeting.mediaProperties.getCurrentConnectionInfo = sinon.stub().resolves({connectionType: 'udp', selectedCandidatePairChanges: 2, numTransports: 1});
|
|
1535
1654
|
meeting.audio = muteStateStub;
|
|
1536
1655
|
meeting.video = muteStateStub;
|
|
1537
1656
|
sinon.stub(Media, 'createMediaConnection').returns(fakeMediaConnection);
|
|
@@ -1631,11 +1750,14 @@ describe('plugin-meetings', () => {
|
|
|
1631
1750
|
turnServerUsed: true,
|
|
1632
1751
|
retriedWithTurnServer: false,
|
|
1633
1752
|
isMultistream: false,
|
|
1753
|
+
isJoinWithMediaRetry: false,
|
|
1634
1754
|
signalingState: 'unknown',
|
|
1635
1755
|
connectionState: 'unknown',
|
|
1636
1756
|
iceConnectionState: 'unknown',
|
|
1637
1757
|
someReachabilityMetric1: 'some value1',
|
|
1638
1758
|
someReachabilityMetric2: 'some value2',
|
|
1759
|
+
selectedCandidatePairChanges: 2,
|
|
1760
|
+
numTransports: 1,
|
|
1639
1761
|
}
|
|
1640
1762
|
);
|
|
1641
1763
|
});
|
|
@@ -1735,11 +1857,14 @@ describe('plugin-meetings', () => {
|
|
|
1735
1857
|
turnServerUsed: true,
|
|
1736
1858
|
retriedWithTurnServer: false,
|
|
1737
1859
|
isMultistream: false,
|
|
1860
|
+
isJoinWithMediaRetry: false,
|
|
1738
1861
|
signalingState: 'unknown',
|
|
1739
1862
|
connectionState: 'unknown',
|
|
1740
1863
|
iceConnectionState: 'unknown',
|
|
1741
1864
|
someReachabilityMetric1: 'some value1',
|
|
1742
1865
|
someReachabilityMetric2: 'some value2',
|
|
1866
|
+
selectedCandidatePairChanges: 2,
|
|
1867
|
+
numTransports: 1,
|
|
1743
1868
|
}
|
|
1744
1869
|
);
|
|
1745
1870
|
});
|
|
@@ -2213,9 +2338,12 @@ describe('plugin-meetings', () => {
|
|
|
2213
2338
|
turnServerUsed: true,
|
|
2214
2339
|
retriedWithTurnServer: true,
|
|
2215
2340
|
isMultistream: false,
|
|
2341
|
+
isJoinWithMediaRetry: false,
|
|
2216
2342
|
signalingState: 'unknown',
|
|
2217
2343
|
connectionState: 'unknown',
|
|
2218
2344
|
iceConnectionState: 'unknown',
|
|
2345
|
+
selectedCandidatePairChanges: 2,
|
|
2346
|
+
numTransports: 1,
|
|
2219
2347
|
},
|
|
2220
2348
|
]);
|
|
2221
2349
|
|
|
@@ -2394,8 +2522,11 @@ describe('plugin-meetings', () => {
|
|
|
2394
2522
|
correlation_id: meeting.correlationId,
|
|
2395
2523
|
locus_id: meeting.locusUrl.split('/').pop(),
|
|
2396
2524
|
connectionType: 'udp',
|
|
2525
|
+
selectedCandidatePairChanges: 2,
|
|
2526
|
+
numTransports: 1,
|
|
2397
2527
|
isMultistream: false,
|
|
2398
2528
|
retriedWithTurnServer: true,
|
|
2529
|
+
isJoinWithMediaRetry: false,
|
|
2399
2530
|
},
|
|
2400
2531
|
]);
|
|
2401
2532
|
meeting.roap.doTurnDiscovery;
|
|
@@ -2536,8 +2667,11 @@ describe('plugin-meetings', () => {
|
|
|
2536
2667
|
correlation_id: meeting.correlationId,
|
|
2537
2668
|
locus_id: meeting.locusUrl.split('/').pop(),
|
|
2538
2669
|
connectionType: 'udp',
|
|
2670
|
+
selectedCandidatePairChanges: 2,
|
|
2671
|
+
numTransports: 1,
|
|
2539
2672
|
isMultistream: false,
|
|
2540
2673
|
retriedWithTurnServer: false,
|
|
2674
|
+
isJoinWithMediaRetry: false,
|
|
2541
2675
|
someReachabilityMetric1: 'some value1',
|
|
2542
2676
|
someReachabilityMetric2: 'some value2',
|
|
2543
2677
|
}
|
|
@@ -2596,9 +2730,12 @@ describe('plugin-meetings', () => {
|
|
|
2596
2730
|
turnServerUsed: true,
|
|
2597
2731
|
retriedWithTurnServer: false,
|
|
2598
2732
|
isMultistream: false,
|
|
2733
|
+
isJoinWithMediaRetry: false,
|
|
2599
2734
|
signalingState: 'unknown',
|
|
2600
2735
|
connectionState: 'unknown',
|
|
2601
2736
|
iceConnectionState: 'unknown',
|
|
2737
|
+
selectedCandidatePairChanges: 2,
|
|
2738
|
+
numTransports: 1,
|
|
2602
2739
|
}
|
|
2603
2740
|
);
|
|
2604
2741
|
|
|
@@ -3017,7 +3154,7 @@ describe('plugin-meetings', () => {
|
|
|
3017
3154
|
meeting.mediaId = 'fake media id';
|
|
3018
3155
|
meeting.selfUrl = 'selfUrl';
|
|
3019
3156
|
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
|
|
3020
|
-
meeting.mediaProperties.
|
|
3157
|
+
meeting.mediaProperties.getCurrentConnectionInfo = sinon.stub().resolves({connectionType: 'udp', selectedCandidatePairChanges: 2, numTransports: 1});
|
|
3021
3158
|
meeting.setMercuryListener = sinon.stub();
|
|
3022
3159
|
meeting.locusInfo.onFullLocus = sinon.stub();
|
|
3023
3160
|
meeting.webex.meetings.geoHintInfo = {regionCode: 'EU', countryCode: 'UK'};
|
|
@@ -6778,21 +6915,13 @@ describe('plugin-meetings', () => {
|
|
|
6778
6915
|
}),
|
|
6779
6916
|
};
|
|
6780
6917
|
meeting.setupMediaConnectionListeners();
|
|
6781
|
-
meeting.deferSDPAnswer = {
|
|
6782
|
-
resolve: sinon.stub(),
|
|
6783
|
-
reject: sinon.stub(),
|
|
6784
|
-
};
|
|
6785
6918
|
meeting.sdpResponseTimer = '1234';
|
|
6786
|
-
meeting.mediaProperties
|
|
6919
|
+
sinon.stub(meeting.mediaProperties, 'waitForMediaConnectionConnected').resolves();
|
|
6787
6920
|
|
|
6788
|
-
eventListeners[Event.REMOTE_SDP_ANSWER_PROCESSED]();
|
|
6789
6921
|
meeting.config.reconnection.enabled = true;
|
|
6790
6922
|
meeting.currentMediaStatus = {audio: true};
|
|
6791
6923
|
meeting.reconnectionManager = new ReconnectionManager(meeting);
|
|
6792
|
-
meeting.reconnectionManager
|
|
6793
|
-
meeting.reconnectionManager.reset = sinon.stub().returns(true);
|
|
6794
|
-
meeting.reconnectionManager.cleanup = sinon.stub().returns(true);
|
|
6795
|
-
meeting.reconnectionManager.setStatus = sinon.stub();
|
|
6924
|
+
sinon.stub(meeting.reconnectionManager, 'reconnect').returns(Promise.resolve());
|
|
6796
6925
|
});
|
|
6797
6926
|
|
|
6798
6927
|
it('should throw error if media not established before trying reconnect', async () => {
|
|
@@ -6812,87 +6941,72 @@ describe('plugin-meetings', () => {
|
|
|
6812
6941
|
}
|
|
6813
6942
|
});
|
|
6814
6943
|
|
|
6815
|
-
it('should
|
|
6816
|
-
|
|
6944
|
+
it('should call the right functions', async () => {
|
|
6945
|
+
const options = {id: 'fake options'};
|
|
6946
|
+
await meeting.reconnect(options);
|
|
6947
|
+
|
|
6948
|
+
sinon.stub(meeting, 'waitForRemoteSDPAnswer').resolves();
|
|
6817
6949
|
|
|
6818
|
-
assert.calledWith(
|
|
6819
|
-
TriggerProxy.trigger,
|
|
6820
|
-
sinon.match.instanceOf(Meeting),
|
|
6821
|
-
{file: 'meeting/index', function: 'reconnect'},
|
|
6822
|
-
'meeting:reconnectionSuccess'
|
|
6823
|
-
);
|
|
6824
|
-
assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
|
|
6825
|
-
name: 'client.media.recovered',
|
|
6826
|
-
payload: {
|
|
6827
|
-
recoveredBy: 'new',
|
|
6828
|
-
},
|
|
6829
|
-
options: {
|
|
6830
|
-
meetingId: meeting.id,
|
|
6831
|
-
},
|
|
6832
|
-
});
|
|
6833
6950
|
assert.calledOnceWithExactly(
|
|
6834
|
-
meeting.reconnectionManager.
|
|
6835
|
-
|
|
6951
|
+
meeting.reconnectionManager.reconnect,
|
|
6952
|
+
options,
|
|
6953
|
+
sinon.match.any
|
|
6836
6954
|
);
|
|
6837
|
-
|
|
6955
|
+
const callback = meeting.reconnectionManager.reconnect.getCalls()[0].args[1];
|
|
6838
6956
|
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6957
|
+
// call the completion callback
|
|
6958
|
+
assert.isFunction(callback);
|
|
6959
|
+
await callback();
|
|
6960
|
+
|
|
6961
|
+
// check that the right things were called by the callback
|
|
6962
|
+
assert.calledOnceWithExactly(meeting.waitForRemoteSDPAnswer);
|
|
6963
|
+
assert.calledOnceWithExactly(meeting.mediaProperties.waitForMediaConnectionConnected);
|
|
6842
6964
|
});
|
|
6843
6965
|
});
|
|
6844
6966
|
|
|
6845
6967
|
describe('unsuccessful reconnect', () => {
|
|
6968
|
+
let logUploadSpy;
|
|
6969
|
+
|
|
6846
6970
|
beforeEach(() => {
|
|
6847
|
-
|
|
6971
|
+
logUploadSpy = sinon.spy(meeting, 'uploadLogs');
|
|
6848
6972
|
meeting.currentMediaStatus = {audio: true};
|
|
6849
6973
|
meeting.reconnectionManager = new ReconnectionManager(meeting);
|
|
6850
6974
|
meeting.reconnectionManager.reconnect = sinon
|
|
6851
6975
|
.stub()
|
|
6852
6976
|
.returns(Promise.reject(new Error()));
|
|
6853
|
-
meeting.reconnectionManager.reset = sinon.stub().returns(true);
|
|
6854
6977
|
});
|
|
6855
6978
|
|
|
6856
|
-
it('should
|
|
6979
|
+
it('should upload logs on reconnect failure', async () => {
|
|
6857
6980
|
await assert.isRejected(meeting.reconnect());
|
|
6858
6981
|
assert.calledWith(
|
|
6859
6982
|
TriggerProxy.trigger,
|
|
6860
6983
|
sinon.match.instanceOf(Meeting),
|
|
6861
6984
|
{file: 'meeting/index', function: 'reconnect'},
|
|
6862
|
-
|
|
6863
|
-
|
|
6985
|
+
EVENTS.REQUEST_UPLOAD_LOGS,
|
|
6986
|
+
sinon.match.instanceOf(Meeting)
|
|
6864
6987
|
);
|
|
6865
6988
|
});
|
|
6866
6989
|
|
|
6867
|
-
it('should
|
|
6990
|
+
it('should fail without uploading logs if there is no reconnectionManager', async () => {
|
|
6991
|
+
meeting.reconnectionManager = null;
|
|
6868
6992
|
await assert.isRejected(meeting.reconnect());
|
|
6869
|
-
assert(
|
|
6870
|
-
assert.calledWith(
|
|
6871
|
-
Metrics.sendBehavioralMetric,
|
|
6872
|
-
BEHAVIORAL_METRICS.MEETING_RECONNECT_FAILURE,
|
|
6873
|
-
{
|
|
6874
|
-
correlation_id: meeting.correlationId,
|
|
6875
|
-
locus_id: meeting.locusUrl.split('/').pop(),
|
|
6876
|
-
reason: sinon.match.any,
|
|
6877
|
-
stack: sinon.match.any,
|
|
6878
|
-
}
|
|
6879
|
-
);
|
|
6993
|
+
assert.notCalled(logUploadSpy);
|
|
6880
6994
|
});
|
|
6881
6995
|
|
|
6882
|
-
it('should
|
|
6996
|
+
it('should fail without uploading logs if there is no media established', async () => {
|
|
6997
|
+
meeting.currentMediaStatus = null;
|
|
6883
6998
|
await assert.isRejected(meeting.reconnect());
|
|
6884
|
-
assert.
|
|
6885
|
-
TriggerProxy.trigger,
|
|
6886
|
-
sinon.match.instanceOf(Meeting),
|
|
6887
|
-
{file: 'meeting/index', function: 'reconnect'},
|
|
6888
|
-
EVENTS.REQUEST_UPLOAD_LOGS,
|
|
6889
|
-
sinon.match.instanceOf(Meeting)
|
|
6890
|
-
);
|
|
6999
|
+
assert.notCalled(logUploadSpy);
|
|
6891
7000
|
});
|
|
6892
7001
|
|
|
6893
|
-
it('should
|
|
6894
|
-
|
|
6895
|
-
|
|
7002
|
+
it('should resolve if the error is ReconnectionNotStartedError', async () => {
|
|
7003
|
+
meeting.reconnectionManager.reconnect.returns(
|
|
7004
|
+
Promise.reject(new ReconnectionNotStartedError())
|
|
7005
|
+
);
|
|
7006
|
+
await meeting.reconnect();
|
|
7007
|
+
|
|
7008
|
+
// logs shouldn't be uploaded
|
|
7009
|
+
assert.notCalled(logUploadSpy);
|
|
6896
7010
|
});
|
|
6897
7011
|
});
|
|
6898
7012
|
});
|
|
@@ -8100,6 +8214,21 @@ describe('plugin-meetings', () => {
|
|
|
8100
8214
|
EVENT_TRIGGERS.MEETING_INTERPRETATION_UPDATE
|
|
8101
8215
|
);
|
|
8102
8216
|
});
|
|
8217
|
+
|
|
8218
|
+
it('listens to the locus manual caption update event', () => {
|
|
8219
|
+
meeting.locusInfo.emit(
|
|
8220
|
+
{function: 'test', file: 'test'},
|
|
8221
|
+
'CONTROLS_MEETING_MANUAL_CAPTION_UPDATED',
|
|
8222
|
+
{enable: true}
|
|
8223
|
+
);
|
|
8224
|
+
|
|
8225
|
+
assert.calledWith(
|
|
8226
|
+
TriggerProxy.trigger,
|
|
8227
|
+
meeting,
|
|
8228
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
8229
|
+
EVENT_TRIGGERS.MEETING_MANUAL_CAPTION_UPDATED
|
|
8230
|
+
);
|
|
8231
|
+
});
|
|
8103
8232
|
});
|
|
8104
8233
|
|
|
8105
8234
|
describe('#setUpLocusUrlListener', () => {
|
|
@@ -765,6 +765,9 @@ describe('plugin-meetings', () => {
|
|
|
765
765
|
{functionName: 'canStartTranscribing', displayHint: 'TRANSCRIPTION_CONTROL_START'},
|
|
766
766
|
{functionName: 'canStopTranscribing', displayHint: 'TRANSCRIPTION_CONTROL_STOP'},
|
|
767
767
|
{functionName: 'isClosedCaptionActive', displayHint: 'CAPTION_STATUS_ACTIVE'},
|
|
768
|
+
{functionName: 'canStartManualCaption', displayHint: 'MANUAL_CAPTION_START'},
|
|
769
|
+
{functionName: 'canStopManualCaption', displayHint: 'MANUAL_CAPTION_STOP'},
|
|
770
|
+
{functionName: 'isManualCaptionActive', displayHint: 'MANUAL_CAPTION_STATUS_ACTIVE'},
|
|
768
771
|
{functionName: 'isWebexAssistantActive', displayHint: 'WEBEX_ASSISTANT_STATUS_ACTIVE'},
|
|
769
772
|
{functionName: 'canViewCaptionPanel', displayHint: 'ENABLE_CAPTION_PANEL'},
|
|
770
773
|
{functionName: 'isRealTimeTranslationEnabled', displayHint: 'DISPLAY_REAL_TIME_TRANSLATION'},
|
|
@@ -513,13 +513,8 @@ describe('plugin-meetings', () => {
|
|
|
513
513
|
});
|
|
514
514
|
describe('#getAllMeetings', () => {
|
|
515
515
|
it('calls MeetingCollection to get all meetings with supplied options', () => {
|
|
516
|
-
webex.meetings.getAllMeetings(
|
|
517
|
-
test: test1,
|
|
518
|
-
});
|
|
516
|
+
webex.meetings.getAllMeetings();
|
|
519
517
|
assert.calledOnce(webex.meetings.meetingCollection.getAll);
|
|
520
|
-
assert.calledWith(webex.meetings.meetingCollection.getAll, {
|
|
521
|
-
test: test1,
|
|
522
|
-
});
|
|
523
518
|
});
|
|
524
519
|
});
|
|
525
520
|
});
|