@morgan-stanley/composeui-fdc3 0.1.0-alpha.5

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.
Files changed (75) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +6 -0
  3. package/jest.config.ts +23 -0
  4. package/package.json +49 -0
  5. package/rollup.config.js +16 -0
  6. package/src/ComposeUIChannel.spec.ts +242 -0
  7. package/src/ComposeUIContextListener.spec.ts +109 -0
  8. package/src/ComposeUIDesktopAgent.spec.ts +197 -0
  9. package/src/ComposeUIDesktopAgent.ts +252 -0
  10. package/src/ComposeUIIntentHandling.spec.ts +369 -0
  11. package/src/ComposeUIMessageRouterChannelFactory.spec.ts +200 -0
  12. package/src/ComposeUIMessageRouterMetadataClient.spec.ts +240 -0
  13. package/src/ComposeUIMessageRouterOpenClient.spec.ts +239 -0
  14. package/src/index.ts +66 -0
  15. package/src/infrastructure/ChannelFactory.ts +25 -0
  16. package/src/infrastructure/ChannelItem.ts +20 -0
  17. package/src/infrastructure/ChannelType.ts +14 -0
  18. package/src/infrastructure/ComposeUIChannel.ts +87 -0
  19. package/src/infrastructure/ComposeUIContextListener.ts +154 -0
  20. package/src/infrastructure/ComposeUIErrors.ts +21 -0
  21. package/src/infrastructure/ComposeUIIntentListener.ts +105 -0
  22. package/src/infrastructure/ComposeUIIntentResolution.ts +58 -0
  23. package/src/infrastructure/ComposeUIPrivateChannel.ts +197 -0
  24. package/src/infrastructure/ComposeUITopic.ts +155 -0
  25. package/src/infrastructure/IntentsClient.ts +22 -0
  26. package/src/infrastructure/MessageRouterChannelFactory.ts +182 -0
  27. package/src/infrastructure/MessageRouterIntentsClient.ts +125 -0
  28. package/src/infrastructure/MessageRouterMetadataClient.ts +75 -0
  29. package/src/infrastructure/MessageRouterOpenClient.ts +106 -0
  30. package/src/infrastructure/MetadataClient.ts +19 -0
  31. package/src/infrastructure/OpenAppIdentifier.ts +18 -0
  32. package/src/infrastructure/OpenClient.ts +18 -0
  33. package/src/infrastructure/PrivateChannelContextListenerEventListener.ts +45 -0
  34. package/src/infrastructure/PrivateChannelDisconnectEventListener.ts +45 -0
  35. package/src/infrastructure/messages/Fdc3AddContextListenerRequest.ts +22 -0
  36. package/src/infrastructure/messages/Fdc3AddContextListenerResponse.ts +17 -0
  37. package/src/infrastructure/messages/Fdc3CreateAppChannelRequest.ts +17 -0
  38. package/src/infrastructure/messages/Fdc3CreateAppChannelResponse.ts +17 -0
  39. package/src/infrastructure/messages/Fdc3CreatePrivateChannelRequest.ts +16 -0
  40. package/src/infrastructure/messages/Fdc3CreatePrivateChannelResponse.ts +17 -0
  41. package/src/infrastructure/messages/Fdc3FindChannelRequest.ts +24 -0
  42. package/src/infrastructure/messages/Fdc3FindChannelResponse.ts +17 -0
  43. package/src/infrastructure/messages/Fdc3FindInstancesRequest.ts +17 -0
  44. package/src/infrastructure/messages/Fdc3FindInstancesResponse.ts +18 -0
  45. package/src/infrastructure/messages/Fdc3FindIntentRequest.ts +24 -0
  46. package/src/infrastructure/messages/Fdc3FindIntentResponse.ts +19 -0
  47. package/src/infrastructure/messages/Fdc3FindIntentsByContextRequest.ts +23 -0
  48. package/src/infrastructure/messages/Fdc3FindIntentsByContextResponse.ts +19 -0
  49. package/src/infrastructure/messages/Fdc3GetAppMetadataRequest.ts +17 -0
  50. package/src/infrastructure/messages/Fdc3GetAppMetadataResponse.ts +18 -0
  51. package/src/infrastructure/messages/Fdc3GetCurrentContextRequest.ts +18 -0
  52. package/src/infrastructure/messages/Fdc3GetInfoRequest.ts +17 -0
  53. package/src/infrastructure/messages/Fdc3GetInfoResponse.ts +18 -0
  54. package/src/infrastructure/messages/Fdc3GetIntentResultRequest.ts +23 -0
  55. package/src/infrastructure/messages/Fdc3GetIntentResultResponse.ts +23 -0
  56. package/src/infrastructure/messages/Fdc3GetOpenedAppContextRequest.ts +15 -0
  57. package/src/infrastructure/messages/Fdc3GetOpenedAppContextResponse.ts +18 -0
  58. package/src/infrastructure/messages/Fdc3GetUserChannelsRequest.ts +15 -0
  59. package/src/infrastructure/messages/Fdc3GetUserChannelsResponse.ts +18 -0
  60. package/src/infrastructure/messages/Fdc3IntentListenerRequest.ts +22 -0
  61. package/src/infrastructure/messages/Fdc3IntentListenerResponse.ts +17 -0
  62. package/src/infrastructure/messages/Fdc3JoinUserChannelRequest.ts +15 -0
  63. package/src/infrastructure/messages/Fdc3JoinUserChannelResponse.ts +20 -0
  64. package/src/infrastructure/messages/Fdc3OpenRequest.ts +21 -0
  65. package/src/infrastructure/messages/Fdc3OpenResponse.ts +18 -0
  66. package/src/infrastructure/messages/Fdc3PrivateChannelInternalEvent.ts +26 -0
  67. package/src/infrastructure/messages/Fdc3RaiseIntentForContextRequest.ts +20 -0
  68. package/src/infrastructure/messages/Fdc3RaiseIntentRequest.ts +24 -0
  69. package/src/infrastructure/messages/Fdc3RaiseIntentResolutionRequest.ts +20 -0
  70. package/src/infrastructure/messages/Fdc3RaiseIntentResponse.ts +21 -0
  71. package/src/infrastructure/messages/Fdc3RemoveContextListenerRequest.ts +19 -0
  72. package/src/infrastructure/messages/Fdc3RemoveContextListenerResponse.ts +17 -0
  73. package/src/infrastructure/messages/Fdc3StoreIntentResultRequest.ts +29 -0
  74. package/src/infrastructure/messages/Fdc3StoreIntentResultResponse.ts +17 -0
  75. package/tsconfig.json +15 -0
@@ -0,0 +1,369 @@
1
+ /*
2
+ * Morgan Stanley makes this available to you under the Apache License,
3
+ * Version 2.0 (the "License"). You may obtain a copy of the License at
4
+ * http://www.apache.org/licenses/LICENSE-2.0.
5
+ * See the NOTICE file distributed with this work for additional information
6
+ * regarding copyright ownership. Unless required by applicable law or agreed
7
+ * to in writing, software distributed under the License is distributed on an
8
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
9
+ * or implied. See the License for the specific language governing permissions
10
+ * and limitations under the License.
11
+ *
12
+ */
13
+
14
+ import { jest } from '@jest/globals';
15
+ import { ComposeUIDesktopAgent } from './ComposeUIDesktopAgent';
16
+ import { ComposeUITopic } from './infrastructure/ComposeUITopic';
17
+ import { AppIdentifier, Channel, ChannelError, Context, IntentHandler, Listener, PrivateChannel } from '@finos/fdc3';
18
+ import { ComposeUIErrors } from './infrastructure/ComposeUIErrors';
19
+ import { Fdc3FindIntentsByContextResponse } from './infrastructure/messages/Fdc3FindIntentsByContextResponse';
20
+ import { Fdc3RaiseIntentResponse } from './infrastructure/messages/Fdc3RaiseIntentResponse';
21
+ import { ComposeUIIntentListener } from './infrastructure/ComposeUIIntentListener';
22
+ import { ChannelType } from './infrastructure/ChannelType';
23
+
24
+ describe("Tests for ComposeUIDesktopAgent's intent handling", () => {
25
+
26
+ beforeEach(() => {
27
+ window.composeui = {
28
+ fdc3: {
29
+ config: {
30
+ appId: "testAppId",
31
+ instanceId: "testInstanceId"
32
+ },
33
+ channelId : "test",
34
+ openAppIdentifier: {
35
+ openedAppContextId: "test"
36
+ }
37
+ }
38
+ };
39
+ });
40
+
41
+ it('findIntent will throw error as no answer was provided by the DesktopAgent backend', async () => {
42
+ const messageRouterClientMock = {
43
+ clientId: "dummy",
44
+ subscribe: jest.fn(() => {
45
+ return Promise.resolve({ unsubscribe: () => { } });
46
+ }),
47
+
48
+ publish: jest.fn(() => { return Promise.resolve() }),
49
+ connect: jest.fn(() => { return Promise.resolve() }),
50
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
51
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
52
+ registerService: jest.fn(() => { return Promise.resolve() }),
53
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
54
+ invoke: jest.fn(() => { return Promise.resolve(undefined) })
55
+ };
56
+
57
+ const testDesktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
58
+ await expect(testDesktopAgent.findIntent("testIntent"))
59
+ .rejects
60
+ .toThrow(ComposeUIErrors.NoAnswerWasProvided);
61
+ });
62
+
63
+ it('findIntent will throw error as it got error from the DesktopAgent backend', async () => {
64
+ const fdc3IntentResponse = {
65
+ appIntent: [],
66
+ error: "Error happens..."
67
+ };
68
+ const messageRouterClientMock = {
69
+ clientId: "dummy",
70
+ subscribe: jest.fn(() => {
71
+ return Promise.resolve({ unsubscribe: () => { } });
72
+ }),
73
+
74
+ publish: jest.fn(() => { return Promise.resolve() }),
75
+ connect: jest.fn(() => { return Promise.resolve() }),
76
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
77
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
78
+ registerService: jest.fn(() => { return Promise.resolve() }),
79
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
80
+ invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(fdc3IntentResponse)}`) })
81
+ };
82
+ const testDesktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
83
+ await expect(testDesktopAgent.findIntent("testIntent"))
84
+ .rejects
85
+ .toThrow("Error happens...");
86
+
87
+ expect(messageRouterClientMock.invoke).toHaveBeenCalledWith(ComposeUITopic.findIntent(), JSON.stringify({ fdc3InstanceId: window?.composeui?.fdc3.config?.instanceId, intent: "testIntent" }));
88
+ });
89
+
90
+ it('findIntent will return AppIntent', async () => {
91
+ const messageRouterClientMock = {
92
+ clientId: "dummy",
93
+ subscribe: jest.fn(() => {
94
+ return Promise.resolve({ unsubscribe: () => { } });
95
+ }),
96
+
97
+ publish: jest.fn(() => { return Promise.resolve() }),
98
+ connect: jest.fn(() => { return Promise.resolve() }),
99
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
100
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
101
+ registerService: jest.fn(() => { return Promise.resolve() }),
102
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
103
+ invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify({ appIntent: { itent: "dummyIntent", apps: [{ appId: "appId1" }, { appId: "appdId2" }] } })}`) })
104
+ };
105
+ const testDesktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
106
+ var resultAppIntent = await testDesktopAgent.findIntent("dummyIntent");
107
+ expect(messageRouterClientMock.invoke).toHaveBeenCalledWith(ComposeUITopic.findIntent(), JSON.stringify({ fdc3InstanceId: window?.composeui?.fdc3.config?.instanceId, intent: "dummyIntent" }));
108
+ expect(resultAppIntent).toMatchObject({ itent: "dummyIntent", apps: [{ appId: "appId1" }, { appId: "appdId2" }] });
109
+ });
110
+
111
+ it('findIntentsByContext throws error no response came from the DesktopAgent service, undefined message', async () => {
112
+ const messageRouterClientMock = {
113
+ clientId: "dummy",
114
+ subscribe: jest.fn(() => {
115
+ return Promise.resolve({ unsubscribe: () => { } });
116
+ }),
117
+
118
+ publish: jest.fn(() => { return Promise.resolve() }),
119
+ connect: jest.fn(() => { return Promise.resolve() }),
120
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
121
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
122
+ registerService: jest.fn(() => { return Promise.resolve() }),
123
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
124
+ invoke: jest.fn(() => { return Promise.resolve(undefined) })
125
+ };
126
+
127
+ const testDesktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
128
+ await expect(testDesktopAgent.findIntentsByContext({ type: "fdc3.Instrument" }))
129
+ .rejects
130
+ .toThrow(ComposeUIErrors.NoAnswerWasProvided);
131
+ });
132
+
133
+ it('findIntentsByContext throws error as it got error message from the DesktopAgent service', async () => {
134
+ const fdc3IntentResponse: Fdc3FindIntentsByContextResponse = {
135
+ appIntents: [],
136
+ error: "Error happens..."
137
+ };
138
+ const messageRouterClientMock = {
139
+ clientId: "dummy",
140
+ subscribe: jest.fn(() => {
141
+ return Promise.resolve({ unsubscribe: () => { } });
142
+ }),
143
+
144
+ publish: jest.fn(() => { return Promise.resolve() }),
145
+ connect: jest.fn(() => { return Promise.resolve() }),
146
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
147
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
148
+ registerService: jest.fn(() => { return Promise.resolve() }),
149
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
150
+ invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(fdc3IntentResponse)}`) })
151
+ };
152
+ const testDesktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
153
+ await expect(testDesktopAgent.findIntentsByContext({ type: "testType" }))
154
+ .rejects
155
+ .toThrow(fdc3IntentResponse.error);
156
+
157
+ expect(messageRouterClientMock.invoke).toHaveBeenCalledWith(ComposeUITopic.findIntentsByContext(), JSON.stringify({ fdc3InstanceId: window.composeui.fdc3.config?.instanceId, context: { type: "testType" } }));
158
+ });
159
+
160
+ it('findIntentsByContext resolves and calls the invoke method of the messageRouterClient', async () => {
161
+ const request = {
162
+ fdc3InstanceId: window?.composeui?.fdc3.config?.instanceId,
163
+ context: {
164
+ type: 'fdc3.Instrument'
165
+ }
166
+ };
167
+
168
+ const response: Fdc3FindIntentsByContextResponse = {
169
+ appIntents: [
170
+ {
171
+ intent: { name: 'fdc3.Instrument', displayName: 'fdc3.Instrument' },
172
+ apps: [
173
+ { appId: "appId1" },
174
+ { appId: "appId2" }
175
+ ]
176
+ },
177
+ {
178
+ intent: { name: 'fdc3.Instrument2', displayName: 'fdc3.Instrument2' },
179
+ apps: [
180
+ { appId: "appId3" },
181
+ { appId: "appId4" }
182
+ ]
183
+ }
184
+ ]
185
+ };
186
+
187
+ const messageRouterClientMock = {
188
+ clientId: "dummy",
189
+ subscribe: jest.fn(() => {
190
+ return Promise.resolve({ unsubscribe: () => { } });
191
+ }),
192
+
193
+ publish: jest.fn(() => { return Promise.resolve() }),
194
+ connect: jest.fn(() => { return Promise.resolve() }),
195
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
196
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
197
+ registerService: jest.fn(() => { return Promise.resolve() }),
198
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
199
+ invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`) })
200
+ };
201
+ const testDesktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
202
+ var resultAppIntent = await testDesktopAgent.findIntentsByContext({ type: "fdc3.Instrument" });
203
+
204
+ expect(messageRouterClientMock.invoke).toHaveBeenCalledWith(ComposeUITopic.findIntentsByContext(), JSON.stringify(request));
205
+ expect(resultAppIntent).toMatchObject(response.appIntents!);
206
+ });
207
+
208
+ it('raiseIntent will throw exception, due no answer came from the DesktopAgent service', async () => {
209
+ const messageRouterClientMock = {
210
+ clientId: "dummy",
211
+ subscribe: jest.fn(() => {
212
+ return Promise.resolve({ unsubscribe: () => { } });
213
+ }),
214
+
215
+ publish: jest.fn(() => { return Promise.resolve() }),
216
+ connect: jest.fn(() => { return Promise.resolve() }),
217
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
218
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
219
+ registerService: jest.fn(() => { return Promise.resolve() }),
220
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
221
+ invoke: jest.fn(() => { return Promise.resolve(undefined) })
222
+ };
223
+
224
+ const testDesktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
225
+ await expect(testDesktopAgent.raiseIntent("testIntent", { type: "fdc3.Instrument" }))
226
+ .rejects
227
+ .toThrow(ComposeUIErrors.NoAnswerWasProvided);
228
+
229
+ expect(messageRouterClientMock.invoke).toHaveBeenCalledTimes(1);
230
+ });
231
+
232
+ it('raiseIntent will throw exception, due error was defined by the DesktopAgent service', async () => {
233
+ const fdc3IntentResponse: Fdc3RaiseIntentResponse = {
234
+ messageId: "1",
235
+ error: "Error happens..."
236
+ };
237
+ const messageRouterClientMock = {
238
+ clientId: "dummy",
239
+ subscribe: jest.fn(() => {
240
+ return Promise.resolve({ unsubscribe: () => { } });
241
+ }),
242
+
243
+ publish: jest.fn(() => { return Promise.resolve() }),
244
+ connect: jest.fn(() => { return Promise.resolve() }),
245
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
246
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
247
+ registerService: jest.fn(() => { return Promise.resolve() }),
248
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
249
+ invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(fdc3IntentResponse)}`) })
250
+ };
251
+ const testDesktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
252
+ await expect(testDesktopAgent.raiseIntent("testIntent", { type: "testType" }))
253
+ .rejects
254
+ .toThrow(fdc3IntentResponse.error);
255
+
256
+ expect(messageRouterClientMock.invoke).toHaveBeenCalledTimes(1);
257
+ });
258
+
259
+ it('raiseIntent will resolve the first item, due the DesktopAgent service sent just one application', async () => {
260
+ const fdc3IntentResponse: Fdc3RaiseIntentResponse = {
261
+ messageId: "1",
262
+ intent: "test",
263
+ appMetadata: { appId: "test1" }
264
+ };
265
+ const messageRouterClientMock = {
266
+ clientId: "dummy",
267
+ subscribe: jest.fn(() => {
268
+ return Promise.resolve({ unsubscribe: () => { } });
269
+ }),
270
+
271
+ publish: jest.fn(() => { return Promise.resolve() }),
272
+ connect: jest.fn(() => { return Promise.resolve() }),
273
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
274
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
275
+ registerService: jest.fn(() => { return Promise.resolve() }),
276
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
277
+ invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(fdc3IntentResponse)}`) })
278
+ };
279
+
280
+
281
+ const channelFactoryMock = {
282
+ getChannel: jest.fn((channelId: string, channelType: ChannelType) => { return <Promise<Channel>>Promise.reject("not implemented") }),
283
+ createPrivateChannel: jest.fn(() => { return <Promise<PrivateChannel>>Promise.reject("not implemented") }),
284
+ getIntentListener: jest.fn((intent: string, handler: IntentHandler) => { return <Promise<Listener>>Promise.reject("not implemented") })
285
+ };
286
+
287
+ const testDesktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
288
+ var result = await testDesktopAgent.raiseIntent("test", { type: "test" });
289
+ expect(messageRouterClientMock.invoke).toHaveBeenCalledTimes(1);
290
+ expect(result.intent).toMatch("test");
291
+ expect(result.source).toMatchObject(<AppIdentifier>fdc3IntentResponse.appMetadata)
292
+
293
+ });
294
+
295
+ it('addIntentListener will resolve an intentListener', async () => {
296
+ const messageRouterClientMock = {
297
+ clientId: "dummy",
298
+ subscribe: jest.fn(() => {
299
+ return Promise.resolve({ unsubscribe: () => { } });
300
+ }),
301
+
302
+ publish: jest.fn(() => { return Promise.resolve() }),
303
+ connect: jest.fn(() => { return Promise.resolve() }),
304
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
305
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
306
+ registerService: jest.fn(() => { return Promise.resolve() }),
307
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
308
+ invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify({ stored: true })}`) })
309
+ };
310
+ const testDesktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
311
+ const intentHandler: IntentHandler = (context, metadata) => {
312
+ return;
313
+ };
314
+ const result = await testDesktopAgent.addIntentListener("testIntent", intentHandler);
315
+
316
+ expect(messageRouterClientMock.subscribe).toHaveBeenCalledTimes(1);
317
+ expect(result).toBeInstanceOf(ComposeUIIntentListener);
318
+ });
319
+
320
+ it('addIntentListener will fail as no answer provided', async () => {
321
+ const messageRouterClientMock = {
322
+ clientId: "dummy",
323
+ subscribe: jest.fn(() => {
324
+ return Promise.resolve({ unsubscribe: () => { } });
325
+ }),
326
+
327
+ publish: jest.fn(() => { return Promise.resolve() }),
328
+ connect: jest.fn(() => { return Promise.resolve() }),
329
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
330
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
331
+ registerService: jest.fn(() => { return Promise.resolve() }),
332
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
333
+ invoke: jest.fn(() => { return Promise.resolve("") })
334
+ };
335
+ const testDesktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
336
+ const intentHandler: IntentHandler = (context, metadata) => {
337
+ return;
338
+ };
339
+
340
+ await expect(testDesktopAgent.addIntentListener("testIntent", intentHandler))
341
+ .rejects
342
+ .toThrow(ComposeUIErrors.NoAnswerWasProvided);
343
+ });
344
+
345
+ it('addIntentListener will fail as the service not stored', async () => {
346
+ const messageRouterClientMock = {
347
+ clientId: "dummy",
348
+ subscribe: jest.fn(() => {
349
+ return Promise.resolve({ unsubscribe: () => { } });
350
+ }),
351
+
352
+ publish: jest.fn(() => { return Promise.resolve() }),
353
+ connect: jest.fn(() => { return Promise.resolve() }),
354
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
355
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
356
+ registerService: jest.fn(() => { return Promise.resolve() }),
357
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
358
+ invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify({ stored: false, error: undefined })}`) })
359
+ };
360
+ const testDesktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
361
+ const intentHandler: IntentHandler = (context, metadata) => {
362
+ return;
363
+ };
364
+
365
+ await expect(testDesktopAgent.addIntentListener("testIntent", intentHandler))
366
+ .rejects
367
+ .toThrow(ComposeUIErrors.SubscribeFailure);
368
+ });
369
+ });
@@ -0,0 +1,200 @@
1
+ /*
2
+ * Morgan Stanley makes this available to you under the Apache License,
3
+ * Version 2.0 (the "License"). You may obtain a copy of the License at
4
+ * http://www.apache.org/licenses/LICENSE-2.0.
5
+ * See the NOTICE file distributed with this work for additional information
6
+ * regarding copyright ownership. Unless required by applicable law or agreed
7
+ * to in writing, software distributed under the License is distributed on an
8
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
9
+ * or implied. See the License for the specific language governing permissions
10
+ * and limitations under the License.
11
+ */
12
+
13
+ import { ChannelError } from "@finos/fdc3";
14
+ import { ChannelFactory } from "./infrastructure/ChannelFactory";
15
+ import { MessageRouterChannelFactory } from "./infrastructure/MessageRouterChannelFactory";
16
+ import { Fdc3JoinUserChannelResponse } from "./infrastructure/messages/Fdc3JoinUserChannelResponse";
17
+ import { ComposeUIChannel } from "./infrastructure/ComposeUIChannel";
18
+ import { Fdc3GetUserChannelsResponse } from "./infrastructure/messages/Fdc3GetUserChannelsResponse";
19
+
20
+ describe("", () => {
21
+ let channelFactory: ChannelFactory;
22
+
23
+ it('joinUserChannel returns CreationFailed error as no response received', async() => {
24
+ let messageRouterClient = {
25
+ clientId: "dummyId",
26
+ subscribe: jest.fn(() => { return Promise.resolve({ unsubscribe: () => { } }); }),
27
+ publish: jest.fn(() => { return Promise.resolve() }),
28
+ connect: jest.fn(() => { return Promise.resolve() }),
29
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
30
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
31
+ registerService: jest.fn(() => { return Promise.resolve() }),
32
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
33
+ invoke: jest.fn(() => { return Promise.resolve(undefined)})
34
+ };
35
+
36
+ channelFactory = new MessageRouterChannelFactory(messageRouterClient, "dummyId");
37
+
38
+ await expect(channelFactory.joinUserChannel("dummyId"))
39
+ .rejects
40
+ .toThrow(ChannelError.CreationFailed);
41
+
42
+ expect(messageRouterClient.invoke).toHaveBeenCalledTimes(1);
43
+ });
44
+
45
+ it('joinUserChannel returns error as error received in the response', async() => {
46
+ const response: Fdc3JoinUserChannelResponse = {
47
+ error: "testError",
48
+ success: false
49
+ };
50
+
51
+ let messageRouterClient = {
52
+ clientId: "dummyId",
53
+ subscribe: jest.fn(() => { return Promise.resolve({ unsubscribe: () => { } }); }),
54
+ publish: jest.fn(() => { return Promise.resolve() }),
55
+ connect: jest.fn(() => { return Promise.resolve() }),
56
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
57
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
58
+ registerService: jest.fn(() => { return Promise.resolve() }),
59
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
60
+ invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`)})
61
+ };
62
+
63
+ channelFactory = new MessageRouterChannelFactory(messageRouterClient, "dummyId");
64
+
65
+ await expect(channelFactory.joinUserChannel("dummyId"))
66
+ .rejects
67
+ .toThrow("testError");
68
+
69
+ expect(messageRouterClient.invoke).toHaveBeenCalledTimes(1);
70
+ });
71
+
72
+ it('joinUserChannel returns error as the success property set to false', async() => {
73
+ const response: Fdc3JoinUserChannelResponse = {
74
+ displayMetadata: {
75
+ name: "test",
76
+ },
77
+ success: false
78
+ };
79
+
80
+ let messageRouterClient = {
81
+ clientId: "dummyId",
82
+ subscribe: jest.fn(() => { return Promise.resolve({ unsubscribe: () => { } }); }),
83
+ publish: jest.fn(() => { return Promise.resolve() }),
84
+ connect: jest.fn(() => { return Promise.resolve() }),
85
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
86
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
87
+ registerService: jest.fn(() => { return Promise.resolve() }),
88
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
89
+ invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`)})
90
+ };
91
+
92
+ channelFactory = new MessageRouterChannelFactory(messageRouterClient, "dummyId");
93
+
94
+ await expect(channelFactory.joinUserChannel("dummyId"))
95
+ .rejects
96
+ .toThrow(ChannelError.CreationFailed);
97
+
98
+ expect(messageRouterClient.invoke).toHaveBeenCalledTimes(1);
99
+ });
100
+
101
+ it('joinUserChannel returns channel', async() => {
102
+ const response: Fdc3JoinUserChannelResponse = {
103
+ displayMetadata: {
104
+ name: "test",
105
+ },
106
+ success: true
107
+ };
108
+
109
+ let messageRouterClient = {
110
+ clientId: "dummyId",
111
+ subscribe: jest.fn(() => { return Promise.resolve({ unsubscribe: () => { } }); }),
112
+ publish: jest.fn(() => { return Promise.resolve() }),
113
+ connect: jest.fn(() => { return Promise.resolve() }),
114
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
115
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
116
+ registerService: jest.fn(() => { return Promise.resolve() }),
117
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
118
+ invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`)})
119
+ };
120
+
121
+ channelFactory = new MessageRouterChannelFactory(messageRouterClient, "dummyId");
122
+
123
+ const result = await channelFactory.joinUserChannel("dummyId");
124
+ expect(result).toBeInstanceOf(ComposeUIChannel);
125
+ expect(messageRouterClient.invoke).toHaveBeenCalledTimes(1);
126
+ });
127
+
128
+ it('getUserChannels returns NoChannelFound error as no response received', async() => {
129
+ let messageRouterClient = {
130
+ clientId: "dummyId",
131
+ subscribe: jest.fn(() => { return Promise.resolve({ unsubscribe: () => { } }); }),
132
+ publish: jest.fn(() => { return Promise.resolve() }),
133
+ connect: jest.fn(() => { return Promise.resolve() }),
134
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
135
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
136
+ registerService: jest.fn(() => { return Promise.resolve() }),
137
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
138
+ invoke: jest.fn(() => { return Promise.resolve(undefined)})
139
+ };
140
+
141
+ channelFactory = new MessageRouterChannelFactory(messageRouterClient, "dummyId");
142
+
143
+ await expect(channelFactory.getUserChannels())
144
+ .rejects
145
+ .toThrow(ChannelError.NoChannelFound);
146
+
147
+ expect(messageRouterClient.invoke).toHaveBeenCalledTimes(1);
148
+ });
149
+
150
+ it('getUserChannels returns error as error response received', async() => {
151
+ const response: Fdc3GetUserChannelsResponse = {
152
+ error: "testError"
153
+ };
154
+
155
+ let messageRouterClient = {
156
+ clientId: "dummyId",
157
+ subscribe: jest.fn(() => { return Promise.resolve({ unsubscribe: () => { } }); }),
158
+ publish: jest.fn(() => { return Promise.resolve() }),
159
+ connect: jest.fn(() => { return Promise.resolve() }),
160
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
161
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
162
+ registerService: jest.fn(() => { return Promise.resolve() }),
163
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
164
+ invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`)})
165
+ };
166
+
167
+ channelFactory = new MessageRouterChannelFactory(messageRouterClient, "dummyId");
168
+
169
+ await expect(channelFactory.getUserChannels())
170
+ .rejects
171
+ .toThrow("testError");
172
+
173
+ expect(messageRouterClient.invoke).toHaveBeenCalledTimes(1);
174
+ });
175
+
176
+ it('getUserChannels returns channels', async() => {
177
+ const response: Fdc3GetUserChannelsResponse = {
178
+ channels: [{id: "testId", type: "user", displayMetadata: {name: "testDisplayMetadata"}}]
179
+ };
180
+
181
+ let messageRouterClient = {
182
+ clientId: "dummyId",
183
+ subscribe: jest.fn(() => { return Promise.resolve({ unsubscribe: () => { } }); }),
184
+ publish: jest.fn(() => { return Promise.resolve() }),
185
+ connect: jest.fn(() => { return Promise.resolve() }),
186
+ registerEndpoint: jest.fn(() => { return Promise.resolve() }),
187
+ unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
188
+ registerService: jest.fn(() => { return Promise.resolve() }),
189
+ unregisterService: jest.fn(() => { return Promise.resolve() }),
190
+ invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`)})
191
+ };
192
+
193
+ channelFactory = new MessageRouterChannelFactory(messageRouterClient, "dummyId");
194
+
195
+ const result = await channelFactory.getUserChannels();
196
+ expect(result).toBeDefined();
197
+ expect(result.length).toBe(1);
198
+ expect(result.at(0)).toMatchObject({id: "testId", type: "user", displayMetadata: {name: "testDisplayMetadata"}})
199
+ });
200
+ });