mockaton 8.12.6 → 8.12.7
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 +25 -12
- package/package.json +1 -1
- package/src/Api.js +14 -11
- package/src/ApiConstants.js +2 -2
- package/src/Commander.js +3 -3
- package/src/Dashboard.js +18 -21
- package/src/Watcher.js +7 -7
package/README.md
CHANGED
|
@@ -7,8 +7,9 @@ An HTTP mock server for simulating APIs with minimal setup
|
|
|
7
7
|
— ideal for triggering difficult to reproduce backend states.
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
##
|
|
11
|
-
Mockaton
|
|
10
|
+
## Overview
|
|
11
|
+
With Mockaton, you don’t need to write code for wiring up your mocks. Instead, a
|
|
12
|
+
given directory is scanned for filenames following a convention similar to the URLs.
|
|
12
13
|
|
|
13
14
|
For example, for <code>/<b>api/user</b>/1234</code> the filename would be:
|
|
14
15
|
<pre>
|
|
@@ -158,16 +159,6 @@ putting its built assets in `config.staticDir`. And simulate the flow by Bulk Se
|
|
|
158
159
|
|
|
159
160
|
<br/>
|
|
160
161
|
|
|
161
|
-
## Alternatives
|
|
162
|
-
- Chrome DevTools allows for [overriding responses](https://developer.chrome.com/docs/devtools/overrides)
|
|
163
|
-
- Reverse Proxies such as [Burp](https://portswigger.net/burp) are also handy for overriding responses.
|
|
164
|
-
- [MSW (Mock Server Worker)](https://mswjs.io)
|
|
165
|
-
- [Nock](https://github.com/nock/nock)
|
|
166
|
-
- [Fetch Mock](https://github.com/wheresrhys/fetch-mock)
|
|
167
|
-
- [Mentoss](https://github.com/humanwhocodes/mentoss)
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
<br/>
|
|
171
162
|
|
|
172
163
|
## You can write JSON mocks in JavaScript or TypeScript
|
|
173
164
|
For example, `api/foo.GET.200.js`
|
|
@@ -606,3 +597,25 @@ default, but the `proxyFallback`, `colledProxied`, and `corsAllowed` are not aff
|
|
|
606
597
|
```js
|
|
607
598
|
await mockaton.reset()
|
|
608
599
|
```
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
<br/>
|
|
603
|
+
|
|
604
|
+
## Alternatives worth learning as well
|
|
605
|
+
|
|
606
|
+
### Proxy-like
|
|
607
|
+
These are similar to Mockaton in the sense that you can modify the
|
|
608
|
+
mock response without loosing or risking your frontend code state. For
|
|
609
|
+
example, if you are polling, and you want to test the state change.
|
|
610
|
+
|
|
611
|
+
- Chrome DevTools allows for [overriding responses](https://developer.chrome.com/docs/devtools/overrides)
|
|
612
|
+
- Reverse Proxies such as [Burp](https://portswigger.net/burp) are also handy for overriding responses
|
|
613
|
+
|
|
614
|
+
### Client side
|
|
615
|
+
In contrast to Mockaton, which is an HTTP Server, these programs
|
|
616
|
+
mock the client (e.g., `fetch`) in Node.js and browsers.
|
|
617
|
+
|
|
618
|
+
- [MSW (Mock Server Worker)](https://mswjs.io)
|
|
619
|
+
- [Nock](https://github.com/nock/nock)
|
|
620
|
+
- [Fetch Mock](https://github.com/wheresrhys/fetch-mock)
|
|
621
|
+
- [Mentoss](https://github.com/humanwhocodes/mentoss) Has a server side too
|
package/package.json
CHANGED
package/src/Api.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { join } from 'node:path'
|
|
7
7
|
import { cookie } from './cookie.js'
|
|
8
|
-
import {
|
|
8
|
+
import { uiSyncVersion } from './Watcher.js'
|
|
9
9
|
import { parseJSON } from './utils/http-request.js'
|
|
10
10
|
import { listFilesRecursively } from './utils/fs.js'
|
|
11
11
|
import * as mockBrokersCollection from './mockBrokersCollection.js'
|
|
@@ -31,9 +31,9 @@ export const apiGetRequests = new Map([
|
|
|
31
31
|
[API.mocks, listMockBrokers],
|
|
32
32
|
[API.cookies, listCookies],
|
|
33
33
|
[API.fallback, getProxyFallback],
|
|
34
|
-
[API.arEvents, longPollAR_Events],
|
|
35
34
|
[API.comments, listComments],
|
|
36
35
|
[API.globalDelay, getGlobalDelay],
|
|
36
|
+
[API.syncVersion, longPollClientSyncVersion],
|
|
37
37
|
[API.collectProxied, getCollectProxied]
|
|
38
38
|
])
|
|
39
39
|
|
|
@@ -76,23 +76,26 @@ function listStaticFiles(req, response) {
|
|
|
76
76
|
: [])
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
function
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
sendJSON(response, arEvents.count)
|
|
79
|
+
function longPollClientSyncVersion(req, response) {
|
|
80
|
+
if (uiSyncVersion.version !== Number(req.headers[DF.syncVersion])) {
|
|
81
|
+
// e.g., tab was hidden while new mocks were added or removed
|
|
82
|
+
sendJSON(response, uiSyncVersion.version)
|
|
84
83
|
return
|
|
85
84
|
}
|
|
85
|
+
|
|
86
86
|
function onAddOrRemoveMock() {
|
|
87
|
-
|
|
88
|
-
sendJSON(response,
|
|
87
|
+
uiSyncVersion.unsubscribe(onAddOrRemoveMock)
|
|
88
|
+
sendJSON(response, uiSyncVersion.version)
|
|
89
89
|
}
|
|
90
|
+
|
|
90
91
|
response.setTimeout(LONG_POLL_SERVER_TIMEOUT, onAddOrRemoveMock)
|
|
92
|
+
|
|
91
93
|
req.on('error', () => {
|
|
92
|
-
|
|
94
|
+
uiSyncVersion.unsubscribe(onAddOrRemoveMock)
|
|
93
95
|
response.destroy()
|
|
94
96
|
})
|
|
95
|
-
|
|
97
|
+
|
|
98
|
+
uiSyncVersion.subscribe(onAddOrRemoveMock)
|
|
96
99
|
}
|
|
97
100
|
|
|
98
101
|
|
package/src/ApiConstants.js
CHANGED
|
@@ -14,7 +14,7 @@ export const API = {
|
|
|
14
14
|
proxied: MOUNT + '/proxied',
|
|
15
15
|
cors: MOUNT + '/cors',
|
|
16
16
|
static: MOUNT + '/static',
|
|
17
|
-
|
|
17
|
+
syncVersion: MOUNT + '/sync_version'
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export const DF = { // Dashboard Fields (XHR)
|
|
@@ -22,7 +22,7 @@ export const DF = { // Dashboard Fields (XHR)
|
|
|
22
22
|
routeUrlMask: 'route_url_mask',
|
|
23
23
|
delayed: 'delayed',
|
|
24
24
|
proxied: 'proxied',
|
|
25
|
-
|
|
25
|
+
syncVersion: 'last_received_sync_version'
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export const DEFAULT_500_COMMENT = '(Mockaton 500)'
|
package/src/Commander.js
CHANGED
|
@@ -92,11 +92,11 @@ export class Commander {
|
|
|
92
92
|
return this.#patch(API.reset)
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
return fetch(API.
|
|
95
|
+
getSyncVersion(currentSyncVersion, abortSignal) {
|
|
96
|
+
return fetch(API.syncVersion, {
|
|
97
97
|
signal: AbortSignal.any([abortSignal, AbortSignal.timeout(LONG_POLL_SERVER_TIMEOUT + 1000)]),
|
|
98
98
|
headers: {
|
|
99
|
-
[DF.
|
|
99
|
+
[DF.syncVersion]: currentSyncVersion
|
|
100
100
|
}
|
|
101
101
|
})
|
|
102
102
|
}
|
package/src/Dashboard.js
CHANGED
|
@@ -526,45 +526,42 @@ function CloudIcon() {
|
|
|
526
526
|
}
|
|
527
527
|
|
|
528
528
|
|
|
529
|
-
/**
|
|
529
|
+
/**
|
|
530
|
+
* # Poll UI Sync Version
|
|
531
|
+
* The version increments when a mock file is added or removed
|
|
532
|
+
*/
|
|
530
533
|
|
|
531
534
|
function initLongPoll() {
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
pollAR_Events()
|
|
535
|
+
poll.oldSyncVersion = 0
|
|
536
|
+
poll.controller = new AbortController()
|
|
537
|
+
poll()
|
|
536
538
|
document.addEventListener('visibilitychange', () => {
|
|
537
539
|
if (document.hidden) {
|
|
538
|
-
|
|
539
|
-
|
|
540
|
+
poll.controller.abort('_hidden_tab_')
|
|
541
|
+
poll.controller = new AbortController()
|
|
540
542
|
}
|
|
541
543
|
else
|
|
542
|
-
|
|
544
|
+
poll()
|
|
543
545
|
})
|
|
544
546
|
}
|
|
545
547
|
|
|
546
|
-
async function
|
|
547
|
-
if (pollAR_Events.isPolling)
|
|
548
|
-
return
|
|
548
|
+
async function poll() {
|
|
549
549
|
try {
|
|
550
|
-
|
|
551
|
-
const response = await mockaton.getAR_EventsCount(pollAR_Events.oldAR_EventsCount, pollAR_Events.controller.signal)
|
|
550
|
+
const response = await mockaton.getSyncVersion(poll.oldSyncVersion, poll.controller.signal)
|
|
552
551
|
if (response.ok) {
|
|
553
|
-
const
|
|
554
|
-
if (
|
|
555
|
-
|
|
552
|
+
const syncVersion = await response.json()
|
|
553
|
+
if (poll.oldSyncVersion !== syncVersion) { // because it could be < or >
|
|
554
|
+
poll.oldSyncVersion = syncVersion
|
|
556
555
|
await init()
|
|
557
556
|
}
|
|
558
|
-
|
|
559
|
-
pollAR_Events()
|
|
557
|
+
poll()
|
|
560
558
|
}
|
|
561
559
|
else
|
|
562
560
|
throw response.status
|
|
563
561
|
}
|
|
564
562
|
catch (error) {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
setTimeout(pollAR_Events, 3000)
|
|
563
|
+
if (error !== '_hidden_tab_')
|
|
564
|
+
setTimeout(poll, 3000)
|
|
568
565
|
}
|
|
569
566
|
}
|
|
570
567
|
|
package/src/Watcher.js
CHANGED
|
@@ -7,12 +7,12 @@ import { isFile } from './utils/fs.js'
|
|
|
7
7
|
import * as mockBrokerCollection from './mockBrokersCollection.js'
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
/** # AR = Add or Remove Mock */
|
|
11
|
-
export const
|
|
12
|
-
|
|
10
|
+
/** # AR = Add or Remove Mock Event */
|
|
11
|
+
export const uiSyncVersion = new class extends EventEmitter {
|
|
12
|
+
version = 0
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
this.
|
|
14
|
+
increment() {
|
|
15
|
+
this.version++
|
|
16
16
|
super.emit('AR')
|
|
17
17
|
}
|
|
18
18
|
subscribe(listener) {
|
|
@@ -30,11 +30,11 @@ export function watchMocksDir() {
|
|
|
30
30
|
return
|
|
31
31
|
if (isFile(join(dir, file))) {
|
|
32
32
|
if (mockBrokerCollection.registerMock(file, 'isFromWatcher'))
|
|
33
|
-
|
|
33
|
+
uiSyncVersion.increment()
|
|
34
34
|
}
|
|
35
35
|
else {
|
|
36
36
|
mockBrokerCollection.unregisterMock(file)
|
|
37
|
-
|
|
37
|
+
uiSyncVersion.increment()
|
|
38
38
|
}
|
|
39
39
|
})
|
|
40
40
|
}
|