mockaton 2.0.0 → 2.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/README-dashboard.png +0 -0
- package/README.md +41 -26
- package/Tests.js +5 -2
- package/index.d.ts +2 -1
- package/package.json +1 -1
- package/sample-mocks/api/user/friends.GET.500.txt +7 -0
- package/sample-mocks/api/user/likes.GET.200.js +3 -1
- package/sample-mocks/api/user/links.GET.200.js +8 -0
- package/src/Api.js +0 -1
- package/src/Config.js +6 -4
- package/src/MockDispatcher.js +8 -6
- package/src/Mockaton.js +2 -0
- package/src/mockBrokersCollection.js +3 -1
- package/sample-mocks/api/user/.GET.500.txt +0 -7
- package/sample-mocks/api/user/edit-name.PATCH.500.txt +0 -0
- package/sample-mocks/api/user/likes.GET.500.txt +0 -0
- package/sample-mocks/api/user/logout.POST.500.txt +0 -0
- package/sample-mocks/api/user/loves.GET.200.js +0 -7
- package/sample-mocks/api/user/loves.GET.500.txt +0 -0
- package/sample-mocks/api/user/videos.GET.500.txt +0 -0
- package/sample-mocks/api/video/[id].GET.500.txt +0 -0
- package/sample-mocks/api/video/stat/[stat-id]/[video-id].GET.500.txt +0 -0
- package/sample-mocks/api/video/stat/[stat-id]/all-videos?limit=[limit].GET.500.txt +0 -0
package/README-dashboard.png
CHANGED
|
Binary file
|
package/README.md
CHANGED
|
@@ -16,8 +16,7 @@ be used for downloading a TAR of your XHR requests following that convention.
|
|
|
16
16
|
### Mock Variants
|
|
17
17
|
Each route can have many mocks, which could either be:
|
|
18
18
|
- Different response __status code__.
|
|
19
|
-
- e.g. for testing error responses.
|
|
20
|
-
Error_ mock is autogenerated for routes that have no 500.
|
|
19
|
+
- e.g. for testing error responses.
|
|
21
20
|
- __Comment__ on the filename, which is anything within parentheses.
|
|
22
21
|
- e.g. `api/user(my-comment).POST.201.json`
|
|
23
22
|
|
|
@@ -29,7 +28,7 @@ The first file in **alphabetical order** becomes the default mock.
|
|
|
29
28
|
### Optionally, you can write mocks in JavaScript
|
|
30
29
|
An Object, Array, or String is sent as JSON.
|
|
31
30
|
|
|
32
|
-
`api/
|
|
31
|
+
`api/foo.GET.200.js`
|
|
33
32
|
```js
|
|
34
33
|
export default [
|
|
35
34
|
{ id: 0 }
|
|
@@ -56,7 +55,7 @@ The best way to learn _Mockaton_ is by checking out this repo and
|
|
|
56
55
|
exploring its [sample-mocks/](./sample-mocks) directory. Then, run
|
|
57
56
|
[`./_usage_example.js`](./_usage_example.js) and you’ll see this dashboard:
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
<img src="./README-dashboard.png" style="max-width:890px"/>
|
|
60
59
|
|
|
61
60
|
|
|
62
61
|
## Delay 🕓
|
|
@@ -98,27 +97,10 @@ interface Config {
|
|
|
98
97
|
skipOpen?: boolean // Prevents opening the dashboard in a browser
|
|
99
98
|
proxyFallback?: string // e.g. http://localhost:9999 Target for relaying routes without mocks
|
|
100
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?: []
|
|
101
102
|
}
|
|
102
103
|
```
|
|
103
|
-
|
|
104
|
-
## Cookies
|
|
105
|
-
```js
|
|
106
|
-
import { jwtCookie } from 'mockaton'
|
|
107
|
-
|
|
108
|
-
Config.cookies = {
|
|
109
|
-
'My Admin User': 'my-cookie=1;Path=/;SameSite=strict',
|
|
110
|
-
'My Normal User': 'my-cookie=0;Path=/;SameSite=strict',
|
|
111
|
-
'My JWT': jwtCookie('my-cookie', {
|
|
112
|
-
email: 'john.doe@example.com',
|
|
113
|
-
picture: 'https://cdn.auth0.com/avatars/jd.png'
|
|
114
|
-
})
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
The key is just a label used for selecting a particular cookie in the dashboard.
|
|
118
|
-
|
|
119
|
-
`jwtCookie` has a hardcoded header and signature. In other
|
|
120
|
-
words, it’s useful if you only care about its payload.
|
|
121
|
-
|
|
122
104
|
---
|
|
123
105
|
|
|
124
106
|
## File Name Convention
|
|
@@ -127,10 +109,9 @@ words, it’s useful if you only care about its payload.
|
|
|
127
109
|
### Extension
|
|
128
110
|
`.Method.HttpResponseStatusCode.FileExt`
|
|
129
111
|
|
|
130
|
-
The **file extension** can anything, but `.md`
|
|
131
|
-
for documentation, and mock processors (more on that later).
|
|
112
|
+
The **file extension** can be anything, but `.md` is reserved for documentation.
|
|
132
113
|
|
|
133
|
-
The `Config.allowedExt` regex defaults to: `/\.(json|txt|md|
|
|
114
|
+
The `Config.allowedExt` regex defaults to: `/\.(json|txt|md|js)$/`
|
|
134
115
|
|
|
135
116
|
|
|
136
117
|
### Dynamic Parameters
|
|
@@ -172,6 +153,40 @@ api/foo/?bar=[bar].GET.200.json
|
|
|
172
153
|
api/foo/(my comment).GET.200.json
|
|
173
154
|
```
|
|
174
155
|
|
|
156
|
+
|
|
157
|
+
## `Config.cookies`
|
|
158
|
+
The selected cookie is sent in every response in the `Set-Cookie` header.
|
|
159
|
+
```js
|
|
160
|
+
import { jwtCookie } from 'mockaton'
|
|
161
|
+
|
|
162
|
+
Config.cookies = {
|
|
163
|
+
'My Admin User': 'my-cookie=1;Path=/;SameSite=strict',
|
|
164
|
+
'My Normal User': 'my-cookie=0;Path=/;SameSite=strict',
|
|
165
|
+
'My JWT': jwtCookie('my-cookie', {
|
|
166
|
+
email: 'john.doe@example.com',
|
|
167
|
+
picture: 'https://cdn.auth0.com/avatars/jd.png'
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
The key is just a label used for selecting a particular cookie in the dashboard.
|
|
172
|
+
|
|
173
|
+
`jwtCookie` has a hardcoded header and signature. In other
|
|
174
|
+
words, it’s useful if you only care about its payload.
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
## `Config.extraHeaders`
|
|
178
|
+
They are applied last, right before ending the response. In
|
|
179
|
+
other words, they can overwrite the `Content-Type`. They are
|
|
180
|
+
not tuples, the header name goes in even-numbered indices.
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
Config.extraHeaders = [
|
|
184
|
+
'Server', 'Mockaton',
|
|
185
|
+
'Set-Cookie', 'another-cookie=FOO;Path=/;SameSite=strict',
|
|
186
|
+
'Set-Cookie', 'another-cookie=BAR;Path=/;SameSite=strict'
|
|
187
|
+
]
|
|
188
|
+
```
|
|
189
|
+
|
|
175
190
|
## Documenting Contracts (.md)
|
|
176
191
|
This is handy for documenting request payload parameters. The dashboard will
|
|
177
192
|
print the Markdown document (as plain text) above the actual payload content.
|
package/Tests.js
CHANGED
|
@@ -110,7 +110,9 @@ const server = Mockaton({
|
|
|
110
110
|
cookies: {
|
|
111
111
|
userA: 'CookieA',
|
|
112
112
|
userB: 'CookieB'
|
|
113
|
-
}
|
|
113
|
+
},
|
|
114
|
+
generate500: true,
|
|
115
|
+
extraHeaders: ['Server', 'MockatonTester']
|
|
114
116
|
})
|
|
115
117
|
server.on('listening', runTests)
|
|
116
118
|
|
|
@@ -157,7 +159,7 @@ async function runTests() {
|
|
|
157
159
|
await reset()
|
|
158
160
|
for (const [url, file, body] of fixtures)
|
|
159
161
|
await testMockDispatching(url, file, body)
|
|
160
|
-
|
|
162
|
+
|
|
161
163
|
await testMockDispatching('/api/object', 'api/object.GET.200.js', { JSON_FROM_JS: true }, mimeFor('.json'))
|
|
162
164
|
await testJsFunctionMocks()
|
|
163
165
|
|
|
@@ -204,6 +206,7 @@ async function testMockDispatching(url, file, expectedBody, forcedMime = void 0)
|
|
|
204
206
|
it('status: ' + status, () => equal(res.status, status))
|
|
205
207
|
it('cookie: ' + mime, () => equal(res.headers.get('set-cookie'), 'CookieA'))
|
|
206
208
|
it('delay is under 1 sec', () => equal((new Date()).getTime() - now.getTime() < 1000, true))
|
|
209
|
+
it('extra header', () => equal(res.headers.get('server'), 'MockatonTester'))
|
|
207
210
|
})
|
|
208
211
|
}
|
|
209
212
|
|
package/index.d.ts
CHANGED
|
@@ -7,10 +7,11 @@ interface Config {
|
|
|
7
7
|
port?: number
|
|
8
8
|
delay?: number
|
|
9
9
|
cookies?: object
|
|
10
|
-
database?: object
|
|
11
10
|
skipOpen?: boolean
|
|
12
11
|
proxyFallback?: string
|
|
13
12
|
allowedExt?: RegExp
|
|
13
|
+
generate500?: boolean,
|
|
14
|
+
extraHeaders?: [string, string][]
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export function Mockaton(options: Config): Server
|
package/package.json
CHANGED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
This is a plain text response for (/api/friends).
|
|
2
|
+
|
|
3
|
+
In this case, it’s for mocking up a 500 - Internal Server Error.
|
|
4
|
+
|
|
5
|
+
This file could have been empty, or some JSON if it had a `.json` extension.
|
|
6
|
+
|
|
7
|
+
By the way, on initialization an 500 is auto-generated for routes that don’t have a 500.
|
package/src/Api.js
CHANGED
package/src/Config.js
CHANGED
|
@@ -9,10 +9,11 @@ export const Config = {
|
|
|
9
9
|
port: 0, // auto-assigned
|
|
10
10
|
delay: 1200, // milliseconds
|
|
11
11
|
cookies: {}, // defaults to the first kv
|
|
12
|
-
database: {},
|
|
13
12
|
skipOpen: false,
|
|
14
13
|
proxyFallback: '', // e.g. http://localhost:9999
|
|
15
|
-
allowedExt: /\.(json|txt|md|js)
|
|
14
|
+
allowedExt: /\.(json|txt|md|js)$/, // Just for excluding temporary editor files (e.g. JetBrains appends a ~)
|
|
15
|
+
generate500: false,
|
|
16
|
+
extraHeaders: []
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export function setup(options) {
|
|
@@ -24,10 +25,11 @@ export function setup(options) {
|
|
|
24
25
|
port: port => Number.isInteger(port) && port >= 0 && port < 2 ** 16,
|
|
25
26
|
delay: ms => Number.isInteger(ms) && ms > 0,
|
|
26
27
|
cookies: is(Object),
|
|
27
|
-
database: is(Object),
|
|
28
28
|
skipOpen: is(Boolean),
|
|
29
29
|
proxyFallback: is(String),
|
|
30
|
-
allowedExt: is(RegExp)
|
|
30
|
+
allowedExt: is(RegExp),
|
|
31
|
+
generate500: is(Boolean),
|
|
32
|
+
extraHeaders: Array.isArray
|
|
31
33
|
})
|
|
32
34
|
}
|
|
33
35
|
|
package/src/MockDispatcher.js
CHANGED
|
@@ -31,11 +31,6 @@ export async function dispatchMock(req, response) {
|
|
|
31
31
|
const { file, status, delay } = broker
|
|
32
32
|
console.log('\n', req.url, '→\n ', file)
|
|
33
33
|
|
|
34
|
-
response.statusCode = status
|
|
35
|
-
response.setHeader('content-type', mimeFor(file))
|
|
36
|
-
if (cookie.getCurrent())
|
|
37
|
-
response.setHeader('set-cookie', cookie.getCurrent())
|
|
38
|
-
|
|
39
34
|
let mockText
|
|
40
35
|
if (file.endsWith('.js')) {
|
|
41
36
|
response.setHeader('content-type', mimeFor('.json'))
|
|
@@ -44,8 +39,15 @@ export async function dispatchMock(req, response) {
|
|
|
44
39
|
? jsExport(req, response)
|
|
45
40
|
: JSON.stringify(jsExport)
|
|
46
41
|
}
|
|
47
|
-
else
|
|
42
|
+
else {
|
|
43
|
+
response.setHeader('content-type', mimeFor(file))
|
|
48
44
|
mockText = readMock(file)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (cookie.getCurrent())
|
|
48
|
+
response.setHeader('set-cookie', cookie.getCurrent())
|
|
49
|
+
|
|
50
|
+
response.writeHead(status, Config.extraHeaders)
|
|
49
51
|
setTimeout(() => response.end(mockText), delay)
|
|
50
52
|
}
|
|
51
53
|
catch (error) {
|
package/src/Mockaton.js
CHANGED
|
@@ -14,6 +14,8 @@ export function Mockaton(options) {
|
|
|
14
14
|
mockBrokerCollection.init()
|
|
15
15
|
|
|
16
16
|
return createServer(async (req, response) => {
|
|
17
|
+
response.setHeader('Server', 'Mockaton')
|
|
18
|
+
|
|
17
19
|
const { url, method } = req
|
|
18
20
|
if (method === 'GET' && apiGetRequests.has(url))
|
|
19
21
|
apiGetRequests.get(url)(req, response)
|
|
@@ -39,7 +39,9 @@ export function init() {
|
|
|
39
39
|
else
|
|
40
40
|
collection[method][urlMask].register(file)
|
|
41
41
|
}
|
|
42
|
-
|
|
42
|
+
|
|
43
|
+
if (Config.generate500)
|
|
44
|
+
forEachBroker(broker => broker.ensureItHas500())
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
function forEachBroker(fn) {
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
This is a plain text response for (/api/user).
|
|
2
|
-
|
|
3
|
-
In this case, it’s for mocking up a 500 - Internal Server Error.
|
|
4
|
-
|
|
5
|
-
This file could have been empty, or some JSON if it had a `.json` extension.
|
|
6
|
-
|
|
7
|
-
By the way, on initialization an 500 is auto-generated for routes that don’t have a 500.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|