@webex/plugin-meetings 3.12.0-next.12 → 3.12.0-next.14

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.
@@ -723,7 +723,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
723
723
  }, _callee1);
724
724
  }))();
725
725
  },
726
- version: "3.12.0-next.12"
726
+ version: "3.12.0-next.14"
727
727
  });
728
728
  var _default = exports.default = Webinar;
729
729
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -94,5 +94,5 @@
94
94
  "//": [
95
95
  "TODO: upgrade jwt-decode when moving to node 18"
96
96
  ],
97
- "version": "3.12.0-next.12"
97
+ "version": "3.12.0-next.14"
98
98
  }
@@ -2598,6 +2598,7 @@ export default class LocusInfo extends EventsScope {
2598
2598
  {
2599
2599
  muted: parsedSelves.current.remoteMuted,
2600
2600
  unmuteAllowed: parsedSelves.current.unmuteAllowed,
2601
+ modifiedBy: parsedSelves.current.modifiedBy ?? null,
2601
2602
  }
2602
2603
  );
2603
2604
  }
@@ -1811,7 +1811,11 @@ export default class Meetings extends WebexPlugin {
1811
1811
  // For type LOCUS_ID we need to parse the locus object to get the information
1812
1812
  // about the caller and callee
1813
1813
  // Meeting Added event will be created in `handleLocusEvent`
1814
- if (type !== DESTINATION_TYPE.LOCUS_ID) {
1814
+ // Only emit MEETING_ADDED if the meeting still exists in the collection.
1815
+ // If fetchMeetingInfo failed and the meeting was destroyed in the catch block,
1816
+ // skip emitting to prevent orphaned meeting references on the consumer side.
1817
+ // @ts-ignore - getMeetingByType types value as object but accepts strings (same as handleLocusEvent)
1818
+ if (type !== DESTINATION_TYPE.LOCUS_ID && this.getMeetingByType(_ID_, meeting.id)) {
1815
1819
  if (!meeting.sipUri) {
1816
1820
  meeting.setSipUri(destination);
1817
1821
  }
@@ -2024,7 +2024,7 @@ describe('plugin-meetings', () => {
2024
2024
  function: 'updateSelf',
2025
2025
  },
2026
2026
  LOCUSINFO.EVENTS.SELF_REMOTE_MUTE_STATUS_UPDATED,
2027
- {muted: true, unmuteAllowed: true}
2027
+ {muted: true, unmuteAllowed: true, modifiedBy: null}
2028
2028
  );
2029
2029
 
2030
2030
  // but sometimes "previous self" is defined, but without controls.audio.muted, so we test this here:
@@ -2039,7 +2039,7 @@ describe('plugin-meetings', () => {
2039
2039
  function: 'updateSelf',
2040
2040
  },
2041
2041
  LOCUSINFO.EVENTS.SELF_REMOTE_MUTE_STATUS_UPDATED,
2042
- {muted: true, unmuteAllowed: true}
2042
+ {muted: true, unmuteAllowed: true, modifiedBy: null}
2043
2043
  );
2044
2044
  });
2045
2045
 
@@ -2098,7 +2098,7 @@ describe('plugin-meetings', () => {
2098
2098
  function: 'updateSelf',
2099
2099
  },
2100
2100
  LOCUSINFO.EVENTS.SELF_REMOTE_MUTE_STATUS_UPDATED,
2101
- {muted: true, unmuteAllowed: true}
2101
+ {muted: true, unmuteAllowed: true, modifiedBy: null}
2102
2102
  );
2103
2103
  });
2104
2104
 
@@ -2237,7 +2237,7 @@ describe('plugin-meetings', () => {
2237
2237
  function: 'updateSelf',
2238
2238
  },
2239
2239
  LOCUSINFO.EVENTS.SELF_REMOTE_MUTE_STATUS_UPDATED,
2240
- {muted: true, unmuteAllowed: false}
2240
+ {muted: true, unmuteAllowed: false, modifiedBy: null}
2241
2241
  );
2242
2242
 
2243
2243
  // now change only disallowUnmute
@@ -2255,7 +2255,28 @@ describe('plugin-meetings', () => {
2255
2255
  function: 'updateSelf',
2256
2256
  },
2257
2257
  LOCUSINFO.EVENTS.SELF_REMOTE_MUTE_STATUS_UPDATED,
2258
- {muted: true, unmuteAllowed: true}
2258
+ {muted: true, unmuteAllowed: true, modifiedBy: null}
2259
+ );
2260
+ });
2261
+
2262
+ it('should include modifiedBy in payload when muted by host', () => {
2263
+ locusInfo.webex.internal.device.url = self.deviceUrl;
2264
+ locusInfo.updateSelf(self);
2265
+ const newSelf = cloneDeep(self);
2266
+ newSelf.controls.audio.muted = true;
2267
+ newSelf.controls.audio.meta = {modifiedBy: 'host-uuid-123'};
2268
+
2269
+ locusInfo.emitScoped = sinon.stub();
2270
+ locusInfo.updateSelf(newSelf);
2271
+
2272
+ assert.calledWith(
2273
+ locusInfo.emitScoped,
2274
+ {
2275
+ file: 'locus-info',
2276
+ function: 'updateSelf',
2277
+ },
2278
+ LOCUSINFO.EVENTS.SELF_REMOTE_MUTE_STATUS_UPDATED,
2279
+ {muted: true, unmuteAllowed: true, modifiedBy: 'host-uuid-123'}
2259
2280
  );
2260
2281
  });
2261
2282
 
@@ -2833,6 +2833,39 @@ describe('plugin-meetings', () => {
2833
2833
  checkCreateMeetingWithNoMeetingInfo(true, true);
2834
2834
  });
2835
2835
 
2836
+ it('does not emit meeting:added when meeting is destroyed due to missing meeting info', async () => {
2837
+ // Make destroy actually remove the meeting from the collection
2838
+ // so that getMeetingByType returns null in the finally block
2839
+ webex.meetings.destroy = sinon.stub().callsFake((meeting) => {
2840
+ webex.meetings.meetingCollection.delete(meeting.id);
2841
+ });
2842
+
2843
+ try {
2844
+ await webex.meetings.createMeeting(
2845
+ 'test destination',
2846
+ 'test type',
2847
+ undefined,
2848
+ undefined,
2849
+ undefined,
2850
+ true
2851
+ );
2852
+ assert.fail('should have thrown NoMeetingInfoError');
2853
+ } catch (err) {
2854
+ assert.instanceOf(err, NoMeetingInfoError);
2855
+ }
2856
+
2857
+ assert.calledOnce(webex.meetings.destroy);
2858
+
2859
+ // meeting:added should NOT have been triggered since the meeting was destroyed
2860
+ assert.neverCalledWith(
2861
+ TriggerProxy.trigger,
2862
+ sinon.match.any,
2863
+ sinon.match({function: 'createMeeting'}),
2864
+ 'meeting:added',
2865
+ sinon.match.any
2866
+ );
2867
+ });
2868
+
2836
2869
  it('creates the meeting avoiding meeting info fetch by passing type as DESTINATION_TYPE.ONE_ON_ONE_CALL', async () => {
2837
2870
  const meeting = await webex.meetings.createMeeting(
2838
2871
  'test destination',