mockaton 4.0.1 → 5.0.1

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
@@ -21,7 +21,6 @@ exploring its [sample-mocks/](./sample-mocks) directory. Then, run
21
21
 
22
22
  <img src="./README-dashboard.png" style="max-width:820px"/>
23
23
 
24
-
25
24
  ## Basic Usage
26
25
  ```
27
26
  npm install mockaton
@@ -52,7 +51,7 @@ interface Config {
52
51
  onReady?: (dashboardUrl: string) => void // defaults to openInBrowser. pass a noop to prevent opening the dashboard
53
52
  cookies?: object
54
53
  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 ~)
54
+ allowedExt?: RegExp // /\.(md|json|txt|js)$/ Just for excluding temporary editor files (e.g. JetBrains appends a ~)
56
55
  extraHeaders?: []
57
56
  }
58
57
  ```
@@ -61,8 +60,7 @@ interface Config {
61
60
 
62
61
  ## Mock Variants
63
62
  Each route can have many mocks, which could either be:
64
- - Different response __status code__.
65
- - e.g. for testing error responses.
63
+ - Different response __status code__. For example, for testing error responses.
66
64
  - __Comment__ on the filename, which is anything within parentheses.
67
65
  - e.g. `api/user(my-comment).POST.201.json`
68
66
 
@@ -81,11 +79,18 @@ export default [
81
79
  ]
82
80
  ```
83
81
 
84
- Or, export default a function. There, you
85
- can override the response status and the default JSON content
86
- type. But don’t call `response.end()`, just return a string.
82
+ Or, export default a function. In it, you can override the response status and the
83
+ default JSON content type. But don’t call `response.end()`, just return a string.
84
+
85
+ In a sense, you can think of this is an HTTP handler. So you can read or
86
+ write to a database, or pull data from a backend. The `request` is of type
87
+ [IncomingMessage](https://nodejs.org/api/http.html#class-httpincomingmessage), and the
88
+ `response` a [ServerResponse](https://nodejs.org/api/http.html#class-httpserverresponse).
87
89
  ```js
88
- export default function (req, response) {
90
+ export default function optionalName(request, response) {
91
+ globalThis.myDatabase ??= { count: 0 }
92
+ globalThis.myDatabase.count++
93
+
89
94
  return JSON.stringify({ a: 1 })
90
95
  }
91
96
  ```
@@ -104,15 +109,16 @@ particular response. They are handy for testing spinners.
104
109
  The delay is globally configurable via `Config.delay = 1200` (milliseconds).
105
110
 
106
111
 
112
+
107
113
  ## File Name Convention
108
114
 
109
115
 
110
116
  ### Extension
111
- `.Method.HttpResponseStatusCode.FileExt`
117
+ `.Method.ResponseStatusCode.FileExt`
112
118
 
113
119
  The **file extension** can be anything, but `.md` is reserved for documentation.
114
120
 
115
- The `Config.allowedExt` regex defaults to: `/\.(json|txt|md|js)$/`
121
+ The `Config.allowedExt` regex defaults to: `/\.(md|json|txt|js)$/`
116
122
 
117
123
 
118
124
  ### Dynamic Parameters
@@ -157,6 +163,14 @@ api/foo/(my comment).GET.200.json
157
163
 
158
164
  ## `Config.cookies`
159
165
  The selected cookie is sent in every response in the `Set-Cookie` header.
166
+
167
+ The key is just a label used for selecting a particular cookie in the
168
+ dashboard. In the dashboard, only one cookie can be selected. If you need
169
+ more cookies you can inject additional cookies globally in `Config.extraHeaders`.
170
+
171
+ `jwtCookie` has a hardcoded header and signature. In other
172
+ words, it’s useful if you only care about its payload.
173
+
160
174
  ```js
161
175
  import { jwtCookie } from 'mockaton'
162
176
 
@@ -169,15 +183,11 @@ Config.cookies = {
169
183
  })
170
184
  }
171
185
  ```
172
- The key is just a label used for selecting a particular cookie in the dashboard.
173
-
174
- `jwtCookie` has a hardcoded header and signature. In other
175
- words, it’s useful if you only care about its payload.
176
-
177
186
 
178
187
  ## `Config.extraHeaders`
179
- They are applied last, right before ending the response. In other words, they
180
- can overwrite the `Content-Type`. The header name goes in even indices.
188
+ They are applied last, right before ending the response.
189
+ In other words, they can overwrite the `Content-Type`. Note
190
+ that it's an array and the header name goes in even indices.
181
191
 
182
192
  ```js
183
193
  Config.extraHeaders = [
@@ -188,16 +198,15 @@ Config.extraHeaders = [
188
198
  ```
189
199
 
190
200
  ## Documenting Contracts (.md)
191
- This is handy for documenting request payload parameters. The dashboard will
192
- print the Markdown document (as plain text) above the actual payload content.
201
+ This is handy for documenting request payload parameters. The
202
+ dashboard prints the Markdown document as plain text (I know, I know).
193
203
 
194
- Create a markdown file following the same filename convention.
195
- The status code can be any number. For example,
196
204
  ```text
197
- api/foo/[user-id].POST.201.md
205
+ api/foo/[user-id].POST.md
198
206
  api/foo/[user-id].POST.201.json
199
207
  ```
200
208
 
209
+ ---
201
210
 
202
211
  ## API
203
212
 
@@ -229,8 +238,7 @@ fetch(addr + '/mockaton/reset', {
229
238
  ```
230
239
 
231
240
  ### Select a cookie
232
- In `Config.cookies`, each key is the label used
233
- for changing it. Only one cookie can be set.
241
+ In `Config.cookies`, each key is the label used for changing it.
234
242
  ```js
235
243
  fetch(addr + '/mockaton/cookies', {
236
244
  method: 'PATCH',
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": "4.0.1",
5
+ "version": "5.0.1",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "license": "MIT",
@@ -0,0 +1,9 @@
1
+ # Request Body
2
+
3
+ ```json
4
+ {
5
+ "new_name": "John"
6
+ }
7
+ ```
8
+
9
+ This is just documentation. In this example, for the request body payload.
package/src/Config.js CHANGED
@@ -11,7 +11,7 @@ export const Config = {
11
11
  cookies: {}, // defaults to the first kv
12
12
  onReady: openInBrowser,
13
13
  proxyFallback: '', // e.g. http://localhost:9999
14
- allowedExt: /\.(json|txt|md|js)$/, // Just for excluding temporary editor files (e.g. JetBrains appends a ~)
14
+ allowedExt: /\.(md|json|txt|js)$/, // Just for excluding temporary editor files (e.g. JetBrains appends a ~)
15
15
  extraHeaders: []
16
16
  }
17
17
 
package/src/Dashboard.js CHANGED
@@ -132,8 +132,7 @@ function SectionByMethod({ method, brokers }) {
132
132
  r('tbody', null,
133
133
  r('th', null, method),
134
134
  Object.entries(brokers)
135
- .sort((a, b) => a[0].localeCompare(b[0]))
136
- .filter(([, broker]) => broker.mocks.length) // handles Markdown doc
135
+ .filter(([, broker]) => broker.mocks.length > 1) // Excludes Markdown only routes (>1 because of the autogen500)
137
136
  .map(([urlMask, broker]) =>
138
137
  r('tr', null,
139
138
  r('td', null, r(PreviewLink, { method, urlMask, documentation: broker.documentation })),
package/src/MockBroker.js CHANGED
@@ -78,7 +78,7 @@ export class MockBroker {
78
78
  }
79
79
 
80
80
  #registerTemp500() {
81
- const { urlMask, method } = Route.parseFilename(this.mocks[0])
81
+ const { urlMask, method } = Route.parseFilename(this.mocks[0] || this.documentation)
82
82
  let mask = urlMask
83
83
  const t = join(Config.mocksDir, urlMask)
84
84
  if (existsSync(t) && lstatSync(t).isDirectory())
package/src/Route.js CHANGED
@@ -44,23 +44,43 @@ export class Route {
44
44
 
45
45
  static parseFilename(file) {
46
46
  const tokens = file.replace(Route.reComments, '').split('.')
47
+ return file.endsWith('.md')
48
+ ? parseDocumentation(tokens)
49
+ : parseMock(tokens)
50
+ }
51
+ }
52
+
53
+ function parseDocumentation(tokens) { // TESTME
54
+ if (tokens.length < 3)
55
+ return { error: 'Invalid Documentation Filename Convention' }
56
+
57
+ const method = tokens.at(-2)
58
+ if (!httpMethods.includes(method))
59
+ return { error: `Unrecognized HTTP Method: "${method}"` }
60
+
61
+ return {
62
+ urlMask: '/' + removeTrailingSlash(tokens.at(-3)),
63
+ method,
64
+ status: 200
65
+ }
66
+ }
47
67
 
48
- if (tokens.length < 4)
49
- return { error: 'Invalid Filename Convention' }
68
+ function parseMock(tokens) {
69
+ if (tokens.length < 4)
70
+ return { error: 'Invalid Filename Convention' }
50
71
 
51
- const status = Number(tokens.at(-2))
52
- if (!responseStatusIsValid(status))
53
- return { error: `Invalid HTTP Response Status: "${status}"` }
72
+ const status = Number(tokens.at(-2))
73
+ if (!responseStatusIsValid(status))
74
+ return { error: `Invalid HTTP Response Status: "${status}"` }
54
75
 
55
- const method = tokens.at(-3)
56
- if (!httpMethods.includes(method))
57
- return { error: `Unrecognized HTTP Method: "${method}"` }
76
+ const method = tokens.at(-3)
77
+ if (!httpMethods.includes(method))
78
+ return { error: `Unrecognized HTTP Method: "${method}"` }
58
79
 
59
- return {
60
- urlMask: '/' + removeTrailingSlash(tokens.at(-4)),
61
- method,
62
- status
63
- }
80
+ return {
81
+ urlMask: '/' + removeTrailingSlash(tokens.at(-4)),
82
+ method,
83
+ status
64
84
  }
65
85
  }
66
86
 
@@ -1,12 +0,0 @@
1
- # PATCH /api/user/edit
2
-
3
- ## Expected Request Body
4
- ```json
5
- {
6
- "new_name": "John"
7
- }
8
- ```
9
-
10
- Example of a markdown file for documenting the request contract.
11
-
12
- Markdown files can be seen in the mock server dashboard as well.