vitest-websocket-mock 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -80,6 +80,11 @@ A `WS` instance has the following attributes:
80
80
  new message. The resolved value is the received message (deserialized as a
81
81
  JavaScript Object if the `WS` was instantiated with the `{ jsonProtocol: true }`
82
82
  option).
83
+ - `messages`: an array that synchronously and cumulatively records every
84
+ message received by the `WS` instance, in the order they were received.
85
+ Since it's updated synchronously, it can be used to assert that no message
86
+ has been received without waiting on a timeout (see
87
+ [Run assertions on received messages](#run-assertions-on-received-messages)).
83
88
 
84
89
  ### Methods on a `WS` instance
85
90
 
@@ -97,11 +102,17 @@ A `WS` instance has the following attributes:
97
102
  on received messages easier:
98
103
 
99
104
  - `.toReceiveMessage`: async matcher that waits for the next message received
100
- by the the mock websocket server, and asserts its content. It will time out
105
+ by the mock websocket server, and asserts its content. It will time out
101
106
  with a helpful message after 1000ms.
102
107
  - `.toHaveReceivedMessages`: synchronous matcher that checks that all the
103
108
  expected messages have been received by the mock websocket server.
104
109
 
110
+ **Note**: `.toHaveReceivedMessages([])` always passes, since it only checks
111
+ that every expected message is included in the received messages, and an
112
+ empty list of expected messages is trivially satisfied. To assert that _no_
113
+ message has been received, check `server.messages` directly instead (see
114
+ below).
115
+
105
116
  ### Run assertions on messages as they are received by the mock server
106
117
 
107
118
  ```js
@@ -116,6 +127,21 @@ test('the server keeps track of received messages, and yields them as they come
116
127
  });
117
128
  ```
118
129
 
130
+ ### Assert that a message has not been received
131
+
132
+ `server.messages` is updated synchronously, so it can be checked immediately
133
+ without waiting for a timeout:
134
+
135
+ ```js
136
+ test('asserts that no message has been received', async () => {
137
+ const server = new WS('ws://localhost:1234');
138
+ const client = new WebSocket('ws://localhost:1234');
139
+
140
+ await server.connected;
141
+ expect(server.messages).toEqual([]);
142
+ });
143
+ ```
144
+
119
145
  ### Send messages to the connected clients
120
146
 
121
147
  ```js
@@ -177,7 +203,7 @@ This can be used to test behaviour for a client that connects to a WebSocket ser
177
203
  ```js
178
204
  test('rejects connections that fail the verifyClient option', async () => {
179
205
  new WS('ws://localhost:1234', { verifyClient: () => false });
180
- const errorCallback = vitest.fn();
206
+ const errorCallback = vi.fn();
181
207
 
182
208
  await expect(
183
209
  new Promise((resolve, reject) => {
@@ -200,7 +226,7 @@ This can be used to test behaviour for a client that connects to a WebSocket ser
200
226
  test('rejects connections that fail the selectProtocol option', async () => {
201
227
  const selectProtocol = () => null;
202
228
  new WS('ws://localhost:1234', { selectProtocol });
203
- const errorCallback = vitest.fn();
229
+ const errorCallback = vi.fn();
204
230
 
205
231
  await expect(
206
232
  new Promise((resolve, reject) => {
@@ -256,7 +282,7 @@ it('the server can refuse connections', async () => {
256
282
  });
257
283
 
258
284
  const client = new WebSocket('ws://localhost:1234');
259
- client.onclose = (event: CloseEvent) => {
285
+ client.onclose = (event) => {
260
286
  expect(event.code).toBe(1003);
261
287
  expect(event.wasClean).toBe(false);
262
288
  expect(event.reason).toBe('NOPE');
@@ -292,7 +318,7 @@ afterEach(() => {
292
318
 
293
319
  `mock-socket` has a strong usage of delays (`setTimeout` to be more specific). This means using `vi.useFakeTimers();` will cause issues such as the client appearing to never connect to the server.
294
320
 
295
- While running the websocket server from tests within the vitest-dom environment (as opposed to node)
321
+ While running the websocket server from tests within the jsdom environment (as opposed to node)
296
322
  you may see errors of the nature:
297
323
 
298
324
  ```bash
@@ -306,7 +332,7 @@ adding `require('setimmediate');` to your `setupTests.js`.
306
332
  ## Testing React applications
307
333
 
308
334
  When testing React applications, `vitest-websocket-mock` will look for
309
- `@testing-library/react`'s implementation of [`act`](https://reactjs.org/docs/test-utils.html#act).
335
+ `@testing-library/react`'s implementation of [`act`](https://react.dev/reference/react/act).
310
336
  If it is available, it will wrap all the necessary calls in `act`, so you don't have to.
311
337
 
312
338
  If `@testing-library/react` is not available, we will assume that you're not testing a React application,
package/dist/index.d.ts CHANGED
@@ -1,88 +1,67 @@
1
- import { Server, Client, CloseOptions, ServerOptions } from 'mock-socket';
2
- import { RawMatcherFn } from '@vitest/expect';
3
-
4
- /**
5
- * @copyright Romain Bertrand 2018
6
- * @copyright Akiomi Kamakura 2023
7
- */
8
-
1
+ import { Client, CloseOptions, Server, ServerOptions } from "mock-socket";
2
+ import { RawMatcherFn } from "@vitest/expect";
3
+ //#region src/derivers/deriveToHaveReceivedMessage.d.ts
9
4
  declare function deriveToHaveReceivedMessage(name: string, fn: RawMatcherFn): RawMatcherFn;
10
-
11
- /**
12
- * @copyright Romain Bertrand 2018
13
- * @copyright Akiomi Kamakura 2023
14
- */
15
-
5
+ //#endregion
6
+ //#region src/derivers/deriveToReceiveMessage.d.ts
16
7
  declare function deriveToReceiveMessage(name: string, fn: RawMatcherFn): RawMatcherFn;
17
-
8
+ //#endregion
9
+ //#region src/derivers/types.d.ts
18
10
  /**
19
11
  * @copyright Romain Bertrand 2018
20
12
  * @copyright Akiomi Kamakura 2023
21
13
  */
22
14
  interface ReceiveMessageOptions {
23
- timeout?: number;
15
+ timeout?: number;
24
16
  }
25
-
17
+ //#endregion
18
+ //#region src/queue.d.ts
26
19
  /**
27
20
  * @copyright Romain Bertrand 2018
28
21
  */
29
22
  declare class Queue<ItemT> {
30
- pendingItems: Array<ItemT>;
31
- nextItemResolver: () => void;
32
- nextItem: Promise<void>;
33
- put(item: ItemT): void;
34
- get(): Promise<ItemT>;
23
+ pendingItems: Array<ItemT>;
24
+ nextItemResolver: () => void;
25
+ nextItem: Promise<void>;
26
+ put(item: ItemT): void;
27
+ get(): Promise<ItemT>;
35
28
  }
36
-
37
- /**
38
- * @copyright Romain Bertrand 2018
39
- * @copyright Akiomi Kamakura 2023
40
- */
41
-
29
+ //#endregion
30
+ //#region src/websocket.d.ts
42
31
  interface WSOptions extends ServerOptions {
43
- jsonProtocol?: boolean;
32
+ jsonProtocol?: boolean;
44
33
  }
45
34
  type DeserializedMessage<TMessage = object> = string | TMessage;
46
35
  declare class WS {
47
- server: Server;
48
- serializer: (deserializedMessage: DeserializedMessage) => string;
49
- deserializer: (message: string) => DeserializedMessage;
50
- static instances: Array<WS>;
51
- messages: Array<DeserializedMessage>;
52
- messagesToConsume: Queue<unknown>;
53
- private _isConnected;
54
- private _isClosed;
55
- static clean(): void;
56
- constructor(url: string, opts?: WSOptions);
57
- get connected(): Promise<Client>;
58
- get closed(): Promise<void>;
59
- get nextMessage(): Promise<unknown>;
60
- on(eventName: 'connection' | 'message' | 'close', callback: (socket: Client) => void): void;
61
- send(message: DeserializedMessage): void;
62
- close(options?: CloseOptions): void;
63
- error(options?: CloseOptions): void;
36
+ server: Server;
37
+ serializer: (deserializedMessage: DeserializedMessage) => string;
38
+ deserializer: (message: string) => DeserializedMessage;
39
+ static instances: Array<WS>;
40
+ messages: Array<DeserializedMessage>;
41
+ messagesToConsume: Queue<unknown>;
42
+ private _isConnected;
43
+ private _isClosed;
44
+ static clean(): void;
45
+ constructor(url: string, opts?: WSOptions);
46
+ get connected(): Promise<Client>;
47
+ get closed(): Promise<void>;
48
+ get nextMessage(): Promise<unknown>;
49
+ on(eventName: 'connection' | 'message' | 'close', callback: (socket: Client) => void): void;
50
+ send(message: DeserializedMessage): void;
51
+ close(options?: CloseOptions): void;
52
+ error(options?: CloseOptions): void;
64
53
  }
65
-
66
- /**
67
- * @copyright Romain Bertrand 2018
68
- * @copyright Akiomi Kamakura 2023
69
- */
70
-
54
+ //#endregion
55
+ //#region src/matchers/index.d.ts
71
56
  interface CustomMatchers<R = unknown> {
72
- toReceiveMessage<TMessage = object>(message: DeserializedMessage<TMessage>, options?: ReceiveMessageOptions): Promise<R>;
73
- toHaveReceivedMessages<TMessage = object>(messages: Array<DeserializedMessage<TMessage>>): R;
57
+ toReceiveMessage<TMessage = object>(message: DeserializedMessage<TMessage>, options?: ReceiveMessageOptions): Promise<R>;
58
+ toHaveReceivedMessages<TMessage = object>(messages: Array<DeserializedMessage<TMessage>>): R;
74
59
  }
75
-
76
- /**
77
- * @copyright Romain Bertrand 2018
78
- * @copyright Akiomi Kamakura 2023
79
- */
80
-
81
- declare module 'vitest' {
82
- interface Assertion<T = any> extends CustomMatchers<T> {
83
- }
84
- interface AsymmetricMatchersContaining extends CustomMatchers {
85
- }
60
+ //#endregion
61
+ //#region src/extend-expect.d.ts
62
+ declare module '@vitest/expect' {
63
+ interface Assertion<T = any> extends CustomMatchers<T> {}
64
+ interface AsymmetricMatchersContaining extends CustomMatchers {}
86
65
  }
87
-
88
- export { ReceiveMessageOptions, WS, WS as default, deriveToHaveReceivedMessage, deriveToReceiveMessage };
66
+ //#endregion
67
+ export { type ReceiveMessageOptions, WS, WS as default, deriveToHaveReceivedMessage, deriveToReceiveMessage };
package/dist/index.js CHANGED
@@ -1,281 +1,254 @@
1
- var __defProp = Object.defineProperty;
2
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
- }) : x)(function(x) {
5
- if (typeof require !== "undefined")
6
- return require.apply(this, arguments);
7
- throw Error('Dynamic require of "' + x + '" is not supported');
8
- });
9
- var __export = (target, all) => {
10
- for (var name in all)
11
- __defProp(target, name, { get: all[name], enumerable: true });
12
- };
13
-
14
- // src/extend-expect.ts
1
+ import { createRequire } from "node:module";
15
2
  import { expect } from "vitest";
16
-
17
- // src/matchers/index.ts
18
- var matchers_exports = {};
19
- __export(matchers_exports, {
20
- toHaveReceivedMessages: () => toHaveReceivedMessages_default,
21
- toReceiveMessage: () => toReceiveMessage_default
22
- });
23
-
24
- // src/websocket.ts
25
3
  import { Server } from "mock-socket";
26
-
27
- // src/act-compat.ts
28
- var act;
4
+ //#region \0rolldown/runtime.js
5
+ var __defProp = Object.defineProperty;
6
+ var __exportAll = (all, no_symbols) => {
7
+ let target = {};
8
+ for (var name in all) __defProp(target, name, {
9
+ get: all[name],
10
+ enumerable: true
11
+ });
12
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
13
+ return target;
14
+ };
15
+ var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
16
+ //#endregion
17
+ //#region src/act-compat.ts
18
+ let act;
29
19
  try {
30
- act = __require("@testing-library/react").act;
20
+ act = __require("@testing-library/react").act;
31
21
  } catch (_) {
32
- act = (callback) => {
33
- callback();
34
- };
22
+ act = (callback) => {
23
+ callback();
24
+ };
35
25
  }
36
26
  var act_compat_default = act;
37
-
38
- // src/queue.ts
27
+ //#endregion
28
+ //#region src/queue.ts
29
+ /**
30
+ * @copyright Romain Bertrand 2018
31
+ */
39
32
  var Queue = class {
40
- pendingItems = [];
41
- nextItemResolver;
42
- nextItem = new Promise((done) => this.nextItemResolver = done);
43
- put(item) {
44
- this.pendingItems.push(item);
45
- this.nextItemResolver();
46
- this.nextItem = new Promise((done) => this.nextItemResolver = done);
47
- }
48
- get() {
49
- const item = this.pendingItems.shift();
50
- if (item) {
51
- return Promise.resolve(item);
52
- }
53
- let resolver;
54
- const nextItemPromise = new Promise((done) => resolver = done);
55
- this.nextItem.then(() => {
56
- resolver(this.pendingItems.shift());
57
- });
58
- return nextItemPromise;
59
- }
33
+ pendingItems = [];
34
+ nextItemResolver;
35
+ nextItem = new Promise((done) => this.nextItemResolver = done);
36
+ put(item) {
37
+ this.pendingItems.push(item);
38
+ this.nextItemResolver();
39
+ this.nextItem = new Promise((done) => this.nextItemResolver = done);
40
+ }
41
+ get() {
42
+ const item = this.pendingItems.shift();
43
+ if (item) return Promise.resolve(item);
44
+ let resolver;
45
+ const nextItemPromise = new Promise((done) => resolver = done);
46
+ this.nextItem.then(() => {
47
+ resolver(this.pendingItems.shift());
48
+ });
49
+ return nextItemPromise;
50
+ }
60
51
  };
61
-
62
- // src/websocket.ts
63
- var identity = (x) => x;
64
- var WS = class _WS {
65
- server;
66
- serializer;
67
- deserializer;
68
- static instances = [];
69
- messages = [];
70
- messagesToConsume = new Queue();
71
- _isConnected;
72
- _isClosed;
73
- static clean() {
74
- _WS.instances.forEach((instance) => {
75
- instance.close();
76
- instance.messages = [];
77
- });
78
- _WS.instances = [];
79
- }
80
- constructor(url, opts = {}) {
81
- _WS.instances.push(this);
82
- const { jsonProtocol = false, ...serverOptions } = opts;
83
- this.serializer = jsonProtocol ? JSON.stringify : identity;
84
- this.deserializer = jsonProtocol ? JSON.parse : identity;
85
- let connectionResolver;
86
- let closedResolver;
87
- this._isConnected = new Promise((done) => connectionResolver = done);
88
- this._isClosed = new Promise((done) => closedResolver = done);
89
- this.server = new Server(url, serverOptions);
90
- this.server.on("close", closedResolver);
91
- this.server.on("connection", (socket) => {
92
- connectionResolver(socket);
93
- socket.on("message", (message) => {
94
- const parsedMessage = this.deserializer(message);
95
- this.messages.push(parsedMessage);
96
- this.messagesToConsume.put(parsedMessage);
97
- });
98
- });
99
- }
100
- get connected() {
101
- let resolve;
102
- const connectedPromise = new Promise((done) => resolve = done);
103
- const waitForConnected = async () => {
104
- await act_compat_default(async () => {
105
- await this._isConnected;
106
- });
107
- resolve(await this._isConnected);
108
- };
109
- waitForConnected();
110
- return connectedPromise;
111
- }
112
- get closed() {
113
- let resolve;
114
- const closedPromise = new Promise((done) => resolve = done);
115
- const waitForclosed = async () => {
116
- await act_compat_default(async () => {
117
- await this._isClosed;
118
- });
119
- await this._isClosed;
120
- resolve();
121
- };
122
- waitForclosed();
123
- return closedPromise;
124
- }
125
- get nextMessage() {
126
- return this.messagesToConsume.get();
127
- }
128
- on(eventName, callback) {
129
- this.server.on(eventName, callback);
130
- }
131
- send(message) {
132
- act_compat_default(() => {
133
- this.server.emit("message", this.serializer(message));
134
- });
135
- }
136
- close(options) {
137
- act_compat_default(() => {
138
- this.server.close(options);
139
- });
140
- }
141
- error(options) {
142
- act_compat_default(() => {
143
- this.server.emit("error", null);
144
- });
145
- this.server.close(options);
146
- }
52
+ //#endregion
53
+ //#region src/websocket.ts
54
+ /**
55
+ * @copyright Romain Bertrand 2018
56
+ * @copyright Akiomi Kamakura 2023
57
+ */
58
+ const identity = (x) => x;
59
+ var WS = class WS {
60
+ server;
61
+ serializer;
62
+ deserializer;
63
+ static instances = [];
64
+ messages = [];
65
+ messagesToConsume = new Queue();
66
+ _isConnected;
67
+ _isClosed;
68
+ static clean() {
69
+ WS.instances.forEach((instance) => {
70
+ instance.close();
71
+ instance.messages = [];
72
+ });
73
+ WS.instances = [];
74
+ }
75
+ constructor(url, opts = {}) {
76
+ WS.instances.push(this);
77
+ const { jsonProtocol = false, ...serverOptions } = opts;
78
+ this.serializer = jsonProtocol ? JSON.stringify : identity;
79
+ this.deserializer = jsonProtocol ? JSON.parse : identity;
80
+ let connectionResolver;
81
+ let closedResolver;
82
+ this._isConnected = new Promise((done) => connectionResolver = done);
83
+ this._isClosed = new Promise((done) => closedResolver = done);
84
+ this.server = new Server(url, serverOptions);
85
+ this.server.on("close", closedResolver);
86
+ this.server.on("connection", (socket) => {
87
+ connectionResolver(socket);
88
+ socket.on("message", (message) => {
89
+ const parsedMessage = this.deserializer(message);
90
+ this.messages.push(parsedMessage);
91
+ this.messagesToConsume.put(parsedMessage);
92
+ });
93
+ });
94
+ }
95
+ get connected() {
96
+ let resolve;
97
+ const connectedPromise = new Promise((done) => resolve = done);
98
+ const waitForConnected = async () => {
99
+ await act_compat_default(async () => {
100
+ await this._isConnected;
101
+ });
102
+ resolve(await this._isConnected);
103
+ };
104
+ waitForConnected();
105
+ return connectedPromise;
106
+ }
107
+ get closed() {
108
+ let resolve;
109
+ const closedPromise = new Promise((done) => resolve = done);
110
+ const waitForclosed = async () => {
111
+ await act_compat_default(async () => {
112
+ await this._isClosed;
113
+ });
114
+ await this._isClosed;
115
+ resolve();
116
+ };
117
+ waitForclosed();
118
+ return closedPromise;
119
+ }
120
+ get nextMessage() {
121
+ return this.messagesToConsume.get();
122
+ }
123
+ on(eventName, callback) {
124
+ this.server.on(eventName, callback);
125
+ }
126
+ send(message) {
127
+ act_compat_default(() => {
128
+ this.server.emit("message", this.serializer(message));
129
+ });
130
+ }
131
+ close(options) {
132
+ act_compat_default(() => {
133
+ this.server.close(options);
134
+ });
135
+ }
136
+ error(options) {
137
+ act_compat_default(() => {
138
+ this.server.emit("error", null);
139
+ });
140
+ this.server.close(options);
141
+ }
147
142
  };
143
+ //#endregion
144
+ //#region src/matcherUtils.ts
145
+ /**
146
+ * Plain-text replacements for `this.utils.matcherHint` / `printExpected` /
147
+ * `printReceived`. Matcher messages must not contain ANSI color codes, so
148
+ * that color detection (e.g. AI-agent environments) cannot make them differ
149
+ * between environments; the reporter renders its own colored diff from the
150
+ * `actual` / `expected` returned by matchers.
151
+ */
152
+ function matcherHint(matcher, isNot = false) {
153
+ return `expect(WS).${isNot ? "not." : ""}${matcher}(expected)`;
154
+ }
155
+ const SPACE_SYMBOL = "·";
156
+ function replaceTrailingSpaces(text) {
157
+ return text.replace(/\s+$/gm, (spaces) => SPACE_SYMBOL.repeat(spaces.length));
158
+ }
159
+ function printValue(value) {
160
+ return replaceTrailingSpaces(this.utils.stringify(value));
161
+ }
162
+ function formatComparison(hint, expectedLabel, expected, receivedLabel, received) {
163
+ return hint + `
148
164
 
149
- // src/derivers/makeInvalidWsMessage.ts
165
+ ${expectedLabel}\n ${printValue.call(this, expected)}\n${receivedLabel}\n ${printValue.call(this, received)}`;
166
+ }
167
+ //#endregion
168
+ //#region src/derivers/makeInvalidWsMessage.ts
150
169
  function makeInvalidWsMessage(ws, matcher) {
151
- return this.utils.matcherHint(this.isNot ? `.not.${matcher}` : `.${matcher}`, "WS", "expected") + `
170
+ return matcherHint(matcher, this.isNot) + `
152
171
 
153
172
  Expected the websocket object to be a valid WS mock.
154
- Received: ${typeof ws}
155
- ${this.utils.printReceived(ws)}`;
173
+ Received: ${typeof ws}\n ${printValue.call(this, ws)}`;
156
174
  }
157
-
158
- // src/derivers/deriveToHaveReceivedMessage.ts
175
+ //#endregion
176
+ //#region src/derivers/deriveToHaveReceivedMessage.ts
159
177
  function deriveToHaveReceivedMessage(name, fn) {
160
- return function(ws, expected, options) {
161
- const isWS = ws instanceof WS;
162
- if (!isWS) {
163
- return {
164
- pass: this.isNot,
165
- // always fail
166
- message: makeInvalidWsMessage.bind(this, ws, name)
167
- };
168
- }
169
- return fn.call(this, ws.messages, expected, options);
170
- };
178
+ return function(ws, expected, options) {
179
+ if (!(ws instanceof WS)) return {
180
+ pass: this.isNot,
181
+ message: makeInvalidWsMessage.bind(this, ws, name)
182
+ };
183
+ return fn.call(this, ws.messages, expected, options);
184
+ };
171
185
  }
172
-
173
- // src/derivers/deriveToReceiveMessage.ts
174
- var WAIT_DELAY = 1e3;
175
- var TIMEOUT = Symbol("timeout");
186
+ //#endregion
187
+ //#region src/derivers/deriveToReceiveMessage.ts
188
+ const WAIT_DELAY = 1e3;
189
+ const TIMEOUT = Symbol("timeout");
176
190
  function deriveToReceiveMessage(name, fn) {
177
- return async function(ws, expected, options) {
178
- const isWS = ws instanceof WS;
179
- if (!isWS) {
180
- return {
181
- pass: this.isNot,
182
- // always fail
183
- message: makeInvalidWsMessage.bind(this, ws, name)
184
- };
185
- }
186
- const waitDelay = options?.timeout ?? WAIT_DELAY;
187
- const messageOrTimeout = await Promise.race([
188
- ws.nextMessage,
189
- new Promise((resolve) => setTimeout(() => resolve(TIMEOUT), waitDelay))
190
- ]);
191
- if (messageOrTimeout === TIMEOUT) {
192
- return {
193
- pass: this.isNot,
194
- // always fail
195
- message: () => this.utils.matcherHint(`${this.isNot ? ".not" : ""}.${name}`, "WS", "expected") + `
191
+ return async function(ws, expected, options) {
192
+ if (!(ws instanceof WS)) return {
193
+ pass: this.isNot,
194
+ message: makeInvalidWsMessage.bind(this, ws, name)
195
+ };
196
+ const waitDelay = options?.timeout ?? WAIT_DELAY;
197
+ const messageOrTimeout = await Promise.race([ws.nextMessage, new Promise((resolve) => setTimeout(() => resolve(TIMEOUT), waitDelay))]);
198
+ if (messageOrTimeout === TIMEOUT) return {
199
+ pass: this.isNot,
200
+ message: () => matcherHint(name, this.isNot) + `
196
201
 
197
202
  Expected the websocket server to receive a message,
198
203
  but it didn't receive anything in ${waitDelay}ms.`
199
- };
200
- } else {
201
- const received = messageOrTimeout;
202
- return Promise.resolve(fn.call(this, received, expected, options));
203
- }
204
- };
204
+ };
205
+ else {
206
+ const received = messageOrTimeout;
207
+ return Promise.resolve(fn.call(this, received, expected, options));
208
+ }
209
+ };
205
210
  }
206
-
207
- // src/matchers/toHaveReceivedMessages.ts
208
- var toHaveReceivedMessages = deriveToHaveReceivedMessage(
209
- "toHaveReceivedMessages",
210
- function(received, expected) {
211
- const equalities = expected.map(
212
- (expectedMsg) => (
213
- // object comparison to handle JSON protocols
214
- received.some((receivedMsg) => this.equals(receivedMsg, expectedMsg))
215
- )
216
- );
217
- const pass = this.isNot ? equalities.some(Boolean) : equalities.every(Boolean);
218
- const message = pass ? () => this.utils.matcherHint(".not.toHaveReceivedMessages", "WS", "expected") + `
219
-
220
- Expected the WS server to not have received the following messages:
221
- ${this.utils.printExpected(expected)}
222
- But it received:
223
- ${this.utils.printReceived(received)}` : () => {
224
- return this.utils.matcherHint(".toHaveReceivedMessages", "WS", "expected") + `
225
-
226
- Expected the WS server to have received the following messages:
227
- ${this.utils.printExpected(expected)}
228
- Received:
229
- ${this.utils.printReceived(received)}
230
-
231
- `;
232
- };
233
- return {
234
- actual: received,
235
- expected,
236
- message,
237
- pass
238
- };
239
- }
240
- );
241
- var toHaveReceivedMessages_default = toHaveReceivedMessages;
242
-
243
- // src/matchers/toReceiveMessage.ts
244
- import { diff } from "@vitest/utils/diff";
245
- var toReceiveMessage = deriveToReceiveMessage("toReceiveMessage", function(received, expected) {
246
- const pass = this.equals(received, expected);
247
- const message = pass ? () => this.utils.matcherHint(".not.toReceiveMessage", "WS", "expected") + `
248
-
249
- Expected the next received message to not equal:
250
- ${this.utils.printExpected(expected)}
251
- Received:
252
- ${this.utils.printReceived(received)}` : () => {
253
- const diffString = diff(expected, received, { expand: this.expand });
254
- return this.utils.matcherHint(".toReceiveMessage", "WS", "expected") + `
255
-
256
- Expected the next received message to equal:
257
- ${this.utils.printExpected(expected)}
258
- Received:
259
- ${this.utils.printReceived(received)}
260
-
261
- Difference:
262
-
263
- ${diffString}`;
264
- };
265
- return {
266
- actual: received,
267
- expected,
268
- message,
269
- pass
270
- };
211
+ //#endregion
212
+ //#region src/derivers/index.ts
213
+ /**
214
+ * @copyright Romain Bertrand 2018
215
+ * @copyright Akiomi Kamakura 2023
216
+ */
217
+ //#endregion
218
+ //#region src/matchers/toHaveReceivedMessages.ts
219
+ const toHaveReceivedMessages = deriveToHaveReceivedMessage("toHaveReceivedMessages", function(received, expected) {
220
+ const equalities = expected.map((expectedMsg) => received.some((receivedMsg) => this.equals(receivedMsg, expectedMsg)));
221
+ const pass = this.isNot ? equalities.some(Boolean) : equalities.every(Boolean);
222
+ return {
223
+ actual: received,
224
+ expected,
225
+ message: pass ? () => formatComparison.call(this, matcherHint("toHaveReceivedMessages", true), "Expected the WS server to not have received the following messages:", expected, "But it received:", received) : () => formatComparison.call(this, matcherHint("toHaveReceivedMessages"), "Expected the WS server to have received the following messages:", expected, "Received:", received),
226
+ pass
227
+ };
271
228
  });
272
- var toReceiveMessage_default = toReceiveMessage;
273
-
274
- // src/extend-expect.ts
229
+ //#endregion
230
+ //#region src/matchers/toReceiveMessage.ts
231
+ const toReceiveMessage = deriveToReceiveMessage("toReceiveMessage", function(received, expected) {
232
+ const pass = this.equals(received, expected);
233
+ return {
234
+ actual: received,
235
+ expected,
236
+ message: pass ? () => formatComparison.call(this, matcherHint("toReceiveMessage", true), "Expected the next received message to not equal:", expected, "Received:", received) : () => formatComparison.call(this, matcherHint("toReceiveMessage"), "Expected the next received message to equal:", expected, "Received:", received),
237
+ pass
238
+ };
239
+ });
240
+ //#endregion
241
+ //#region src/matchers/index.ts
242
+ var matchers_exports = /* @__PURE__ */ __exportAll({
243
+ toHaveReceivedMessages: () => toHaveReceivedMessages,
244
+ toReceiveMessage: () => toReceiveMessage
245
+ });
246
+ //#endregion
247
+ //#region src/extend-expect.ts
248
+ /**
249
+ * @copyright Romain Bertrand 2018
250
+ * @copyright Akiomi Kamakura 2023
251
+ */
275
252
  expect.extend(matchers_exports);
276
- export {
277
- WS,
278
- WS as default,
279
- deriveToHaveReceivedMessage,
280
- deriveToReceiveMessage
281
- };
253
+ //#endregion
254
+ export { WS, WS as default, deriveToHaveReceivedMessage, deriveToReceiveMessage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitest-websocket-mock",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Mock websockets and assert complex websocket interactions with Vitest",
5
5
  "type": "module",
6
6
  "repository": {
@@ -18,9 +18,10 @@
18
18
  "scripts": {
19
19
  "clean": "rimraf dist",
20
20
  "prebuild": "npm run clean",
21
- "build": "tsup",
22
- "lint": "prettier --check . && eslint .",
23
- "format": "prettier --write .",
21
+ "build": "tsdown",
22
+ "typecheck": "tsc --noEmit",
23
+ "lint": "biome check .",
24
+ "format": "biome check --write .",
24
25
  "prepublishOnly": "npm run build",
25
26
  "test": "vitest --run",
26
27
  "test:watch": "vitest"
@@ -34,31 +35,26 @@
34
35
  "author": "Akiomi Kamakura",
35
36
  "license": "MIT",
36
37
  "devDependencies": {
37
- "@typescript-eslint/eslint-plugin": "^5.59.0",
38
- "@typescript-eslint/parser": "^5.59.0",
39
- "@vitest/coverage-v8": "^3.0.0",
40
- "eslint": "^8.38.0",
41
- "eslint-config-prettier": "^8.5.0",
42
- "eslint-config-react-app": "^7.0.1",
43
- "eslint-plugin-react-hooks": "^4.6.0",
44
- "eslint-plugin-react-refresh": "^0.3.4",
45
- "eslint-plugin-simple-import-sort": "^10.0.0",
46
- "prettier": "^2.0.2",
38
+ "@biomejs/biome": "^2.5.3",
39
+ "@types/node": "^26.1.1",
40
+ "@vitest/coverage-v8": "^4.1.10",
47
41
  "rimraf": "^4.1.2",
48
- "tsup": "^7.0.0",
49
- "typescript": "^4.0.2",
50
- "vite": "^5.0.6",
51
- "vitest": "^3.0.0"
42
+ "tsdown": "^0.22.5",
43
+ "typescript": "^7.0.2",
44
+ "vite": "^8.1.4",
45
+ "vitest": "^4.1.10"
52
46
  },
53
47
  "peerDependencies": {
54
- "vitest": ">=3"
48
+ "vitest": ">=4"
55
49
  },
56
50
  "dependencies": {
57
- "@vitest/utils": "^3.0.0",
58
51
  "mock-socket": "^9.2.1"
59
52
  },
60
53
  "files": [
61
54
  "dist",
62
55
  "LICENSE"
63
- ]
56
+ ],
57
+ "overrides": {
58
+ "esbuild": "^0.28.1"
59
+ }
64
60
  }