mockaton 8.0.3 → 8.1.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 CHANGED
@@ -15,7 +15,7 @@ can be used for downloading a TAR of your XHR requests following that convention
15
15
 
16
16
  ## Getting Started Demo
17
17
  - Checkout this repo
18
- - `npm install tsx`
18
+ - `npm install tsx` (optional)
19
19
  - `npm run demo:ts`
20
20
  which will open the following dashboard
21
21
  - Explore the [sample-mocks/](./sample-mocks) directory
@@ -47,7 +47,7 @@ _Reset_ button is for registering newly added, removed, or renamed mocks.
47
47
  - Similarly, it allows for checking out long-lived branches that have old API contracts
48
48
 
49
49
  ## Motivation
50
- - Avoids having to spin up and maintain hefty or complex backends when developing UIs.
50
+ - Avoids spinning up and maintaining hefty backends when developing UIs.
51
51
  - For a deterministic and comprehensive backend state. For example, having all the possible
52
52
  state variants of a collection helps for spotting inadvertent bugs.
53
53
 
@@ -177,7 +177,7 @@ but since that’s part of the query string, it’s ignored anyway.
177
177
 
178
178
 
179
179
  ### Index-like route
180
- For instance, let's say you have `api/foo/bar`, and
180
+ For instance, lets say you have `api/foo/bar`, and
181
181
  `api/foo`. For the latter you have two options:
182
182
 
183
183
  **Option A.** Place it outside the directory:
@@ -207,11 +207,6 @@ Defaults to `0`, which means auto-assigned
207
207
  Defaults to `/(\.DS_Store|~)$/`
208
208
 
209
209
 
210
- ### `proxyFallback?: string`
211
- Lets you specify a target server for serving routes you don’t have mocks for.
212
- For example, `Config.proxyFallback = 'http://example.com:8080'`
213
-
214
-
215
210
  ### `delay?: number` 🕓
216
211
  The clock icon next to the mock selector is a checkbox for delaying a
217
212
  particular response. They are handy for testing spinners.
@@ -219,6 +214,11 @@ particular response. They are handy for testing spinners.
219
214
  The delay is globally configurable via `Config.delay = 1200` (milliseconds).
220
215
 
221
216
 
217
+ ### `proxyFallback?: string`
218
+ Lets you specify a target server for serving routes you don’t have mocks for.
219
+ For example, `Config.proxyFallback = 'http://example.com:8080'`
220
+
221
+
222
222
  ### `staticDir?: string`
223
223
  Files under `Config.staticDir` don’t use the filename convention.
224
224
  Also, they take precedence over the `GET` mocks in `Config.mockDir`.
@@ -305,7 +305,7 @@ import { jsToJsonPlugin } from 'mockaton'
305
305
 
306
306
  Config.plugins = [
307
307
  [/\.(js|ts)$/, jsToJsonPlugin], // Default
308
- [/\.yaml$/, yamlToJsonPlugin],
308
+ [/\.yml$/, yamlToJsonPlugin],
309
309
  [/foo\.GET\.200\.txt$/, capitalizePlugin], // e.g. GET /api/foo would be capitalized
310
310
  ]
311
311
 
@@ -328,7 +328,7 @@ function capitalizePlugin(filePath) {
328
328
  ### `corsAllowed?: boolean`
329
329
  Defaults to `corsAllowed = false`
330
330
 
331
- When `corsAllowed === true`, these are the default options:
331
+ When `Config.corsAllowed === true`, these are the default options:
332
332
  ```js
333
333
  Config.corsOrigins = ['*']
334
334
  Config.corsMethods = ['GET', 'PUT', 'DELETE', 'POST', 'PATCH', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT']
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": "8.0.3",
5
+ "version": "8.1.0",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "license": "MIT",
package/src/Dashboard.css CHANGED
@@ -5,7 +5,8 @@
5
5
  @media (prefers-color-scheme: light) {
6
6
  :root {
7
7
  --color4xxBackground: #ffedd1;
8
- --colorAccent: #1e88e5;
8
+ --colorAccent: #0072d6;
9
+ --colorAccentAlt: #01873b;
9
10
  --colorBackground: #fff;
10
11
  --colorHeaderBackground: #f4f4f4;
11
12
  --colorComboBoxBackground: #fafafa;
@@ -23,6 +24,7 @@
23
24
  :root {
24
25
  --color4xxBackground: #403630;
25
26
  --colorAccent: #1f91ff;
27
+ --colorAccentAlt: #00E676;
26
28
  --colorBackground: #161616;
27
29
  --colorHeaderBackground: #090909;
28
30
  --colorComboBoxBackground: #252525;
@@ -286,7 +288,7 @@ main {
286
288
  .ProgressBar {
287
289
  position: relative;
288
290
  width: 100%;
289
- height: 16px;
291
+ height: 2px;
290
292
  background: var(--colorComboBoxHeaderBackground);
291
293
 
292
294
  div {
@@ -295,7 +297,7 @@ main {
295
297
  left: 0;
296
298
  height: 100%;
297
299
  background: var(--colorAccent);
298
- animation: _kfProgress;
300
+ animation-name: _kfProgress;
299
301
  /*animation-duration: It's in JavaScript */
300
302
  }
301
303
 
@@ -328,7 +330,7 @@ main {
328
330
  a {
329
331
  display: inline-block;
330
332
  padding: 6px 0;
331
- color: var(--colorAccent);
333
+ color: var(--colorAccentAlt);
332
334
  text-decoration: none;
333
335
 
334
336
  &:hover {
@@ -6,7 +6,7 @@
6
6
  <link rel="icon" href="data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m235 33.7v202c0 9.19-5.81 14-17.4 14-11.6 0-17.4-4.83-17.4-14v-151c-0.115-4.49-6.72-5.88-8.46-0.87l-48.3 155c-2.22 7.01-7.72 10.1-16 9.9-3.63-0.191-7.01-1.14-9.66-2.89-2.89-1.72-4.83-4.34-5.57-7.72-11.1-37-22.6-74.3-34.1-111-4.34-14-8.95-31.4-14-48.3-1.82-4.83-8.16-5.32-8.46 1.16v156c0 9.19-5.81 14-17.4 14-11.6 0-17.4-4.83-17.4-14v-207c0-5.74 2.62-13.2 9.39-16.3 7.5-3.14 15-4.05 21.8-3.8 3.14 0 6.03 0.686 8.95 1.46 3.14 0.797 6.03 1.98 8.7 3.63 2.65 1.38 5.32 3.14 7.5 5.57 2.22 2.22 3.87 4.83 5.07 7.72l45.8 157c4.63-15.9 32.4-117 33.3-121 4.12-13.8 7.72-26.5 10.9-38.7 1.16-2.65 2.89-5.32 5.07-7.5 2.15-2.15 4.58-4.12 7.5-5.32 2.65-1.57 5.57-2.89 8.46-3.63 3.14-0.797 9.44-0.988 12.1-0.988 11.6 1.07 29.4 9.14 29.4 27z' fill='%23808080'/%3E%3C/svg%3E">
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1">
8
8
  <meta name="description" content="Mock Server for developing UIs">
9
- <title>Mock Server</title>
9
+ <title>Mockaton</title>
10
10
  </head>
11
11
  <body>
12
12
  <script src="/Dashboard.js" type="module"></script>
package/src/Dashboard.js CHANGED
@@ -6,16 +6,17 @@ import { DEFAULT_500_COMMENT } from '/ApiConstants.js'
6
6
  const Strings = {
7
7
  allow_cors: 'Allow CORS',
8
8
  bulk_select_by_comment: 'Bulk Select by Comment',
9
+ bulk_select_by_comment_disabled_title: 'No mock files have comments, which are anything within parentheses on the filename.',
9
10
  click_link_to_preview: 'Click a link to preview it',
10
11
  cookie: 'Cookie',
12
+ cookie_disabled_title: 'No cookies specified in Config.cookies',
11
13
  delay: 'Delay',
12
14
  empty_response_body: '/* Empty Response Body */',
13
15
  internal_server_error: 'Internal Server Error',
14
16
  mock: 'Mock',
15
17
  reset: 'Reset',
16
18
  select_one: 'Select One',
17
- static: 'Static',
18
- title: 'Mockaton'
19
+ static: 'Static'
19
20
  }
20
21
 
21
22
  const CSS = {
@@ -59,7 +60,6 @@ function App([brokersByMethod, cookies, comments, corsAllowed, staticFiles]) {
59
60
  }
60
61
 
61
62
  function DevPanel(brokersByMethod, cookies, comments, corsAllowed, staticFiles) {
62
- document.title = Strings.title
63
63
  return (
64
64
  r('div', null,
65
65
  r('menu', null,
@@ -79,12 +79,14 @@ function DevPanel(brokersByMethod, cookies, comments, corsAllowed, staticFiles)
79
79
  }
80
80
 
81
81
  function CookieSelector({ list }) {
82
+ const disabled = list.length <= 1
82
83
  return (
83
84
  r('label', null,
84
85
  r('span', null, Strings.cookie),
85
86
  r('select', {
86
87
  autocomplete: 'off',
87
- disabled: list.length <= 1,
88
+ disabled,
89
+ title: disabled ? Strings.cookie_disabled_title : '',
88
90
  onChange() {
89
91
  mockaton.selectCookie(this.value)
90
92
  .catch(console.error)
@@ -107,6 +109,7 @@ function BulkSelector({ comments }) {
107
109
  r('select', {
108
110
  autocomplete: 'off',
109
111
  disabled,
112
+ title: disabled ? Strings.bulk_select_by_comment_disabled_title : '',
110
113
  onChange() {
111
114
  mockaton.bulkSelectByComment(this.value)
112
115
  .then(init)
@@ -202,7 +205,10 @@ function PreviewLink({ method, urlMask }) {
202
205
  renderPayloadImage(this.href)
203
206
  else
204
207
  updatePayloadViewer(await res.text() || Strings.empty_response_body, mime)
205
- refPayloadFile.current.innerText = this.closest('tr').querySelector('select').value
208
+ empty(refPayloadFile.current)
209
+ refPayloadFile.current.append(PayloadViewerTitle({
210
+ file: this.closest('tr').querySelector('select').value
211
+ }))
206
212
  }
207
213
  catch (error) {
208
214
  console.error(error)
@@ -211,6 +217,15 @@ function PreviewLink({ method, urlMask }) {
211
217
  }, urlMask))
212
218
  }
213
219
 
220
+ function PayloadViewerTitle({ file }) {
221
+ const { urlMask, method, status, ext } = parseFilename(file)
222
+ return (
223
+ r('span', null,
224
+ urlMask + '.' + method + '.',
225
+ r('abbr', { title: HttpStatus[status] }, status),
226
+ '.' + ext))
227
+ }
228
+
214
229
  function ProgressBar() {
215
230
  return (
216
231
  r('div', { className: CSS.ProgressBar },
@@ -382,3 +397,91 @@ function createSvgElement(tagName, props, ...children) {
382
397
  function useRef() {
383
398
  return { current: null }
384
399
  }
400
+
401
+ const HttpStatus = {
402
+ 100: 'Continue',
403
+ 101: 'Switching Protocols',
404
+ 102: 'Processing',
405
+ 103: 'Early Hints',
406
+ 200: 'OK',
407
+ 201: 'Created',
408
+ 202: 'Accepted',
409
+ 203: 'Non-Authoritative Information',
410
+ 204: 'No Content',
411
+ 205: 'Reset Content',
412
+ 206: 'Partial Content',
413
+ 207: 'Multi-Status',
414
+ 208: 'Already Reported',
415
+ 218: 'This is fine (Apache Web Server)',
416
+ 226: 'IM Used',
417
+ 300: 'Multiple Choices',
418
+ 301: 'Moved Permanently',
419
+ 302: 'Found',
420
+ 303: 'See Other',
421
+ 304: 'Not Modified',
422
+ 306: 'Switch Proxy',
423
+ 307: 'Temporary Redirect',
424
+ 308: 'Resume Incomplete',
425
+ 400: 'Bad Request',
426
+ 401: 'Unauthorized',
427
+ 402: 'Payment Required',
428
+ 403: 'Forbidden',
429
+ 404: 'Not Found',
430
+ 405: 'Method Not Allowed',
431
+ 406: 'Not Acceptable',
432
+ 407: 'Proxy Authentication Required',
433
+ 408: 'Request Timeout',
434
+ 409: 'Conflict',
435
+ 410: 'Gone',
436
+ 411: 'Length Required',
437
+ 412: 'Precondition Failed',
438
+ 413: 'Request Entity Too Large',
439
+ 414: 'Request-URI Too Long',
440
+ 415: 'Unsupported Media Type',
441
+ 416: 'Requested Range Not Satisfiable',
442
+ 417: 'Expectation Failed',
443
+ 418: 'I’m a teapot',
444
+ 419: 'Page Expired (Laravel Framework)',
445
+ 420: 'Method Failure (Spring Framework)',
446
+ 421: 'Misdirected Request',
447
+ 422: 'Unprocessable Entity',
448
+ 423: 'Locked',
449
+ 424: 'Failed Dependency',
450
+ 426: 'Upgrade Required',
451
+ 428: 'Precondition Required',
452
+ 429: 'Too Many Requests',
453
+ 431: 'Request Header Fields Too Large',
454
+ 440: 'Login Time-out',
455
+ 444: 'Connection Closed Without Response',
456
+ 449: 'Retry With',
457
+ 450: 'Blocked by Windows Parental Controls',
458
+ 451: 'Unavailable For Legal Reasons',
459
+ 494: 'Request Header Too Large',
460
+ 495: 'SSL Certificate Error',
461
+ 496: 'SSL Certificate Required',
462
+ 497: 'HTTP Request Sent to HTTPS Port',
463
+ 498: 'Invalid Token (Esri)',
464
+ 499: 'Client Closed Request',
465
+ 500: 'Internal Server Error',
466
+ 501: 'Not Implemented',
467
+ 502: 'Bad Gateway',
468
+ 503: 'Service Unavailable',
469
+ 504: 'Gateway Timeout',
470
+ 505: 'HTTP Version Not Supported',
471
+ 506: 'Variant Also Negotiates',
472
+ 507: 'Insufficient Storage',
473
+ 508: 'Loop Detected',
474
+ 509: 'Bandwidth Limit Exceeded',
475
+ 510: 'Not Extended',
476
+ 511: 'Network Authentication Required',
477
+ 520: 'Unknown Error',
478
+ 521: 'Web Server Is Down',
479
+ 522: 'Connection Timed Out',
480
+ 523: 'Origin Is Unreachable',
481
+ 524: 'A Timeout Occurred',
482
+ 525: 'SSL Handshake Failed',
483
+ 526: 'Invalid SSL Certificate',
484
+ 527: 'Railgun Listener to Origin Error',
485
+ 530: 'Origin DNS Error',
486
+ 598: 'Network Read Timeout Error'
487
+ }
package/src/Filename.js CHANGED
@@ -39,7 +39,8 @@ export function parseFilename(file) {
39
39
  return {
40
40
  urlMask: '/' + removeTrailingSlash(tokens.slice(0, -3).join('.')),
41
41
  method: tokens.at(-3),
42
- status: Number(tokens.at(-2))
42
+ status: Number(tokens.at(-2)),
43
+ ext: tokens.at(-1)
43
44
  }
44
45
  }
45
46