vitest-websocket-mock 0.1.2 → 0.2.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/LICENSE CHANGED
@@ -1,27 +1,5 @@
1
- Copyright 2023 Akiomi Kamakura
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy
4
- of this software and associated documentation files (the "Software"), to deal
5
- in the Software without restriction, including without limitation the rights
6
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- copies of the Software, and to permit persons to whom the Software is
8
- furnished to do so, subject to the following conditions:
9
-
10
- The above copyright notice and this permission notice shall be included in all
11
- copies or substantial portions of the Software.
12
-
13
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
- SOFTWARE.
20
-
21
- The major part of vitest-websocket-mock implementation is based on jest-webosocket-mock, which is subject to the same license.
22
- Here is the original copyright notice for jest-webosocket-mock:
23
-
24
1
  Copyright 2018 Romain Bertrand
2
+ Copyright 2023 Akiomi Kamakura
25
3
 
26
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
27
5
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -8,13 +8,11 @@ A set of utilities and Vitest matchers to help testing complex websocket interac
8
8
  A patched fork of [romgain/jest-websocket-mock](https://github.com/romgain/jest-websocket-mock).
9
9
 
10
10
  **Examples:**
11
- ~~Several examples are provided in the [examples folder](https://github.com/akiomik/vitest-websocket-mock/blob/main/examples/).
12
- In particular:~~
11
+ Several examples are provided in the [examples folder](https://github.com/akiomik/vitest-websocket-mock/blob/main/examples/).
12
+ In particular:
13
13
 
14
- NOTE: These examples are currently not working :cry:
15
-
16
- - [testing a redux saga that manages a websocket connection](https://github.com/akiomik/vitest-websocket-mock/blob/main/examples/redux-saga/src/__tests__/saga.test.js)
17
- - [testing a component using the saga above](https://github.com/akiomik/vitest-websocket-mock/blob/main/examples/redux-saga/src/__tests__/App.test.js)
14
+ - [testing a redux saga that manages a websocket connection](https://github.com/akiomik/vitest-websocket-mock/blob/main/examples/redux-saga/src/__tests__/saga.test.ts)
15
+ - [testing a component using the saga above](https://github.com/akiomik/vitest-websocket-mock/blob/main/examples/redux-saga/src/__tests__/App.test.tsx)
18
16
  - [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)
19
17
 
20
18
  ## Install
@@ -292,7 +290,7 @@ afterEach(() => {
292
290
 
293
291
  ## Known issues
294
292
 
295
- `mock-socket` has a strong usage of delays (`setTimeout` to be more specific). This means using `vitest.useFakeTimers();` will cause issues such as the client appearing to never connect to the server.
293
+ `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.
296
294
 
297
295
  While running the websocket server from tests within the vitest-dom environment (as opposed to node)
298
296
  you may see errors of the nature:
@@ -343,8 +341,6 @@ restrict yourself to the browser APIs!
343
341
 
344
342
  ## Examples
345
343
 
346
- ~~For a real life example, see the
344
+ For a real life example, see the
347
345
  [examples directory](https://github.com/akiomik/vitest-websocket-mock/tree/main/examples),
348
- and in particular the saga tests.~~
349
-
350
- NOTE: These examples are currently not working :cry:
346
+ and in particular the saga tests.
package/dist/index.d.ts CHANGED
@@ -20,9 +20,6 @@ interface WSOptions extends ServerOptions {
20
20
  jsonProtocol?: boolean;
21
21
  }
22
22
  type DeserializedMessage<TMessage = object> = string | TMessage;
23
- interface MockWebSocket extends Omit<Client, 'close'> {
24
- close(options?: CloseOptions): void;
25
- }
26
23
  declare class WS {
27
24
  server: Server;
28
25
  serializer: (deserializedMessage: DeserializedMessage) => string;
@@ -37,7 +34,7 @@ declare class WS {
37
34
  get connected(): Promise<Client>;
38
35
  get closed(): Promise<void>;
39
36
  get nextMessage(): Promise<unknown>;
40
- on(eventName: 'connection' | 'message' | 'close', callback: (socket: MockWebSocket) => void): void;
37
+ on(eventName: 'connection' | 'message' | 'close', callback: (socket: Client) => void): void;
41
38
  send(message: DeserializedMessage): void;
42
39
  close(options?: CloseOptions): void;
43
40
  error(options?: CloseOptions): void;
package/dist/index.js CHANGED
@@ -71,7 +71,8 @@ var WS = class _WS {
71
71
  const { jsonProtocol = false, ...serverOptions } = opts;
72
72
  this.serializer = jsonProtocol ? JSON.stringify : identity;
73
73
  this.deserializer = jsonProtocol ? JSON.parse : identity;
74
- let connectionResolver, closedResolver;
74
+ let connectionResolver;
75
+ let closedResolver;
75
76
  this._isConnected = new Promise((done) => connectionResolver = done);
76
77
  this._isClosed = new Promise((done) => closedResolver = done);
77
78
  this.server = new Server(url, serverOptions);
@@ -136,7 +137,7 @@ var WS = class _WS {
136
137
 
137
138
  // src/matchers.ts
138
139
  var WAIT_DELAY = 1e3;
139
- var TIMEOUT = Symbol("timoeut");
140
+ var TIMEOUT = Symbol("timeout");
140
141
  var makeInvalidWsMessage = function makeInvalidWsMessage2(ws, matcher) {
141
142
  return this.utils.matcherHint(this.isNot ? `.not.${matcher}` : `.${matcher}`, "WS", "expected") + `
142
143
 
@@ -144,14 +145,14 @@ Expected the websocket object to be a valid WS mock.
144
145
  Received: ${typeof ws}
145
146
  ${this.utils.printReceived(ws)}`;
146
147
  };
147
- expect.extend({
148
- async toReceiveMessage(ws, expected, options) {
148
+ var deriveToReceiveMessage = (name, fn) => {
149
+ return async function(ws, expected, options) {
149
150
  const isWS = ws instanceof WS;
150
151
  if (!isWS) {
151
152
  return {
152
153
  pass: this.isNot,
153
154
  // always fail
154
- message: makeInvalidWsMessage.bind(this, ws, "toReceiveMessage")
155
+ message: makeInvalidWsMessage.bind(this, ws, name)
155
156
  };
156
157
  }
157
158
  const waitDelay = options?.timeout ?? WAIT_DELAY;
@@ -163,22 +164,28 @@ expect.extend({
163
164
  return {
164
165
  pass: this.isNot,
165
166
  // always fail
166
- message: () => this.utils.matcherHint(this.isNot ? ".not.toReceiveMessage" : ".toReceiveMessage", "WS", "expected") + `
167
+ message: () => this.utils.matcherHint(`${this.isNot ? ".not" : ""}.${name}`, "WS", "expected") + `
167
168
 
168
169
  Expected the websocket server to receive a message,
169
170
  but it didn't receive anything in ${waitDelay}ms.`
170
171
  };
172
+ } else {
173
+ const received = messageOrTimeout;
174
+ const result = await Promise.resolve(fn.call(this, received, expected, options));
175
+ return { name, ...result };
171
176
  }
172
- const received = messageOrTimeout;
173
- const pass = this.equals(received, expected);
174
- const message = pass ? () => this.utils.matcherHint(".not.toReceiveMessage", "WS", "expected") + `
177
+ };
178
+ };
179
+ var toReceiveMessage = deriveToReceiveMessage("toReceiveMessage", function(received, expected) {
180
+ const pass = this.equals(received, expected);
181
+ const message = pass ? () => this.utils.matcherHint(".not.toReceiveMessage", "WS", "expected") + `
175
182
 
176
183
  Expected the next received message to not equal:
177
184
  ${this.utils.printExpected(expected)}
178
185
  Received:
179
186
  ${this.utils.printReceived(received)}` : () => {
180
- const diffString = diff(expected, received, { expand: this.expand });
181
- return this.utils.matcherHint(".toReceiveMessage", "WS", "expected") + `
187
+ const diffString = diff(expected, received, { expand: this.expand });
188
+ return this.utils.matcherHint(".toReceiveMessage", "WS", "expected") + `
182
189
 
183
190
  Expected the next received message to equal:
184
191
  ${this.utils.printExpected(expected)}
@@ -188,54 +195,64 @@ Received:
188
195
  Difference:
189
196
 
190
197
  ${diffString}`;
191
- };
192
- return {
193
- actual: received,
194
- expected,
195
- message,
196
- name: "toReceiveMessage",
197
- pass
198
- };
199
- },
200
- toHaveReceivedMessages(ws, messages) {
198
+ };
199
+ return {
200
+ actual: received,
201
+ expected,
202
+ message,
203
+ pass
204
+ };
205
+ });
206
+ var deriveToHaveReceivedMessage = (name, fn) => {
207
+ return function(ws, expected, options) {
201
208
  const isWS = ws instanceof WS;
202
209
  if (!isWS) {
203
210
  return {
204
211
  pass: this.isNot,
205
212
  // always fail
206
- message: makeInvalidWsMessage.bind(this, ws, "toHaveReceivedMessages")
213
+ message: makeInvalidWsMessage.bind(this, ws, name)
207
214
  };
208
215
  }
209
- const received = messages.map(
210
- (expected) => (
216
+ const result = fn.call(this, ws.messages, expected, options);
217
+ return { name, ...result };
218
+ };
219
+ };
220
+ var toHaveReceivedMessages = deriveToHaveReceivedMessage(
221
+ "toHaveReceivedMessages",
222
+ function(received, expected) {
223
+ const equalities = expected.map(
224
+ (expectedMsg) => (
211
225
  // object comparison to handle JSON protocols
212
- ws.messages.some((actual) => this.equals(actual, expected))
226
+ received.some((receivedMsg) => this.equals(receivedMsg, expectedMsg))
213
227
  )
214
228
  );
215
- const pass = this.isNot ? received.some(Boolean) : received.every(Boolean);
229
+ const pass = this.isNot ? equalities.some(Boolean) : equalities.every(Boolean);
216
230
  const message = pass ? () => this.utils.matcherHint(".not.toHaveReceivedMessages", "WS", "expected") + `
217
231
 
218
232
  Expected the WS server to not have received the following messages:
219
- ${this.utils.printExpected(messages)}
233
+ ${this.utils.printExpected(expected)}
220
234
  But it received:
221
- ${this.utils.printReceived(ws.messages)}` : () => {
235
+ ${this.utils.printReceived(received)}` : () => {
222
236
  return this.utils.matcherHint(".toHaveReceivedMessages", "WS", "expected") + `
223
237
 
224
238
  Expected the WS server to have received the following messages:
225
- ${this.utils.printExpected(messages)}
239
+ ${this.utils.printExpected(expected)}
226
240
  Received:
227
- ${this.utils.printReceived(ws.messages)}
241
+ ${this.utils.printReceived(received)}
228
242
 
229
243
  `;
230
244
  };
231
245
  return {
232
- actual: ws.messages,
233
- expected: messages,
246
+ actual: received,
247
+ expected,
234
248
  message,
235
- name: "toHaveReceivedMessages",
236
249
  pass
237
250
  };
238
251
  }
252
+ );
253
+ expect.extend({
254
+ toReceiveMessage,
255
+ toHaveReceivedMessages
239
256
  });
240
257
  export {
241
258
  WS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitest-websocket-mock",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Mock websockets and assert complex websocket interactions with Vitest",
5
5
  "type": "module",
6
6
  "repository": {
@@ -34,26 +34,28 @@
34
34
  "author": "Akiomi Kamakura",
35
35
  "license": "MIT",
36
36
  "devDependencies": {
37
- "@typescript-eslint/eslint-plugin": "^5.45.0",
38
- "@typescript-eslint/parser": "^5.45.0",
39
- "@vitest/coverage-c8": "^0.32.2",
40
- "eslint": "^8.28.0",
37
+ "@typescript-eslint/eslint-plugin": "^5.59.0",
38
+ "@typescript-eslint/parser": "^5.59.0",
39
+ "@vitest/coverage-v8": "^0.32.2",
40
+ "eslint": "^8.38.0",
41
41
  "eslint-config-prettier": "^8.5.0",
42
42
  "eslint-config-react-app": "^7.0.1",
43
+ "eslint-plugin-react-hooks": "^4.6.0",
44
+ "eslint-plugin-react-refresh": "^0.3.4",
43
45
  "eslint-plugin-simple-import-sort": "^10.0.0",
44
46
  "prettier": "^2.0.2",
45
47
  "rimraf": "^4.1.2",
46
48
  "tsup": "^7.0.0",
47
49
  "typescript": "^4.0.2",
48
50
  "vite": "^4.3.9",
49
- "vitest": "^0.31.0"
51
+ "vitest": "^0.32.0"
50
52
  },
51
53
  "peerDependencies": {
52
- "vitest": "^0.31.0"
54
+ "vitest": "^0.32.0"
53
55
  },
54
56
  "dependencies": {
55
57
  "jest-diff": "^29.2.0",
56
- "mock-socket": "^9.1.0"
58
+ "mock-socket": "^9.2.1"
57
59
  },
58
60
  "files": [
59
61
  "dist",