@webex/plugin-meetings 3.0.0-beta.259 → 3.0.0-beta.260
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/constants.js +7 -2
- package/dist/constants.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/meeting/index.js +362 -281
- package/dist/meeting/index.js.map +1 -1
- package/dist/types/constants.d.ts +2 -0
- package/dist/types/meeting/index.d.ts +14 -2
- package/package.json +19 -19
- package/src/constants.ts +4 -0
- package/src/meeting/index.ts +58 -1
- package/test/unit/spec/meeting/index.js +119 -2
|
@@ -1029,3 +1029,5 @@ export declare const IP_VERSION: {
|
|
|
1029
1029
|
readonly ipv4_and_ipv6: 1;
|
|
1030
1030
|
};
|
|
1031
1031
|
export type IP_VERSION = (typeof IP_VERSION)[keyof typeof IP_VERSION];
|
|
1032
|
+
export declare const MEETING_PERMISSION_TOKEN_REFRESH_THRESHOLD_IN_SEC = 30;
|
|
1033
|
+
export declare const MEETING_PERMISSION_TOKEN_REFRESH_REASON = "ttl-join";
|
|
@@ -964,7 +964,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
964
964
|
joinWithMedia(options?: {
|
|
965
965
|
joinOptions?: any;
|
|
966
966
|
mediaOptions?: AddMediaOptions;
|
|
967
|
-
}):
|
|
967
|
+
}): Promise<{
|
|
968
|
+
join: any;
|
|
969
|
+
media: any;
|
|
970
|
+
}>;
|
|
968
971
|
/**
|
|
969
972
|
* Initiates the reconnection of the media in the meeting
|
|
970
973
|
*
|
|
@@ -1029,7 +1032,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1029
1032
|
* if joining as host on second loop, pass pin and pass moderator if joining as guest on second loop
|
|
1030
1033
|
* Scenario D: Joining any other way (sip, pstn, conversationUrl, link just need to specify resourceId)
|
|
1031
1034
|
*/
|
|
1032
|
-
join(options?: any): any
|
|
1035
|
+
join(options?: any): Promise<any>;
|
|
1033
1036
|
/**
|
|
1034
1037
|
* Connects to low latency mercury and reconnects if the address has changed
|
|
1035
1038
|
* It will also disconnect if called when the meeting has ended
|
|
@@ -1547,4 +1550,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1547
1550
|
* @returns {number} time left in seconds
|
|
1548
1551
|
*/
|
|
1549
1552
|
getPermissionTokenTimeLeftInSec(): number | undefined;
|
|
1553
|
+
/**
|
|
1554
|
+
* Check if there is enough time left till the permission token expires
|
|
1555
|
+
* If not - refresh the permission token
|
|
1556
|
+
*
|
|
1557
|
+
* @param {number} threshold - time in seconds
|
|
1558
|
+
* @param {string} reason - reason for refreshing the permission token
|
|
1559
|
+
* @returns {Promise<void>}
|
|
1560
|
+
*/
|
|
1561
|
+
checkAndRefreshPermissionToken(threshold: number, reason: string): Promise<void>;
|
|
1550
1562
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/plugin-meetings",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.260",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
|
|
6
6
|
"contributors": [
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"build": "yarn run -T tsc --declaration true --declarationDir ./dist/types"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@webex/plugin-meetings": "3.0.0-beta.
|
|
36
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
37
|
-
"@webex/test-helper-mocha": "3.0.0-beta.
|
|
38
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
39
|
-
"@webex/test-helper-retry": "3.0.0-beta.
|
|
40
|
-
"@webex/test-helper-test-users": "3.0.0-beta.
|
|
35
|
+
"@webex/plugin-meetings": "3.0.0-beta.260",
|
|
36
|
+
"@webex/test-helper-chai": "3.0.0-beta.260",
|
|
37
|
+
"@webex/test-helper-mocha": "3.0.0-beta.260",
|
|
38
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.260",
|
|
39
|
+
"@webex/test-helper-retry": "3.0.0-beta.260",
|
|
40
|
+
"@webex/test-helper-test-users": "3.0.0-beta.260",
|
|
41
41
|
"chai": "^4.3.4",
|
|
42
42
|
"chai-as-promised": "^7.1.1",
|
|
43
43
|
"jsdom-global": "3.0.2",
|
|
@@ -46,19 +46,19 @@
|
|
|
46
46
|
"typescript": "^4.7.4"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@webex/common": "3.0.0-beta.
|
|
49
|
+
"@webex/common": "3.0.0-beta.260",
|
|
50
50
|
"@webex/internal-media-core": "2.0.4",
|
|
51
|
-
"@webex/internal-plugin-conversation": "3.0.0-beta.
|
|
52
|
-
"@webex/internal-plugin-device": "3.0.0-beta.
|
|
53
|
-
"@webex/internal-plugin-llm": "3.0.0-beta.
|
|
54
|
-
"@webex/internal-plugin-mercury": "3.0.0-beta.
|
|
55
|
-
"@webex/internal-plugin-metrics": "3.0.0-beta.
|
|
56
|
-
"@webex/internal-plugin-support": "3.0.0-beta.
|
|
57
|
-
"@webex/internal-plugin-user": "3.0.0-beta.
|
|
58
|
-
"@webex/media-helpers": "3.0.0-beta.
|
|
59
|
-
"@webex/plugin-people": "3.0.0-beta.
|
|
60
|
-
"@webex/plugin-rooms": "3.0.0-beta.
|
|
61
|
-
"@webex/webex-core": "3.0.0-beta.
|
|
51
|
+
"@webex/internal-plugin-conversation": "3.0.0-beta.260",
|
|
52
|
+
"@webex/internal-plugin-device": "3.0.0-beta.260",
|
|
53
|
+
"@webex/internal-plugin-llm": "3.0.0-beta.260",
|
|
54
|
+
"@webex/internal-plugin-mercury": "3.0.0-beta.260",
|
|
55
|
+
"@webex/internal-plugin-metrics": "3.0.0-beta.260",
|
|
56
|
+
"@webex/internal-plugin-support": "3.0.0-beta.260",
|
|
57
|
+
"@webex/internal-plugin-user": "3.0.0-beta.260",
|
|
58
|
+
"@webex/media-helpers": "3.0.0-beta.260",
|
|
59
|
+
"@webex/plugin-people": "3.0.0-beta.260",
|
|
60
|
+
"@webex/plugin-rooms": "3.0.0-beta.260",
|
|
61
|
+
"@webex/webex-core": "3.0.0-beta.260",
|
|
62
62
|
"ampersand-collection": "^2.0.2",
|
|
63
63
|
"bowser": "^2.11.0",
|
|
64
64
|
"btoa": "^1.2.1",
|
package/src/constants.ts
CHANGED
|
@@ -1249,3 +1249,7 @@ export const IP_VERSION = {
|
|
|
1249
1249
|
} as const;
|
|
1250
1250
|
|
|
1251
1251
|
export type IP_VERSION = (typeof IP_VERSION)[keyof typeof IP_VERSION];
|
|
1252
|
+
|
|
1253
|
+
// constant for if the permissionToken is about to expire in the next 30 seconds, refresh it
|
|
1254
|
+
export const MEETING_PERMISSION_TOKEN_REFRESH_THRESHOLD_IN_SEC = 30;
|
|
1255
|
+
export const MEETING_PERMISSION_TOKEN_REFRESH_REASON = 'ttl-join';
|
package/src/meeting/index.ts
CHANGED
|
@@ -97,6 +97,8 @@ import {
|
|
|
97
97
|
SELF_ROLES,
|
|
98
98
|
INTERPRETATION,
|
|
99
99
|
SELF_POLICY,
|
|
100
|
+
MEETING_PERMISSION_TOKEN_REFRESH_THRESHOLD_IN_SEC,
|
|
101
|
+
MEETING_PERMISSION_TOKEN_REFRESH_REASON,
|
|
100
102
|
} from '../constants';
|
|
101
103
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
102
104
|
import ParameterError from '../common/errors/parameter';
|
|
@@ -4437,7 +4439,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4437
4439
|
* if joining as host on second loop, pass pin and pass moderator if joining as guest on second loop
|
|
4438
4440
|
* Scenario D: Joining any other way (sip, pstn, conversationUrl, link just need to specify resourceId)
|
|
4439
4441
|
*/
|
|
4440
|
-
public join(options: any = {}) {
|
|
4442
|
+
public async join(options: any = {}) {
|
|
4441
4443
|
// @ts-ignore - fix type
|
|
4442
4444
|
if (!this.webex.meetings.registered) {
|
|
4443
4445
|
const errorMessage = 'Meeting:index#join --> Device not registered';
|
|
@@ -4548,6 +4550,43 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4548
4550
|
|
|
4549
4551
|
this.isMultistream = !!options.enableMultistream;
|
|
4550
4552
|
|
|
4553
|
+
try {
|
|
4554
|
+
// refresh the permission token if its about to expire in 10sec
|
|
4555
|
+
await this.checkAndRefreshPermissionToken(
|
|
4556
|
+
MEETING_PERMISSION_TOKEN_REFRESH_THRESHOLD_IN_SEC,
|
|
4557
|
+
MEETING_PERMISSION_TOKEN_REFRESH_REASON
|
|
4558
|
+
);
|
|
4559
|
+
} catch (error) {
|
|
4560
|
+
LoggerProxy.logger.error('Meeting:index#join --> Failed to refresh permission token:', error);
|
|
4561
|
+
|
|
4562
|
+
if (
|
|
4563
|
+
error instanceof CaptchaError ||
|
|
4564
|
+
error instanceof PasswordError ||
|
|
4565
|
+
error instanceof PermissionError
|
|
4566
|
+
) {
|
|
4567
|
+
this.meetingFiniteStateMachine.fail(error);
|
|
4568
|
+
|
|
4569
|
+
// Upload logs on refreshpermissionToken refresh Failure
|
|
4570
|
+
Trigger.trigger(
|
|
4571
|
+
this,
|
|
4572
|
+
{
|
|
4573
|
+
file: 'meeting/index',
|
|
4574
|
+
function: 'join',
|
|
4575
|
+
},
|
|
4576
|
+
EVENTS.REQUEST_UPLOAD_LOGS,
|
|
4577
|
+
this
|
|
4578
|
+
);
|
|
4579
|
+
|
|
4580
|
+
joinFailed(error);
|
|
4581
|
+
|
|
4582
|
+
this.deferJoin = undefined;
|
|
4583
|
+
|
|
4584
|
+
// if refresh permission token requires captcha, password or permission, we are throwing the errors
|
|
4585
|
+
// and bubble it up to client
|
|
4586
|
+
return Promise.reject(error);
|
|
4587
|
+
}
|
|
4588
|
+
}
|
|
4589
|
+
|
|
4551
4590
|
return MeetingUtil.joinMeetingOptions(this, options)
|
|
4552
4591
|
.then((join) => {
|
|
4553
4592
|
this.meetingFiniteStateMachine.join();
|
|
@@ -7401,4 +7440,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7401
7440
|
// (permissionTokenExp is a epoch timestamp, not a time to live duration)
|
|
7402
7441
|
return (permissionTokenExpValue - now) / 1000;
|
|
7403
7442
|
}
|
|
7443
|
+
|
|
7444
|
+
/**
|
|
7445
|
+
* Check if there is enough time left till the permission token expires
|
|
7446
|
+
* If not - refresh the permission token
|
|
7447
|
+
*
|
|
7448
|
+
* @param {number} threshold - time in seconds
|
|
7449
|
+
* @param {string} reason - reason for refreshing the permission token
|
|
7450
|
+
* @returns {Promise<void>}
|
|
7451
|
+
*/
|
|
7452
|
+
public checkAndRefreshPermissionToken(threshold: number, reason: string): Promise<void> {
|
|
7453
|
+
const permissionTokenTimeLeft = this.getPermissionTokenTimeLeftInSec();
|
|
7454
|
+
|
|
7455
|
+
if (permissionTokenTimeLeft !== undefined && permissionTokenTimeLeft <= threshold) {
|
|
7456
|
+
return this.refreshPermissionToken(reason);
|
|
7457
|
+
}
|
|
7458
|
+
|
|
7459
|
+
return Promise.resolve();
|
|
7460
|
+
}
|
|
7404
7461
|
}
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
DISPLAY_HINTS,
|
|
30
30
|
SELF_POLICY,
|
|
31
31
|
IP_VERSION,
|
|
32
|
+
ERROR_DICTIONARY,
|
|
32
33
|
} from '@webex/plugin-meetings/src/constants';
|
|
33
34
|
import * as InternalMediaCoreModule from '@webex/internal-media-core';
|
|
34
35
|
import {
|
|
@@ -798,6 +799,7 @@ describe('plugin-meetings', () => {
|
|
|
798
799
|
webex.meetings.registered = true;
|
|
799
800
|
meeting.updateLLMConnection = sinon.stub();
|
|
800
801
|
});
|
|
802
|
+
|
|
801
803
|
describe('successful', () => {
|
|
802
804
|
beforeEach(() => {
|
|
803
805
|
sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve(joinMeetingResult));
|
|
@@ -918,7 +920,7 @@ describe('plugin-meetings', () => {
|
|
|
918
920
|
});
|
|
919
921
|
});
|
|
920
922
|
});
|
|
921
|
-
describe('lmm
|
|
923
|
+
describe('lmm, transcription & permissionTokenRefresh decoupling', () => {
|
|
922
924
|
beforeEach(() => {
|
|
923
925
|
sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve(joinMeetingResult));
|
|
924
926
|
});
|
|
@@ -1021,7 +1023,6 @@ describe('plugin-meetings', () => {
|
|
|
1021
1023
|
try {
|
|
1022
1024
|
await defer.promise;
|
|
1023
1025
|
} catch (err) {
|
|
1024
|
-
console.log(Metrics.sendBehavioralMetric.getCalls())
|
|
1025
1026
|
assert.deepEqual(Metrics.sendBehavioralMetric.getCalls()[0].args, [
|
|
1026
1027
|
BEHAVIORAL_METRICS.JOIN_SUCCESS, {correlation_id: meeting.correlationId}
|
|
1027
1028
|
])
|
|
@@ -1036,6 +1037,76 @@ describe('plugin-meetings', () => {
|
|
|
1036
1037
|
}
|
|
1037
1038
|
})
|
|
1038
1039
|
})
|
|
1040
|
+
|
|
1041
|
+
describe('refreshPermissionToken', () => {
|
|
1042
|
+
it('should continue if permissionTokenRefresh fails with a generic error', async () => {
|
|
1043
|
+
meeting.checkAndRefreshPermissionToken = sinon.stub().rejects(new Error('bad day'));
|
|
1044
|
+
const stateMachineFailSpy = sinon.spy(meeting.meetingFiniteStateMachine, 'fail');
|
|
1045
|
+
|
|
1046
|
+
try {
|
|
1047
|
+
const result = await meeting.join();
|
|
1048
|
+
assert.notCalled(stateMachineFailSpy);
|
|
1049
|
+
assert.equal(result, joinMeetingResult);
|
|
1050
|
+
assert.calledOnceWithExactly(meeting.checkAndRefreshPermissionToken, 30, 'ttl-join');
|
|
1051
|
+
} catch (error) {
|
|
1052
|
+
assert.fail('join should not throw an Error');
|
|
1053
|
+
}
|
|
1054
|
+
})
|
|
1055
|
+
|
|
1056
|
+
it('should throw if permissionTokenRefresh fails with a captcha error', async () => {
|
|
1057
|
+
meeting.checkAndRefreshPermissionToken = sinon.stub().rejects(new CaptchaError('bad captcha'));
|
|
1058
|
+
const stateMachineFailSpy = sinon.spy(meeting.meetingFiniteStateMachine, 'fail');
|
|
1059
|
+
const joinMeetingOptionsSpy = sinon.spy(MeetingUtil, 'joinMeetingOptions');
|
|
1060
|
+
|
|
1061
|
+
try {
|
|
1062
|
+
await meeting.join();
|
|
1063
|
+
assert.fail('join should have thrown a Captcha Error.');
|
|
1064
|
+
} catch (error) {
|
|
1065
|
+
assert.calledOnce(stateMachineFailSpy);
|
|
1066
|
+
assert.calledOnceWithExactly(meeting.checkAndRefreshPermissionToken, 30, 'ttl-join');
|
|
1067
|
+
assert.instanceOf(error, CaptchaError);
|
|
1068
|
+
assert.equal(error.message, 'bad captcha');
|
|
1069
|
+
// should not get to the end promise chain, which does do the join
|
|
1070
|
+
assert.notCalled(joinMeetingOptionsSpy);
|
|
1071
|
+
}
|
|
1072
|
+
})
|
|
1073
|
+
|
|
1074
|
+
it('should throw if permissionTokenRefresh fails with a password error', async () => {
|
|
1075
|
+
meeting.checkAndRefreshPermissionToken = sinon.stub().rejects(new PasswordError('bad password'));
|
|
1076
|
+
const stateMachineFailSpy = sinon.spy(meeting.meetingFiniteStateMachine, 'fail');
|
|
1077
|
+
const joinMeetingOptionsSpy = sinon.spy(MeetingUtil.joinMeetingOptions);
|
|
1078
|
+
|
|
1079
|
+
try {
|
|
1080
|
+
await meeting.join();
|
|
1081
|
+
assert.fail('join should have thrown a Password Error.');
|
|
1082
|
+
} catch (error) {
|
|
1083
|
+
assert.calledOnce(stateMachineFailSpy);
|
|
1084
|
+
assert.calledOnceWithExactly(meeting.checkAndRefreshPermissionToken, 30, 'ttl-join');
|
|
1085
|
+
assert.instanceOf(error, PasswordError);
|
|
1086
|
+
assert.equal(error.message, 'bad password');
|
|
1087
|
+
// should not get to the end promise chain, which does do the join
|
|
1088
|
+
assert.notCalled(joinMeetingOptionsSpy);
|
|
1089
|
+
}
|
|
1090
|
+
})
|
|
1091
|
+
|
|
1092
|
+
it('should throw if permissionTokenRefresh fails with a permission error', async () => {
|
|
1093
|
+
meeting.checkAndRefreshPermissionToken = sinon.stub().rejects(new PermissionError('bad permission'));
|
|
1094
|
+
const stateMachineFailSpy = sinon.spy(meeting.meetingFiniteStateMachine, 'fail');
|
|
1095
|
+
const joinMeetingOptionsSpy = sinon.spy(MeetingUtil.joinMeetingOptions);
|
|
1096
|
+
|
|
1097
|
+
try {
|
|
1098
|
+
await meeting.join();
|
|
1099
|
+
assert.fail('join should have thrown a Permission Error.');
|
|
1100
|
+
} catch (error) {
|
|
1101
|
+
assert.calledOnce(stateMachineFailSpy);
|
|
1102
|
+
assert.calledOnceWithExactly(meeting.checkAndRefreshPermissionToken, 30, 'ttl-join');
|
|
1103
|
+
assert.instanceOf(error, PermissionError);
|
|
1104
|
+
assert.equal(error.message, 'bad permission');
|
|
1105
|
+
// should not get to the end promise chain, which does do the join
|
|
1106
|
+
assert.notCalled(joinMeetingOptionsSpy);
|
|
1107
|
+
}
|
|
1108
|
+
})
|
|
1109
|
+
})
|
|
1039
1110
|
})
|
|
1040
1111
|
});
|
|
1041
1112
|
|
|
@@ -8309,4 +8380,50 @@ describe('plugin-meetings', () => {
|
|
|
8309
8380
|
assert.equal(meeting.getPermissionTokenTimeLeftInSec(), -1);
|
|
8310
8381
|
});
|
|
8311
8382
|
});
|
|
8383
|
+
|
|
8384
|
+
describe('#checkAndRefreshPermissionToken', () => {
|
|
8385
|
+
it('should not fire refreshPermissionToken if permissionToken is not defined', async() => {
|
|
8386
|
+
meeting.getPermissionTokenTimeLeftInSec = sinon.stub().returns(undefined)
|
|
8387
|
+
meeting.refreshPermissionToken = sinon.stub().returns(Promise.resolve('test return value'));
|
|
8388
|
+
|
|
8389
|
+
const returnValue = await meeting.checkAndRefreshPermissionToken(10, 'ttl-join');
|
|
8390
|
+
|
|
8391
|
+
assert.calledOnce(meeting.getPermissionTokenTimeLeftInSec);
|
|
8392
|
+
assert.notCalled(meeting.refreshPermissionToken);
|
|
8393
|
+
assert.equal(returnValue, undefined);
|
|
8394
|
+
});
|
|
8395
|
+
|
|
8396
|
+
it('should fire refreshPermissionToken if time left is below 10sec', async() => {
|
|
8397
|
+
meeting.getPermissionTokenTimeLeftInSec = sinon.stub().returns(9)
|
|
8398
|
+
meeting.refreshPermissionToken = sinon.stub().returns(Promise.resolve('test return value'));
|
|
8399
|
+
|
|
8400
|
+
const returnValue = await meeting.checkAndRefreshPermissionToken(10, 'ttl-join');
|
|
8401
|
+
|
|
8402
|
+
assert.calledOnce(meeting.getPermissionTokenTimeLeftInSec);
|
|
8403
|
+
assert.calledOnceWithExactly(meeting.refreshPermissionToken, 'ttl-join');
|
|
8404
|
+
assert.equal(returnValue, 'test return value');
|
|
8405
|
+
});
|
|
8406
|
+
|
|
8407
|
+
it('should fire refreshPermissionToken if time left is equal 10sec', async () => {
|
|
8408
|
+
meeting.getPermissionTokenTimeLeftInSec = sinon.stub().returns(10)
|
|
8409
|
+
meeting.refreshPermissionToken = sinon.stub().returns(Promise.resolve('test return value'));
|
|
8410
|
+
|
|
8411
|
+
const returnValue = await meeting.checkAndRefreshPermissionToken(10, 'ttl-join');
|
|
8412
|
+
|
|
8413
|
+
assert.calledOnce(meeting.getPermissionTokenTimeLeftInSec);
|
|
8414
|
+
assert.calledOnceWithExactly(meeting.refreshPermissionToken, 'ttl-join');
|
|
8415
|
+
assert.equal(returnValue, 'test return value');
|
|
8416
|
+
});
|
|
8417
|
+
|
|
8418
|
+
it('should not fire refreshPermissionToken if time left is higher than 10sec', async () => {
|
|
8419
|
+
meeting.getPermissionTokenTimeLeftInSec = sinon.stub().returns(11)
|
|
8420
|
+
meeting.refreshPermissionToken = sinon.stub().returns(Promise.resolve('test return value'));
|
|
8421
|
+
|
|
8422
|
+
const returnValue = await meeting.checkAndRefreshPermissionToken(10, 'ttl-join');
|
|
8423
|
+
|
|
8424
|
+
assert.calledOnce(meeting.getPermissionTokenTimeLeftInSec);
|
|
8425
|
+
assert.notCalled(meeting.refreshPermissionToken);
|
|
8426
|
+
assert.equal(returnValue, undefined);
|
|
8427
|
+
});
|
|
8428
|
+
});
|
|
8312
8429
|
});
|