Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/exodusmovement/replay
Record/inspect/replay fetch and WebSocket sessions
https://github.com/exodusmovement/replay
Last synced: 8 days ago
JSON representation
Record/inspect/replay fetch and WebSocket sessions
- Host: GitHub
- URL: https://github.com/exodusmovement/replay
- Owner: ExodusMovement
- License: mit
- Created: 2024-08-06T15:43:17.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2024-09-11T14:04:59.000Z (2 months ago)
- Last Synced: 2024-09-11T22:02:18.021Z (2 months ago)
- Language: JavaScript
- Homepage: https://npmjs.com/@exodus/replay
- Size: 302 KB
- Stars: 1
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
# Record/inspect/replay `fetch` and `WebSocket` sessions
For offline testing
These implementations are not specific to `@exodus/test` and can be used separately
Zero-dependencies, bundleable
Replayers can run in V8 / JavaScriptCore / Hermes even with no network API implemented at all
```js
import { fetchRecorder, fetchReplayer, WebSocketRecorder, WebSocketReplayer, prettyJSON } from '@exodus/replay'
```Generated logs [are human-readable](#samples)
### `fetchRecorder(log[, { fetch }])`
Returns a `fetch` implementation that appends all requests to the provided `log` array
`log` is expected to be an array and is mutated by appending new requests
If a base `fetch` implementation is not passed, global `fetch` is used as the base
That can be overriden, e.g. `fetchRecorder(log, { fetch: require('node-fetch') })`
### `fetchReplayer(log)`
Returns a `fetch` implementation that replies with requests from the provided `log` array
Requests are served by "first matching" order and are discarded from an internal log clone
`log` is expected to be an array and is not mutated
### `WebSocketRecorder(log[, { WebSocket }])`
Returns a `WebSocket` implementation that appends all sessions to the provided `log` array
`log` is expected to be an array and is mutated by appending new sessions
If a base `WebSocket` implementation is not passed, global `WebSocket` is used as the base
That can be overriden, e.g. `WebSocketRecorder(log, { WebSocket: require('ws') })`
### `WebSocketReplayer(log[, { interval = 0 }])`
Returns a `WebSocket` implementation that replies with sessions from the provided `log` array
Sessions are served by "first matching" order and are discarded from an internal log clone
`log` is expected to be an array and is not mutated
Optionally, `interval` can be used to control replay speed:
- `interval = 0` for immediate event firing without delays (default)
- `interval = Infinity` for event timing matching the original recording
- `interval = number` for delay between events of `Math.min(number, recorededDelay)`
### `prettyJSON(data, { width = 120 })`
Use it to pretty-print logs: `prettyJSON(log)`
Like `JSON.stringify()`, but with pretty-printing for readability and ease if inspection
The output is parse-able with `JSON.parse()`
For simplicity, fitting into `width` is not guaranteed, but the output is stable between runs
## Samples
### `fetch` recording
```json
{
"request": {
"resource": "https://jsonplaceholder.typicode.com/users/2",
"options": { "headers": [["accept", "application/json"]] }
},
"status": 200,
"statusText": "OK",
"ok": true,
"headers": [
...
["connection", "keep-alive"],
["content-encoding", "br"],
["content-type", "application/json; charset=utf-8"],
["date", "Sat, 03 Aug 2024 16:57:51 GMT"],
...
],
"url": "https://jsonplaceholder.typicode.com/users/2",
"redirected": false,
"type": "basic",
"bodyType": "json",
"body": {
"id": 2,
"name": "Ervin Howell",
"username": "Antonette",
"email": "[email protected]",
"address": {
"street": "Victor Plains",
"suite": "Suite 879",
"city": "Wisokyburgh",
"zipcode": "90566-7771",
"geo": { "lat": "-43.9509", "lng": "-34.4618" }
},
"phone": "010-692-6593 x09125",
"website": "anastasia.net",
"company": {
"name": "Deckow-Crist",
"catchPhrase": "Proactive didactic contingency",
"bs": "synergize scalable supply-chains"
}
}
}
```### `WebSocket` recording
```json
{
"url": "wss://javascript.info/article/websocket/demo/hello",
"log": [
{ "type": "get readyState", "at": 24, "value": 0 },
{ "type": "open", "at": 426 },
{ "type": "get readyState", "at": 426, "value": 1 },
{ "type": "get bufferedAmount", "at": 427, "value": 0 },
{ "type": "send()", "at": 427, "data": "Hi there" },
{ "type": "get bufferedAmount", "at": 427, "value": 8 },
{ "type": "message", "at": 543, "data": "Hello from server, there!" },
{ "type": "close()", "at": 543 },
{ "type": "get readyState", "at": 543, "value": 2 },
{ "type": "close", "at": 661, "code": 1005, "reason": "", "wasClean": true },
{ "type": "get readyState", "at": 661, "value": 3 }
]
}
```