airdcpp-apisocket 3.0.0-beta.4 → 3.0.0-beta.6
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/dist-es/tests/{helpers.d.ts → mock-server.d.ts} +26 -4
- package/dist-es/tests/mock-server.js +198 -0
- package/dist-es/tests/mock-server.js.map +1 -0
- package/dist-es/tests/test-utils.d.ts +1 -0
- package/dist-es/tests/test-utils.js +5 -0
- package/dist-es/tests/test-utils.js.map +1 -0
- package/package.json +1 -1
- package/src/tests/Socket.test.ts +34 -38
- package/src/tests/mock-server.ts +328 -0
- package/src/tests/public_helpers.test.ts +25 -43
- package/src/tests/test-utils.ts +5 -0
- package/dist-es/tests/helpers.js +0 -134
- package/dist-es/tests/helpers.js.map +0 -1
- package/src/tests/helpers.ts +0 -210
@@ -1,6 +1,5 @@
|
|
1
1
|
import * as Options from '../types/options.js';
|
2
|
-
export declare const
|
3
|
-
declare const getMockConsole: () => {
|
2
|
+
export declare const getMockConsole: () => {
|
4
3
|
log: import("jest-mock").Mock<(a1: any, a2: any, a3: any, a4: any) => void>;
|
5
4
|
info: import("jest-mock").Mock<(a1: any, a2: any, a3: any, a4: any) => void>;
|
6
5
|
warn: import("jest-mock").Mock<(a1: any, a2: any, a3: any, a4: any) => void>;
|
@@ -65,10 +64,33 @@ declare const getConnectedSocket: (server: ReturnType<typeof getMockServer>, use
|
|
65
64
|
error: import("jest-mock").Mock<(a1: any, a2: any, a3: any, a4: any) => void>;
|
66
65
|
};
|
67
66
|
}>;
|
68
|
-
|
69
|
-
|
67
|
+
interface MockServerOptions {
|
68
|
+
url: string;
|
69
|
+
reportMissingListeners?: boolean;
|
70
|
+
}
|
71
|
+
declare const getMockServer: (initialOptions?: Partial<MockServerOptions>) => {
|
72
|
+
addRequestHandler: <DataT extends object | undefined>(method: string, path: string, data?: DataT, subscriptionCallback?: Callback) => void;
|
70
73
|
addErrorHandler: (method: string, path: string, errorStr: string | null, errorCode: number, subscriptionCallback?: Callback) => void;
|
74
|
+
addSubscriptionHandler: (moduleName: string, listenerName: string, entityId?: string | number) => {
|
75
|
+
fire: (data: object, entityId?: string | number) => void;
|
76
|
+
subscribeFn: import("jest-mock").Mock<import("jest-mock").UnknownFunction>;
|
77
|
+
unsubscribeFn: import("jest-mock").Mock<import("jest-mock").UnknownFunction>;
|
78
|
+
path: string;
|
79
|
+
};
|
80
|
+
addHookHandler: (moduleName: string, listenerName: string) => {
|
81
|
+
fire: (data: object, entityId?: string | number) => void;
|
82
|
+
subscribeFn: import("jest-mock").Mock<import("jest-mock").UnknownFunction>;
|
83
|
+
unsubscribeFn: import("jest-mock").Mock<import("jest-mock").UnknownFunction>;
|
84
|
+
path: string;
|
85
|
+
addResolver: (completionId: number) => {
|
86
|
+
fire: (data: object) => void;
|
87
|
+
resolveFn: import("jest-mock").Mock<import("jest-mock").UnknownFunction>;
|
88
|
+
rejectFn: import("jest-mock").Mock<import("jest-mock").UnknownFunction>;
|
89
|
+
};
|
90
|
+
};
|
91
|
+
ignoreMissingHandler: (method: string, path: string) => void;
|
71
92
|
stop: () => void;
|
72
93
|
send: (data: object) => void;
|
94
|
+
url: string;
|
73
95
|
};
|
74
96
|
export { getMockServer, getSocket, getConnectedSocket, DEFAULT_CONNECT_PARAMS, DEFAULT_AUTH_RESPONSE };
|
@@ -0,0 +1,198 @@
|
|
1
|
+
import { Socket } from '../NodeSocket.js';
|
2
|
+
import { Server, WebSocket } from 'mock-socket';
|
3
|
+
import { jest } from '@jest/globals';
|
4
|
+
import ApiConstants from '../ApiConstants.js';
|
5
|
+
import { EventEmitter } from 'events';
|
6
|
+
const VERBOSE = false;
|
7
|
+
export const getMockConsole = () => ({
|
8
|
+
log: jest.fn((a1, a2, a3, a4) => {
|
9
|
+
if (VERBOSE) {
|
10
|
+
console.log(a1, a2, a3, a4);
|
11
|
+
}
|
12
|
+
}),
|
13
|
+
info: jest.fn((a1, a2, a3, a4) => {
|
14
|
+
if (VERBOSE) {
|
15
|
+
console.info(a1, a2, a3, a4);
|
16
|
+
}
|
17
|
+
}),
|
18
|
+
warn: jest.fn((a1, a2, a3, a4) => {
|
19
|
+
console.warn(a1, a2, a3, a4);
|
20
|
+
}),
|
21
|
+
error: jest.fn((a1, a2, a3, a4) => {
|
22
|
+
console.error(a1, a2, a3, a4);
|
23
|
+
}),
|
24
|
+
});
|
25
|
+
const DEFAULT_CONNECT_PARAMS = {
|
26
|
+
username: 'test',
|
27
|
+
password: 'test',
|
28
|
+
url: 'ws://localhost:7171/api/v1/',
|
29
|
+
};
|
30
|
+
const getDefaultSocketOptions = (mockConsole) => ({
|
31
|
+
...DEFAULT_CONNECT_PARAMS,
|
32
|
+
logOutput: mockConsole,
|
33
|
+
logLevel: VERBOSE ? 'verbose' : 'warn',
|
34
|
+
});
|
35
|
+
const DEFAULT_AUTH_RESPONSE = {
|
36
|
+
auth_token: 'b823187f-4aab-4b71-9764-e63e88401a26',
|
37
|
+
refresh_token: '5124faasf-4aab-4b71-9764-e63e88401a26',
|
38
|
+
user: {
|
39
|
+
permissions: ['admin'],
|
40
|
+
username: 'test',
|
41
|
+
active_sessions: 1,
|
42
|
+
last_login: 0,
|
43
|
+
},
|
44
|
+
system: {
|
45
|
+
cid: 'AHLUODI2YZ2U7FDWMHFNJU65ERGKUN4MH7GW5LY',
|
46
|
+
hostname: 'ubuntu-htpc',
|
47
|
+
network_type: 'private',
|
48
|
+
path_separator: '/',
|
49
|
+
platform: 'other',
|
50
|
+
language: 'fi',
|
51
|
+
},
|
52
|
+
wizard_pending: false,
|
53
|
+
};
|
54
|
+
const getSocket = (socketOptions = {}, mockConsole = getMockConsole()) => {
|
55
|
+
const socket = Socket({
|
56
|
+
...getDefaultSocketOptions(mockConsole),
|
57
|
+
...socketOptions,
|
58
|
+
}, WebSocket);
|
59
|
+
return { socket, mockConsole };
|
60
|
+
};
|
61
|
+
const getDefaultConnectOptions = () => ({
|
62
|
+
console: getMockConsole(),
|
63
|
+
authResponse: DEFAULT_AUTH_RESPONSE,
|
64
|
+
});
|
65
|
+
const getConnectedSocket = async (server, userOptions) => {
|
66
|
+
const options = {
|
67
|
+
...getDefaultConnectOptions(),
|
68
|
+
...userOptions,
|
69
|
+
};
|
70
|
+
server.addRequestHandler('POST', ApiConstants.LOGIN_URL, options.authResponse, options.authCallback);
|
71
|
+
const { socket, mockConsole } = getSocket(options.socketOptions, options.console);
|
72
|
+
await socket.connect();
|
73
|
+
return { socket, mockConsole };
|
74
|
+
};
|
75
|
+
const toEmitId = (path, method) => {
|
76
|
+
return `${path}_${method}`;
|
77
|
+
};
|
78
|
+
const DEFAULT_MOCK_SERVER_OPTIONS = {
|
79
|
+
url: DEFAULT_CONNECT_PARAMS.url,
|
80
|
+
reportMissingListeners: true,
|
81
|
+
};
|
82
|
+
const getMockServer = (initialOptions = {}) => {
|
83
|
+
const { url, reportMissingListeners } = {
|
84
|
+
...DEFAULT_MOCK_SERVER_OPTIONS,
|
85
|
+
...initialOptions,
|
86
|
+
};
|
87
|
+
const mockServer = new Server(url);
|
88
|
+
let socket;
|
89
|
+
const emitter = new EventEmitter();
|
90
|
+
const send = (data) => {
|
91
|
+
socket.send(JSON.stringify(data));
|
92
|
+
};
|
93
|
+
const addServerHandler = (method, path, responseData, subscriptionCallback) => {
|
94
|
+
emitter.addListener(toEmitId(path, method), (request, s) => {
|
95
|
+
if (subscriptionCallback) {
|
96
|
+
subscriptionCallback(request);
|
97
|
+
}
|
98
|
+
const response = {
|
99
|
+
callback_id: request.callback_id,
|
100
|
+
...responseData,
|
101
|
+
};
|
102
|
+
s.send(JSON.stringify(response));
|
103
|
+
});
|
104
|
+
};
|
105
|
+
const addDummyDataHandler = (method, path) => {
|
106
|
+
emitter.addListener(toEmitId(path, method), (request, s) => {
|
107
|
+
// Do nothing
|
108
|
+
});
|
109
|
+
};
|
110
|
+
const addRequestHandler = (method, path, data, subscriptionCallback) => {
|
111
|
+
addServerHandler(method, path, {
|
112
|
+
data,
|
113
|
+
code: 200,
|
114
|
+
}, subscriptionCallback);
|
115
|
+
};
|
116
|
+
const addErrorHandler = (method, path, errorStr, errorCode, subscriptionCallback) => {
|
117
|
+
addServerHandler(method, path, {
|
118
|
+
error: !errorStr ? null : {
|
119
|
+
message: errorStr,
|
120
|
+
},
|
121
|
+
code: errorCode,
|
122
|
+
}, subscriptionCallback);
|
123
|
+
};
|
124
|
+
const addSubscriptionHandlerImpl = (moduleName, type, listenerName, entityId) => {
|
125
|
+
const subscribeFn = jest.fn();
|
126
|
+
const unsubscribeFn = jest.fn();
|
127
|
+
const path = entityId ? `${moduleName}/${entityId}/${type}/${listenerName}` : `${moduleName}/${type}/${listenerName}`;
|
128
|
+
addRequestHandler('POST', path, undefined, subscribeFn);
|
129
|
+
addRequestHandler('DELETE', path, undefined, unsubscribeFn);
|
130
|
+
const fire = (data, entityId) => {
|
131
|
+
send({
|
132
|
+
event: listenerName,
|
133
|
+
data,
|
134
|
+
id: entityId,
|
135
|
+
});
|
136
|
+
};
|
137
|
+
return {
|
138
|
+
fire,
|
139
|
+
subscribeFn,
|
140
|
+
unsubscribeFn,
|
141
|
+
path,
|
142
|
+
};
|
143
|
+
};
|
144
|
+
const addSubscriptionHandler = (moduleName, listenerName, entityId) => {
|
145
|
+
return addSubscriptionHandlerImpl(moduleName, 'listeners', listenerName, entityId);
|
146
|
+
};
|
147
|
+
const addHookHandler = (moduleName, listenerName) => {
|
148
|
+
const subscriber = addSubscriptionHandlerImpl(moduleName, 'hooks', listenerName);
|
149
|
+
const addResolver = (completionId) => {
|
150
|
+
const resolveFn = jest.fn();
|
151
|
+
const rejectFn = jest.fn();
|
152
|
+
addRequestHandler('POST', `${subscriber.path}/${completionId}/resolve`, undefined, resolveFn);
|
153
|
+
addRequestHandler('POST', `${subscriber.path}/${completionId}/reject`, undefined, rejectFn);
|
154
|
+
const fire = (data) => {
|
155
|
+
send({
|
156
|
+
event: listenerName,
|
157
|
+
data,
|
158
|
+
completion_id: completionId,
|
159
|
+
});
|
160
|
+
};
|
161
|
+
return { fire, resolveFn, rejectFn };
|
162
|
+
};
|
163
|
+
return {
|
164
|
+
addResolver,
|
165
|
+
...subscriber,
|
166
|
+
};
|
167
|
+
};
|
168
|
+
mockServer.on('connection', s => {
|
169
|
+
socket = s;
|
170
|
+
socket.on('message', (messageObj) => {
|
171
|
+
const request = JSON.parse(messageObj);
|
172
|
+
const emitId = toEmitId(request.path, request.method);
|
173
|
+
const processed = emitter.emit(emitId, request, s);
|
174
|
+
if (reportMissingListeners && !processed) {
|
175
|
+
console.warn(`Mock server: no listeners for event ${request.method} ${request.path}`);
|
176
|
+
}
|
177
|
+
});
|
178
|
+
});
|
179
|
+
mockServer.on('close', () => {
|
180
|
+
emitter.removeAllListeners();
|
181
|
+
});
|
182
|
+
return {
|
183
|
+
addRequestHandler,
|
184
|
+
addErrorHandler,
|
185
|
+
addSubscriptionHandler,
|
186
|
+
addHookHandler,
|
187
|
+
ignoreMissingHandler: addDummyDataHandler,
|
188
|
+
stop: () => {
|
189
|
+
mockServer.stop(() => {
|
190
|
+
// ...
|
191
|
+
});
|
192
|
+
},
|
193
|
+
send,
|
194
|
+
url,
|
195
|
+
};
|
196
|
+
};
|
197
|
+
export { getMockServer, getSocket, getConnectedSocket, DEFAULT_CONNECT_PARAMS, DEFAULT_AUTH_RESPONSE };
|
198
|
+
//# sourceMappingURL=mock-server.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"mock-server.js","sourceRoot":"","sources":["../../src/tests/mock-server.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare const waitForExpect: (func: () => void | Promise<void>) => Promise<{}>;
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../../src/tests/test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,MAAM,iBAAiB,CAAC;AAEpD,MAAM,cAAc,GAAG,IAAI,CAAC;AAC5B,YAAY;AACZ,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAgC,EAAE,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC"}
|
package/package.json
CHANGED
package/src/tests/Socket.test.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import {
|
2
2
|
DEFAULT_AUTH_RESPONSE, DEFAULT_CONNECT_PARAMS,
|
3
|
-
getConnectedSocket, getMockServer, getSocket
|
4
|
-
} from './
|
3
|
+
getConnectedSocket, getMockServer, getSocket
|
4
|
+
} from './mock-server.js';
|
5
5
|
|
6
6
|
import ApiConstants from '../ApiConstants.js';
|
7
7
|
|
@@ -9,6 +9,7 @@ import { HookCallback, HookSubscriberInfo, SubscriptionRemoveHandler } from '../
|
|
9
9
|
import { IncomingSubscriptionEvent } from '../types/api_internal.js';
|
10
10
|
|
11
11
|
import { jest } from '@jest/globals';
|
12
|
+
import { waitForExpect } from './test-utils.js';
|
12
13
|
|
13
14
|
let server: ReturnType<typeof getMockServer>;
|
14
15
|
|
@@ -29,7 +30,7 @@ describe('socket', () => {
|
|
29
30
|
|
30
31
|
describe('auth', () => {
|
31
32
|
test('should handle valid credentials', async () => {
|
32
|
-
server.
|
33
|
+
server.addRequestHandler('POST', ApiConstants.LOGIN_URL, DEFAULT_AUTH_RESPONSE);
|
33
34
|
const connectedCallback = jest.fn();
|
34
35
|
|
35
36
|
const { socket, mockConsole } = getSocket();
|
@@ -48,7 +49,7 @@ describe('socket', () => {
|
|
48
49
|
});
|
49
50
|
|
50
51
|
test('should handle valid refresh token', async () => {
|
51
|
-
server.
|
52
|
+
server.addRequestHandler('POST', ApiConstants.LOGIN_URL, DEFAULT_AUTH_RESPONSE);
|
52
53
|
const connectedCallback = jest.fn();
|
53
54
|
|
54
55
|
const { socket, mockConsole } = getSocket();
|
@@ -106,7 +107,7 @@ describe('socket', () => {
|
|
106
107
|
|
107
108
|
// Valid connect attempt
|
108
109
|
server = getMockServer();
|
109
|
-
server.
|
110
|
+
server.addRequestHandler('POST', ApiConstants.LOGIN_URL, DEFAULT_AUTH_RESPONSE);
|
110
111
|
|
111
112
|
await socket.connect(DEFAULT_CONNECT_PARAMS.username, DEFAULT_CONNECT_PARAMS.password, false);
|
112
113
|
|
@@ -125,17 +126,19 @@ describe('socket', () => {
|
|
125
126
|
socket.onDisconnected = disconnectedCallback;
|
126
127
|
|
127
128
|
// Dummy listener
|
128
|
-
server.
|
129
|
+
server.addRequestHandler('POST', 'hubs/listeners/hub_updated', undefined);
|
129
130
|
await socket.addListener('hubs', 'hub_updated', dummyfn);
|
130
131
|
|
131
132
|
// Dummy pending request
|
133
|
+
server.ignoreMissingHandler('DELETE', 'dummyLogoutDelete');
|
134
|
+
|
132
135
|
socket.delete('dummyLogoutDelete').catch((error: Error) => {
|
133
136
|
// TODO: fix, too unreliable at the moment (depends on the timings)
|
134
137
|
//expect(error.message).toEqual('Socket disconnected');
|
135
138
|
});
|
136
139
|
|
137
140
|
// Logout
|
138
|
-
server.
|
141
|
+
server.addRequestHandler('DELETE', ApiConstants.LOGOUT_URL);
|
139
142
|
await socket.logout();
|
140
143
|
|
141
144
|
expect(sessionResetCallback.mock.calls.length).toBe(1);
|
@@ -206,7 +209,7 @@ describe('socket', () => {
|
|
206
209
|
expect(mockConsole.error.mock.calls.length).toBe(1);
|
207
210
|
|
208
211
|
server = getMockServer();
|
209
|
-
server.
|
212
|
+
server.addRequestHandler('POST', ApiConstants.CONNECT_URL, undefined);
|
210
213
|
jest.runOnlyPendingTimers();
|
211
214
|
jest.runOnlyPendingTimers();
|
212
215
|
jest.runOnlyPendingTimers();
|
@@ -257,7 +260,7 @@ describe('socket', () => {
|
|
257
260
|
socket.disconnect();
|
258
261
|
await waitForExpect(() => expect(socket.isActive()).toEqual(false));
|
259
262
|
|
260
|
-
server.
|
263
|
+
server.addRequestHandler('POST', ApiConstants.CONNECT_URL, undefined);
|
261
264
|
await socket.reconnect();
|
262
265
|
expect(socket.isConnected()).toEqual(true);
|
263
266
|
|
@@ -285,7 +288,7 @@ describe('socket', () => {
|
|
285
288
|
server.addErrorHandler('POST', ApiConstants.CONNECT_URL, ErrorResponse, 400);
|
286
289
|
|
287
290
|
const authCallback = jest.fn();
|
288
|
-
server.
|
291
|
+
server.addRequestHandler('POST', ApiConstants.LOGIN_URL, DEFAULT_AUTH_RESPONSE, authCallback);
|
289
292
|
|
290
293
|
jest.runOnlyPendingTimers();
|
291
294
|
socket.reconnect();
|
@@ -328,6 +331,9 @@ describe('socket', () => {
|
|
328
331
|
test('should report request timeouts', async () => {
|
329
332
|
const { socket, mockConsole } = await getConnectedSocket(server);
|
330
333
|
|
334
|
+
server.ignoreMissingHandler('POST', 'hubs/listeners/hub_updated');
|
335
|
+
server.ignoreMissingHandler('POST', 'hubs/listeners/hub_added');
|
336
|
+
|
331
337
|
jest.useFakeTimers();
|
332
338
|
socket.addListener('hubs', 'hub_updated', dummyfn)
|
333
339
|
.catch(() => {});
|
@@ -388,8 +394,8 @@ describe('socket', () => {
|
|
388
394
|
|
389
395
|
test('should handle listener messages', async () => {
|
390
396
|
const { socket, mockConsole } = await getConnectedSocket(server);
|
391
|
-
server.
|
392
|
-
server.
|
397
|
+
server.addSubscriptionHandler('hubs', 'hub_updated');
|
398
|
+
server.addSubscriptionHandler('hubs', 'hub_updated', entityId);
|
393
399
|
|
394
400
|
const commonSubscriptionCallback = jest.fn();
|
395
401
|
const entitySubscriptionCallback = jest.fn();
|
@@ -415,8 +421,7 @@ describe('socket', () => {
|
|
415
421
|
test('should handle listener removal', async () => {
|
416
422
|
const { socket, mockConsole } = await getConnectedSocket(server);
|
417
423
|
|
418
|
-
const
|
419
|
-
server.addDataHandler('POST', 'hubs/listeners/hub_updated', undefined, subscribeCallback);
|
424
|
+
const hubUpdatedListener = server.addSubscriptionHandler('hubs', 'hub_updated');
|
420
425
|
|
421
426
|
// Add two simultaneous pending add events
|
422
427
|
const p1 = socket.addListener('hubs', 'hub_updated', dummyfn);
|
@@ -428,17 +433,14 @@ describe('socket', () => {
|
|
428
433
|
const removeListener1 = await p1;
|
429
434
|
const removeListener2 = await p2;
|
430
435
|
|
431
|
-
expect(
|
436
|
+
expect(hubUpdatedListener.subscribeFn.mock.calls.length).toBe(1);
|
432
437
|
expect(socket.getPendingSubscriptionCount()).toBe(0);
|
433
438
|
|
434
|
-
const deleteCallback = jest.fn();
|
435
|
-
server.addDataHandler('DELETE', 'hubs/listeners/hub_updated', undefined, deleteCallback);
|
436
|
-
|
437
439
|
removeListener1();
|
438
|
-
expect(
|
440
|
+
expect(hubUpdatedListener.unsubscribeFn.mock.calls.length).toBe(0); // Shouldn't call API yet, still one left
|
439
441
|
|
440
442
|
removeListener2();
|
441
|
-
await waitForExpect(() => expect(
|
443
|
+
await waitForExpect(() => expect(hubUpdatedListener.unsubscribeFn.mock.calls.length).toBe(1));
|
442
444
|
|
443
445
|
expect(socket.hasListeners()).toBe(false);
|
444
446
|
|
@@ -466,11 +468,9 @@ describe('socket', () => {
|
|
466
468
|
});
|
467
469
|
|
468
470
|
describe('hooks', () => {
|
469
|
-
const
|
470
|
-
|
471
|
-
|
472
|
-
completion_id: 1,
|
473
|
-
};
|
471
|
+
const HOOK_MODULE = 'queue';
|
472
|
+
const HOOK_NAME = 'queue_bundle_finished_hook';
|
473
|
+
const HOOK_COMPLETION_ID = 1;
|
474
474
|
|
475
475
|
const hookSubscriberInfo: HookSubscriberInfo = {
|
476
476
|
id: 'sfv_checker',
|
@@ -487,26 +487,22 @@ describe('socket', () => {
|
|
487
487
|
|
488
488
|
// Add hook
|
489
489
|
{
|
490
|
-
const
|
491
|
-
server.addDataHandler('POST', 'queue/hooks/queue_bundle_finished_hook', undefined, hookAddCallback);
|
490
|
+
const hook = server.addHookHandler(HOOK_MODULE, HOOK_NAME);
|
492
491
|
|
493
492
|
removeListener = await socket.addHook(
|
494
|
-
|
495
|
-
|
493
|
+
HOOK_MODULE,
|
494
|
+
HOOK_NAME,
|
496
495
|
rejectCallback,
|
497
496
|
hookSubscriberInfo
|
498
497
|
);
|
499
498
|
|
500
|
-
expect((
|
501
|
-
expect(
|
502
|
-
}
|
499
|
+
expect((hook.subscribeFn.mock.calls[0][0] as any).data).toEqual(hookSubscriberInfo);
|
500
|
+
expect(hook.subscribeFn.mock.calls.length).toBe(1);
|
503
501
|
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
server.send(hookEventData);
|
509
|
-
await waitForExpect(() => expect(hookEventCallback.mock.calls.length).toBe(1));
|
502
|
+
// Simulate action
|
503
|
+
const hookResolver = hook.addResolver(HOOK_COMPLETION_ID);
|
504
|
+
hookResolver.fire({});
|
505
|
+
await waitForExpect(() => expect(hookResolver.rejectFn.mock.calls.length).toBe(1));
|
510
506
|
}
|
511
507
|
|
512
508
|
// Clean up
|
@@ -0,0 +1,328 @@
|
|
1
|
+
import { Socket } from '../NodeSocket.js';
|
2
|
+
import { Client, Server, WebSocket } from 'mock-socket';
|
3
|
+
import { jest } from '@jest/globals';
|
4
|
+
|
5
|
+
import { OutgoingRequest, RequestSuccessResponse, RequestErrorResponse } from '../types/api_internal.js';
|
6
|
+
import * as Options from '../types/options.js';
|
7
|
+
import ApiConstants from '../ApiConstants.js';
|
8
|
+
import { EventEmitter } from 'events';
|
9
|
+
|
10
|
+
const VERBOSE = false;
|
11
|
+
|
12
|
+
export const getMockConsole = () => ({
|
13
|
+
log: jest.fn((a1: any, a2: any, a3: any, a4: any) => {
|
14
|
+
if (VERBOSE) {
|
15
|
+
console.log(a1, a2, a3, a4);
|
16
|
+
}
|
17
|
+
}),
|
18
|
+
info: jest.fn((a1: any, a2: any, a3: any, a4: any) => {
|
19
|
+
if (VERBOSE) {
|
20
|
+
console.info(a1, a2, a3, a4);
|
21
|
+
}
|
22
|
+
}),
|
23
|
+
warn: jest.fn((a1: any, a2: any, a3: any, a4: any) => {
|
24
|
+
console.warn(a1, a2, a3, a4);
|
25
|
+
}),
|
26
|
+
error: jest.fn((a1: any, a2: any, a3: any, a4: any) => {
|
27
|
+
console.error(a1, a2, a3, a4);
|
28
|
+
}),
|
29
|
+
});
|
30
|
+
|
31
|
+
const DEFAULT_CONNECT_PARAMS = {
|
32
|
+
username: 'test',
|
33
|
+
password: 'test',
|
34
|
+
url: 'ws://localhost:7171/api/v1/',
|
35
|
+
};
|
36
|
+
|
37
|
+
const getDefaultSocketOptions = (mockConsole: Options.LogOutput): Options.APISocketOptions => ({
|
38
|
+
...DEFAULT_CONNECT_PARAMS,
|
39
|
+
logOutput: mockConsole,
|
40
|
+
logLevel: VERBOSE ? 'verbose' : 'warn',
|
41
|
+
});
|
42
|
+
|
43
|
+
const DEFAULT_AUTH_RESPONSE = {
|
44
|
+
auth_token: 'b823187f-4aab-4b71-9764-e63e88401a26',
|
45
|
+
refresh_token: '5124faasf-4aab-4b71-9764-e63e88401a26',
|
46
|
+
user: {
|
47
|
+
permissions: [ 'admin' ],
|
48
|
+
username: 'test',
|
49
|
+
active_sessions: 1,
|
50
|
+
last_login: 0,
|
51
|
+
},
|
52
|
+
system: {
|
53
|
+
cid: 'AHLUODI2YZ2U7FDWMHFNJU65ERGKUN4MH7GW5LY',
|
54
|
+
hostname: 'ubuntu-htpc',
|
55
|
+
network_type: 'private',
|
56
|
+
path_separator: '/',
|
57
|
+
platform: 'other',
|
58
|
+
language: 'fi',
|
59
|
+
},
|
60
|
+
wizard_pending: false,
|
61
|
+
};
|
62
|
+
|
63
|
+
export type MockSocketOptions = Omit<Options.APISocketOptions, 'username' | 'password' | 'url'> & {
|
64
|
+
username?: string;
|
65
|
+
password?: string;
|
66
|
+
url?: string;
|
67
|
+
};
|
68
|
+
|
69
|
+
const getSocket = (socketOptions: MockSocketOptions = {}, mockConsole = getMockConsole()) => {
|
70
|
+
const socket = Socket(
|
71
|
+
{
|
72
|
+
...getDefaultSocketOptions(mockConsole),
|
73
|
+
...socketOptions,
|
74
|
+
},
|
75
|
+
WebSocket as any
|
76
|
+
);
|
77
|
+
|
78
|
+
return { socket, mockConsole };
|
79
|
+
};
|
80
|
+
|
81
|
+
|
82
|
+
type Callback = (requestData: object) => void;
|
83
|
+
|
84
|
+
interface ConnectOptions {
|
85
|
+
socketOptions?: MockSocketOptions;
|
86
|
+
authCallback?: Callback;
|
87
|
+
authResponse?: object;
|
88
|
+
console?: ReturnType<typeof getMockConsole>;
|
89
|
+
}
|
90
|
+
|
91
|
+
const getDefaultConnectOptions = () => ({
|
92
|
+
console: getMockConsole(),
|
93
|
+
authResponse: DEFAULT_AUTH_RESPONSE,
|
94
|
+
});
|
95
|
+
|
96
|
+
const getConnectedSocket = async (
|
97
|
+
server: ReturnType<typeof getMockServer>,
|
98
|
+
userOptions?: ConnectOptions,
|
99
|
+
) => {
|
100
|
+
const options = {
|
101
|
+
...getDefaultConnectOptions(),
|
102
|
+
...userOptions,
|
103
|
+
};
|
104
|
+
|
105
|
+
server.addRequestHandler('POST', ApiConstants.LOGIN_URL, options.authResponse, options.authCallback);
|
106
|
+
|
107
|
+
const { socket, mockConsole } = getSocket(options.socketOptions, options.console);
|
108
|
+
await socket.connect();
|
109
|
+
|
110
|
+
return { socket, mockConsole };
|
111
|
+
};
|
112
|
+
|
113
|
+
const toEmitId = (path: string, method: string) => {
|
114
|
+
return `${path}_${method}`;
|
115
|
+
};
|
116
|
+
|
117
|
+
interface MockServerOptions {
|
118
|
+
url: string;
|
119
|
+
reportMissingListeners?: boolean;
|
120
|
+
}
|
121
|
+
|
122
|
+
const DEFAULT_MOCK_SERVER_OPTIONS: MockServerOptions = {
|
123
|
+
url: DEFAULT_CONNECT_PARAMS.url,
|
124
|
+
reportMissingListeners: true,
|
125
|
+
}
|
126
|
+
|
127
|
+
const getMockServer = (initialOptions: Partial<MockServerOptions> = {}) => {
|
128
|
+
const { url, reportMissingListeners }: MockServerOptions = {
|
129
|
+
...DEFAULT_MOCK_SERVER_OPTIONS,
|
130
|
+
...initialOptions,
|
131
|
+
};
|
132
|
+
|
133
|
+
const mockServer = new Server(url);
|
134
|
+
let socket: Client;
|
135
|
+
const emitter = new EventEmitter();
|
136
|
+
|
137
|
+
const send = (data: object) => {
|
138
|
+
socket.send(JSON.stringify(data));
|
139
|
+
};
|
140
|
+
|
141
|
+
const addServerHandler = <DataT extends object | undefined>(
|
142
|
+
method: string,
|
143
|
+
path: string,
|
144
|
+
responseData: Omit<RequestSuccessResponse<DataT>, 'callback_id'> | Omit<RequestErrorResponse, 'callback_id'>,
|
145
|
+
subscriptionCallback?: Callback
|
146
|
+
) => {
|
147
|
+
emitter.addListener(
|
148
|
+
toEmitId(path, method),
|
149
|
+
(request: OutgoingRequest, s: WebSocket) => {
|
150
|
+
if (subscriptionCallback) {
|
151
|
+
subscriptionCallback(request);
|
152
|
+
}
|
153
|
+
|
154
|
+
const response: RequestSuccessResponse | RequestErrorResponse = {
|
155
|
+
callback_id: request.callback_id,
|
156
|
+
...responseData,
|
157
|
+
};
|
158
|
+
|
159
|
+
s.send(JSON.stringify(response));
|
160
|
+
}
|
161
|
+
);
|
162
|
+
};
|
163
|
+
|
164
|
+
const addDummyDataHandler = (method: string, path: string) => {
|
165
|
+
emitter.addListener(
|
166
|
+
toEmitId(path, method),
|
167
|
+
(request: OutgoingRequest, s: WebSocket) => {
|
168
|
+
// Do nothing
|
169
|
+
}
|
170
|
+
);
|
171
|
+
}
|
172
|
+
|
173
|
+
const addRequestHandler = <DataT extends object | undefined>(
|
174
|
+
method: string,
|
175
|
+
path: string,
|
176
|
+
data?: DataT,
|
177
|
+
subscriptionCallback?: Callback
|
178
|
+
) => {
|
179
|
+
addServerHandler<DataT>(
|
180
|
+
method,
|
181
|
+
path, {
|
182
|
+
data,
|
183
|
+
code: 200,
|
184
|
+
},
|
185
|
+
subscriptionCallback
|
186
|
+
);
|
187
|
+
}
|
188
|
+
|
189
|
+
const addErrorHandler = (
|
190
|
+
method: string,
|
191
|
+
path: string,
|
192
|
+
errorStr: string | null,
|
193
|
+
errorCode: number,
|
194
|
+
subscriptionCallback?: Callback
|
195
|
+
) => {
|
196
|
+
addServerHandler(
|
197
|
+
method,
|
198
|
+
path,
|
199
|
+
{
|
200
|
+
error: !errorStr ? null as any : {
|
201
|
+
message: errorStr,
|
202
|
+
},
|
203
|
+
code: errorCode,
|
204
|
+
},
|
205
|
+
subscriptionCallback
|
206
|
+
);
|
207
|
+
}
|
208
|
+
|
209
|
+
const addSubscriptionHandlerImpl = (
|
210
|
+
moduleName: string,
|
211
|
+
type: string,
|
212
|
+
listenerName: string,
|
213
|
+
entityId?: string | number,
|
214
|
+
) => {
|
215
|
+
const subscribeFn = jest.fn();
|
216
|
+
const unsubscribeFn = jest.fn();
|
217
|
+
|
218
|
+
const path = entityId ? `${moduleName}/${entityId}/${type}/${listenerName}` : `${moduleName}/${type}/${listenerName}`;
|
219
|
+
|
220
|
+
addRequestHandler('POST', path, undefined, subscribeFn);
|
221
|
+
addRequestHandler('DELETE', path, undefined, unsubscribeFn);
|
222
|
+
|
223
|
+
const fire = (data: object, entityId?: string | number) => {
|
224
|
+
send({
|
225
|
+
event: listenerName,
|
226
|
+
data,
|
227
|
+
id: entityId,
|
228
|
+
});
|
229
|
+
}
|
230
|
+
|
231
|
+
return {
|
232
|
+
fire,
|
233
|
+
|
234
|
+
subscribeFn,
|
235
|
+
unsubscribeFn,
|
236
|
+
|
237
|
+
path,
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
|
242
|
+
const addSubscriptionHandler = (
|
243
|
+
moduleName: string,
|
244
|
+
listenerName: string,
|
245
|
+
entityId?: string | number,
|
246
|
+
) => {
|
247
|
+
return addSubscriptionHandlerImpl(moduleName, 'listeners', listenerName, entityId);
|
248
|
+
}
|
249
|
+
|
250
|
+
const addHookHandler = (
|
251
|
+
moduleName: string,
|
252
|
+
listenerName: string,
|
253
|
+
) => {
|
254
|
+
const subscriber = addSubscriptionHandlerImpl(moduleName, 'hooks', listenerName);
|
255
|
+
|
256
|
+
const addResolver = (completionId: number) => {
|
257
|
+
const resolveFn = jest.fn();
|
258
|
+
const rejectFn = jest.fn();
|
259
|
+
|
260
|
+
addRequestHandler(
|
261
|
+
'POST',
|
262
|
+
`${subscriber.path}/${completionId}/resolve`,
|
263
|
+
undefined,
|
264
|
+
resolveFn
|
265
|
+
);
|
266
|
+
|
267
|
+
addRequestHandler(
|
268
|
+
'POST',
|
269
|
+
`${subscriber.path}/${completionId}/reject`,
|
270
|
+
undefined,
|
271
|
+
rejectFn
|
272
|
+
);
|
273
|
+
|
274
|
+
const fire = (data: object) => {
|
275
|
+
send({
|
276
|
+
event: listenerName,
|
277
|
+
data,
|
278
|
+
completion_id: completionId,
|
279
|
+
});
|
280
|
+
}
|
281
|
+
|
282
|
+
return { fire, resolveFn, rejectFn };
|
283
|
+
};
|
284
|
+
|
285
|
+
return {
|
286
|
+
addResolver,
|
287
|
+
|
288
|
+
...subscriber,
|
289
|
+
}
|
290
|
+
}
|
291
|
+
|
292
|
+
|
293
|
+
mockServer.on('connection', s => {
|
294
|
+
socket = s;
|
295
|
+
|
296
|
+
socket.on('message', (messageObj) => {
|
297
|
+
const request: OutgoingRequest = JSON.parse(messageObj as string);
|
298
|
+
const emitId = toEmitId(request.path, request.method);
|
299
|
+
const processed = emitter.emit(emitId, request, s);
|
300
|
+
if (reportMissingListeners && !processed) {
|
301
|
+
console.warn(`Mock server: no listeners for event ${request.method} ${request.path}`);
|
302
|
+
}
|
303
|
+
});
|
304
|
+
});
|
305
|
+
|
306
|
+
mockServer.on('close', () => {
|
307
|
+
emitter.removeAllListeners();
|
308
|
+
});
|
309
|
+
|
310
|
+
return {
|
311
|
+
addRequestHandler,
|
312
|
+
addErrorHandler,
|
313
|
+
|
314
|
+
addSubscriptionHandler,
|
315
|
+
addHookHandler,
|
316
|
+
|
317
|
+
ignoreMissingHandler: addDummyDataHandler,
|
318
|
+
stop: () => {
|
319
|
+
mockServer.stop(() => {
|
320
|
+
// ...
|
321
|
+
});
|
322
|
+
},
|
323
|
+
send,
|
324
|
+
url,
|
325
|
+
};
|
326
|
+
};
|
327
|
+
|
328
|
+
export { getMockServer, getSocket, getConnectedSocket, DEFAULT_CONNECT_PARAMS, DEFAULT_AUTH_RESPONSE };
|
@@ -1,15 +1,14 @@
|
|
1
1
|
import {
|
2
2
|
getMockServer,
|
3
3
|
getConnectedSocket,
|
4
|
-
|
5
|
-
} from './
|
4
|
+
} from './mock-server.js';
|
5
|
+
import { waitForExpect } from './test-utils.js';
|
6
6
|
|
7
7
|
import { jest } from '@jest/globals';
|
8
8
|
|
9
9
|
import { addContextMenuItems } from '../PublicHelpers.js';
|
10
10
|
import { SelectedMenuItemListenerData, MenuItemListHookData, MenuItemListHookAcceptData } from '../types/public_helpers_internal.js';
|
11
11
|
import { HookSubscriberInfo, MenuCallbackProperties, MenuClickHandlerProperties } from '../types/index.js';
|
12
|
-
import { IncomingSubscriptionEvent } from '../types/api_internal.js';
|
13
12
|
|
14
13
|
|
15
14
|
let server: ReturnType<typeof getMockServer>;
|
@@ -97,19 +96,10 @@ describe('public helpers', () => {
|
|
97
96
|
// Socket handlers
|
98
97
|
const { socket } = await getConnectedSocket(server);
|
99
98
|
|
100
|
-
const
|
101
|
-
server.addDataHandler('POST', `menus/listeners/${MENU_ID}_menuitem_selected`, undefined, listenerAddCallback);
|
102
|
-
|
103
|
-
const hookAddCallback = jest.fn();
|
104
|
-
const hookResolveCallback = jest.fn();
|
105
|
-
server.addDataHandler('POST', `menus/hooks/${MENU_ID}_list_menuitems`, undefined, hookAddCallback);
|
106
|
-
server.addDataHandler(
|
107
|
-
'POST',
|
108
|
-
`menus/hooks/${MENU_ID}_list_menuitems/${HOOK_COMPLETION_ID}/resolve`,
|
109
|
-
menuItemListData,
|
110
|
-
hookResolveCallback
|
111
|
-
);
|
99
|
+
const itemSelectedListener = server.addSubscriptionHandler('menus', `${MENU_ID}_menuitem_selected`);
|
112
100
|
|
101
|
+
const listItemsHook = server.addHookHandler('menus', `${MENU_ID}_list_menuitems`);
|
102
|
+
const listItemsResolver = listItemsHook.addResolver(HOOK_COMPLETION_ID);
|
113
103
|
|
114
104
|
// Add menu items
|
115
105
|
const onClickItem1Mock = jest.fn();
|
@@ -166,33 +156,29 @@ describe('public helpers', () => {
|
|
166
156
|
SUBSCRIBER_INFO,
|
167
157
|
);
|
168
158
|
|
169
|
-
expect(
|
170
|
-
expect(
|
159
|
+
expect(itemSelectedListener.subscribeFn).toHaveBeenCalledTimes(1);
|
160
|
+
expect(listItemsHook.subscribeFn).toHaveBeenCalledTimes(1);
|
171
161
|
|
172
162
|
|
173
163
|
// List items hook
|
174
164
|
{
|
175
|
-
const
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
permissions: PERMISSIONS,
|
181
|
-
supports: SUPPORTS,
|
182
|
-
},
|
183
|
-
completion_id: 1,
|
165
|
+
const menuItemListData: MenuItemListHookData<string, null> = {
|
166
|
+
selected_ids: selectedMenuIds,
|
167
|
+
entity_id: null,
|
168
|
+
permissions: PERMISSIONS,
|
169
|
+
supports: SUPPORTS,
|
184
170
|
};
|
185
171
|
|
186
|
-
|
172
|
+
listItemsResolver.fire(menuItemListData);
|
187
173
|
}
|
188
174
|
|
189
175
|
// Validate list items results
|
190
176
|
{
|
191
177
|
await waitForExpect(() => {
|
192
|
-
expect(
|
178
|
+
expect(listItemsResolver.resolveFn).toHaveBeenCalledTimes(1);
|
193
179
|
});
|
194
180
|
|
195
|
-
expect(
|
181
|
+
expect(listItemsResolver.resolveFn).toHaveBeenCalledWith(
|
196
182
|
expect.objectContaining({
|
197
183
|
data: menuItemListData
|
198
184
|
}),
|
@@ -214,22 +200,18 @@ describe('public helpers', () => {
|
|
214
200
|
|
215
201
|
// Select event listener
|
216
202
|
{
|
217
|
-
const
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
supports: SUPPORTS,
|
227
|
-
form_values: FORM_VALUES
|
228
|
-
},
|
229
|
-
completion_id: HOOK_COMPLETION_ID,
|
203
|
+
const selectData: SelectedMenuItemListenerData<string, null> = {
|
204
|
+
menuitem_id: MENU_ITEM1_ID,
|
205
|
+
hook_id: SUBSCRIBER_INFO.id,
|
206
|
+
menu_id: MENU_ID,
|
207
|
+
entity_id: null,
|
208
|
+
selected_ids: selectedMenuIds,
|
209
|
+
permissions: PERMISSIONS,
|
210
|
+
supports: SUPPORTS,
|
211
|
+
form_values: FORM_VALUES
|
230
212
|
};
|
231
213
|
|
232
|
-
|
214
|
+
itemSelectedListener.fire(selectData);
|
233
215
|
}
|
234
216
|
|
235
217
|
// Validate select event results
|
package/dist-es/tests/helpers.js
DELETED
@@ -1,134 +0,0 @@
|
|
1
|
-
import { Socket } from '../NodeSocket.js';
|
2
|
-
import { Server, WebSocket } from 'mock-socket';
|
3
|
-
import { jest } from '@jest/globals';
|
4
|
-
import ApiConstants from '../ApiConstants.js';
|
5
|
-
import { EventEmitter } from 'events';
|
6
|
-
import waitForExpectOriginal from 'wait-for-expect';
|
7
|
-
const EXCEPT_TIMEOUT = 1000;
|
8
|
-
//@ts-ignore
|
9
|
-
export const waitForExpect = (func) => waitForExpectOriginal.default(func, EXCEPT_TIMEOUT);
|
10
|
-
const VERBOSE = false;
|
11
|
-
const getMockConsole = () => ({
|
12
|
-
log: jest.fn((a1, a2, a3, a4) => {
|
13
|
-
if (VERBOSE) {
|
14
|
-
console.log(a1, a2, a3, a4);
|
15
|
-
}
|
16
|
-
}),
|
17
|
-
info: jest.fn((a1, a2, a3, a4) => {
|
18
|
-
if (VERBOSE) {
|
19
|
-
console.info(a1, a2, a3, a4);
|
20
|
-
}
|
21
|
-
}),
|
22
|
-
warn: jest.fn((a1, a2, a3, a4) => {
|
23
|
-
console.warn(a1, a2, a3, a4);
|
24
|
-
}),
|
25
|
-
error: jest.fn((a1, a2, a3, a4) => {
|
26
|
-
console.error(a1, a2, a3, a4);
|
27
|
-
}),
|
28
|
-
});
|
29
|
-
const DEFAULT_CONNECT_PARAMS = {
|
30
|
-
username: 'test',
|
31
|
-
password: 'test',
|
32
|
-
url: 'ws://localhost:7171/api/v1/',
|
33
|
-
};
|
34
|
-
const getDefaultSocketOptions = (mockConsole) => ({
|
35
|
-
...DEFAULT_CONNECT_PARAMS,
|
36
|
-
logOutput: mockConsole,
|
37
|
-
logLevel: VERBOSE ? 'verbose' : 'warn',
|
38
|
-
});
|
39
|
-
const DEFAULT_AUTH_RESPONSE = {
|
40
|
-
auth_token: 'b823187f-4aab-4b71-9764-e63e88401a26',
|
41
|
-
refresh_token: '5124faasf-4aab-4b71-9764-e63e88401a26',
|
42
|
-
user: {
|
43
|
-
permissions: ['admin'],
|
44
|
-
username: 'test',
|
45
|
-
active_sessions: 1,
|
46
|
-
last_login: 0,
|
47
|
-
},
|
48
|
-
system: {
|
49
|
-
cid: 'AHLUODI2YZ2U7FDWMHFNJU65ERGKUN4MH7GW5LY',
|
50
|
-
hostname: 'ubuntu-htpc',
|
51
|
-
network_type: 'private',
|
52
|
-
path_separator: '/',
|
53
|
-
platform: 'other',
|
54
|
-
language: 'fi',
|
55
|
-
},
|
56
|
-
wizard_pending: false,
|
57
|
-
};
|
58
|
-
const getSocket = (socketOptions = {}, mockConsole = getMockConsole()) => {
|
59
|
-
const socket = Socket({
|
60
|
-
...getDefaultSocketOptions(mockConsole),
|
61
|
-
...socketOptions,
|
62
|
-
}, WebSocket);
|
63
|
-
return { socket, mockConsole };
|
64
|
-
};
|
65
|
-
const getDefaultConnectOptions = () => ({
|
66
|
-
console: getMockConsole(),
|
67
|
-
authResponse: DEFAULT_AUTH_RESPONSE,
|
68
|
-
});
|
69
|
-
const getConnectedSocket = async (server, userOptions) => {
|
70
|
-
const options = {
|
71
|
-
...getDefaultConnectOptions(),
|
72
|
-
...userOptions,
|
73
|
-
};
|
74
|
-
server.addDataHandler('POST', ApiConstants.LOGIN_URL, options.authResponse, options.authCallback);
|
75
|
-
const { socket, mockConsole } = getSocket(options.socketOptions, options.console);
|
76
|
-
await socket.connect();
|
77
|
-
return { socket, mockConsole };
|
78
|
-
};
|
79
|
-
const toEmitId = (path, method) => {
|
80
|
-
return `${path}_${method}`;
|
81
|
-
};
|
82
|
-
const getMockServer = (url = DEFAULT_CONNECT_PARAMS.url) => {
|
83
|
-
const mockServer = new Server(url);
|
84
|
-
let socket;
|
85
|
-
const emitter = new EventEmitter();
|
86
|
-
const addServerHandler = (method, path, responseData, subscriptionCallback) => {
|
87
|
-
emitter.addListener(toEmitId(path, method), (request, s) => {
|
88
|
-
if (subscriptionCallback) {
|
89
|
-
subscriptionCallback(request);
|
90
|
-
}
|
91
|
-
const response = {
|
92
|
-
callback_id: request.callback_id,
|
93
|
-
...responseData,
|
94
|
-
};
|
95
|
-
s.send(JSON.stringify(response));
|
96
|
-
});
|
97
|
-
};
|
98
|
-
mockServer.on('connection', s => {
|
99
|
-
socket = s;
|
100
|
-
socket.on('message', (messageObj) => {
|
101
|
-
const request = JSON.parse(messageObj);
|
102
|
-
emitter.emit(toEmitId(request.path, request.method), request, s);
|
103
|
-
});
|
104
|
-
});
|
105
|
-
mockServer.on('close', () => {
|
106
|
-
emitter.removeAllListeners();
|
107
|
-
});
|
108
|
-
return {
|
109
|
-
addDataHandler: (method, path, data, subscriptionCallback) => {
|
110
|
-
addServerHandler(method, path, {
|
111
|
-
data,
|
112
|
-
code: 200,
|
113
|
-
}, subscriptionCallback);
|
114
|
-
},
|
115
|
-
addErrorHandler: (method, path, errorStr, errorCode, subscriptionCallback) => {
|
116
|
-
addServerHandler(method, path, {
|
117
|
-
error: !errorStr ? null : {
|
118
|
-
message: errorStr,
|
119
|
-
},
|
120
|
-
code: errorCode,
|
121
|
-
}, subscriptionCallback);
|
122
|
-
},
|
123
|
-
stop: () => {
|
124
|
-
mockServer.stop(() => {
|
125
|
-
// ...
|
126
|
-
});
|
127
|
-
},
|
128
|
-
send: (data) => {
|
129
|
-
socket.send(JSON.stringify(data));
|
130
|
-
},
|
131
|
-
};
|
132
|
-
};
|
133
|
-
export { getMockServer, getSocket, getConnectedSocket, DEFAULT_CONNECT_PARAMS, DEFAULT_AUTH_RESPONSE };
|
134
|
-
//# sourceMappingURL=helpers.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/tests/helpers.ts"],"names":[],"mappings":"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"}
|
package/src/tests/helpers.ts
DELETED
@@ -1,210 +0,0 @@
|
|
1
|
-
import { Socket } from '../NodeSocket.js';
|
2
|
-
import { Client, Server, WebSocket } from 'mock-socket';
|
3
|
-
import { jest } from '@jest/globals';
|
4
|
-
|
5
|
-
import { OutgoingRequest, RequestSuccessResponse, RequestErrorResponse } from '../types/api_internal.js';
|
6
|
-
import * as Options from '../types/options.js';
|
7
|
-
import ApiConstants from '../ApiConstants.js';
|
8
|
-
import { EventEmitter } from 'events';
|
9
|
-
|
10
|
-
import waitForExpectOriginal from 'wait-for-expect';
|
11
|
-
|
12
|
-
const EXCEPT_TIMEOUT = 1000;
|
13
|
-
//@ts-ignore
|
14
|
-
export const waitForExpect = (func: () => void | Promise<void>) => waitForExpectOriginal.default(func, EXCEPT_TIMEOUT);
|
15
|
-
|
16
|
-
const VERBOSE = false;
|
17
|
-
|
18
|
-
const getMockConsole = () => ({
|
19
|
-
log: jest.fn((a1: any, a2: any, a3: any, a4: any) => {
|
20
|
-
if (VERBOSE) {
|
21
|
-
console.log(a1, a2, a3, a4);
|
22
|
-
}
|
23
|
-
}),
|
24
|
-
info: jest.fn((a1: any, a2: any, a3: any, a4: any) => {
|
25
|
-
if (VERBOSE) {
|
26
|
-
console.info(a1, a2, a3, a4);
|
27
|
-
}
|
28
|
-
}),
|
29
|
-
warn: jest.fn((a1: any, a2: any, a3: any, a4: any) => {
|
30
|
-
console.warn(a1, a2, a3, a4);
|
31
|
-
}),
|
32
|
-
error: jest.fn((a1: any, a2: any, a3: any, a4: any) => {
|
33
|
-
console.error(a1, a2, a3, a4);
|
34
|
-
}),
|
35
|
-
});
|
36
|
-
|
37
|
-
const DEFAULT_CONNECT_PARAMS = {
|
38
|
-
username: 'test',
|
39
|
-
password: 'test',
|
40
|
-
url: 'ws://localhost:7171/api/v1/',
|
41
|
-
};
|
42
|
-
|
43
|
-
const getDefaultSocketOptions = (mockConsole: Options.LogOutput): Options.APISocketOptions => ({
|
44
|
-
...DEFAULT_CONNECT_PARAMS,
|
45
|
-
logOutput: mockConsole,
|
46
|
-
logLevel: VERBOSE ? 'verbose' : 'warn',
|
47
|
-
});
|
48
|
-
|
49
|
-
const DEFAULT_AUTH_RESPONSE = {
|
50
|
-
auth_token: 'b823187f-4aab-4b71-9764-e63e88401a26',
|
51
|
-
refresh_token: '5124faasf-4aab-4b71-9764-e63e88401a26',
|
52
|
-
user: {
|
53
|
-
permissions: [ 'admin' ],
|
54
|
-
username: 'test',
|
55
|
-
active_sessions: 1,
|
56
|
-
last_login: 0,
|
57
|
-
},
|
58
|
-
system: {
|
59
|
-
cid: 'AHLUODI2YZ2U7FDWMHFNJU65ERGKUN4MH7GW5LY',
|
60
|
-
hostname: 'ubuntu-htpc',
|
61
|
-
network_type: 'private',
|
62
|
-
path_separator: '/',
|
63
|
-
platform: 'other',
|
64
|
-
language: 'fi',
|
65
|
-
},
|
66
|
-
wizard_pending: false,
|
67
|
-
};
|
68
|
-
|
69
|
-
export type MockSocketOptions = Omit<Options.APISocketOptions, 'username' | 'password' | 'url'> & {
|
70
|
-
username?: string;
|
71
|
-
password?: string;
|
72
|
-
url?: string;
|
73
|
-
};
|
74
|
-
|
75
|
-
const getSocket = (socketOptions: MockSocketOptions = {}, mockConsole = getMockConsole()) => {
|
76
|
-
const socket = Socket(
|
77
|
-
{
|
78
|
-
...getDefaultSocketOptions(mockConsole),
|
79
|
-
...socketOptions,
|
80
|
-
},
|
81
|
-
WebSocket as any
|
82
|
-
);
|
83
|
-
|
84
|
-
return { socket, mockConsole };
|
85
|
-
};
|
86
|
-
|
87
|
-
|
88
|
-
type Callback = (requestData: object) => void;
|
89
|
-
|
90
|
-
interface ConnectOptions {
|
91
|
-
socketOptions?: MockSocketOptions;
|
92
|
-
authCallback?: Callback;
|
93
|
-
authResponse?: object;
|
94
|
-
console?: ReturnType<typeof getMockConsole>;
|
95
|
-
}
|
96
|
-
|
97
|
-
const getDefaultConnectOptions = () => ({
|
98
|
-
console: getMockConsole(),
|
99
|
-
authResponse: DEFAULT_AUTH_RESPONSE,
|
100
|
-
});
|
101
|
-
|
102
|
-
const getConnectedSocket = async (
|
103
|
-
server: ReturnType<typeof getMockServer>,
|
104
|
-
userOptions?: ConnectOptions,
|
105
|
-
) => {
|
106
|
-
const options = {
|
107
|
-
...getDefaultConnectOptions(),
|
108
|
-
...userOptions,
|
109
|
-
};
|
110
|
-
|
111
|
-
server.addDataHandler('POST', ApiConstants.LOGIN_URL, options.authResponse, options.authCallback);
|
112
|
-
|
113
|
-
const { socket, mockConsole } = getSocket(options.socketOptions, options.console);
|
114
|
-
await socket.connect();
|
115
|
-
|
116
|
-
return { socket, mockConsole };
|
117
|
-
};
|
118
|
-
|
119
|
-
const toEmitId = (path: string, method: string) => {
|
120
|
-
return `${path}_${method}`;
|
121
|
-
};
|
122
|
-
|
123
|
-
const getMockServer = (url = DEFAULT_CONNECT_PARAMS.url) => {
|
124
|
-
const mockServer = new Server(url);
|
125
|
-
let socket: Client;
|
126
|
-
const emitter = new EventEmitter();
|
127
|
-
|
128
|
-
const addServerHandler = <DataT extends object | undefined>(
|
129
|
-
method: string,
|
130
|
-
path: string,
|
131
|
-
responseData: Omit<RequestSuccessResponse<DataT>, 'callback_id'> | Omit<RequestErrorResponse, 'callback_id'>,
|
132
|
-
subscriptionCallback?: Callback
|
133
|
-
) => {
|
134
|
-
emitter.addListener(
|
135
|
-
toEmitId(path, method),
|
136
|
-
(request: OutgoingRequest, s: WebSocket) => {
|
137
|
-
if (subscriptionCallback) {
|
138
|
-
subscriptionCallback(request);
|
139
|
-
}
|
140
|
-
|
141
|
-
const response: RequestSuccessResponse | RequestErrorResponse = {
|
142
|
-
callback_id: request.callback_id,
|
143
|
-
...responseData,
|
144
|
-
};
|
145
|
-
|
146
|
-
s.send(JSON.stringify(response));
|
147
|
-
}
|
148
|
-
);
|
149
|
-
};
|
150
|
-
|
151
|
-
mockServer.on('connection', s => {
|
152
|
-
socket = s;
|
153
|
-
|
154
|
-
socket.on('message', (messageObj) => {
|
155
|
-
const request: OutgoingRequest = JSON.parse(messageObj as string);
|
156
|
-
emitter.emit(toEmitId(request.path, request.method), request, s);
|
157
|
-
});
|
158
|
-
});
|
159
|
-
|
160
|
-
mockServer.on('close', () => {
|
161
|
-
emitter.removeAllListeners();
|
162
|
-
});
|
163
|
-
|
164
|
-
return {
|
165
|
-
addDataHandler: <DataT extends object | undefined>(
|
166
|
-
method: string,
|
167
|
-
path: string,
|
168
|
-
data?: DataT,
|
169
|
-
subscriptionCallback?: Callback
|
170
|
-
) => {
|
171
|
-
addServerHandler<DataT>(
|
172
|
-
method,
|
173
|
-
path, {
|
174
|
-
data,
|
175
|
-
code: 200,
|
176
|
-
},
|
177
|
-
subscriptionCallback
|
178
|
-
);
|
179
|
-
},
|
180
|
-
addErrorHandler: (
|
181
|
-
method: string,
|
182
|
-
path: string,
|
183
|
-
errorStr: string | null,
|
184
|
-
errorCode: number,
|
185
|
-
subscriptionCallback?: Callback
|
186
|
-
) => {
|
187
|
-
addServerHandler(
|
188
|
-
method,
|
189
|
-
path,
|
190
|
-
{
|
191
|
-
error: !errorStr ? null as any : {
|
192
|
-
message: errorStr,
|
193
|
-
},
|
194
|
-
code: errorCode,
|
195
|
-
},
|
196
|
-
subscriptionCallback
|
197
|
-
);
|
198
|
-
},
|
199
|
-
stop: () => {
|
200
|
-
mockServer.stop(() => {
|
201
|
-
// ...
|
202
|
-
});
|
203
|
-
},
|
204
|
-
send: (data: object) => {
|
205
|
-
socket.send(JSON.stringify(data));
|
206
|
-
},
|
207
|
-
};
|
208
|
-
};
|
209
|
-
|
210
|
-
export { getMockServer, getSocket, getConnectedSocket, DEFAULT_CONNECT_PARAMS, DEFAULT_AUTH_RESPONSE };
|