@webex/plugin-meetings 3.8.1-next.41 → 3.8.1-next.43

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.
@@ -83,6 +83,7 @@ export type CallStateForMetrics = {
83
83
  loginType?: string;
84
84
  userNameInput?: string;
85
85
  emailInput?: string;
86
+ pstnCorrelationId?: string;
86
87
  };
87
88
  export declare const MEDIA_UPDATE_TYPE: {
88
89
  TRANSCODED_MEDIA_CONNECTION: string;
@@ -515,6 +516,16 @@ export default class Meeting extends StatelessWebexPlugin {
515
516
  * @param {string} correlationId
516
517
  */
517
518
  set correlationId(correlationId: string);
519
+ /**
520
+ * Getter - Returns callStateForMetrics.pstnCorrelationId
521
+ * @returns {string | undefined}
522
+ */
523
+ get pstnCorrelationId(): string | undefined;
524
+ /**
525
+ * Setter - sets callStateForMetrics.pstnCorrelationId
526
+ * @param {string | undefined} correlationId
527
+ */
528
+ set pstnCorrelationId(correlationId: string | undefined);
518
529
  /**
519
530
  * Getter - Returns callStateForMetrics.userNameInput
520
531
  * @returns {string}
@@ -1341,7 +1352,7 @@ export default class Meeting extends StatelessWebexPlugin {
1341
1352
  * @memberof Meeting
1342
1353
  * @returns {Promise}
1343
1354
  */
1344
- disconnectPhoneAudio(): Promise<[any, any]>;
1355
+ disconnectPhoneAudio(): Promise<void>;
1345
1356
  /**
1346
1357
  * Moves the call to the specified resourceId
1347
1358
  * @param {String} resourceId
@@ -458,7 +458,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
458
458
  }, _callee7);
459
459
  }))();
460
460
  },
461
- version: "3.8.1-next.41"
461
+ version: "3.8.1-next.43"
462
462
  });
463
463
  var _default = exports.default = Webinar;
464
464
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -43,7 +43,7 @@
43
43
  "@webex/eslint-config-legacy": "0.0.0",
44
44
  "@webex/jest-config-legacy": "0.0.0",
45
45
  "@webex/legacy-tools": "0.0.0",
46
- "@webex/plugin-rooms": "3.8.1-next.13",
46
+ "@webex/plugin-rooms": "3.8.1-next.14",
47
47
  "@webex/test-helper-chai": "3.8.1-next.11",
48
48
  "@webex/test-helper-mocha": "3.8.1-next.11",
49
49
  "@webex/test-helper-mock-webex": "3.8.1-next.11",
@@ -63,20 +63,20 @@
63
63
  "@webex/common": "3.8.1-next.11",
64
64
  "@webex/event-dictionary-ts": "^1.0.1819",
65
65
  "@webex/internal-media-core": "2.18.5",
66
- "@webex/internal-plugin-conversation": "3.8.1-next.16",
67
- "@webex/internal-plugin-device": "3.8.1-next.14",
68
- "@webex/internal-plugin-llm": "3.8.1-next.15",
69
- "@webex/internal-plugin-mercury": "3.8.1-next.14",
70
- "@webex/internal-plugin-metrics": "3.8.1-next.14",
71
- "@webex/internal-plugin-support": "3.8.1-next.16",
72
- "@webex/internal-plugin-user": "3.8.1-next.14",
73
- "@webex/internal-plugin-voicea": "3.8.1-next.41",
66
+ "@webex/internal-plugin-conversation": "3.8.1-next.17",
67
+ "@webex/internal-plugin-device": "3.8.1-next.15",
68
+ "@webex/internal-plugin-llm": "3.8.1-next.16",
69
+ "@webex/internal-plugin-mercury": "3.8.1-next.15",
70
+ "@webex/internal-plugin-metrics": "3.8.1-next.15",
71
+ "@webex/internal-plugin-support": "3.8.1-next.17",
72
+ "@webex/internal-plugin-user": "3.8.1-next.15",
73
+ "@webex/internal-plugin-voicea": "3.8.1-next.42",
74
74
  "@webex/media-helpers": "3.8.1-next.16",
75
- "@webex/plugin-people": "3.8.1-next.14",
76
- "@webex/plugin-rooms": "3.8.1-next.13",
75
+ "@webex/plugin-people": "3.8.1-next.15",
76
+ "@webex/plugin-rooms": "3.8.1-next.14",
77
77
  "@webex/ts-sdp": "^1.8.1",
78
78
  "@webex/web-capabilities": "^1.6.0",
79
- "@webex/webex-core": "3.8.1-next.14",
79
+ "@webex/webex-core": "3.8.1-next.15",
80
80
  "ampersand-collection": "^2.0.2",
81
81
  "bowser": "^2.11.0",
82
82
  "btoa": "^1.2.1",
@@ -92,5 +92,5 @@
92
92
  "//": [
93
93
  "TODO: upgrade jwt-decode when moving to node 18"
94
94
  ],
95
- "version": "3.8.1-next.41"
95
+ "version": "3.8.1-next.43"
96
96
  }
@@ -251,6 +251,7 @@ export type CallStateForMetrics = {
251
251
  loginType?: string;
252
252
  userNameInput?: string;
253
253
  emailInput?: string;
254
+ pstnCorrelationId?: string;
254
255
  };
255
256
 
256
257
  export const MEDIA_UPDATE_TYPE = {
@@ -1683,6 +1684,22 @@ export default class Meeting extends StatelessWebexPlugin {
1683
1684
  this.callStateForMetrics.correlationId = correlationId;
1684
1685
  }
1685
1686
 
1687
+ /**
1688
+ * Getter - Returns callStateForMetrics.pstnCorrelationId
1689
+ * @returns {string | undefined}
1690
+ */
1691
+ get pstnCorrelationId(): string | undefined {
1692
+ return this.callStateForMetrics.pstnCorrelationId;
1693
+ }
1694
+
1695
+ /**
1696
+ * Setter - sets callStateForMetrics.pstnCorrelationId
1697
+ * @param {string | undefined} correlationId
1698
+ */
1699
+ set pstnCorrelationId(correlationId: string | undefined) {
1700
+ this.callStateForMetrics.pstnCorrelationId = correlationId;
1701
+ }
1702
+
1686
1703
  /**
1687
1704
  * Getter - Returns callStateForMetrics.userNameInput
1688
1705
  * @returns {string}
@@ -6093,8 +6110,9 @@ export default class Meeting extends StatelessWebexPlugin {
6093
6110
  */
6094
6111
  private dialInPstn() {
6095
6112
  if (this.isPhoneProvisioned(this.dialInDeviceStatus)) return Promise.resolve(); // prevent multiple dial in devices from being provisioned
6113
+ this.pstnCorrelationId = uuid.v4();
6096
6114
 
6097
- const {correlationId, locusUrl} = this;
6115
+ const {pstnCorrelationId, locusUrl} = this;
6098
6116
 
6099
6117
  if (!this.dialInUrl) this.dialInUrl = `dialin:///${uuid.v4()}`;
6100
6118
 
@@ -6102,7 +6120,7 @@ export default class Meeting extends StatelessWebexPlugin {
6102
6120
  this.meetingRequest
6103
6121
  // @ts-ignore
6104
6122
  .dialIn({
6105
- correlationId,
6123
+ correlationId: pstnCorrelationId,
6106
6124
  dialInUrl: this.dialInUrl,
6107
6125
  locusUrl,
6108
6126
  clientUrl: this.deviceUrl,
@@ -6111,12 +6129,17 @@ export default class Meeting extends StatelessWebexPlugin {
6111
6129
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_DIAL_IN_FAILURE, {
6112
6130
  correlation_id: this.correlationId,
6113
6131
  dial_in_url: this.dialInUrl,
6132
+ dial_in_correlation_id: pstnCorrelationId,
6114
6133
  locus_id: locusUrl.split('/').pop(),
6115
6134
  client_url: this.deviceUrl,
6116
6135
  reason: error.error?.message,
6117
6136
  stack: error.stack,
6118
6137
  });
6119
6138
 
6139
+ if (this.pstnCorrelationId === pstnCorrelationId) {
6140
+ this.pstnCorrelationId = undefined;
6141
+ }
6142
+
6120
6143
  return Promise.reject(error);
6121
6144
  })
6122
6145
  );
@@ -6131,8 +6154,9 @@ export default class Meeting extends StatelessWebexPlugin {
6131
6154
  */
6132
6155
  private dialOutPstn(phoneNumber: string) {
6133
6156
  if (this.isPhoneProvisioned(this.dialOutDeviceStatus)) return Promise.resolve(); // prevent multiple dial out devices from being provisioned
6157
+ this.pstnCorrelationId = uuid.v4();
6134
6158
 
6135
- const {correlationId, locusUrl} = this;
6159
+ const {locusUrl, pstnCorrelationId} = this;
6136
6160
 
6137
6161
  if (!this.dialOutUrl) this.dialOutUrl = `dialout:///${uuid.v4()}`;
6138
6162
 
@@ -6140,7 +6164,7 @@ export default class Meeting extends StatelessWebexPlugin {
6140
6164
  this.meetingRequest
6141
6165
  // @ts-ignore
6142
6166
  .dialOut({
6143
- correlationId,
6167
+ correlationId: pstnCorrelationId,
6144
6168
  dialOutUrl: this.dialOutUrl,
6145
6169
  phoneNumber,
6146
6170
  locusUrl,
@@ -6150,12 +6174,17 @@ export default class Meeting extends StatelessWebexPlugin {
6150
6174
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_DIAL_OUT_FAILURE, {
6151
6175
  correlation_id: this.correlationId,
6152
6176
  dial_out_url: this.dialOutUrl,
6177
+ dial_out_correlation_id: pstnCorrelationId,
6153
6178
  locus_id: locusUrl.split('/').pop(),
6154
6179
  client_url: this.deviceUrl,
6155
6180
  reason: error.error?.message,
6156
6181
  stack: error.stack,
6157
6182
  });
6158
6183
 
6184
+ if (this.pstnCorrelationId === pstnCorrelationId) {
6185
+ this.pstnCorrelationId = undefined;
6186
+ }
6187
+
6159
6188
  return Promise.reject(error);
6160
6189
  })
6161
6190
  );
@@ -6169,6 +6198,8 @@ export default class Meeting extends StatelessWebexPlugin {
6169
6198
  * @returns {Promise}
6170
6199
  */
6171
6200
  public disconnectPhoneAudio() {
6201
+ const correlationToClear = this.pstnCorrelationId;
6202
+
6172
6203
  return Promise.all([
6173
6204
  this.isPhoneProvisioned(this.dialInDeviceStatus)
6174
6205
  ? MeetingUtil.disconnectPhoneAudio(this, this.dialInUrl)
@@ -6176,7 +6207,11 @@ export default class Meeting extends StatelessWebexPlugin {
6176
6207
  this.isPhoneProvisioned(this.dialOutDeviceStatus)
6177
6208
  ? MeetingUtil.disconnectPhoneAudio(this, this.dialOutUrl)
6178
6209
  : Promise.resolve(),
6179
- ]);
6210
+ ]).then(() => {
6211
+ if (this.pstnCorrelationId === correlationToClear) {
6212
+ this.pstnCorrelationId = undefined;
6213
+ }
6214
+ });
6180
6215
  }
6181
6216
 
6182
6217
  /**
@@ -485,6 +485,18 @@ describe('plugin-meetings', () => {
485
485
  });
486
486
  });
487
487
 
488
+ it('pstnCorrelationId getter/setter should work correctly', () => {
489
+ const testPstnCorrelationId = uuid.v4();
490
+
491
+ meeting.pstnCorrelationId = testPstnCorrelationId;
492
+ assert.equal(meeting.pstnCorrelationId, testPstnCorrelationId);
493
+ assert.equal(meeting.callStateForMetrics.pstnCorrelationId, testPstnCorrelationId);
494
+
495
+ meeting.pstnCorrelationId = undefined;
496
+ assert.equal(meeting.pstnCorrelationId, undefined);
497
+ assert.equal(meeting.callStateForMetrics.pstnCorrelationId, undefined);
498
+ });
499
+
488
500
  describe('creates ReceiveSlot manager instance', () => {
489
501
  let mockReceiveSlotManagerCtor;
490
502
  let providedCreateSlotCallback;
@@ -6526,12 +6538,17 @@ describe('plugin-meetings', () => {
6526
6538
  const DIAL_IN_URL = meeting.dialInUrl;
6527
6539
 
6528
6540
  assert.calledWith(meeting.meetingRequest.dialIn, {
6529
- correlationId: meeting.correlationId,
6541
+ correlationId: meeting.pstnCorrelationId,
6530
6542
  dialInUrl: DIAL_IN_URL,
6531
6543
  locusUrl: meeting.locusUrl,
6532
6544
  clientUrl: meeting.deviceUrl,
6533
6545
  });
6534
6546
  assert.notCalled(meeting.meetingRequest.dialOut);
6547
+
6548
+ // Verify pstnCorrelationId was set
6549
+ assert.exists(meeting.pstnCorrelationId);
6550
+ assert.notEqual(meeting.pstnCorrelationId, meeting.correlationId);
6551
+ const firstPstnCorrelationId = meeting.pstnCorrelationId
6535
6552
 
6536
6553
  meeting.meetingRequest.dialIn.resetHistory();
6537
6554
 
@@ -6539,12 +6556,18 @@ describe('plugin-meetings', () => {
6539
6556
  await meeting.usePhoneAudio();
6540
6557
 
6541
6558
  assert.calledWith(meeting.meetingRequest.dialIn, {
6542
- correlationId: meeting.correlationId,
6559
+ correlationId: meeting.pstnCorrelationId,
6543
6560
  dialInUrl: DIAL_IN_URL,
6544
6561
  locusUrl: meeting.locusUrl,
6545
6562
  clientUrl: meeting.deviceUrl,
6546
6563
  });
6547
6564
  assert.notCalled(meeting.meetingRequest.dialOut);
6565
+ // A new PSTN correlationId should be generated for the second attempt
6566
+ assert.notEqual(
6567
+ meeting.pstnCorrelationId,
6568
+ firstPstnCorrelationId,
6569
+ 'pstnCorrelationId should be regenerated on each dial-in attempt'
6570
+ );
6548
6571
  });
6549
6572
 
6550
6573
  it('given a phone number, triggers dial-out, delegating request to meetingRequest correctly', async () => {
@@ -6554,7 +6577,7 @@ describe('plugin-meetings', () => {
6554
6577
  const DIAL_OUT_URL = meeting.dialOutUrl;
6555
6578
 
6556
6579
  assert.calledWith(meeting.meetingRequest.dialOut, {
6557
- correlationId: meeting.correlationId,
6580
+ correlationId: meeting.pstnCorrelationId,
6558
6581
  dialOutUrl: DIAL_OUT_URL,
6559
6582
  locusUrl: meeting.locusUrl,
6560
6583
  clientUrl: meeting.deviceUrl,
@@ -6562,49 +6585,126 @@ describe('plugin-meetings', () => {
6562
6585
  });
6563
6586
  assert.notCalled(meeting.meetingRequest.dialIn);
6564
6587
 
6588
+ // Verify pstnCorrelationId was set
6589
+ assert.exists(meeting.pstnCorrelationId);
6590
+ assert.notEqual(meeting.pstnCorrelationId, meeting.correlationId);
6591
+ const firstPstnCorrelationId = meeting.pstnCorrelationId;
6592
+
6565
6593
  meeting.meetingRequest.dialOut.resetHistory();
6566
6594
 
6567
6595
  // try again. the dial out urls should match
6568
6596
  await meeting.usePhoneAudio(phoneNumber);
6569
6597
 
6570
6598
  assert.calledWith(meeting.meetingRequest.dialOut, {
6571
- correlationId: meeting.correlationId,
6599
+ correlationId: meeting.pstnCorrelationId,
6572
6600
  dialOutUrl: DIAL_OUT_URL,
6573
6601
  locusUrl: meeting.locusUrl,
6574
6602
  clientUrl: meeting.deviceUrl,
6575
6603
  phoneNumber,
6576
6604
  });
6577
6605
  assert.notCalled(meeting.meetingRequest.dialIn);
6606
+ // A new PSTN correlationId should be generated for the second attempt
6607
+ assert.notEqual(
6608
+ meeting.pstnCorrelationId,
6609
+ firstPstnCorrelationId,
6610
+ 'pstnCorrelationId should be regenerated on each dial-out attempt'
6611
+ );
6578
6612
  });
6579
6613
 
6580
- it('rejects if the request failed (dial in)', () => {
6581
- const error = 'something bad happened';
6614
+ it('rejects if the request failed (dial in)', async () => {
6615
+ const error = {error: {message: 'dial in failed'}, stack: 'error stack'};
6582
6616
 
6583
6617
  meeting.meetingRequest.dialIn = sinon.stub().returns(Promise.reject(error));
6584
6618
 
6585
- return meeting
6586
- .usePhoneAudio()
6587
- .then(() => Promise.reject(new Error('Promise resolved when it should have rejected')))
6588
- .catch((e) => {
6589
- assert.equal(e, error);
6590
-
6591
- return Promise.resolve();
6619
+ try {
6620
+ await meeting.usePhoneAudio();
6621
+ throw new Error('Promise resolved when it should have rejected');
6622
+ } catch (e) {
6623
+ assert.equal(e, error);
6624
+
6625
+ // Verify behavioral metric was sent with dial_in_correlation_id
6626
+ assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ADD_DIAL_IN_FAILURE, {
6627
+ correlation_id: meeting.correlationId,
6628
+ dial_in_url: meeting.dialInUrl,
6629
+ dial_in_correlation_id: sinon.match.string,
6630
+ locus_id: meeting.locusUrl.split('/').pop(),
6631
+ client_url: meeting.deviceUrl,
6632
+ reason: error.error.message,
6633
+ stack: error.stack,
6592
6634
  });
6635
+
6636
+ // Verify pstnCorrelationId was cleared after error
6637
+ assert.equal(meeting.pstnCorrelationId, undefined);
6638
+ }
6593
6639
  });
6594
6640
 
6595
6641
  it('rejects if the request failed (dial out)', async () => {
6596
- const error = 'something bad happened';
6642
+ const error = {error: {message: 'dial out failed'}, stack: 'error stack'};
6597
6643
 
6598
6644
  meeting.meetingRequest.dialOut = sinon.stub().returns(Promise.reject(error));
6599
6645
 
6600
- return meeting
6601
- .usePhoneAudio('+441234567890')
6602
- .then(() => Promise.reject(new Error('Promise resolved when it should have rejected')))
6603
- .catch((e) => {
6604
- assert.equal(e, error);
6605
-
6606
- return Promise.resolve();
6646
+ try {
6647
+ await meeting.usePhoneAudio('+441234567890');
6648
+ throw new Error('Promise resolved when it should have rejected');
6649
+ } catch (e) {
6650
+ assert.equal(e, error);
6651
+
6652
+ // Verify behavioral metric was sent with dial_out_correlation_id
6653
+ assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ADD_DIAL_OUT_FAILURE, {
6654
+ correlation_id: meeting.correlationId,
6655
+ dial_out_url: meeting.dialOutUrl,
6656
+ dial_out_correlation_id: sinon.match.string,
6657
+ locus_id: meeting.locusUrl.split('/').pop(),
6658
+ client_url: meeting.deviceUrl,
6659
+ reason: error.error.message,
6660
+ stack: error.stack,
6607
6661
  });
6662
+
6663
+ // Verify pstnCorrelationId was cleared after error
6664
+ assert.equal(meeting.pstnCorrelationId, undefined);
6665
+ }
6666
+ });
6667
+ });
6668
+
6669
+ describe('#disconnectPhoneAudio', () => {
6670
+ beforeEach(() => {
6671
+ // Mock the MeetingUtil.disconnectPhoneAudio method
6672
+ sinon.stub(MeetingUtil, 'disconnectPhoneAudio').resolves();
6673
+ meeting.dialInUrl = 'dialin:///test-dial-in-url';
6674
+ meeting.dialOutUrl = 'dialout:///test-dial-out-url';
6675
+ meeting.dialInDeviceStatus = 'JOINED';
6676
+ meeting.dialOutDeviceStatus = 'JOINED';
6677
+ });
6678
+
6679
+ afterEach(() => {
6680
+ MeetingUtil.disconnectPhoneAudio.restore();
6681
+ });
6682
+
6683
+ it('should disconnect phone audio and clear pstnCorrelationId', async () => {
6684
+ meeting.pstnCorrelationId = 'test-pstn-correlation-id';
6685
+
6686
+ await meeting.disconnectPhoneAudio();
6687
+
6688
+ // Verify that pstnCorrelationId is cleared
6689
+ assert.equal(meeting.pstnCorrelationId, undefined);
6690
+
6691
+ // Verify that MeetingUtil.disconnectPhoneAudio was called for both dial-in and dial-out
6692
+ assert.calledTwice(MeetingUtil.disconnectPhoneAudio);
6693
+ assert.calledWith(MeetingUtil.disconnectPhoneAudio, meeting, meeting.dialInUrl);
6694
+ assert.calledWith(MeetingUtil.disconnectPhoneAudio, meeting, meeting.dialOutUrl);
6695
+ });
6696
+
6697
+ it('should handle case when no PSTN connection is active', async () => {
6698
+ meeting.dialInDeviceStatus = 'IDLE';
6699
+ meeting.dialOutDeviceStatus = 'IDLE';
6700
+ meeting.pstnCorrelationId = 'test-pstn-correlation-id';
6701
+
6702
+ await meeting.disconnectPhoneAudio();
6703
+
6704
+ // Verify that pstnCorrelationId is still cleared even when no phone connection is active
6705
+ assert.equal(meeting.pstnCorrelationId, undefined);
6706
+ // And verify no disconnect was attempted
6707
+ assert.notCalled(MeetingUtil.disconnectPhoneAudio);
6608
6708
  });
6609
6709
  });
6610
6710