mockaton 2.3.0 → 3.0.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 +51 -49
- package/Tests.js +1 -1
- package/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/Api.js +16 -12
- package/src/Config.js +5 -9
- package/src/Mockaton.js +2 -2
- package/src/mockBrokersCollection.js +2 -1
- package/src/utils/http-response.js +5 -0
- package/src/utils/openInBrowser.js +8 -0
- package/src/utils/validate.js +4 -0
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Mockaton
|
|
2
2
|
_Mockaton_ is a mock server for developing and testing frontends.
|
|
3
3
|
|
|
4
|
-
It scans
|
|
4
|
+
It scans a given directory for files following a specific
|
|
5
5
|
file name convention, which is similar to the URL paths. For
|
|
6
6
|
example, the following file will be served for `/api/user/1234`
|
|
7
7
|
```
|
|
@@ -13,7 +13,54 @@ extension](https://github.com/ericfortis/devtools-ext-tar-http-requests) can
|
|
|
13
13
|
be used for downloading a TAR of your XHR requests following that convention.
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
## Getting Started
|
|
17
|
+
The best way to learn _Mockaton_ is by checking out this repo and
|
|
18
|
+
exploring its [sample-mocks/](./sample-mocks) directory. Then, run
|
|
19
|
+
[`./_usage_example.js`](./_usage_example.js) and you’ll see this dashboard:
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
<img src="./README-dashboard.png" style="max-width:820px"/>
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## Basic Usage
|
|
26
|
+
```
|
|
27
|
+
npm install mockaton
|
|
28
|
+
```
|
|
29
|
+
Create a `my-mockaton.js` file
|
|
30
|
+
```js
|
|
31
|
+
import { resolve } from 'node:path'
|
|
32
|
+
import { Mockaton } from 'mockaton'
|
|
33
|
+
|
|
34
|
+
Mockaton({
|
|
35
|
+
mocksDir: resolve('my-mocks-dir'),
|
|
36
|
+
port: 2345
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
node my-mockaton.js
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Config Options
|
|
45
|
+
```ts
|
|
46
|
+
interface Config {
|
|
47
|
+
mocksDir: string
|
|
48
|
+
staticDir?: string
|
|
49
|
+
host?: string, // defaults to 'localhost'
|
|
50
|
+
port?: number // defaults to 0, which means auto-assigned
|
|
51
|
+
delay?: number // defaults to 1200 (ms)
|
|
52
|
+
open?: (dashboardUrl: string) => void // pass a noop to prevent opening the dashboard
|
|
53
|
+
cookies?: object
|
|
54
|
+
proxyFallback?: string // e.g. http://localhost:9999 Target for relaying routes without mocks
|
|
55
|
+
allowedExt?: RegExp // /\.(json|txt|md|js)$/ Just for excluding temporary editor files (e.g. JetBrains appends a ~)
|
|
56
|
+
generate500?: boolean // autogenerates an Internal Server Error empty mock for routes that have no 500
|
|
57
|
+
extraHeaders?: []
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Mock Variants
|
|
17
64
|
Each route can have many mocks, which could either be:
|
|
18
65
|
- Different response __status code__.
|
|
19
66
|
- e.g. for testing error responses.
|
|
@@ -25,7 +72,7 @@ UI, or programmatically, for instance, for setting up tests.
|
|
|
25
72
|
|
|
26
73
|
The first file in **alphabetical order** becomes the default mock.
|
|
27
74
|
|
|
28
|
-
|
|
75
|
+
## You can write JSON mocks in JavaScript
|
|
29
76
|
An Object, Array, or String is sent as JSON.
|
|
30
77
|
|
|
31
78
|
`api/foo.GET.200.js`
|
|
@@ -45,18 +92,11 @@ export default function (req, response) {
|
|
|
45
92
|
```
|
|
46
93
|
|
|
47
94
|
|
|
48
|
-
|
|
95
|
+
## Proxying Routes
|
|
49
96
|
`Config.proxyFallback` lets you specify a target
|
|
50
97
|
server for serving routes you don’t have mocks for.
|
|
51
98
|
|
|
52
99
|
|
|
53
|
-
## Getting Started
|
|
54
|
-
The best way to learn _Mockaton_ is by checking out this repo and
|
|
55
|
-
exploring its [sample-mocks/](./sample-mocks) directory. Then, run
|
|
56
|
-
[`./_usage_example.js`](./_usage_example.js) and you’ll see this dashboard:
|
|
57
|
-
|
|
58
|
-
<img src="./README-dashboard.png" style="max-width:890px"/>
|
|
59
|
-
|
|
60
100
|
|
|
61
101
|
## Delay 🕓
|
|
62
102
|
The clock icon next to the mock selector is a checkbox for delaying a
|
|
@@ -64,44 +104,6 @@ particular response. They are handy for testing spinners.
|
|
|
64
104
|
|
|
65
105
|
The delay is globally configurable via `Config.delay = 1200` (milliseconds).
|
|
66
106
|
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
## Basic Usage (see [_usage_example.js](./_usage_example.js))
|
|
70
|
-
```
|
|
71
|
-
npm install mockaton
|
|
72
|
-
```
|
|
73
|
-
Create a `my-mockaton.js` file
|
|
74
|
-
```js
|
|
75
|
-
import { resolve } from 'node:path'
|
|
76
|
-
import { Mockaton } from 'mockaton'
|
|
77
|
-
|
|
78
|
-
Mockaton({
|
|
79
|
-
mocksDir: resolve('my-mocks-dir'),
|
|
80
|
-
port: 2345
|
|
81
|
-
})
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
```sh
|
|
85
|
-
node my-mockaton.js
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Config Options
|
|
89
|
-
```ts
|
|
90
|
-
interface Config {
|
|
91
|
-
mocksDir: string
|
|
92
|
-
staticDir?: string
|
|
93
|
-
host?: string, // defaults to 'localhost'
|
|
94
|
-
port?: number // defaults to 0, which means auto-assigned
|
|
95
|
-
delay?: number // defaults to 1200 (ms)
|
|
96
|
-
cookies?: object
|
|
97
|
-
skipOpen?: boolean // Prevents opening the dashboard in a browser
|
|
98
|
-
proxyFallback?: string // e.g. http://localhost:9999 Target for relaying routes without mocks
|
|
99
|
-
allowedExt?: RegExp // /\.(json|txt|md|js)$/ Just for excluding temporary editor files (e.g. JetBrains appends a ~)
|
|
100
|
-
generate500?: boolean // autogenerates an Internal Server Error empty mock for routes that have no 500
|
|
101
|
-
extraHeaders?: []
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
---
|
|
105
107
|
|
|
106
108
|
## File Name Convention
|
|
107
109
|
|
package/Tests.js
CHANGED
package/index.d.ts
CHANGED
package/package.json
CHANGED
package/src/Api.js
CHANGED
|
@@ -9,7 +9,7 @@ import { Config } from './Config.js'
|
|
|
9
9
|
import { DF, API } from './ApiConstants.js'
|
|
10
10
|
import { parseJSON } from './utils/http-request.js'
|
|
11
11
|
import * as mockBrokersCollection from './mockBrokersCollection.js'
|
|
12
|
-
import { sendOK, sendBadRequest, sendJSON, sendFile } from './utils/http-response.js'
|
|
12
|
+
import { sendOK, sendBadRequest, sendJSON, sendFile, sendUnprocessableContent } from './utils/http-response.js'
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
export const apiGetRequests = new Map([
|
|
@@ -24,11 +24,11 @@ export const apiGetRequests = new Map([
|
|
|
24
24
|
])
|
|
25
25
|
|
|
26
26
|
export const apiPatchRequests = new Map([
|
|
27
|
-
[API.bulkSelect, bulkUpdateBrokersByCommentTag],
|
|
28
27
|
[API.edit, updateBroker],
|
|
29
28
|
[API.reset, reinitialize],
|
|
30
29
|
[API.cookies, selectCookie],
|
|
31
|
-
[API.fallback, updateProxyFallback]
|
|
30
|
+
[API.fallback, updateProxyFallback],
|
|
31
|
+
[API.bulkSelect, bulkUpdateBrokersByCommentTag]
|
|
32
32
|
])
|
|
33
33
|
|
|
34
34
|
function serveDashboard(_, response) {
|
|
@@ -48,6 +48,11 @@ function listMockBrokers(_, response) {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
|
|
51
|
+
function reinitialize(_, response) {
|
|
52
|
+
mockBrokersCollection.init()
|
|
53
|
+
sendOK(response)
|
|
54
|
+
}
|
|
55
|
+
|
|
51
56
|
async function selectCookie(req, response) {
|
|
52
57
|
try {
|
|
53
58
|
cookie.setCurrent(await parseJSON(req))
|
|
@@ -59,15 +64,14 @@ async function selectCookie(req, response) {
|
|
|
59
64
|
}
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
function reinitialize(_, response) {
|
|
63
|
-
mockBrokersCollection.init()
|
|
64
|
-
sendOK(response)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
67
|
async function updateBroker(req, response) {
|
|
68
68
|
try {
|
|
69
69
|
const body = await parseJSON(req)
|
|
70
70
|
const broker = mockBrokersCollection.getBrokerByFilename(body[DF.file])
|
|
71
|
+
if (!broker) {
|
|
72
|
+
sendUnprocessableContent(response)
|
|
73
|
+
return
|
|
74
|
+
}
|
|
71
75
|
if (DF.delayed in body)
|
|
72
76
|
broker.updateDelay(body[DF.delayed])
|
|
73
77
|
broker.updateFile(body[DF.file])
|
|
@@ -79,9 +83,9 @@ async function updateBroker(req, response) {
|
|
|
79
83
|
}
|
|
80
84
|
}
|
|
81
85
|
|
|
82
|
-
async function
|
|
86
|
+
async function updateProxyFallback(req, response) {
|
|
83
87
|
try {
|
|
84
|
-
|
|
88
|
+
Config.proxyFallback = await parseJSON(req)
|
|
85
89
|
sendOK(response)
|
|
86
90
|
}
|
|
87
91
|
catch (error) {
|
|
@@ -90,9 +94,9 @@ async function bulkUpdateBrokersByCommentTag(req, response) {
|
|
|
90
94
|
}
|
|
91
95
|
}
|
|
92
96
|
|
|
93
|
-
async function
|
|
97
|
+
async function bulkUpdateBrokersByCommentTag(req, response) {
|
|
94
98
|
try {
|
|
95
|
-
|
|
99
|
+
mockBrokersCollection.setMocksMatchingComment(await parseJSON(req))
|
|
96
100
|
sendOK(response)
|
|
97
101
|
}
|
|
98
102
|
catch (error) {
|
package/src/Config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { validate, is, optional } from './utils/validate.js'
|
|
1
|
+
import { openInBrowser } from './utils/openInBrowser.js'
|
|
2
|
+
import { validate, is, optional, isDirectory } from './utils/validate.js'
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
export const Config = {
|
|
@@ -8,8 +8,8 @@ export const Config = {
|
|
|
8
8
|
host: '127.0.0.1',
|
|
9
9
|
port: 0, // auto-assigned
|
|
10
10
|
delay: 1200, // milliseconds
|
|
11
|
+
open: openInBrowser,
|
|
11
12
|
cookies: {}, // defaults to the first kv
|
|
12
|
-
skipOpen: false,
|
|
13
13
|
proxyFallback: '', // e.g. http://localhost:9999
|
|
14
14
|
allowedExt: /\.(json|txt|md|js)$/, // Just for excluding temporary editor files (e.g. JetBrains appends a ~)
|
|
15
15
|
generate500: false,
|
|
@@ -24,17 +24,13 @@ export function setup(options) {
|
|
|
24
24
|
host: is(String),
|
|
25
25
|
port: port => Number.isInteger(port) && port >= 0 && port < 2 ** 16,
|
|
26
26
|
delay: ms => Number.isInteger(ms) && ms > 0,
|
|
27
|
+
open: is(Function),
|
|
27
28
|
cookies: is(Object),
|
|
28
|
-
|
|
29
|
-
proxyFallback: is(String),
|
|
29
|
+
proxyFallback: optional(URL.canParse),
|
|
30
30
|
allowedExt: is(RegExp),
|
|
31
31
|
generate500: is(Boolean),
|
|
32
32
|
extraHeaders: Array.isArray
|
|
33
33
|
})
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
function isDirectory(dir) {
|
|
37
|
-
return exists(dir) && lstatSync(dir).isDirectory()
|
|
38
|
-
}
|
|
39
|
-
|
|
40
36
|
|
package/src/Mockaton.js
CHANGED
|
@@ -54,7 +54,8 @@ export const getAll = () => collection
|
|
|
54
54
|
|
|
55
55
|
export const getBrokerByFilename = file => {
|
|
56
56
|
const { method, urlMask } = Route.parseFilename(file)
|
|
57
|
-
|
|
57
|
+
if (collection[method])
|
|
58
|
+
return collection[method][urlMask]
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
// Searching the routes in reverse order so dynamic params (e.g.
|
|
@@ -54,6 +54,11 @@ export function sendNotFound(response) {
|
|
|
54
54
|
response.end()
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
export function sendUnprocessableContent(response) {
|
|
58
|
+
response.statusCode = 422
|
|
59
|
+
response.end()
|
|
60
|
+
}
|
|
61
|
+
|
|
57
62
|
export function sendInternalServerError(response) {
|
|
58
63
|
response.statusCode = 500
|
|
59
64
|
response.end()
|
package/src/utils/validate.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { existsSync as exists, lstatSync } from 'node:fs'
|
|
2
|
+
|
|
3
|
+
|
|
1
4
|
export function validate(obj, shape) {
|
|
2
5
|
for (const [field, value] of Object.entries(obj))
|
|
3
6
|
if (!shape[field](value))
|
|
@@ -6,3 +9,4 @@ export function validate(obj, shape) {
|
|
|
6
9
|
|
|
7
10
|
export const is = ctor => val => val.constructor === ctor
|
|
8
11
|
export const optional = tester => val => !val || tester(val)
|
|
12
|
+
export const isDirectory = dir => exists(dir) && lstatSync(dir).isDirectory()
|