@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.
- package/LICENSE +201 -0
- package/README.md +6 -0
- package/jest.config.ts +23 -0
- package/package.json +49 -0
- package/rollup.config.js +16 -0
- package/src/ComposeUIChannel.spec.ts +242 -0
- package/src/ComposeUIContextListener.spec.ts +109 -0
- package/src/ComposeUIDesktopAgent.spec.ts +197 -0
- package/src/ComposeUIDesktopAgent.ts +252 -0
- package/src/ComposeUIIntentHandling.spec.ts +369 -0
- package/src/ComposeUIMessageRouterChannelFactory.spec.ts +200 -0
- package/src/ComposeUIMessageRouterMetadataClient.spec.ts +240 -0
- package/src/ComposeUIMessageRouterOpenClient.spec.ts +239 -0
- package/src/index.ts +66 -0
- package/src/infrastructure/ChannelFactory.ts +25 -0
- package/src/infrastructure/ChannelItem.ts +20 -0
- package/src/infrastructure/ChannelType.ts +14 -0
- package/src/infrastructure/ComposeUIChannel.ts +87 -0
- package/src/infrastructure/ComposeUIContextListener.ts +154 -0
- package/src/infrastructure/ComposeUIErrors.ts +21 -0
- package/src/infrastructure/ComposeUIIntentListener.ts +105 -0
- package/src/infrastructure/ComposeUIIntentResolution.ts +58 -0
- package/src/infrastructure/ComposeUIPrivateChannel.ts +197 -0
- package/src/infrastructure/ComposeUITopic.ts +155 -0
- package/src/infrastructure/IntentsClient.ts +22 -0
- package/src/infrastructure/MessageRouterChannelFactory.ts +182 -0
- package/src/infrastructure/MessageRouterIntentsClient.ts +125 -0
- package/src/infrastructure/MessageRouterMetadataClient.ts +75 -0
- package/src/infrastructure/MessageRouterOpenClient.ts +106 -0
- package/src/infrastructure/MetadataClient.ts +19 -0
- package/src/infrastructure/OpenAppIdentifier.ts +18 -0
- package/src/infrastructure/OpenClient.ts +18 -0
- package/src/infrastructure/PrivateChannelContextListenerEventListener.ts +45 -0
- package/src/infrastructure/PrivateChannelDisconnectEventListener.ts +45 -0
- package/src/infrastructure/messages/Fdc3AddContextListenerRequest.ts +22 -0
- package/src/infrastructure/messages/Fdc3AddContextListenerResponse.ts +17 -0
- package/src/infrastructure/messages/Fdc3CreateAppChannelRequest.ts +17 -0
- package/src/infrastructure/messages/Fdc3CreateAppChannelResponse.ts +17 -0
- package/src/infrastructure/messages/Fdc3CreatePrivateChannelRequest.ts +16 -0
- package/src/infrastructure/messages/Fdc3CreatePrivateChannelResponse.ts +17 -0
- package/src/infrastructure/messages/Fdc3FindChannelRequest.ts +24 -0
- package/src/infrastructure/messages/Fdc3FindChannelResponse.ts +17 -0
- package/src/infrastructure/messages/Fdc3FindInstancesRequest.ts +17 -0
- package/src/infrastructure/messages/Fdc3FindInstancesResponse.ts +18 -0
- package/src/infrastructure/messages/Fdc3FindIntentRequest.ts +24 -0
- package/src/infrastructure/messages/Fdc3FindIntentResponse.ts +19 -0
- package/src/infrastructure/messages/Fdc3FindIntentsByContextRequest.ts +23 -0
- package/src/infrastructure/messages/Fdc3FindIntentsByContextResponse.ts +19 -0
- package/src/infrastructure/messages/Fdc3GetAppMetadataRequest.ts +17 -0
- package/src/infrastructure/messages/Fdc3GetAppMetadataResponse.ts +18 -0
- package/src/infrastructure/messages/Fdc3GetCurrentContextRequest.ts +18 -0
- package/src/infrastructure/messages/Fdc3GetInfoRequest.ts +17 -0
- package/src/infrastructure/messages/Fdc3GetInfoResponse.ts +18 -0
- package/src/infrastructure/messages/Fdc3GetIntentResultRequest.ts +23 -0
- package/src/infrastructure/messages/Fdc3GetIntentResultResponse.ts +23 -0
- package/src/infrastructure/messages/Fdc3GetOpenedAppContextRequest.ts +15 -0
- package/src/infrastructure/messages/Fdc3GetOpenedAppContextResponse.ts +18 -0
- package/src/infrastructure/messages/Fdc3GetUserChannelsRequest.ts +15 -0
- package/src/infrastructure/messages/Fdc3GetUserChannelsResponse.ts +18 -0
- package/src/infrastructure/messages/Fdc3IntentListenerRequest.ts +22 -0
- package/src/infrastructure/messages/Fdc3IntentListenerResponse.ts +17 -0
- package/src/infrastructure/messages/Fdc3JoinUserChannelRequest.ts +15 -0
- package/src/infrastructure/messages/Fdc3JoinUserChannelResponse.ts +20 -0
- package/src/infrastructure/messages/Fdc3OpenRequest.ts +21 -0
- package/src/infrastructure/messages/Fdc3OpenResponse.ts +18 -0
- package/src/infrastructure/messages/Fdc3PrivateChannelInternalEvent.ts +26 -0
- package/src/infrastructure/messages/Fdc3RaiseIntentForContextRequest.ts +20 -0
- package/src/infrastructure/messages/Fdc3RaiseIntentRequest.ts +24 -0
- package/src/infrastructure/messages/Fdc3RaiseIntentResolutionRequest.ts +20 -0
- package/src/infrastructure/messages/Fdc3RaiseIntentResponse.ts +21 -0
- package/src/infrastructure/messages/Fdc3RemoveContextListenerRequest.ts +19 -0
- package/src/infrastructure/messages/Fdc3RemoveContextListenerResponse.ts +17 -0
- package/src/infrastructure/messages/Fdc3StoreIntentResultRequest.ts +29 -0
- package/src/infrastructure/messages/Fdc3StoreIntentResultResponse.ts +17 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,240 @@
|
|
|
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 { ImplementationMetadata } from "@finos/fdc3";
|
|
14
|
+
import { ComposeUIDesktopAgent } from "./ComposeUIDesktopAgent";
|
|
15
|
+
import { ComposeUIErrors } from "./infrastructure/ComposeUIErrors";
|
|
16
|
+
import { Fdc3GetInfoResponse } from "./infrastructure/messages/Fdc3GetInfoResponse";
|
|
17
|
+
import { Fdc3FindInstancesResponse } from "./infrastructure/messages/Fdc3FindInstancesResponse";
|
|
18
|
+
import { Fdc3GetAppMetadataResponse } from "./infrastructure/messages/Fdc3GetAppMetadataResponse";
|
|
19
|
+
|
|
20
|
+
describe('MessageRouterMetadataClient tests', () => {
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
window.composeui = {
|
|
23
|
+
fdc3: {
|
|
24
|
+
config: {
|
|
25
|
+
appId: "testAppId",
|
|
26
|
+
instanceId: "testInstanceId"
|
|
27
|
+
},
|
|
28
|
+
channelId: "test",
|
|
29
|
+
openAppIdentifier: {
|
|
30
|
+
openedAppContextId: "test"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('getInfo returns no payload', async () => {
|
|
37
|
+
const messageRouterClientMock = {
|
|
38
|
+
clientId: "dummy",
|
|
39
|
+
subscribe: jest.fn(() => { return Promise.resolve({unsubscribe: () => {}});}),
|
|
40
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
41
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
42
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
43
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
44
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
45
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
46
|
+
invoke: jest.fn(() => { return Promise.resolve(undefined) })
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const desktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
|
|
50
|
+
|
|
51
|
+
await expect(desktopAgent.getInfo())
|
|
52
|
+
.rejects
|
|
53
|
+
.toThrow(ComposeUIErrors.NoAnswerWasProvided);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('getInfo returns error', async() => {
|
|
57
|
+
const messageRouterClientMock = {
|
|
58
|
+
clientId: "dummy",
|
|
59
|
+
subscribe: jest.fn(() => { return Promise.resolve({unsubscribe: () => {}});}),
|
|
60
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
61
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
62
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
63
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
64
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
65
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
66
|
+
invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify({ error: "dummyError" })}`) })
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const desktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
|
|
70
|
+
|
|
71
|
+
await expect(desktopAgent.getInfo())
|
|
72
|
+
.rejects
|
|
73
|
+
.toThrow('dummyError');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('getInfo returns ImplemetationMetadata', async() => {
|
|
77
|
+
const implementationMetadata: ImplementationMetadata = {
|
|
78
|
+
fdc3Version: '2.0.0',
|
|
79
|
+
provider: 'ComposeUI',
|
|
80
|
+
providerVersion: '1.0.0',
|
|
81
|
+
optionalFeatures: {
|
|
82
|
+
OriginatingAppMetadata: false,
|
|
83
|
+
UserChannelMembershipAPIs: true
|
|
84
|
+
},
|
|
85
|
+
appMetadata: {
|
|
86
|
+
appId: 'dummyAppId'
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const response : Fdc3GetInfoResponse = {
|
|
91
|
+
implementationMetadata: implementationMetadata
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const messageRouterClientMock = {
|
|
95
|
+
clientId: "dummy",
|
|
96
|
+
subscribe: jest.fn(() => { return Promise.resolve({unsubscribe: () => {}});}),
|
|
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(response)}`) })
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const desktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
|
|
107
|
+
|
|
108
|
+
var result = await desktopAgent.getInfo();
|
|
109
|
+
expect(result).toMatchObject(implementationMetadata);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
it('findInstances returns no payload', async () => {
|
|
114
|
+
const messageRouterClientMock = {
|
|
115
|
+
clientId: "dummy",
|
|
116
|
+
subscribe: jest.fn(() => { return Promise.resolve({unsubscribe: () => {}});}),
|
|
117
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
118
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
119
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
120
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
121
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
122
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
123
|
+
invoke: jest.fn(() => { return Promise.resolve(undefined) })
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const desktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
|
|
127
|
+
|
|
128
|
+
await expect(desktopAgent.findInstances({appId: "test"}))
|
|
129
|
+
.rejects
|
|
130
|
+
.toThrow(ComposeUIErrors.NoAnswerWasProvided);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('findInstances returns error', async() => {
|
|
134
|
+
const messageRouterClientMock = {
|
|
135
|
+
clientId: "dummy",
|
|
136
|
+
subscribe: jest.fn(() => { return Promise.resolve({unsubscribe: () => {}});}),
|
|
137
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
138
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
139
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
140
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
141
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
142
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
143
|
+
invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify({ error: "dummyError" })}`) })
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const desktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
|
|
147
|
+
|
|
148
|
+
await expect(desktopAgent.findInstances({appId: "test"}))
|
|
149
|
+
.rejects
|
|
150
|
+
.toThrow('dummyError');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('findInstances return instances', async() => {
|
|
154
|
+
|
|
155
|
+
const response : Fdc3FindInstancesResponse = {
|
|
156
|
+
instances: [{appId: "test", instanceId: "id"}]
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const messageRouterClientMock = {
|
|
160
|
+
clientId: "dummy",
|
|
161
|
+
subscribe: jest.fn(() => { return Promise.resolve({unsubscribe: () => {}});}),
|
|
162
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
163
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
164
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
165
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
166
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
167
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
168
|
+
invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`) })
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const desktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
|
|
172
|
+
|
|
173
|
+
var result = await desktopAgent.findInstances({appId: "test"});
|
|
174
|
+
expect(result).toMatchObject([{appId: "test", instanceId: "id"}]);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('getAppMetadata returns no payload', async () => {
|
|
178
|
+
const messageRouterClientMock = {
|
|
179
|
+
clientId: "dummy",
|
|
180
|
+
subscribe: jest.fn(() => { return Promise.resolve({unsubscribe: () => {}});}),
|
|
181
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
182
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
183
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
184
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
185
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
186
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
187
|
+
invoke: jest.fn(() => { return Promise.resolve(undefined) })
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const desktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
|
|
191
|
+
|
|
192
|
+
await expect(desktopAgent.getAppMetadata({appId: "test"}))
|
|
193
|
+
.rejects
|
|
194
|
+
.toThrow(ComposeUIErrors.NoAnswerWasProvided);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('getAppMetadata returns error', async() => {
|
|
198
|
+
const messageRouterClientMock = {
|
|
199
|
+
clientId: "dummy",
|
|
200
|
+
subscribe: jest.fn(() => { return Promise.resolve({unsubscribe: () => {}});}),
|
|
201
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
202
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
203
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
204
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
205
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
206
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
207
|
+
invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify({ error: "dummyError" })}`) })
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const desktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
|
|
211
|
+
|
|
212
|
+
await expect(desktopAgent.getAppMetadata({appId: "test"}))
|
|
213
|
+
.rejects
|
|
214
|
+
.toThrow('dummyError');
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('getAppMetadata return instances', async() => {
|
|
218
|
+
|
|
219
|
+
const response : Fdc3GetAppMetadataResponse = {
|
|
220
|
+
appMetadata: { appId: "test" }
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const messageRouterClientMock = {
|
|
224
|
+
clientId: "dummy",
|
|
225
|
+
subscribe: jest.fn(() => { return Promise.resolve({unsubscribe: () => {}});}),
|
|
226
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
227
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
228
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
229
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
230
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
231
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
232
|
+
invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`) })
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const desktopAgent = new ComposeUIDesktopAgent(messageRouterClientMock);
|
|
236
|
+
|
|
237
|
+
var result = await desktopAgent.getAppMetadata({appId: "test"});
|
|
238
|
+
expect(result).toMatchObject({appId: "test"});
|
|
239
|
+
});
|
|
240
|
+
});
|
|
@@ -0,0 +1,239 @@
|
|
|
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 { getCurrentChannel, OpenError } from "@finos/fdc3";
|
|
14
|
+
import { MessageRouterOpenClient } from "./infrastructure/MessageRouterOpenClient";
|
|
15
|
+
import { ComposeUIErrors } from "./infrastructure/ComposeUIErrors";
|
|
16
|
+
import { Fdc3OpenResponse } from "./infrastructure/messages/Fdc3OpenResponse";
|
|
17
|
+
import { MessageRouter } from "@morgan-stanley/composeui-messaging-client";
|
|
18
|
+
import { Fdc3GetOpenedAppContextResponse } from "./infrastructure/messages/Fdc3GetOpenedAppContextResponse";
|
|
19
|
+
import { OpenAppIdentifier } from "./infrastructure/OpenAppIdentifier";
|
|
20
|
+
import { rejects } from "assert";
|
|
21
|
+
|
|
22
|
+
describe('MessageRouter OpenClient tests', () => {
|
|
23
|
+
let client: MessageRouterOpenClient;
|
|
24
|
+
let messageRouterClient: MessageRouter;
|
|
25
|
+
const openAppIdentifier: OpenAppIdentifier = { openedAppContextId: "contextId" };
|
|
26
|
+
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
window.composeui = {
|
|
29
|
+
fdc3: {
|
|
30
|
+
config: {
|
|
31
|
+
appId: "testAppId",
|
|
32
|
+
instanceId: "testInstanceId"
|
|
33
|
+
},
|
|
34
|
+
channelId: "test",
|
|
35
|
+
openAppIdentifier: {
|
|
36
|
+
openedAppContextId: "contextId"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
messageRouterClient = {
|
|
42
|
+
clientId: "dummy",
|
|
43
|
+
subscribe: jest.fn(() => {
|
|
44
|
+
return Promise.resolve({ unsubscribe: () => { } });
|
|
45
|
+
}),
|
|
46
|
+
|
|
47
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
48
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
49
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
50
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
51
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
52
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
53
|
+
invoke: jest.fn(() => { return Promise.resolve(undefined) })
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
client = new MessageRouterOpenClient("fdc3InstanceId", messageRouterClient, openAppIdentifier);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('open throws AppNotFound error as AppIdentifier not set', async() => {
|
|
60
|
+
await expect(client.open())
|
|
61
|
+
.rejects
|
|
62
|
+
.toThrow(OpenError.AppNotFound);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('open throws NoAnswerWasProvided error as no response received by the MessageRouter server', async() => {
|
|
66
|
+
await expect(client.open("appId1"))
|
|
67
|
+
.rejects
|
|
68
|
+
.toThrow(ComposeUIErrors.NoAnswerWasProvided);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('open throws error as error response received by the MessageRouter server', async() => {
|
|
72
|
+
const response: Fdc3OpenResponse = {
|
|
73
|
+
error: "testError"
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
messageRouterClient = {
|
|
77
|
+
clientId: "dummy",
|
|
78
|
+
subscribe: jest.fn(() => {
|
|
79
|
+
return Promise.resolve({ unsubscribe: () => { } });
|
|
80
|
+
}),
|
|
81
|
+
|
|
82
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
83
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
84
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
85
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
86
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
87
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
88
|
+
invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`) })
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
client = new MessageRouterOpenClient("fdc3InstanceId", messageRouterClient, openAppIdentifier);
|
|
92
|
+
await expect(client.open("appId1"))
|
|
93
|
+
.rejects
|
|
94
|
+
.toThrow("testError");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('open returns AppIdentifier response received by the MessageRouter server', async() => {
|
|
98
|
+
const response: Fdc3OpenResponse = {
|
|
99
|
+
appIdentifier: {
|
|
100
|
+
appId: "appId1",
|
|
101
|
+
instanceId: "instanceId1"
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
messageRouterClient = {
|
|
106
|
+
clientId: "dummy",
|
|
107
|
+
subscribe: jest.fn(() => {
|
|
108
|
+
return Promise.resolve({ unsubscribe: () => { } });
|
|
109
|
+
}),
|
|
110
|
+
|
|
111
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
112
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
113
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
114
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
115
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
116
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
117
|
+
invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`) })
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
client = new MessageRouterOpenClient("fdc3InstanceId", messageRouterClient, openAppIdentifier);
|
|
121
|
+
const result = await client.open({appId: "appId1"}, {type: "fdc3.instrument"});
|
|
122
|
+
expect(result).toMatchObject({appId: "appId1", instanceId: "instanceId1"});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('getOpenedAppContext throws error as context id is not set', async() => {
|
|
126
|
+
client = new MessageRouterOpenClient("fdc3InstanceId", messageRouterClient);
|
|
127
|
+
await expect(client.getOpenedAppContext())
|
|
128
|
+
.rejects
|
|
129
|
+
.toThrow("Context id is not defined on the window object.");
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('getOpenedAppContext throws NoAnswerWasProvided error as no response received from the MessageRouter server', async() => {
|
|
133
|
+
await expect(client.getOpenedAppContext())
|
|
134
|
+
.rejects
|
|
135
|
+
.toThrow(ComposeUIErrors.NoAnswerWasProvided);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('getOpenedAppContext throws NoAnswerWasProvided error as not correct response received from the MessageRouter server', async() => {
|
|
139
|
+
const response = {
|
|
140
|
+
payload: "wrongPayload"
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
messageRouterClient = {
|
|
144
|
+
clientId: "dummy",
|
|
145
|
+
subscribe: jest.fn(() => {
|
|
146
|
+
return Promise.resolve({ unsubscribe: () => { } });
|
|
147
|
+
}),
|
|
148
|
+
|
|
149
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
150
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
151
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
152
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
153
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
154
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
155
|
+
invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`) })
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
client = new MessageRouterOpenClient("fdc3InstanceId", messageRouterClient, openAppIdentifier);
|
|
159
|
+
await expect(client.getOpenedAppContext())
|
|
160
|
+
.rejects
|
|
161
|
+
.toThrow(ComposeUIErrors.NoAnswerWasProvided);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('getOpenedAppContext throws error as error response received from the MessageRouter server', async() => {
|
|
165
|
+
const response: Fdc3GetOpenedAppContextResponse = {
|
|
166
|
+
error: "testGetOpenedAppContextError"
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
messageRouterClient = {
|
|
170
|
+
clientId: "dummy",
|
|
171
|
+
subscribe: jest.fn(() => {
|
|
172
|
+
return Promise.resolve({ unsubscribe: () => { } });
|
|
173
|
+
}),
|
|
174
|
+
|
|
175
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
176
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
177
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
178
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
179
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
180
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
181
|
+
invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`) })
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
client = new MessageRouterOpenClient("fdc3InstanceId", messageRouterClient, openAppIdentifier);
|
|
185
|
+
await expect(client.getOpenedAppContext())
|
|
186
|
+
.rejects
|
|
187
|
+
.toThrow("testGetOpenedAppContextError");
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('getOpenedAppContext throws NoAnswerWasProvided error as no context response received from the MessageRouter server', async() => {
|
|
191
|
+
const response: Fdc3GetOpenedAppContextResponse = { };
|
|
192
|
+
|
|
193
|
+
messageRouterClient = {
|
|
194
|
+
clientId: "dummy",
|
|
195
|
+
subscribe: jest.fn(() => {
|
|
196
|
+
return Promise.resolve({ unsubscribe: () => { } });
|
|
197
|
+
}),
|
|
198
|
+
|
|
199
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
200
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
201
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
202
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
203
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
204
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
205
|
+
invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`) })
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
client = new MessageRouterOpenClient("fdc3InstanceId", messageRouterClient, openAppIdentifier);
|
|
209
|
+
await expect(client.getOpenedAppContext())
|
|
210
|
+
.rejects
|
|
211
|
+
.toThrow(ComposeUIErrors.NoAnswerWasProvided);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('getOpenedAppContext returns context', async() => {
|
|
215
|
+
const response: Fdc3GetOpenedAppContextResponse = {
|
|
216
|
+
context: {type: "fdc3.instrument"}
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
messageRouterClient = {
|
|
220
|
+
clientId: "dummy",
|
|
221
|
+
subscribe: jest.fn(() => {
|
|
222
|
+
return Promise.resolve({ unsubscribe: () => { } });
|
|
223
|
+
}),
|
|
224
|
+
|
|
225
|
+
publish: jest.fn(() => { return Promise.resolve() }),
|
|
226
|
+
connect: jest.fn(() => { return Promise.resolve() }),
|
|
227
|
+
registerEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
228
|
+
unregisterEndpoint: jest.fn(() => { return Promise.resolve() }),
|
|
229
|
+
registerService: jest.fn(() => { return Promise.resolve() }),
|
|
230
|
+
unregisterService: jest.fn(() => { return Promise.resolve() }),
|
|
231
|
+
invoke: jest.fn(() => { return Promise.resolve(`${JSON.stringify(response)}`) })
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
client = new MessageRouterOpenClient("fdc3InstanceId", messageRouterClient, openAppIdentifier);
|
|
235
|
+
const result = await client.getOpenedAppContext();
|
|
236
|
+
|
|
237
|
+
expect(result.type).toBe("fdc3.instrument");
|
|
238
|
+
});
|
|
239
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
|
|
15
|
+
import { AppIdentifier, DesktopAgent } from "@finos/fdc3";
|
|
16
|
+
import { ComposeUIDesktopAgent } from "./ComposeUIDesktopAgent";
|
|
17
|
+
import { createMessageRouter } from "@morgan-stanley/composeui-messaging-client";
|
|
18
|
+
import { OpenAppIdentifier } from "./infrastructure/OpenAppIdentifier";
|
|
19
|
+
|
|
20
|
+
declare global {
|
|
21
|
+
interface Window {
|
|
22
|
+
composeui: {
|
|
23
|
+
fdc3: {
|
|
24
|
+
config: AppIdentifier | undefined;
|
|
25
|
+
channelId : string | undefined;
|
|
26
|
+
openAppIdentifier: OpenAppIdentifier | undefined;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
fdc3: DesktopAgent;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function initialize(): Promise<void> {
|
|
34
|
+
//TODO: decide if we want to join to a channel by default.
|
|
35
|
+
let channelId: string | undefined = window.composeui.fdc3.channelId;
|
|
36
|
+
const openAppIdentifier: OpenAppIdentifier | undefined = window.composeui.fdc3.openAppIdentifier;
|
|
37
|
+
const fdc3 = new ComposeUIDesktopAgent(createMessageRouter());
|
|
38
|
+
|
|
39
|
+
if (channelId) {
|
|
40
|
+
await fdc3.joinUserChannel(channelId)
|
|
41
|
+
.then(async() => {
|
|
42
|
+
if (openAppIdentifier) {
|
|
43
|
+
await fdc3.getOpenedAppContext()
|
|
44
|
+
.then(() => {
|
|
45
|
+
window.fdc3 = fdc3;
|
|
46
|
+
window.dispatchEvent(new Event("fdc3Ready"));
|
|
47
|
+
})
|
|
48
|
+
} else {
|
|
49
|
+
window.fdc3 = fdc3;
|
|
50
|
+
window.dispatchEvent(new Event("fdc3Ready"));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
} else {
|
|
54
|
+
if (openAppIdentifier) {
|
|
55
|
+
await fdc3.getOpenedAppContext().then(() => {
|
|
56
|
+
window.fdc3 = fdc3;
|
|
57
|
+
window.dispatchEvent(new Event("fdc3Ready"));
|
|
58
|
+
})
|
|
59
|
+
} else {
|
|
60
|
+
window.fdc3 = fdc3;
|
|
61
|
+
window.dispatchEvent(new Event("fdc3Ready"));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
initialize();
|
|
@@ -0,0 +1,25 @@
|
|
|
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 { Channel, ContextHandler, IntentHandler, Listener, PrivateChannel } from "@finos/fdc3";
|
|
15
|
+
import { ChannelType } from "./ChannelType";
|
|
16
|
+
|
|
17
|
+
export interface ChannelFactory {
|
|
18
|
+
getChannel(channelId: string, channelType: ChannelType): Promise<Channel>;
|
|
19
|
+
createPrivateChannel(): Promise<PrivateChannel>;
|
|
20
|
+
createAppChannel(channelId: string): Promise<Channel>;
|
|
21
|
+
joinUserChannel(channelId: string): Promise<Channel>;
|
|
22
|
+
getUserChannels(): Promise<Channel[]>;
|
|
23
|
+
getIntentListener(intent: string, handler: IntentHandler): Promise<Listener>;
|
|
24
|
+
getContextListener(openHandled: boolean, channel?: Channel, handler?: ContextHandler, contextType?: string | null): Promise<Listener>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
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 { DisplayMetadata } from "@finos/fdc3";
|
|
14
|
+
import { ChannelType } from "./ChannelType";
|
|
15
|
+
|
|
16
|
+
export interface ChannelItem {
|
|
17
|
+
id: string;
|
|
18
|
+
type: ChannelType;
|
|
19
|
+
displayMetadata?: DisplayMetadata;
|
|
20
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
export type ChannelType = "user" | "app" | "private"
|