vitest-websocket-mock 0.7.0 → 0.8.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
@@ -1,11 +1,15 @@
1
- # Vitest websocket mock
1
+ # vitest-websocket-mock
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/vitest-websocket-mock.svg)](https://badge.fury.io/js/vitest-websocket-mock)
4
4
  [![Build Status](https://github.com/akiomik/vitest-websocket-mock/actions/workflows/ci.yml/badge.svg)](https://github.com/akiomik/vitest-websocket-mock/actions)
5
5
  [![codecov](https://codecov.io/gh/akiomik/vitest-websocket-mock/branch/main/graph/badge.svg?token=40OVYIT90L)](https://codecov.io/gh/akiomik/vitest-websocket-mock)
6
6
 
7
- A set of utilities and Vitest matchers to help testing complex websocket interactions.
8
- A patched fork of [romgain/jest-websocket-mock](https://github.com/romgain/jest-websocket-mock).
7
+ A set of utilities and Vitest matchers to help testing complex websocket interactions:
8
+ mock websocket servers, wait for connections and messages, and assert on them
9
+ with dedicated matchers.
10
+
11
+ Originally forked from [romgain/jest-websocket-mock](https://github.com/romgain/jest-websocket-mock),
12
+ and since developed independently as a Vitest-first library.
9
13
 
10
14
  **Examples:**
11
15
  Several examples are provided in the [examples folder](https://github.com/akiomik/vitest-websocket-mock/blob/main/examples/).
@@ -15,8 +19,31 @@ In particular:
15
19
  - [testing a component using the saga above](https://github.com/akiomik/vitest-websocket-mock/blob/main/examples/redux-saga/src/__tests__/App.test.tsx)
16
20
  - [testing a component that manages a websocket connection using react hooks](https://github.com/akiomik/vitest-websocket-mock/blob/main/examples/hooks/src/App.test.tsx)
17
21
 
22
+ ## When to use this vs. MSW
23
+
24
+ [Vitest recommends](https://vitest.dev/guide/mocking/requests) [Mock Service Worker (MSW)](https://mswjs.io)
25
+ for mocking network requests, and MSW has first-class
26
+ [WebSocket support](https://mswjs.io/docs/websocket/). The two address different
27
+ layers of the problem:
28
+
29
+ - **MSW** provides declarative, network-level mocking (`ws.link()` handlers).
30
+ It shines when you want to share handlers between your app, Storybook, and
31
+ tests, or when you also need to mock HTTP or GraphQL.
32
+ - **`vitest-websocket-mock`** provides imperative test-flow ergonomics that MSW
33
+ does not: a `WS` mock-server object, `await server.connected`, a synchronous
34
+ record of received messages in `server.messages`, and custom matchers such as
35
+ `.toReceiveMessage` and `.toHaveReceivedMessages`.
36
+
37
+ If your test reads best as a step-by-step conversation with a mock server
38
+ ("wait for the connection, assert on the next message, reply, assert again"),
39
+ this library is the better fit. Running this library on top of MSW's
40
+ interceptor, which would make the two complementary rather than alternatives,
41
+ is being explored in [#77](https://github.com/akiomik/vitest-websocket-mock/issues/77).
42
+
18
43
  ## Install
19
44
 
45
+ `vitest-websocket-mock` requires Vitest 5 as a peer dependency.
46
+
20
47
  ```bash
21
48
  npm install -D vitest-websocket-mock
22
49
  ```
@@ -65,7 +92,7 @@ const server = new WS('ws://localhost:1234', { jsonProtocol: true });
65
92
  server.send({ type: 'GREETING', payload: 'hello' });
66
93
  ```
67
94
 
68
- - The `mock-server` options `verifyClient` and `selectProtocol` are directly passed-through to the mock-server's constructor.
95
+ - The [`mock-socket`](https://github.com/thoov/mock-socket) server options `verifyClient` and `selectProtocol` are directly passed through to the underlying mock server's constructor.
69
96
 
70
97
  ### Attributes of a `WS` instance
71
98
 
@@ -98,8 +125,9 @@ A `WS` instance has the following attributes:
98
125
 
99
126
  ## Run assertions on received messages
100
127
 
101
- `vitest-websocket-mock` registers custom vitest matchers to make assertions
102
- on received messages easier:
128
+ `vitest-websocket-mock` registers custom Vitest matchers to make assertions
129
+ on received messages easier. They are registered automatically when
130
+ `vitest-websocket-mock` is imported, so no extra setup file is needed:
103
131
 
104
132
  - `.toReceiveMessage`: async matcher that waits for the next message received
105
133
  by the mock websocket server, and asserts its content. It will time out
@@ -329,6 +357,19 @@ You can work around this by installing the setImmediate shim from
329
357
  [https://github.com/YuzuJS/setImmediate](https://github.com/YuzuJS/setImmediate) and
330
358
  adding `require('setimmediate');` to your `setupTests.js`.
331
359
 
360
+ ### The custom matchers are not recognized by TypeScript
361
+
362
+ ```
363
+ Property 'toReceiveMessage' does not exist on type 'Assertion<void, WS>'.
364
+ ```
365
+
366
+ The matchers are contributed with [module augmentation][augmentation], which
367
+ only merges into the copy of `vitest` the augmentation resolves to. Deduplicate
368
+ `vitest` if your project resolves more than one, for example a monorepo where a
369
+ nested package pins its own.
370
+
371
+ [augmentation]: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
372
+
332
373
  ## Testing React applications
333
374
 
334
375
  When testing React applications, `vitest-websocket-mock` will look for
@@ -377,9 +418,3 @@ the `mock-socket` library that `vitest-websocket-mock` uses under the hood only
377
418
  implements the browser API.
378
419
  As a result, `vitest-websocket-mock` will only work with the `ws` library if you
379
420
  restrict yourself to the browser APIs!
380
-
381
- ## Examples
382
-
383
- For a real life example, see the
384
- [examples directory](https://github.com/akiomik/vitest-websocket-mock/tree/main/examples),
385
- and in particular the saga tests.
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
+ import { Matcher } from "vitest";
1
2
  import { Client, CloseOptions, Server, ServerOptions } from "mock-socket";
2
- import { RawMatcherFn } from "@vitest/expect";
3
3
  //#region src/derivers/deriveToHaveReceivedMessage.d.ts
4
- declare function deriveToHaveReceivedMessage(name: string, fn: RawMatcherFn): RawMatcherFn;
4
+ declare function deriveToHaveReceivedMessage(name: string, fn: Matcher): Matcher;
5
5
  //#endregion
6
6
  //#region src/derivers/deriveToReceiveMessage.d.ts
7
- declare function deriveToReceiveMessage(name: string, fn: RawMatcherFn): RawMatcherFn;
7
+ declare function deriveToReceiveMessage(name: string, fn: Matcher): Matcher;
8
8
  //#endregion
9
9
  //#region src/derivers/types.d.ts
10
10
  /**
@@ -32,7 +32,7 @@ interface WSOptions extends ServerOptions {
32
32
  jsonProtocol?: boolean;
33
33
  }
34
34
  type DeserializedMessage<TMessage = object> = string | TMessage;
35
- declare class WS {
35
+ export default class WS {
36
36
  server: Server;
37
37
  serializer: (deserializedMessage: DeserializedMessage) => string;
38
38
  deserializer: (message: string) => DeserializedMessage;
@@ -54,14 +54,13 @@ declare class WS {
54
54
  //#endregion
55
55
  //#region src/matchers/index.d.ts
56
56
  interface CustomMatchers<R = unknown> {
57
- toReceiveMessage<TMessage = object>(message: DeserializedMessage<TMessage>, options?: ReceiveMessageOptions): Promise<R>;
57
+ toReceiveMessage<TMessage = object>(message: DeserializedMessage<TMessage>, options?: ReceiveMessageOptions): Promise<void>;
58
58
  toHaveReceivedMessages<TMessage = object>(messages: Array<DeserializedMessage<TMessage>>): R;
59
59
  }
60
60
  //#endregion
61
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 {}
62
+ declare module 'vitest' {
63
+ interface Matchers<R extends void | Promise<void> = void | Promise<void>, T = unknown> extends CustomMatchers<R> {}
65
64
  }
66
65
  //#endregion
67
- export { type ReceiveMessageOptions, WS, WS as default, deriveToHaveReceivedMessage, deriveToReceiveMessage };
66
+ export { type ReceiveMessageOptions, WS, deriveToHaveReceivedMessage, deriveToReceiveMessage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitest-websocket-mock",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Mock websockets and assert complex websocket interactions with Vitest",
5
5
  "type": "module",
6
6
  "repository": {
@@ -37,15 +37,15 @@
37
37
  "devDependencies": {
38
38
  "@biomejs/biome": "^2.5.3",
39
39
  "@types/node": "^26.1.1",
40
- "@vitest/coverage-v8": "^4.1.10",
41
- "rimraf": "^4.1.2",
42
- "tsdown": "^0.22.5",
40
+ "@vitest/coverage-v8": "^5.0.0",
41
+ "rimraf": "^6.1.3",
42
+ "tsdown": "^0.23.0",
43
43
  "typescript": "^7.0.2",
44
44
  "vite": "^8.1.4",
45
- "vitest": "^4.1.10"
45
+ "vitest": "^5.0.0"
46
46
  },
47
47
  "peerDependencies": {
48
- "vitest": ">=4"
48
+ "vitest": ">=5 <6"
49
49
  },
50
50
  "dependencies": {
51
51
  "mock-socket": "^9.2.1"