mockaton 6.3.10 → 6.3.11

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 CHANGED
@@ -1,4 +1,4 @@
1
- # Mockaton
1
+ # Mockaton
2
2
  _Mockaton_ is a mock server for developing and testing frontends.
3
3
 
4
4
  It scans a given directory for files following a specific
@@ -30,9 +30,10 @@ Create a `my-mockaton.js` file
30
30
  import { resolve } from 'node:path'
31
31
  import { Mockaton } from 'mockaton'
32
32
 
33
+
33
34
  Mockaton({
34
- mocksDir: resolve('my-mocks-dir'),
35
- port: 2345
35
+ mocksDir: resolve('my-mocks-dir'),
36
+ port: 2345
36
37
  })
37
38
  ```
38
39
 
@@ -43,21 +44,21 @@ node my-mockaton.js
43
44
  ## Config Options
44
45
  ```ts
45
46
  interface Config {
46
- mocksDir: string
47
- ignore?: RegExp // defaults to /(\.DS_Store|~)$/
48
-
49
- staticDir?: string
50
-
51
- host?: string, // defaults to 'localhost'
52
- port?: number // defaults to 0, which means auto-assigned
53
- proxyFallback?: string // e.g. http://localhost:9999 Target for relaying routes without mocks
54
-
55
- delay?: number // defaults to 1200 (ms)
56
- cookies?: { [label: string]: string }
57
- extraMimes?: { [fileExt: string]: string }
58
- extraHeaders?: []
59
-
60
- onReady?: (dashboardUrl: string) => void // defaults to trying to open macOS default browser. pass a noop to prevent opening the dashboard
47
+ mocksDir: string
48
+ ignore?: RegExp // defaults to /(\.DS_Store|~)$/
49
+
50
+ staticDir?: string
51
+
52
+ host?: string, // defaults to 'localhost'
53
+ port?: number // defaults to 0, which means auto-assigned
54
+ proxyFallback?: string // e.g. http://localhost:9999 Target for relaying routes without mocks
55
+
56
+ delay?: number // defaults to 1200 (ms)
57
+ cookies?: { [label: string]: string }
58
+ extraMimes?: { [fileExt: string]: string }
59
+ extraHeaders?: []
60
+
61
+ onReady?: (dashboardUrl: string) => void // defaults to trying to open macOS default browser. pass a noop to prevent opening the dashboard
61
62
  }
62
63
  ```
63
64
 
@@ -65,9 +66,9 @@ interface Config {
65
66
 
66
67
  ## Mock Variants
67
68
  Each route can have many mocks, which could either be:
68
- - Different response __status code__. For example, for testing error responses.
69
+ - Different response __status code__. For example, for testing error responses.
69
70
  - __Comment__ on the filename, which is anything within parentheses.
70
- - e.g. `api/user(my-comment).POST.201.json`
71
+ - e.g. `api/user(my-comment).POST.201.json`
71
72
 
72
73
  Those alternatives can be manually selected in the dashboard
73
74
  UI, or programmatically, for instance, for setting up tests.
@@ -80,7 +81,7 @@ An Object, Array, or String is sent as JSON.
80
81
  `api/foo.GET.200.js`
81
82
  ```js
82
83
  export default [
83
- { id: 0 }
84
+ { id: 0 }
84
85
  ]
85
86
  ```
86
87
 
@@ -94,10 +95,10 @@ database, or pull data from a backend. The `request` is of type
94
95
  `response` a [ServerResponse](https://nodejs.org/api/http.html#class-httpserverresponse).
95
96
  ```js
96
97
  export default function optionalName(request, response) {
97
- globalThis.myDatabase ??= { count: 0 }
98
- globalThis.myDatabase.count++
99
-
100
- return JSON.stringify({ a: 1 })
98
+ globalThis.myDatabase ??= { count: 0 }
99
+ globalThis.myDatabase.count++
100
+
101
+ return JSON.stringify({ a: 1 })
101
102
  }
102
103
  ```
103
104
 
@@ -107,7 +108,6 @@ export default function optionalName(request, response) {
107
108
  server for serving routes you don’t have mocks for.
108
109
 
109
110
 
110
-
111
111
  ## Delay 🕓
112
112
  The clock icon next to the mock selector is a checkbox for delaying a
113
113
  particular response. They are handy for testing spinners.
@@ -115,7 +115,6 @@ particular response. They are handy for testing spinners.
115
115
  The delay is globally configurable via `Config.delay = 1200` (milliseconds).
116
116
 
117
117
 
118
-
119
118
  ## File Name Convention
120
119
 
121
120
 
@@ -167,7 +166,6 @@ api/foo/.GET.200.json
167
166
  ```
168
167
 
169
168
 
170
-
171
169
  ## `Config.cookies`
172
170
  The selected cookie is sent in every response in the `Set-Cookie` header.
173
171
 
@@ -181,13 +179,14 @@ words, it’s useful if you only care about its payload.
181
179
  ```js
182
180
  import { jwtCookie } from 'mockaton'
183
181
 
182
+
184
183
  Config.cookies = {
185
- 'My Admin User': 'my-cookie=1;Path=/;SameSite=strict',
186
- 'My Normal User': 'my-cookie=0;Path=/;SameSite=strict',
187
- 'My JWT': jwtCookie('my-cookie', {
188
- email: 'john.doe@example.com',
189
- picture: 'https://cdn.auth0.com/avatars/jd.png'
190
- })
184
+ 'My Admin User': 'my-cookie=1;Path=/;SameSite=strict',
185
+ 'My Normal User': 'my-cookie=0;Path=/;SameSite=strict',
186
+ 'My JWT': jwtCookie('my-cookie', {
187
+ email: 'john.doe@example.com',
188
+ picture: 'https://cdn.auth0.com/avatars/jd.png'
189
+ })
191
190
  }
192
191
  ```
193
192
 
@@ -198,16 +197,16 @@ that it's an array and the header name goes in even indices.
198
197
 
199
198
  ```js
200
199
  Config.extraHeaders = [
201
- 'Server', 'Mockaton',
202
- 'Set-Cookie', 'foo=FOO;Path=/;SameSite=strict',
203
- 'Set-Cookie', 'bar=BAR;Path=/;SameSite=strict'
200
+ 'Server', 'Mockaton',
201
+ 'Set-Cookie', 'foo=FOO;Path=/;SameSite=strict',
202
+ 'Set-Cookie', 'bar=BAR;Path=/;SameSite=strict'
204
203
  ]
205
204
  ```
206
205
 
207
206
  ## `Config.extraMimes`
208
207
  ```js
209
208
  Config.extraMimes = {
210
- jpg: 'application/jpeg'
209
+ jpg: 'application/jpeg'
211
210
  }
212
211
  ```
213
212
 
@@ -218,49 +217,51 @@ Config.extraMimes = {
218
217
  ### Select a mock for a route
219
218
  ```js
220
219
  fetch(addr + '/mockaton/edit', {
221
- method: 'PATCH',
222
- body: JSON.stringify({
223
- file: 'api/foo.200.GET.json',
224
- delayed: true // optional
225
- })
220
+ method: 'PATCH',
221
+ body: JSON.stringify({
222
+ file: 'api/foo.200.GET.json',
223
+ delayed: true // optional
224
+ })
226
225
  })
227
226
  ```
228
227
 
229
228
  ### Select all mocks that have a particular comment
230
229
  ```js
231
230
  fetch(addr + '/mockaton/bulk-select-by-comment', {
232
- method: 'PATCH',
233
- body: JSON.stringify('(demo-a)')
231
+ method: 'PATCH',
232
+ body: JSON.stringify('(demo-a)')
234
233
  })
235
234
  ```
236
235
 
237
- ### Reset
238
- Re-Initialize the collection and its states (selected mocks and cookies, delays, etc.).
236
+ ### List Cookies
237
+ Sends a list of the available cookies along with an "is selected" boolean flag.
239
238
  ```js
240
- fetch(addr + '/mockaton/reset', {
241
- method: 'PATCH'
242
- })
239
+ fetch(addr + '/mockaton/cookies')
243
240
  ```
244
241
 
245
242
  ### Select a cookie
246
243
  In `Config.cookies`, each key is the label used for changing it.
247
244
  ```js
248
245
  fetch(addr + '/mockaton/cookies', {
249
- method: 'PATCH',
250
- body: JSON.stringify('My Normal User')
246
+ method: 'PATCH',
247
+ body: JSON.stringify('My Normal User')
251
248
  })
252
249
  ```
253
250
 
254
- ### List Cookies
255
- Sends a list of the available cookies along with a flag indicated if it’s the selected.
251
+ ### Update Fallback Proxy
256
252
  ```js
257
- fetch(addr + '/mockaton/cookies')
253
+ fetch(addr + '/mockaton/fallback', {
254
+ method: 'PATCH',
255
+ body: JSON.stringify('http://example.com')
256
+ })
258
257
  ```
259
258
 
260
- ### Update Fallback Proxy
259
+ ### Reset
260
+ Re-initialize the collection. So if you added or removed mocks they
261
+ will be considered. The selected mocks, cookies, and delays are
262
+ back to default. But the `Config.proxyFalllback` is not affected.
261
263
  ```js
262
- fetch(addr + '/mockaton/fallback', {
263
- method: 'PATCH',
264
- body: JSON.stringify('http://example.com')
264
+ fetch(addr + '/mockaton/reset', {
265
+ method: 'PATCH'
265
266
  })
266
267
  ```
package/Tests.js CHANGED
@@ -29,7 +29,7 @@ const fixtures = [
29
29
  [
30
30
  '/api',
31
31
  'api/.GET.200.json',
32
- 'index-like route is just the extension convention'
32
+ 'index-like route for /api, which could just be the extension convention'
33
33
  ],
34
34
 
35
35
  // Exact route paths
@@ -150,6 +150,8 @@ async function runTests() {
150
150
  'api/alternative(comment-2).GET.200.json',
151
151
  JSON.stringify({ comment: 2 }))
152
152
 
153
+ await test422WhenUpdatingNonExistingMockAlternative()
154
+
153
155
  await testAutogenerates500(
154
156
  '/api/alternative',
155
157
  `api/alternative${DEFAULT_500_COMMENT}.GET.500.txt`)
@@ -266,6 +268,15 @@ async function testItUpdatesDelayAndFile(url, file, expectedBody) {
266
268
  })
267
269
  }
268
270
 
271
+ async function test422WhenUpdatingNonExistingMockAlternative() {
272
+ await it('There are mocks for /api/the-route but not this one', async () => {
273
+ const res = await request(API.edit, {
274
+ method: 'PATCH',
275
+ body: JSON.stringify({ [DF.file]: 'api/the-route(non-existing-variant).GET.200.json' })
276
+ })
277
+ equal(res.status, 422)
278
+ })
279
+ }
269
280
 
270
281
  async function testAutogenerates500(url, file) {
271
282
  await request(API.edit, {
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": "6.3.10",
5
+ "version": "6.3.11",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "license": "MIT",
package/src/Api.js CHANGED
@@ -57,14 +57,15 @@ async function selectCookie(req, response) {
57
57
  async function updateBroker(req, response) {
58
58
  try {
59
59
  const body = await parseJSON(req)
60
- const broker = mockBrokersCollection.getBrokerByFilename(body[DF.file])
61
- if (!broker) {
60
+ const file = body[DF.file]
61
+ const broker = mockBrokersCollection.getBrokerByFilename(file)
62
+ if (!broker || !broker.mockExists(file)) {
62
63
  sendUnprocessableContent(response)
63
64
  return
64
65
  }
65
66
  if (DF.delayed in body)
66
67
  broker.updateDelay(body[DF.delayed])
67
- broker.updateFile(body[DF.file])
68
+ broker.updateFile(file)
68
69
  sendOK(response)
69
70
  }
70
71
  catch (error) {
package/src/MockBroker.js CHANGED
@@ -42,6 +42,10 @@ export class MockBroker {
42
42
  get delay() { return this.currentMock.delay }
43
43
  get status() { return parseFilename(this.file).status }
44
44
 
45
+ mockExists(file) {
46
+ return this.mocks.includes(file)
47
+ }
48
+
45
49
  updateFile(filename) {
46
50
  this.currentMock.file = filename
47
51
  }
@@ -37,10 +37,6 @@ export function init() {
37
37
  forEachBroker(broker => broker.ensureItHas500())
38
38
  }
39
39
 
40
- function forEachBroker(fn) {
41
- for (const brokers of Object.values(collection))
42
- Object.values(brokers).forEach(fn)
43
- }
44
40
 
45
41
  export const getAll = () => collection
46
42
 
@@ -78,3 +74,8 @@ export function setMocksMatchingComment(comment) {
78
74
  }
79
75
 
80
76
 
77
+ function forEachBroker(fn) {
78
+ for (const brokers of Object.values(collection))
79
+ Object.values(brokers).forEach(fn)
80
+ }
81
+
package/src/utils/fs.js CHANGED
@@ -7,5 +7,6 @@ export const isDirectory = path => lstatSync(path, { throwIfNoEntry: false })?.i
7
7
 
8
8
  export const read = path => readFileSync(path)
9
9
 
10
+ /** @returns {Array<string>} paths relative to `dir` */
10
11
  export const listFilesRecursively = dir => readdirSync(dir, { recursive: true })
11
12
  .filter(f => isFile(join(dir, f)))