@webex/internal-plugin-mercury 3.11.0 → 3.12.0-llmrefactor.2

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.
@@ -0,0 +1,280 @@
1
+ /*!
2
+ * Copyright (c) 2015-2024 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ import {assert} from '@webex/test-helper-chai';
6
+ import sinon from 'sinon';
7
+ import MockWebex from '@webex/test-helper-mock-webex';
8
+ import {MercuryPlugin, config as mercuryConfig} from '@webex/internal-plugin-mercury';
9
+
10
+ describe('plugin-mercury', () => {
11
+ describe('MercuryPlugin', () => {
12
+ let webex, mercuryPlugin;
13
+
14
+ beforeEach(() => {
15
+ webex = new MockWebex({
16
+ children: {
17
+ mercury: MercuryPlugin,
18
+ },
19
+ });
20
+
21
+ webex.internal.feature = {
22
+ getFeature: sinon.stub().resolves(false),
23
+ };
24
+
25
+ webex.credentials = {
26
+ refresh: sinon.stub().resolves(),
27
+ getUserToken: sinon.stub().resolves({
28
+ toString() {
29
+ return 'Bearer FAKE';
30
+ },
31
+ }),
32
+ };
33
+
34
+ webex.internal.device = {
35
+ register: sinon.stub().resolves(),
36
+ refresh: sinon.stub().resolves(),
37
+ webSocketUrl: 'ws://example.com',
38
+ registered: true,
39
+ };
40
+
41
+ webex.internal.services = {
42
+ convertUrlToPriorityHostUrl: sinon.stub().returns('ws://example.com'),
43
+ markFailedUrl: sinon.stub().resolves(),
44
+ isValidHost: sinon.stub().returns(true),
45
+ };
46
+
47
+ webex.internal.newMetrics = {
48
+ callDiagnosticMetrics: {
49
+ setMercuryConnectedStatus: sinon.stub(),
50
+ },
51
+ };
52
+
53
+ webex.config.mercury = mercuryConfig.mercury;
54
+
55
+ mercuryPlugin = webex.internal.mercury;
56
+ });
57
+
58
+ afterEach(() => {
59
+ sinon.restore();
60
+ });
61
+
62
+ describe('#constructor()', () => {
63
+ it('creates an instance with namespace Mercury', () => {
64
+ assert.equal(mercuryPlugin.namespace, 'Mercury');
65
+ });
66
+
67
+ it('has an internal Mercury instance', () => {
68
+ assert.isDefined(mercuryPlugin._mercury);
69
+ });
70
+ });
71
+
72
+ describe('#connected', () => {
73
+ it('returns false when Mercury is not connected', () => {
74
+ assert.equal(mercuryPlugin.connected, false);
75
+ });
76
+
77
+ it('returns true when Mercury is connected', () => {
78
+ mercuryPlugin._mercury.connected = true;
79
+ assert.equal(mercuryPlugin.connected, true);
80
+ });
81
+
82
+ it('returns false when _mercury is undefined', () => {
83
+ mercuryPlugin._mercury = undefined;
84
+ assert.equal(mercuryPlugin.connected, false);
85
+ });
86
+ });
87
+
88
+ describe('#socket', () => {
89
+ it('returns undefined when no socket exists', () => {
90
+ assert.isUndefined(mercuryPlugin.socket);
91
+ });
92
+
93
+ it('returns the socket when connected', () => {
94
+ const mockSocket = {url: 'ws://test.com'};
95
+ mercuryPlugin._mercury.socket = mockSocket;
96
+ assert.equal(mercuryPlugin.socket, mockSocket);
97
+ });
98
+ });
99
+
100
+ describe('#localClusterServiceUrls', () => {
101
+ it('returns undefined when not set', () => {
102
+ assert.isUndefined(mercuryPlugin.localClusterServiceUrls);
103
+ });
104
+
105
+ it('returns the localClusterServiceUrls when set', () => {
106
+ const urls = {mercuryConnectionServiceClusterUrl: 'https://mercury.example.com'};
107
+ mercuryPlugin._mercury.localClusterServiceUrls = urls;
108
+ assert.deepEqual(mercuryPlugin.localClusterServiceUrls, urls);
109
+ });
110
+
111
+ it('returns undefined when _mercury is undefined', () => {
112
+ mercuryPlugin._mercury = undefined;
113
+ assert.isUndefined(mercuryPlugin.localClusterServiceUrls);
114
+ });
115
+ });
116
+
117
+ describe('#getLastError()', () => {
118
+ it('returns undefined when no error occurred', () => {
119
+ assert.isUndefined(mercuryPlugin.getLastError());
120
+ });
121
+
122
+ it('returns the last error when one occurred', () => {
123
+ const error = new Error('test error');
124
+ mercuryPlugin._mercury.lastError = error;
125
+ assert.equal(mercuryPlugin.getLastError(), error);
126
+ });
127
+ });
128
+
129
+ describe('#hasEverConnected', () => {
130
+ it('returns false when never connected', () => {
131
+ assert.equal(mercuryPlugin.hasEverConnected, false);
132
+ });
133
+
134
+ it('returns true when has connected before', () => {
135
+ mercuryPlugin._mercury.hasEverConnected = true;
136
+ assert.equal(mercuryPlugin.hasEverConnected, true);
137
+ });
138
+
139
+ it('returns false when _mercury is undefined', () => {
140
+ mercuryPlugin._mercury = undefined;
141
+ assert.equal(mercuryPlugin.hasEverConnected, false);
142
+ });
143
+ });
144
+
145
+ describe('#connect()', () => {
146
+ it('delegates to Mercury.connect()', () => {
147
+ const connectStub = sinon.stub(mercuryPlugin._mercury, 'connect').resolves();
148
+ const webSocketUrl = 'ws://custom.com';
149
+
150
+ mercuryPlugin.connect(webSocketUrl);
151
+
152
+ sinon.assert.calledOnceWithExactly(connectStub, webSocketUrl);
153
+ });
154
+
155
+ it('calls connect without URL when none provided', () => {
156
+ const connectStub = sinon.stub(mercuryPlugin._mercury, 'connect').resolves();
157
+
158
+ mercuryPlugin.connect();
159
+
160
+ sinon.assert.calledOnceWithExactly(connectStub, undefined);
161
+ });
162
+ });
163
+
164
+ describe('#disconnect()', () => {
165
+ it('delegates to Mercury.disconnect()', () => {
166
+ const disconnectStub = sinon.stub(mercuryPlugin._mercury, 'disconnect').resolves();
167
+ const options = {code: 1000, reason: 'test'};
168
+
169
+ mercuryPlugin.disconnect(options);
170
+
171
+ sinon.assert.calledOnceWithExactly(disconnectStub, options);
172
+ });
173
+
174
+ it('calls disconnect without options when none provided', () => {
175
+ const disconnectStub = sinon.stub(mercuryPlugin._mercury, 'disconnect').resolves();
176
+
177
+ mercuryPlugin.disconnect();
178
+
179
+ sinon.assert.calledOnceWithExactly(disconnectStub, undefined);
180
+ });
181
+ });
182
+
183
+ describe('#logout()', () => {
184
+ it('calls disconnect with code 3050 when reason is not a normal reconnect reason', () => {
185
+ const disconnectStub = sinon.stub(mercuryPlugin._mercury, 'disconnect').resolves();
186
+ mercuryPlugin.config.beforeLogoutOptionsCloseReason = 'done (permanent)';
187
+
188
+ mercuryPlugin.logout();
189
+
190
+ sinon.assert.calledOnceWithExactly(disconnectStub, {
191
+ code: 3050,
192
+ reason: 'done (permanent)',
193
+ });
194
+ });
195
+
196
+ it('calls disconnect with undefined when reason is a normal reconnect reason', () => {
197
+ const disconnectStub = sinon.stub(mercuryPlugin._mercury, 'disconnect').resolves();
198
+ mercuryPlugin.config.beforeLogoutOptionsCloseReason = 'idle';
199
+
200
+ mercuryPlugin.logout();
201
+
202
+ sinon.assert.calledOnceWithExactly(disconnectStub, undefined);
203
+ });
204
+
205
+ it('calls disconnect with undefined when no reason configured', () => {
206
+ const disconnectStub = sinon.stub(mercuryPlugin._mercury, 'disconnect').resolves();
207
+ mercuryPlugin.config.beforeLogoutOptionsCloseReason = undefined;
208
+
209
+ mercuryPlugin.logout();
210
+
211
+ sinon.assert.calledOnceWithExactly(disconnectStub, undefined);
212
+ });
213
+
214
+ [
215
+ {reason: 'idle', expectUndefined: true},
216
+ {reason: 'done (forced)', expectUndefined: true},
217
+ {reason: 'pong not received', expectUndefined: true},
218
+ {reason: 'pong mismatch', expectUndefined: true},
219
+ {reason: 'custom reason', expectUndefined: false},
220
+ {reason: 'done (permanent)', expectUndefined: false},
221
+ ].forEach(({reason, expectUndefined}) => {
222
+ it(`calls disconnect with ${expectUndefined ? 'undefined' : 'code 3050'} for reason "${reason}"`, () => {
223
+ const disconnectStub = sinon.stub(mercuryPlugin._mercury, 'disconnect').resolves();
224
+ mercuryPlugin.config.beforeLogoutOptionsCloseReason = reason;
225
+
226
+ mercuryPlugin.logout();
227
+
228
+ if (expectUndefined) {
229
+ sinon.assert.calledOnceWithExactly(disconnectStub, undefined);
230
+ } else {
231
+ sinon.assert.calledOnceWithExactly(disconnectStub, {code: 3050, reason});
232
+ }
233
+ });
234
+ });
235
+ });
236
+
237
+ describe('#processRegistrationStatusEvent()', () => {
238
+ it('delegates to Mercury.processRegistrationStatusEvent()', () => {
239
+ const processStub = sinon
240
+ .stub(mercuryPlugin._mercury, 'processRegistrationStatusEvent')
241
+ .returns();
242
+ const message = {localClusterServiceUrls: {test: 'url'}};
243
+
244
+ mercuryPlugin.processRegistrationStatusEvent(message);
245
+
246
+ sinon.assert.calledOnceWithExactly(processStub, message);
247
+ });
248
+ });
249
+
250
+ describe('event re-emission', () => {
251
+ it('re-emits events from Mercury to the plugin', (done) => {
252
+ const testData = {test: 'data'};
253
+
254
+ mercuryPlugin.on('event:test', (data) => {
255
+ assert.deepEqual(data, testData);
256
+ done();
257
+ });
258
+
259
+ mercuryPlugin._mercury.trigger('event:test', testData);
260
+ });
261
+
262
+ it('re-emits online event', (done) => {
263
+ mercuryPlugin.on('online', () => {
264
+ done();
265
+ });
266
+
267
+ mercuryPlugin._mercury.trigger('online');
268
+ });
269
+
270
+ it('re-emits offline event', (done) => {
271
+ mercuryPlugin.on('offline', (event) => {
272
+ assert.deepEqual(event, {code: 1000, reason: 'test'});
273
+ done();
274
+ });
275
+
276
+ mercuryPlugin._mercury.trigger('offline', {code: 1000, reason: 'test'});
277
+ });
278
+ });
279
+ });
280
+ });