Skip to content

Commit a4fccf0

Browse files
committed
Mock server: add response logging, allow configuring delay for request responses
1 parent 138d5cd commit a4fccf0

File tree

2 files changed

+33
-8
lines changed

2 files changed

+33
-8
lines changed

src/tests/Socket.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ describe('socket', () => {
248248
jest.runOnlyPendingTimers();
249249
jest.runOnlyPendingTimers();
250250
jest.runOnlyPendingTimers();
251+
jest.runOnlyPendingTimers();
251252

252253
expect(socket.isConnected()).toEqual(true);
253254
expect(mockConsole.warn.mock.calls.length).toBe(0);

src/tests/mocks/mock-server.ts

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { OutgoingRequest, RequestSuccessResponse, RequestErrorResponse } from '.
44
import { EventEmitter } from 'events';
55
import { MOCK_SERVER_URL } from './mock-data.js';
66

7+
import Logger from '../../SocketLogger.js';
8+
import { LoggerOptions } from '../../NodeSocket.js';
9+
710
interface MockFunctionCreator {
811
fn: (...args: any[]) => any;
912
};
@@ -18,28 +21,38 @@ const getDefaultMockCreatorF = () => ({
1821
fn: () => {},
1922
});
2023

21-
interface MockServerOptions {
24+
type DelayF = () => number;
25+
26+
export interface MockServerOptions {
2227
url: string;
2328
reportMissingListeners?: boolean;
2429
mockF: MockFunctionCreator;
30+
delayMs: number | DelayF;
31+
loggerOptions: LoggerOptions;
2532
}
2633

2734
const DEFAULT_MOCK_SERVER_OPTIONS: MockServerOptions = {
2835
url: MOCK_SERVER_URL,
2936
reportMissingListeners: true,
3037
mockF: getDefaultMockCreatorF(),
38+
delayMs: 0,
39+
loggerOptions: {
40+
logLevel: 'warn',
41+
logOutput: console,
42+
}
3143
}
3244

3345
type MockRequestResponseDataObject<DataT extends object | undefined> = Omit<RequestSuccessResponse<DataT>, 'callback_id'> | Omit<RequestErrorResponse, 'callback_id'>;
3446
type MockRequestResponseDataHandler<DataT extends object | undefined> = (request: OutgoingRequest, s: WebSocket) => MockRequestResponseDataObject<DataT>;
3547
type MockRequestResponseData<DataT extends object | undefined> = MockRequestResponseDataObject<DataT> | MockRequestResponseDataHandler<DataT>;
3648

3749
const getMockServer = (initialOptions: Partial<MockServerOptions> = {}) => {
38-
const { url, reportMissingListeners, mockF }: MockServerOptions = {
50+
const { url, reportMissingListeners, mockF, delayMs, loggerOptions }: MockServerOptions = {
3951
...DEFAULT_MOCK_SERVER_OPTIONS,
4052
...initialOptions,
4153
};
4254

55+
const logger = Logger(loggerOptions);
4356
const mockServer = new Server(url);
4457
let socket: Client;
4558
const emitter = new EventEmitter();
@@ -58,10 +71,6 @@ const getMockServer = (initialOptions: Partial<MockServerOptions> = {}) => {
5871
subscriptionCallback?: RequestCallback,
5972
) => {
6073
const requestHandler = (request: OutgoingRequest, s: WebSocket) => {
61-
if (subscriptionCallback) {
62-
subscriptionCallback(request);
63-
}
64-
6574
const data = typeof responseData === 'function' ? responseData(request, s) : responseData;
6675
if (!data ||!data.code) {
6776
throw new Error(`Mock server: response handler for path ${path} must return a status code`);
@@ -72,7 +81,15 @@ const getMockServer = (initialOptions: Partial<MockServerOptions> = {}) => {
7281
...data,
7382
};
7483

75-
s.send(JSON.stringify(response));
84+
const delay = typeof delayMs === 'function' ? delayMs() : delayMs;
85+
setTimeout(() => {
86+
logger.verbose(`Mock server: sending response for request ${request.callback_id} (${method} ${path}):`, data);
87+
if (subscriptionCallback) {
88+
subscriptionCallback(request);
89+
}
90+
91+
s.send(JSON.stringify(response));
92+
}, delay);
7693
};
7794

7895
// Don't add duplicates
@@ -161,6 +178,12 @@ const getMockServer = (initialOptions: Partial<MockServerOptions> = {}) => {
161178
const unsubscribeRemove = addRequestHandler('DELETE', path, undefined, unsubscribeFn);
162179

163180
const fire = (data: object, entityId?: string | number) => {
181+
if (entityId) {
182+
logger.verbose(`Mock server: firing subscriber ${moduleName} ${listenerName} for entity ${entityId}:`, data);
183+
} else {
184+
logger.verbose(`Mock server: firing subscriber ${moduleName} ${listenerName}:`, data);
185+
}
186+
164187
send({
165188
event: listenerName,
166189
data,
@@ -223,6 +246,7 @@ const getMockServer = (initialOptions: Partial<MockServerOptions> = {}) => {
223246
}
224247

225248
const fire = (data: object) => {
249+
logger.verbose(`Mock server: firing hook ${moduleName} ${listenerName}:`, data);
226250
send({
227251
event: listenerName,
228252
data,
@@ -253,7 +277,7 @@ const getMockServer = (initialOptions: Partial<MockServerOptions> = {}) => {
253277
const emitId = toEmitId(request.path, request.method);
254278
const processed = emitter.emit(emitId, request, s);
255279
if (reportMissingListeners && !processed) {
256-
console.warn(`Mock server: no listeners for event ${request.method} ${request.path}`);
280+
logger.warn(`Mock server: no listeners for event ${request.method} ${request.path}`);
257281
}
258282
});
259283
});

0 commit comments

Comments
 (0)