mockaton 7.3.0 → 7.4.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
Binary file
package/README.md CHANGED
@@ -360,3 +360,4 @@ await mockaton.reset()
360
360
  ## TODO
361
361
  - Refactor Tests
362
362
  - Dashboard. List `staticDir` and indicate if it’s overriding some mock.
363
+ - Dashboard. Handle non-json Mock Preview (such as images)
package/index.d.ts CHANGED
@@ -36,19 +36,29 @@ export function jwtCookie(cookieName: string, payload: any): string
36
36
  export class Commander {
37
37
  constructor(addr: string)
38
38
 
39
+ listMocks(): Promise<Response>
40
+
39
41
  select(file: string): Promise<Response>
40
42
 
41
43
  bulkSelectByComment(comment: string): Promise<Response>
42
44
 
45
+
43
46
  setRouteIsDelayed(routeMethod: string, routeUrlMask: string, delayed: boolean): Promise<Response>
44
47
 
48
+
49
+ listCookies(): Promise<Response>
50
+
45
51
  selectCookie(cookieKey: string): Promise<Response>
46
52
 
53
+
54
+ listComments(): Promise<Response>
55
+
47
56
  setProxyFallback(proxyAddr: string): Promise<Response>
48
57
 
49
58
  reset(): Promise<Response>
50
59
 
51
- listCookies(): Promise<Response>
52
60
 
53
- listComments(): Promise<Response>
61
+ getCorsAllowed(): Promise<Response>
62
+
63
+ setCorsAllowed(value: boolean): Promise<Response>
54
64
  }
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": "7.3.0",
5
+ "version": "7.4.0",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "license": "MIT",
@@ -4,6 +4,6 @@
4
4
  export default function (req, response) {
5
5
  return JSON.stringify([
6
6
  'http://example.com/foo',
7
- 'http://example.com/bar',
8
- ])
7
+ 'http://example.com/bar'
8
+ ], null, 2)
9
9
  }
package/src/Dashboard.css CHANGED
@@ -5,30 +5,34 @@
5
5
  @media (prefers-color-scheme: light) {
6
6
  :root {
7
7
  --color4xxBackground: #ffedd1;
8
- --colorAccent: #0171dd;
8
+ --colorAccent: #1e88e5;
9
9
  --colorBackground: #fff;
10
- --colorCodeBackground: #fafafa;
11
10
  --colorComboBoxBackground: #fafafa;
11
+ --colorComboBoxHeaderBackground: #fff;
12
12
  --colorDisabled: #222;
13
+ --colorHeaderBackground: #f7f7f7;
13
14
  --colorHover: #dfefff;
14
- --colorLabel: #777;
15
+ --colorLabel: #666;
15
16
  --colorLightRed: #ffe4ee;
17
+ --colorMockBodyBackground: #fafafa;
16
18
  --colorRed: #da0f00;
17
- --colorSecondaryButtonBackground: #f0f0f0;
19
+ --colorSecondaryButtonBackground: #fafafa;
18
20
  --colorText: #000;
19
21
  }
20
22
  }
21
23
  @media (prefers-color-scheme: dark) {
22
24
  :root {
23
25
  --color4xxBackground: #403630;
24
- --colorAccent: #0682fa;
26
+ --colorAccent: #1f91ff;
25
27
  --colorBackground: #141414;
26
- --colorCodeBackground: #333;
27
28
  --colorComboBoxBackground: #252525;
29
+ --colorComboBoxHeaderBackground: #222;
28
30
  --colorDisabled: #aaa;
31
+ --colorHeaderBackground: #0b0b0b;
29
32
  --colorHover: #023661;
30
33
  --colorLabel: #aaa;
31
34
  --colorLightRed: #ffe4ee;
35
+ --colorMockBodyBackground: #333;
32
36
  --colorRed: #f41606;
33
37
  --colorSecondaryButtonBackground: #444;
34
38
  --colorText: #fff;
@@ -73,41 +77,28 @@ select {
73
77
  }
74
78
  }
75
79
 
76
-
77
- main {
78
- display: flex;
79
- align-items: flex-start;
80
-
81
- > table {
82
- border-collapse: collapse;
83
-
84
- th {
85
- padding-top: 20px;
86
- padding-bottom: 2px;
87
- text-align: left;
88
- }
89
-
90
- tr {
91
- border-bottom: 2px solid transparent;
92
- }
93
- }
94
- }
95
-
96
80
  menu {
81
+ position: fixed;
82
+ z-index: 100;
83
+ top: 0;
84
+ left: 0;
97
85
  display: flex;
86
+ width: 100%;
98
87
  align-items: flex-end;
99
- margin-bottom: 12px;
88
+ padding: 20px 16px;
89
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
90
+ background: var(--colorHeaderBackground);
100
91
  gap: 16px;
101
92
 
102
93
  img {
103
94
  width: 140px;
104
- margin-right: 24px;
95
+ margin-right: 76px;
96
+ margin-left: -1px;
105
97
  }
106
98
 
107
99
  label {
108
100
  span {
109
101
  display: block;
110
- padding-left: 7px;
111
102
  color: var(--colorLabel);
112
103
  font-size: 11px;
113
104
  }
@@ -117,6 +108,7 @@ menu {
117
108
  padding: 4px;
118
109
  margin-top: 2px;
119
110
  font-size: 11px;
111
+ background: var(--colorComboBoxHeaderBackground);
120
112
  }
121
113
  }
122
114
 
@@ -131,6 +123,7 @@ menu {
131
123
  &:hover {
132
124
  background: var(--colorRed);
133
125
  color: white;
126
+ box-shadow: var(--boxShadow1);
134
127
  }
135
128
  }
136
129
 
@@ -142,9 +135,31 @@ menu {
142
135
  }
143
136
  }
144
137
 
138
+
139
+ main {
140
+ display: flex;
141
+ align-items: flex-start;
142
+ margin-top: 64px;
143
+
144
+ > table {
145
+ border-collapse: collapse;
146
+
147
+ th {
148
+ padding-top: 20px;
149
+ padding-bottom: 2px;
150
+ text-align: left;
151
+ }
152
+
153
+ tr {
154
+ border-bottom: 2px solid transparent;
155
+ }
156
+ }
157
+ }
158
+
159
+
145
160
  .PayloadViewer {
146
161
  position: sticky;
147
- top: 0;
162
+ top: 80px;
148
163
  width: 50%;
149
164
  margin-left: 16px;
150
165
 
@@ -153,14 +168,17 @@ menu {
153
168
  }
154
169
 
155
170
  pre {
171
+ overflow: auto;
172
+ max-height: calc(100vh - 160px);
173
+ padding: 12px;
174
+ margin-top: 6px;
175
+ box-shadow: var(--boxShadow1);
176
+ border-radius: 4px;
177
+ background: var(--colorMockBodyBackground);
178
+ white-space: pre;
156
179
  tab-size: 2;
157
180
 
158
- &:not(:empty) {
159
- overflow: auto;
160
- max-height: calc(100vh - 160px);
161
- padding: 12px;
162
- margin-top: 6px;
163
- background: var(--colorCodeBackground);
181
+ code * {
164
182
  font-family: monospace;
165
183
  }
166
184
  }
@@ -172,6 +190,7 @@ menu {
172
190
  display: inline-block;
173
191
  width: 280px;
174
192
  padding: 8px 6px;
193
+ border-radius: 4px;
175
194
  color: var(--colorAccent);
176
195
  text-decoration: none;
177
196
 
@@ -220,6 +239,7 @@ menu {
220
239
  fill: var(--colorText);
221
240
  border-radius: 50%;
222
241
  background: var(--colorSecondaryButtonBackground);
242
+ box-shadow: var(--boxShadow1);
223
243
 
224
244
  &:hover {
225
245
  background: var(--colorHover);
@@ -244,6 +264,7 @@ menu {
244
264
 
245
265
  > span {
246
266
  padding: 4px;
267
+ box-shadow: var(--boxShadow1);
247
268
  font-size: 10px;
248
269
  color: var(--colorText);
249
270
  border-radius: 2px;
@@ -256,6 +277,122 @@ menu {
256
277
  }
257
278
  }
258
279
 
280
+ .ProgressBar {
281
+ position: relative;
282
+ width: 100%;
283
+ height: 16px;
284
+ background: var(--colorComboBoxHeaderBackground);
285
+
286
+ div {
287
+ position: absolute;
288
+ top: 0;
289
+ left: 0;
290
+ height: 100%;
291
+ background: var(--colorAccent);
292
+ animation: _kfProgress;
293
+ /*animation-duration: It's in JavaScript */
294
+ }
295
+
296
+ }
297
+ @keyframes _kfProgress {
298
+ 0% {
299
+ width: 0;
300
+ }
301
+ 100% {
302
+ width: 100%;
303
+ }
304
+ }
305
+
259
306
  .bold {
260
307
  font-weight: bold;
261
308
  }
309
+
310
+
311
+ /*
312
+ * Prism
313
+ */
314
+
315
+ @media (prefers-color-scheme: dark) {
316
+ .token.cdata, .token.comment, .token.doctype, .token.prolog {
317
+ color: #8292a2
318
+ }
319
+ .token.punctuation {
320
+ color: #f8f8f2
321
+ }
322
+ .token.namespace {
323
+ opacity: .7
324
+ }
325
+ .token.constant, .token.deleted, .token.property, .token.symbol, .token.tag {
326
+ color: #f92672
327
+ }
328
+ .token.boolean, .token.number {
329
+ color: #ae81ff
330
+ }
331
+ .token.attr-name, .token.builtin, .token.char, .token.inserted, .token.selector, .token.string {
332
+ color: #a6e22e
333
+ }
334
+ .language-css .token.string, .style .token.string, .token.entity, .token.operator, .token.url, .token.variable {
335
+ color: #f8f8f2
336
+ }
337
+ .token.atrule, .token.attr-value, .token.class-name, .token.function {
338
+ color: #e6db74
339
+ }
340
+ .token.keyword {
341
+ color: #66d9ef
342
+ }
343
+ .token.important, .token.regex {
344
+ color: #fd971f
345
+ }
346
+ .token.bold, .token.important {
347
+ font-weight: 700
348
+ }
349
+ .token.italic {
350
+ font-style: italic
351
+ }
352
+ .token.entity {
353
+ cursor: help
354
+ }
355
+ }
356
+
357
+ @media (prefers-color-scheme: light) {
358
+ .token.cdata, .token.comment, .token.doctype, .token.prolog {
359
+ color: #708090
360
+ }
361
+ .token.punctuation {
362
+ color: #999
363
+ }
364
+ .token.namespace {
365
+ opacity: .7
366
+ }
367
+ .token.constant, .token.deleted, .token.property, .token.symbol, .token.tag {
368
+ color: #ed206a
369
+ }
370
+ .token.boolean, .token.number {
371
+ color: #9b71e8
372
+ }
373
+ .token.attr-name, .token.builtin, .token.char, .token.inserted, .token.selector, .token.string {
374
+ color: #459900
375
+ }
376
+ .language-css .token.string, .style .token.string, .token.entity, .token.operator, .token.url {
377
+ color: #9a6e3a;
378
+ background: hsla(0, 0%, 100%, .5)
379
+ }
380
+ .token.atrule, .token.attr-value, .token.keyword {
381
+ color: #07a
382
+ }
383
+ .token.class-name, .token.function {
384
+ color: #dd4a68
385
+ }
386
+ .token.important, .token.regex, .token.variable {
387
+ color: #e90
388
+ }
389
+ .token.bold, .token.important {
390
+ font-weight: 700
391
+ }
392
+ .token.italic {
393
+ font-style: italic
394
+ }
395
+ .token.entity {
396
+ cursor: help
397
+ }
398
+ }
@@ -1,12 +1,16 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
- <link rel="stylesheet" href="../Dashboard.css">
5
- <link rel="icon" href="data:">
4
+ <meta charset="UTF-8">
5
+ <link rel="stylesheet" href="/Dashboard.css">
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">
6
7
  <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <meta name="description" content="Mock Server for developing UIs">
7
9
  <title>Mock Server</title>
8
10
  </head>
9
11
  <body>
10
- <script src="../Dashboard.js" type="module"></script>
12
+ <script src="/Dashboard.js" type="module"></script>
13
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js" data-manual integrity="sha512-7Z9J3l1+EYfeaPKcGXu3MS/7T+w19WtKQY/n+xzmw4hZhJ9tyYmcUS+4QqAlzhicE5LAfMQSF3iFTK9bQdTxXg==" crossorigin="anonymous" referrerpolicy="no-referrer" defer></script>
14
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-json.min.js" integrity="sha512-QXFMVAusM85vUYDaNgcYeU3rzSlc+bTV4JvkfJhjxSHlQEo+ig53BtnGkvFTiNJh8D+wv6uWAQ2vJaVmxe8d3w==" crossorigin="anonymous" referrerpolicy="no-referrer" defer></script>
11
15
  </body>
12
16
  </html>
package/src/Dashboard.js CHANGED
@@ -10,7 +10,6 @@ const Strings = {
10
10
  cookie: 'Cookie',
11
11
  delay: 'Delay',
12
12
  empty_response_body: '/* Empty Response Body */',
13
- fetching: '⌚ Fetching…',
14
13
  internal_server_error: 'Internal Server Error',
15
14
  mock: 'Mock',
16
15
  reset: 'Reset',
@@ -25,6 +24,7 @@ const CSS = {
25
24
  MockSelector: 'MockSelector',
26
25
  PayloadViewer: 'PayloadViewer',
27
26
  PreviewLink: 'PreviewLink',
27
+ ProgressBar: 'ProgressBar',
28
28
 
29
29
  bold: 'bold',
30
30
  chosen: 'chosen',
@@ -60,7 +60,7 @@ function DevPanel(brokersByMethod, cookies, comments, corsAllowed) {
60
60
  return (
61
61
  r('div', null,
62
62
  r('menu', null,
63
- r('img', { src: 'mockaton-logo.svg', width: 160 }),
63
+ r('img', { src: '/mockaton-logo.svg', width: 160, alt: Strings.title }),
64
64
  r(CookieSelector, { list: cookies }),
65
65
  r(BulkSelector, { comments }),
66
66
  r(CorsCheckbox, { corsAllowed }),
@@ -70,7 +70,8 @@ function DevPanel(brokersByMethod, cookies, comments, corsAllowed) {
70
70
  r(SectionByMethod, { method, brokers }))),
71
71
  r('div', { className: CSS.PayloadViewer },
72
72
  r('h2', { ref: refPayloadFile }, Strings.mock),
73
- r('pre', { ref: refPayloadViewer }, Strings.click_link_to_preview)))))
73
+ r('pre', null,
74
+ r('code', { ref: refPayloadViewer }, Strings.click_link_to_preview))))))
74
75
  }
75
76
 
76
77
  function CookieSelector({ list }) {
@@ -161,14 +162,19 @@ function PreviewLink({ method, urlMask }) {
161
162
  async onClick(event) {
162
163
  event.preventDefault()
163
164
  try {
164
- const spinner = setTimeout(() => refPayloadViewer.current.innerText = Strings.fetching, 180)
165
+ const spinner = setTimeout(() => {
166
+ empty(refPayloadViewer.current)
167
+ refPayloadViewer.current.append(ProgressBar())
168
+ }, 180)
165
169
  const res = await fetch(this.href, {
166
170
  method: this.getAttribute('data-method')
167
171
  })
168
172
  document.querySelector(`.${CSS.PreviewLink}.${CSS.chosen}`)?.classList.remove(CSS.chosen)
169
173
  this.classList.add(CSS.chosen)
170
174
  clearTimeout(spinner)
171
- refPayloadViewer.current.innerText = await res.text() || Strings.empty_response_body
175
+ updatePayloadViewer(
176
+ await res.text() || Strings.empty_response_body,
177
+ res.headers.get('content-type'))
172
178
  refPayloadFile.current.innerText = this.closest('tr').querySelector('select').value
173
179
  }
174
180
  catch (error) {
@@ -178,6 +184,20 @@ function PreviewLink({ method, urlMask }) {
178
184
  }, urlMask))
179
185
  }
180
186
 
187
+ function ProgressBar() {
188
+ return (
189
+ r('div', { className: CSS.ProgressBar },
190
+ r('div', { style: { animationDuration: '1000ms' } }))) // TODO from Config.delay - 180
191
+ }
192
+
193
+ function updatePayloadViewer(body, mime) {
194
+ if (mime === 'application/json' && window.Prism)
195
+ refPayloadViewer.current.innerHTML = window.Prism.highlight(body, window.Prism.languages.json, 'json')
196
+ else
197
+ refPayloadViewer.current.innerText = body
198
+ }
199
+
200
+
181
201
  function MockSelector({ broker }) {
182
202
  const className = (defaultIsSelected, status) => cssClass(
183
203
  CSS.MockSelector,
@@ -309,6 +329,8 @@ function createElement(elem, props = null, ...children) {
309
329
  value.current = node
310
330
  else if (key.startsWith('on'))
311
331
  node.addEventListener(key.replace(/^on/, '').toLowerCase(), value)
332
+ else if (key === 'style')
333
+ Object.assign(node.style, value)
312
334
  else if (key in node)
313
335
  node[key] = value
314
336
  else