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.
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. As a side note, an _Internal Server
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/user/likes.GET.200.js`
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
- ![](./README-dashboard.png)
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` and `.mjs` are reserved
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|mjs)$/`
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
@@ -2,7 +2,7 @@
2
2
  "name": "mockaton",
3
3
  "description": "A deterministic server-side for developing and testing frontend clients",
4
4
  "type": "module",
5
- "version": "2.0.0",
5
+ "version": "2.2.0",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "license": "MIT",
@@ -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.
@@ -1,7 +1,9 @@
1
- // You can write JSON responses in JavaScript.
1
+ // You can write JSON responses in JavaScript.
2
+ // You can export an: Object, Array, or String
2
3
 
3
4
  export default [
4
5
  { id: 0 },
5
6
  { id: 1 },
6
7
  { id: 2 },
7
8
  ]
9
+
@@ -0,0 +1,8 @@
1
+ // You can write JSON responses in JavaScript as a function.
2
+ // Must return a String and they should NOT call `response.end()`
3
+
4
+ export default function (req, response) {
5
+ return JSON.stringify([
6
+ { id: 0 }
7
+ ])
8
+ }
package/src/Api.js CHANGED
@@ -60,7 +60,6 @@ async function selectCookie(req, response) {
60
60
  }
61
61
 
62
62
  function reinitialize(_, response) {
63
- Config.database = {}
64
63
  mockBrokersCollection.init()
65
64
  sendOK(response)
66
65
  }
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)$/ // Just for excluding temporary editor files (e.g. JetBrains appends a ~)
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
 
@@ -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
- forEachBroker(broker => broker.ensureItHas500())
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
@@ -1,7 +0,0 @@
1
- // You can write JSON responses in JavaScript.
2
-
3
- export default function (req, response) {
4
- return JSON.stringify([
5
- { id: 0 }
6
- ])
7
- }
File without changes
File without changes
File without changes