@webex/webex-core 3.8.1 → 3.9.0-multi-llms.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.
- package/README.md +87 -27
- package/dist/index.js +16 -33
- package/dist/index.js.map +1 -1
- package/dist/{lib/services/interceptors/hostmap.js → interceptors/proxy.js} +58 -25
- package/dist/interceptors/proxy.js.map +1 -0
- package/dist/lib/batcher.js +1 -1
- package/dist/lib/constants.js +10 -1
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/credentials/credentials.js +1 -1
- package/dist/lib/credentials/token.js +1 -1
- package/dist/lib/{services-v2/interceptors → interceptors}/server-error.js +1 -1
- package/dist/lib/interceptors/server-error.js.map +1 -0
- package/dist/lib/services/index.js +2 -29
- package/dist/lib/services/index.js.map +1 -1
- package/dist/lib/services/service-host.js +1 -1
- package/dist/lib/services/service-host.js.map +1 -1
- package/dist/lib/services/service-registry.js +1 -1
- package/dist/lib/services/service-registry.js.map +1 -1
- package/dist/lib/services/service-state.js +1 -1
- package/dist/lib/services/service-state.js.map +1 -1
- package/dist/lib/services/services.js +3 -3
- package/dist/lib/services/services.js.map +1 -1
- package/dist/lib/services-v2/index.js +0 -29
- package/dist/lib/services-v2/index.js.map +1 -1
- package/dist/lib/services-v2/metrics.js.map +1 -1
- package/dist/lib/services-v2/service-catalog.js +15 -11
- package/dist/lib/services-v2/service-catalog.js.map +1 -1
- package/dist/lib/services-v2/services-v2.js +160 -111
- package/dist/lib/services-v2/services-v2.js.map +1 -1
- package/dist/lib/services-v2/types.js.map +1 -1
- package/dist/plugins/logger.js +1 -1
- package/dist/webex-core.js +53 -60
- package/dist/webex-core.js.map +1 -1
- package/package.json +14 -14
- package/src/index.js +6 -14
- package/src/interceptors/proxy.js +70 -0
- package/src/lib/constants.js +29 -1
- package/src/lib/{services/interceptors → interceptors}/server-error.js +1 -1
- package/src/lib/services/index.js +2 -7
- package/src/lib/services/service-host.js +1 -1
- package/src/lib/services/service-registry.js +1 -1
- package/src/lib/services/service-state.js +1 -1
- package/src/lib/services/services.js +2 -2
- package/src/lib/services-v2/index.ts +0 -16
- package/src/lib/services-v2/service-catalog.ts +27 -19
- package/src/lib/services-v2/{services-v2.js → services-v2.ts} +188 -104
- package/src/lib/services-v2/types.ts +62 -2
- package/src/webex-core.js +12 -3
- package/test/fixtures/host-catalog-v2.ts +30 -122
- package/test/integration/spec/services/services.js +11 -0
- package/test/integration/spec/services-v2/service-catalog.js +664 -0
- package/test/integration/spec/services-v2/services-v2.js +1136 -0
- package/test/unit/spec/interceptors/proxy.js +73 -0
- package/test/unit/spec/services-v2/service-detail.ts +1 -1
- package/test/unit/spec/services-v2/services-v2.ts +579 -442
- package/test/unit/spec/webex-core.js +62 -2
- package/dist/lib/services/constants.js +0 -17
- package/dist/lib/services/constants.js.map +0 -1
- package/dist/lib/services/interceptors/hostmap.js.map +0 -1
- package/dist/lib/services/interceptors/server-error.js +0 -77
- package/dist/lib/services/interceptors/server-error.js.map +0 -1
- package/dist/lib/services/interceptors/service.js +0 -137
- package/dist/lib/services/interceptors/service.js.map +0 -1
- package/dist/lib/services-v2/constants.js +0 -17
- package/dist/lib/services-v2/constants.js.map +0 -1
- package/dist/lib/services-v2/interceptors/server-error.js.map +0 -1
- package/dist/lib/services-v2/service-host.js +0 -300
- package/dist/lib/services-v2/service-host.js.map +0 -1
- package/dist/lib/services-v2/service-registry.js +0 -534
- package/dist/lib/services-v2/service-registry.js.map +0 -1
- package/dist/lib/services-v2/service-state.js +0 -97
- package/dist/lib/services-v2/service-state.js.map +0 -1
- package/dist/lib/services-v2/service-url.js +0 -119
- package/dist/lib/services-v2/service-url.js.map +0 -1
- package/src/lib/services/constants.js +0 -21
- package/src/lib/services/interceptors/hostmap.js +0 -36
- package/src/lib/services/interceptors/service.js +0 -101
- package/src/lib/services-v2/constants.ts +0 -21
- package/src/lib/services-v2/interceptors/server-error.js +0 -48
- /package/dist/lib/{services-v2/interceptors → interceptors}/hostmap.js +0 -0
- /package/dist/lib/{services-v2/interceptors → interceptors}/hostmap.js.map +0 -0
- /package/dist/lib/{services-v2/interceptors → interceptors}/service.js +0 -0
- /package/dist/lib/{services-v2/interceptors → interceptors}/service.js.map +0 -0
- /package/dist/lib/{services/metrics.js → metrics.js} +0 -0
- /package/dist/lib/{services/metrics.js.map → metrics.js.map} +0 -0
- /package/src/lib/{services-v2/interceptors → interceptors}/hostmap.js +0 -0
- /package/src/lib/{services-v2/interceptors → interceptors}/service.js +0 -0
- /package/src/lib/{services-v2/metrics.js → metrics.js} +0 -0
- /package/src/lib/{services/metrics.js → services-v2/metrics.ts} +0 -0
|
@@ -23,7 +23,7 @@ describe('webex-core', () => {
|
|
|
23
23
|
let catalog;
|
|
24
24
|
|
|
25
25
|
beforeEach(() => {
|
|
26
|
-
webex =
|
|
26
|
+
webex = MockWebex({
|
|
27
27
|
children: {
|
|
28
28
|
services: ServicesV2,
|
|
29
29
|
newMetrics: NewMetrics,
|
|
@@ -33,294 +33,293 @@ describe('webex-core', () => {
|
|
|
33
33
|
catalog = services._getCatalog();
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// services.initialize();
|
|
47
|
-
|
|
48
|
-
// // call the onReady callback
|
|
49
|
-
// services.listenToOnce.getCall(1).args[2]();
|
|
50
|
-
// await waitForAsync();
|
|
51
|
-
|
|
52
|
-
// assert.isFalse(services.initFailed);
|
|
53
|
-
// });
|
|
54
|
-
|
|
55
|
-
// it('initFailed is false when initialization succeeds no credentials are available', async () => {
|
|
56
|
-
// services.listenToOnce = sinon.stub();
|
|
57
|
-
// services.collectPreauthCatalog = sinon.stub().returns(Promise.resolve());
|
|
58
|
-
|
|
59
|
-
// services.initialize();
|
|
60
|
-
|
|
61
|
-
// // call the onReady callback
|
|
62
|
-
// services.listenToOnce.getCall(1).args[2]();
|
|
63
|
-
// await waitForAsync();
|
|
64
|
-
|
|
65
|
-
// assert.isFalse(services.initFailed);
|
|
66
|
-
// });
|
|
67
|
-
|
|
68
|
-
// it.each([
|
|
69
|
-
// {error: new Error('failed'), expectedMessage: 'failed'},
|
|
70
|
-
// {error: undefined, expectedMessage: undefined},
|
|
71
|
-
// ])(
|
|
72
|
-
// 'sets initFailed to true when collectPreauthCatalog errors',
|
|
73
|
-
// async ({error, expectedMessage}) => {
|
|
74
|
-
// services.collectPreauthCatalog = sinon.stub().callsFake(() => {
|
|
75
|
-
// return Promise.reject(error);
|
|
76
|
-
// });
|
|
36
|
+
describe('#initialize', () => {
|
|
37
|
+
it('initFailed is false when initialization succeeds and credentials are available', async () => {
|
|
38
|
+
services.listenToOnce = sinon.stub();
|
|
39
|
+
services.initServiceCatalogs = sinon.stub().returns(Promise.resolve());
|
|
40
|
+
services.webex.credentials = {
|
|
41
|
+
supertoken: {
|
|
42
|
+
access_token: 'token',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
77
45
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
46
|
+
services.initialize();
|
|
47
|
+
|
|
48
|
+
// call the onReady callback
|
|
49
|
+
services.listenToOnce.getCall(1).args[2]();
|
|
50
|
+
await waitForAsync();
|
|
51
|
+
|
|
52
|
+
assert.isFalse(services.initFailed);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('initFailed is false when initialization succeeds no credentials are available', async () => {
|
|
56
|
+
services.listenToOnce = sinon.stub();
|
|
57
|
+
services.collectPreauthCatalog = sinon.stub().returns(Promise.resolve());
|
|
58
|
+
|
|
59
|
+
services.initialize();
|
|
60
|
+
|
|
61
|
+
// call the onReady callback
|
|
62
|
+
services.listenToOnce.getCall(1).args[2]();
|
|
63
|
+
await waitForAsync();
|
|
64
|
+
|
|
65
|
+
assert.isFalse(services.initFailed);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it.each([
|
|
69
|
+
{error: new Error('failed'), expectedMessage: 'failed'},
|
|
70
|
+
{error: undefined, expectedMessage: undefined},
|
|
71
|
+
])(
|
|
72
|
+
'sets initFailed to true when collectPreauthCatalog errors',
|
|
73
|
+
async ({error, expectedMessage}) => {
|
|
74
|
+
services.collectPreauthCatalog = sinon.stub().callsFake(() => {
|
|
75
|
+
return Promise.reject(error);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
services.listenToOnce = sinon.stub();
|
|
79
|
+
services.logger.error = sinon.stub();
|
|
80
|
+
|
|
81
|
+
services.initialize();
|
|
82
|
+
|
|
83
|
+
// call the onReady callback
|
|
84
|
+
services.listenToOnce.getCall(1).args[2]();
|
|
85
|
+
|
|
86
|
+
await waitForAsync();
|
|
87
|
+
|
|
88
|
+
assert.isTrue(services.initFailed);
|
|
89
|
+
sinon.assert.calledWith(
|
|
90
|
+
services.logger.error,
|
|
91
|
+
`services: failed to init initial services when no credentials available, ${expectedMessage}`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
it.each([
|
|
97
|
+
{error: new Error('failed'), expectedMessage: 'failed'},
|
|
98
|
+
{error: undefined, expectedMessage: undefined},
|
|
99
|
+
])(
|
|
100
|
+
'sets initFailed to true when initServiceCatalogs errors',
|
|
101
|
+
async ({error, expectedMessage}) => {
|
|
102
|
+
services.initServiceCatalogs = sinon.stub().callsFake(() => {
|
|
103
|
+
return Promise.reject(error);
|
|
104
|
+
});
|
|
105
|
+
services.webex.credentials = {
|
|
106
|
+
supertoken: {
|
|
107
|
+
access_token: 'token',
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
services.listenToOnce = sinon.stub();
|
|
112
|
+
services.logger.error = sinon.stub();
|
|
113
|
+
|
|
114
|
+
services.initialize();
|
|
115
|
+
|
|
116
|
+
// call the onReady callback
|
|
117
|
+
services.listenToOnce.getCall(1).args[2]();
|
|
118
|
+
|
|
119
|
+
await waitForAsync();
|
|
120
|
+
|
|
121
|
+
assert.isTrue(services.initFailed);
|
|
122
|
+
sinon.assert.calledWith(
|
|
123
|
+
services.logger.error,
|
|
124
|
+
`services: failed to init initial services when credentials available, ${expectedMessage}`
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe('#initServiceCatalogs', () => {
|
|
131
|
+
it('does not set initFailed to true when updateServices succeeds', async () => {
|
|
132
|
+
services.webex.credentials = {
|
|
133
|
+
getOrgId: sinon.stub().returns('orgId'),
|
|
134
|
+
canAuthorize: true,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
services.collectPreauthCatalog = sinon.stub().callsFake(() => {
|
|
138
|
+
return Promise.resolve();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
services.updateServices = sinon.stub().callsFake(() => {
|
|
142
|
+
return Promise.resolve();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
services.logger.error = sinon.stub();
|
|
146
|
+
|
|
147
|
+
await services.initServiceCatalogs();
|
|
148
|
+
|
|
149
|
+
assert.isFalse(services.initFailed);
|
|
150
|
+
|
|
151
|
+
sinon.assert.calledWith(services.collectPreauthCatalog, {orgId: 'orgId'});
|
|
152
|
+
sinon.assert.notCalled(services.logger.warn);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('sets initFailed to true when updateServices errors', async () => {
|
|
156
|
+
const error = new Error('failed');
|
|
157
|
+
|
|
158
|
+
services.webex.credentials = {
|
|
159
|
+
getOrgId: sinon.stub().returns('orgId'),
|
|
160
|
+
canAuthorize: true,
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
services.collectPreauthCatalog = sinon.stub().callsFake(() => {
|
|
164
|
+
return Promise.resolve();
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
services.updateServices = sinon.stub().callsFake(() => {
|
|
168
|
+
return Promise.reject(error);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
services.logger.error = sinon.stub();
|
|
172
|
+
|
|
173
|
+
await services.initServiceCatalogs();
|
|
174
|
+
|
|
175
|
+
assert.isTrue(services.initFailed);
|
|
176
|
+
|
|
177
|
+
sinon.assert.calledWith(services.collectPreauthCatalog, {orgId: 'orgId'});
|
|
178
|
+
sinon.assert.calledWith(services.logger.warn, 'services: cannot retrieve postauth catalog');
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe('#namespace', () => {
|
|
183
|
+
it('is accurate to plugin name', () => {
|
|
184
|
+
assert.equal(services.namespace, 'Services');
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('#_catalogs', () => {
|
|
189
|
+
it('is a weakmap', () => {
|
|
190
|
+
assert.typeOf(services._catalogs, 'weakmap');
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
describe('#validateDomains', () => {
|
|
195
|
+
it('is a boolean', () => {
|
|
196
|
+
assert.isBoolean(services.validateDomains);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
describe('#initFailed', () => {
|
|
201
|
+
it('is a boolean', () => {
|
|
202
|
+
assert.isFalse(services.initFailed);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
describe('#fetchClientRegionInfo', () => {
|
|
207
|
+
beforeEach(() => {
|
|
208
|
+
services.webex.config = {
|
|
209
|
+
services: {
|
|
210
|
+
discovery: {
|
|
211
|
+
sqdiscovery: 'https://test.ciscospark.com/v1/region',
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('successfully resolves with undefined if fetch request failed', () => {
|
|
218
|
+
webex.request = sinon.stub().returns(Promise.reject());
|
|
219
|
+
|
|
220
|
+
return services.fetchClientRegionInfo().then((r) => {
|
|
221
|
+
assert.isUndefined(r);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('successfully resolves with true if fetch request succeeds', () => {
|
|
226
|
+
webex.request = sinon.stub().returns(Promise.resolve({body: true}));
|
|
227
|
+
|
|
228
|
+
return services.fetchClientRegionInfo().then((r) => {
|
|
229
|
+
assert.equal(r, true);
|
|
230
|
+
assert.calledWith(webex.request, {
|
|
231
|
+
uri: 'https://test.ciscospark.com/v1/region',
|
|
232
|
+
addAuthHeader: false,
|
|
233
|
+
headers: {'spark-user-agent': null},
|
|
234
|
+
timeout: 5000,
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
describe('#getMeetingPreferences', () => {
|
|
241
|
+
it('Fetch login users information ', async () => {
|
|
242
|
+
const userPreferences = {userPreferences: 'userPreferences'};
|
|
243
|
+
|
|
244
|
+
webex.request = sinon.stub().returns(Promise.resolve({body: userPreferences}));
|
|
245
|
+
|
|
246
|
+
const res = await services.getMeetingPreferences();
|
|
247
|
+
|
|
248
|
+
assert.calledWith(webex.request, {
|
|
249
|
+
method: 'GET',
|
|
250
|
+
service: 'hydra',
|
|
251
|
+
resource: 'meetingPreferences',
|
|
252
|
+
});
|
|
253
|
+
assert.isDefined(res);
|
|
254
|
+
assert.equal(res, userPreferences);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('Resolve getMeetingPreferences if the api request fails ', async () => {
|
|
258
|
+
webex.request = sinon.stub().returns(Promise.reject());
|
|
259
|
+
|
|
260
|
+
const res = await services.getMeetingPreferences();
|
|
261
|
+
|
|
262
|
+
assert.calledWith(webex.request, {
|
|
263
|
+
method: 'GET',
|
|
264
|
+
service: 'hydra',
|
|
265
|
+
resource: 'meetingPreferences',
|
|
266
|
+
});
|
|
267
|
+
assert.isUndefined(res);
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
describe('#switchActiveClusterIds', () => {
|
|
272
|
+
let serviceHostmap;
|
|
273
|
+
let formattedHM;
|
|
274
|
+
|
|
275
|
+
beforeEach(() => {
|
|
276
|
+
serviceHostmap = serviceHostmapV2;
|
|
277
|
+
formattedHM = services._formatReceivedHostmap(serviceHostmap);
|
|
278
|
+
|
|
279
|
+
services.initServiceCatalogs = sinon.stub().returns(Promise.resolve());
|
|
280
|
+
services.webex.credentials = {
|
|
281
|
+
getOrgId: sinon.stub().returns('')
|
|
282
|
+
};
|
|
283
|
+
catalog.status = {};
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('switches properly when id exists', async () => {
|
|
287
|
+
services._updateActiveServices = sinon.stub().callsFake((data) => {
|
|
288
|
+
Object.assign(services._activeServices, data);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
await services.switchActiveClusterIds({
|
|
292
|
+
conversation: 'urn:TEAM:me-central-1_d:conversation',
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
296
|
+
|
|
297
|
+
assert.calledWith(services._updateActiveServices, {
|
|
298
|
+
conversation: 'urn:TEAM:me-central-1_d:conversation',
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
assert.equal(services._activeServices.conversation, 'urn:TEAM:me-central-1_d:conversation');
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('makes request to fetch when id does not exist', async () => {
|
|
305
|
+
services._updateActiveServices = sinon.stub().callsFake((data) => {
|
|
306
|
+
Object.assign(services._activeServices, data);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
await services.switchActiveClusterIds({
|
|
310
|
+
conversation: 'urn:TEAM:me-central-1_asdf:conversation',
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
314
|
+
});
|
|
315
|
+
});
|
|
317
316
|
|
|
318
317
|
describe('#updateCatalog', () => {
|
|
319
318
|
it('updates the catalog', async () => {
|
|
320
319
|
const serviceGroup = 'postauth';
|
|
321
|
-
const hostmap = [{hostmap: 'hostmap'}];
|
|
320
|
+
const hostmap = {services: [{hostmap: 'hostmap'}]};
|
|
322
321
|
|
|
323
|
-
services._formatReceivedHostmap = sinon.stub().returns([{some: 'hostmap'}]);
|
|
322
|
+
services._formatReceivedHostmap = sinon.stub().returns({services : [{some: 'hostmap'}]});
|
|
324
323
|
|
|
325
324
|
catalog.updateServiceGroups = sinon.stub().returns(Promise.resolve([{some: 'value'}]));
|
|
326
325
|
|
|
@@ -334,118 +333,107 @@ describe('webex-core', () => {
|
|
|
334
333
|
});
|
|
335
334
|
});
|
|
336
335
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
// priority: 5,
|
|
439
|
-
// id: '0:0:0:example',
|
|
440
|
-
// },
|
|
441
|
-
// ],
|
|
442
|
-
// };
|
|
443
|
-
|
|
444
|
-
// const uri = 'http://example.com/somepath';
|
|
445
|
-
|
|
446
|
-
// assert.equal(services.replaceHostFromHostmap(uri), 'http://example-1.com/somepath');
|
|
447
|
-
// });
|
|
448
|
-
// });
|
|
336
|
+
describe('#_fetchNewServiceHostmap()', () => {
|
|
337
|
+
beforeEach(() => {
|
|
338
|
+
sinon.spy(webex.internal.newMetrics.callDiagnosticLatencies, 'measureLatency');
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
afterEach(() => {
|
|
342
|
+
sinon.restore();
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it('checks service request resolves', async () => {
|
|
346
|
+
const mapResponse = 'map response';
|
|
347
|
+
|
|
348
|
+
sinon.stub(services, '_formatReceivedHostmap').resolves(mapResponse);
|
|
349
|
+
sinon.stub(services, 'request').resolves({});
|
|
350
|
+
|
|
351
|
+
const mapResult = await services._fetchNewServiceHostmap({from: 'limited'});
|
|
352
|
+
|
|
353
|
+
assert.deepEqual(mapResult, mapResponse);
|
|
354
|
+
|
|
355
|
+
assert.calledOnceWithExactly(services.request, {
|
|
356
|
+
method: 'GET',
|
|
357
|
+
service: 'u2c',
|
|
358
|
+
resource: '/limited/catalog',
|
|
359
|
+
qs: {format: 'U2CV2'},
|
|
360
|
+
headers: {},
|
|
361
|
+
});
|
|
362
|
+
assert.calledOnceWithExactly(
|
|
363
|
+
webex.internal.newMetrics.callDiagnosticLatencies.measureLatency,
|
|
364
|
+
sinon.match.func,
|
|
365
|
+
'internal.get.u2c.time'
|
|
366
|
+
);
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('checks service request rejects', async () => {
|
|
370
|
+
const error = new Error('some error');
|
|
371
|
+
|
|
372
|
+
sinon.spy(services, '_formatReceivedHostmap');
|
|
373
|
+
sinon.stub(services, 'request').rejects(error);
|
|
374
|
+
|
|
375
|
+
const promise = services._fetchNewServiceHostmap({from: 'limited'});
|
|
376
|
+
const rejectedValue = await assert.isRejected(promise);
|
|
377
|
+
|
|
378
|
+
assert.deepEqual(rejectedValue, error);
|
|
379
|
+
|
|
380
|
+
assert.notCalled(services._formatReceivedHostmap);
|
|
381
|
+
|
|
382
|
+
assert.calledOnceWithExactly(services.request, {
|
|
383
|
+
method: 'GET',
|
|
384
|
+
service: 'u2c',
|
|
385
|
+
resource: '/limited/catalog',
|
|
386
|
+
qs: {format: 'U2CV2'},
|
|
387
|
+
headers: {},
|
|
388
|
+
});
|
|
389
|
+
assert.calledOnceWithExactly(
|
|
390
|
+
webex.internal.newMetrics.callDiagnosticLatencies.measureLatency,
|
|
391
|
+
sinon.match.func,
|
|
392
|
+
'internal.get.u2c.time'
|
|
393
|
+
);
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
describe('replaceHostFromHostmap', () => {
|
|
398
|
+
it('returns the same uri if the hostmap is not set', () => {
|
|
399
|
+
services._hostCatalog = null;
|
|
400
|
+
|
|
401
|
+
const uri = 'http://example.com';
|
|
402
|
+
|
|
403
|
+
assert.equal(services.replaceHostFromHostmap(uri), uri);
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
it('returns the same uri if the hostmap does not contain the host', () => {
|
|
407
|
+
catalog.updateServiceGroups('preauth', [
|
|
408
|
+
{
|
|
409
|
+
id: 'example-1',
|
|
410
|
+
serviceName: 'example-1',
|
|
411
|
+
serviceUrls: [{host: 'example-1.com', baseUrl: 'http://example-1.com', priority: 1}],
|
|
412
|
+
},
|
|
413
|
+
]);
|
|
414
|
+
|
|
415
|
+
const uri = 'http://example.com';
|
|
416
|
+
|
|
417
|
+
assert.equal(services.replaceHostFromHostmap(uri), uri);
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it('returns the replaces the host in the uri with the host from the hostmap', () => {
|
|
421
|
+
catalog.updateServiceGroups('preauth', [
|
|
422
|
+
{
|
|
423
|
+
id: 'example-1',
|
|
424
|
+
serviceName: 'example-1',
|
|
425
|
+
serviceUrls: [
|
|
426
|
+
{host: 'example-1.com', baseUrl: 'http://example-1.com', priority: 1},
|
|
427
|
+
{host: 'example.com', baseUrl: 'http://example.com', priority: 2},
|
|
428
|
+
],
|
|
429
|
+
},
|
|
430
|
+
]);
|
|
431
|
+
|
|
432
|
+
const uri = 'http://example.com/somepath';
|
|
433
|
+
|
|
434
|
+
assert.equal(services.replaceHostFromHostmap(uri), 'http://example-1.com/somepath');
|
|
435
|
+
});
|
|
436
|
+
});
|
|
449
437
|
|
|
450
438
|
describe('#_formatReceivedHostmap()', () => {
|
|
451
439
|
let serviceHostmap;
|
|
@@ -459,7 +447,7 @@ describe('webex-core', () => {
|
|
|
459
447
|
formattedHM = services._formatReceivedHostmap(serviceHostmap);
|
|
460
448
|
|
|
461
449
|
assert(
|
|
462
|
-
serviceHostmap.services.length >= formattedHM.length,
|
|
450
|
+
serviceHostmap.services.length >= formattedHM.services.length,
|
|
463
451
|
'length is not equal or less than'
|
|
464
452
|
);
|
|
465
453
|
});
|
|
@@ -467,7 +455,7 @@ describe('webex-core', () => {
|
|
|
467
455
|
it('has all keys in host map hosts', () => {
|
|
468
456
|
formattedHM = services._formatReceivedHostmap(serviceHostmap);
|
|
469
457
|
|
|
470
|
-
formattedHM.forEach((service) => {
|
|
458
|
+
formattedHM.services.forEach((service) => {
|
|
471
459
|
assert.hasAllKeys(
|
|
472
460
|
service,
|
|
473
461
|
['id', 'serviceName', 'serviceUrls'],
|
|
@@ -486,7 +474,7 @@ describe('webex-core', () => {
|
|
|
486
474
|
it('creates a formmated host map containing all received host map service entries', () => {
|
|
487
475
|
formattedHM = services._formatReceivedHostmap(serviceHostmap);
|
|
488
476
|
|
|
489
|
-
formattedHM.forEach((service) => {
|
|
477
|
+
formattedHM.services.forEach((service) => {
|
|
490
478
|
const foundServiceKey = Object.keys(serviceHostmap.activeServices).find(
|
|
491
479
|
(key) => service.serviceName === key
|
|
492
480
|
);
|
|
@@ -498,7 +486,7 @@ describe('webex-core', () => {
|
|
|
498
486
|
it('creates the expected formatted host map', () => {
|
|
499
487
|
formattedHM = services._formatReceivedHostmap(serviceHostmap);
|
|
500
488
|
|
|
501
|
-
assert.deepEqual(formattedHM, formattedServiceHostmapV2);
|
|
489
|
+
assert.deepEqual(formattedHM.services, formattedServiceHostmapV2);
|
|
502
490
|
});
|
|
503
491
|
|
|
504
492
|
it('has hostCatalog updated', () => {
|
|
@@ -515,48 +503,197 @@ describe('webex-core', () => {
|
|
|
515
503
|
});
|
|
516
504
|
});
|
|
517
505
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
506
|
+
describe('#updateCredentialsConfig()', () => {
|
|
507
|
+
// updateCredentialsConfig must remove `/` if exist. so expected serviceList must be.
|
|
508
|
+
const expectedServiceList = {
|
|
509
|
+
idbroker: 'https://idbroker.webex.com',
|
|
510
|
+
identity: 'https://identity.webex.com',
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
beforeEach(async () => {
|
|
514
|
+
const servicesList = [
|
|
515
|
+
{
|
|
516
|
+
id: 'idbroker',
|
|
517
|
+
name: 'idbroker',
|
|
518
|
+
serviceUrls: [
|
|
519
|
+
{baseUrl: 'https://idbroker.webex.com/', host: 'idbroker.webex.com', priority: 1},
|
|
520
|
+
],
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
id: 'identity',
|
|
524
|
+
name: 'identity',
|
|
525
|
+
serviceUrls: [
|
|
526
|
+
{baseUrl: 'https://identity.webex.com/', host: 'identity.webex.com', priority: 1},
|
|
527
|
+
],
|
|
528
|
+
},
|
|
529
|
+
];
|
|
530
|
+
|
|
531
|
+
catalog.updateServiceGroups('preauth', servicesList);
|
|
532
|
+
await services.updateCredentialsConfig();
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
it('sets the idbroker url properly when trailing slash is not present', () => {
|
|
536
|
+
assert.equal(webex.config.credentials.idbroker.url, expectedServiceList.idbroker);
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
it('sets the identity url properly when a trailing slash is present', () => {
|
|
540
|
+
assert.equal(webex.config.credentials.identity.url, expectedServiceList.identity);
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
it('sets the authorize url properly when authorization string is not provided', () => {
|
|
544
|
+
assert.equal(
|
|
545
|
+
webex.config.credentials.authorizeUrl,
|
|
546
|
+
`${expectedServiceList.idbroker}/idb/oauth2/v1/authorize`
|
|
547
|
+
);
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
it('should retain the authorize url property when authorization string is provided', () => {
|
|
551
|
+
const authUrl = 'http://example-auth-url.com/resource';
|
|
552
|
+
|
|
553
|
+
webex.config.credentials.authorizationString = authUrl;
|
|
554
|
+
webex.config.credentials.authorizeUrl = authUrl;
|
|
555
|
+
|
|
556
|
+
services.updateCredentialsConfig();
|
|
557
|
+
|
|
558
|
+
assert.equal(webex.config.credentials.authorizeUrl, authUrl);
|
|
559
|
+
});
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
describe('#invalidateCache', () => {
|
|
563
|
+
beforeEach( () => {
|
|
564
|
+
services.initServiceCatalogs = sinon.stub().returns(Promise.resolve());
|
|
565
|
+
services.webex.credentials = {
|
|
566
|
+
getOrgId: sinon.stub().returns('')
|
|
567
|
+
};
|
|
568
|
+
catalog.status = {};
|
|
569
|
+
})
|
|
570
|
+
it('should log the timestamp parameter', async () => {
|
|
571
|
+
const timestamp = '1234567890';
|
|
572
|
+
services.logger.info = sinon.stub();
|
|
573
|
+
services._getCatalog = sinon.stub().returns({timestamp: '1234567880'});
|
|
574
|
+
|
|
575
|
+
await services.invalidateCache(timestamp);
|
|
576
|
+
|
|
577
|
+
assert.calledWith(services.logger.info, 'services: invalidate cache, timestamp:', timestamp);
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
it('should call initServiceCatalogs when invalidate timestamp is newer than catalog timestamp', async () => {
|
|
581
|
+
const newTimestamp = '1234567890';
|
|
582
|
+
const oldTimestamp = '1234567880';
|
|
583
|
+
services.logger.info = sinon.stub();
|
|
584
|
+
services._getCatalog = sinon.stub().returns({timestamp: oldTimestamp});
|
|
585
|
+
|
|
586
|
+
await services.invalidateCache(newTimestamp);
|
|
587
|
+
|
|
588
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
589
|
+
assert.calledWith(services.logger.info, 'services: invalidateCache, refresh services');
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
it('should not call initServiceCatalogs when invalidate timestamp is older than catalog timestamp', async () => {
|
|
593
|
+
const oldTimestamp = '1234567880';
|
|
594
|
+
const newTimestamp = '1234567890';
|
|
595
|
+
services._getCatalog = sinon.stub().returns({timestamp: newTimestamp});
|
|
596
|
+
await services.invalidateCache(oldTimestamp);
|
|
597
|
+
|
|
598
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
it('should not call initServiceCatalogs when invalidate timestamp equals catalog timestamp', async () => {
|
|
602
|
+
const timestamp = '1234567890';
|
|
603
|
+
services._getCatalog = sinon.stub().returns({timestamp: timestamp});
|
|
604
|
+
|
|
605
|
+
await services.invalidateCache(timestamp);
|
|
606
|
+
|
|
607
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
it('should handle numeric timestamp strings correctly', async () => {
|
|
611
|
+
const newTimestamp = '1700000000';
|
|
612
|
+
const oldTimestamp = '1600000000';
|
|
613
|
+
services._getCatalog = sinon.stub().returns({timestamp: oldTimestamp});
|
|
614
|
+
|
|
615
|
+
await services.invalidateCache(newTimestamp);
|
|
616
|
+
|
|
617
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
it('should handle undefined catalog gracefully', async () => {
|
|
621
|
+
const timestamp = '1234567890';
|
|
622
|
+
services._getCatalog = sinon.stub().returns(undefined);
|
|
623
|
+
|
|
624
|
+
await services.invalidateCache(timestamp);
|
|
625
|
+
|
|
626
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
it('should handle catalog without timestamp gracefully', async () => {
|
|
630
|
+
const timestamp = '1234567890';
|
|
631
|
+
services._getCatalog = sinon.stub().returns({});
|
|
632
|
+
|
|
633
|
+
await services.invalidateCache(timestamp);
|
|
634
|
+
|
|
635
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
it('should handle null catalog timestamp gracefully', async () => {
|
|
639
|
+
const timestamp = '1234567890';
|
|
640
|
+
services._getCatalog = sinon.stub().returns({timestamp: null});
|
|
641
|
+
|
|
642
|
+
await services.invalidateCache(timestamp);
|
|
643
|
+
|
|
644
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
it('should handle undefined timestamp parameter gracefully', async () => {
|
|
648
|
+
services._getCatalog = sinon.stub().returns({timestamp: '1234567890'});
|
|
649
|
+
|
|
650
|
+
await services.invalidateCache(undefined);
|
|
651
|
+
|
|
652
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
it('should handle null timestamp parameter gracefully', async () => {
|
|
656
|
+
services._getCatalog = sinon.stub().returns({timestamp: '1234567890'});
|
|
657
|
+
|
|
658
|
+
await services.invalidateCache(null);
|
|
659
|
+
|
|
660
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
it('should handle empty string timestamp parameter gracefully', async () => {
|
|
664
|
+
services._getCatalog = sinon.stub().returns({timestamp: '1234567890'});
|
|
665
|
+
|
|
666
|
+
await services.invalidateCache('');
|
|
667
|
+
|
|
668
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
it('should handle non-numeric timestamp strings gracefully', async () => {
|
|
672
|
+
const invalidTimestamp = 'not-a-number';
|
|
673
|
+
services._getCatalog = sinon.stub().returns({timestamp: '1234567890'});
|
|
674
|
+
|
|
675
|
+
await services.invalidateCache(invalidTimestamp);
|
|
676
|
+
|
|
677
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
it('should handle non-numeric catalog timestamp gracefully', async () => {
|
|
681
|
+
const timestamp = '1234567890';
|
|
682
|
+
services._getCatalog = sinon.stub().returns({timestamp: 'not-a-number'});
|
|
683
|
+
|
|
684
|
+
await services.invalidateCache(timestamp);
|
|
685
|
+
|
|
686
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
it('should return a resolved Promise', async () => {
|
|
690
|
+
const timestamp = '1234567890';
|
|
691
|
+
services._getCatalog = sinon.stub().returns({timestamp: '1234567880'});
|
|
692
|
+
|
|
693
|
+
const result = await services.invalidateCache(timestamp);
|
|
694
|
+
|
|
695
|
+
assert.isUndefined(result);
|
|
696
|
+
});
|
|
697
|
+
});
|
|
561
698
|
});
|
|
562
699
|
});
|