mockaton 7.3.1 → 7.4.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.
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/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.1",
5
+ "version": "7.4.1",
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,27 +5,29 @@
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: #fff;
13
14
  --colorHover: #dfefff;
14
- --colorLabel: #777;
15
+ --colorLabel: #666;
15
16
  --colorLightRed: #ffe4ee;
16
17
  --colorRed: #da0f00;
17
- --colorSecondaryButtonBackground: #f0f0f0;
18
+ --colorSecondaryButtonBackground: #fafafa;
18
19
  --colorText: #000;
19
20
  }
20
21
  }
21
22
  @media (prefers-color-scheme: dark) {
22
23
  :root {
23
24
  --color4xxBackground: #403630;
24
- --colorAccent: #0682fa;
25
+ --colorAccent: #1f91ff;
25
26
  --colorBackground: #141414;
26
- --colorCodeBackground: #333;
27
27
  --colorComboBoxBackground: #252525;
28
+ --colorComboBoxHeaderBackground: #222;
28
29
  --colorDisabled: #aaa;
30
+ --colorHeaderBackground: #141414;
29
31
  --colorHover: #023661;
30
32
  --colorLabel: #aaa;
31
33
  --colorLightRed: #ffe4ee;
@@ -73,41 +75,26 @@ select {
73
75
  }
74
76
  }
75
77
 
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
78
  menu {
79
+ position: fixed;
80
+ z-index: 100;
81
+ top: 0;
82
+ left: 0;
97
83
  display: flex;
84
+ width: 100%;
98
85
  align-items: flex-end;
99
- margin-bottom: 12px;
86
+ padding: 16px 16px;
87
+ background: var(--colorHeaderBackground);
100
88
  gap: 16px;
101
89
 
102
90
  img {
103
91
  width: 140px;
104
- margin-right: 24px;
92
+ margin-right: 75px;
105
93
  }
106
94
 
107
95
  label {
108
96
  span {
109
97
  display: block;
110
- padding-left: 7px;
111
98
  color: var(--colorLabel);
112
99
  font-size: 11px;
113
100
  }
@@ -117,6 +104,7 @@ menu {
117
104
  padding: 4px;
118
105
  margin-top: 2px;
119
106
  font-size: 11px;
107
+ background: var(--colorComboBoxHeaderBackground);
120
108
  }
121
109
  }
122
110
 
@@ -131,6 +119,7 @@ menu {
131
119
  &:hover {
132
120
  background: var(--colorRed);
133
121
  color: white;
122
+ box-shadow: var(--boxShadow1);
134
123
  }
135
124
  }
136
125
 
@@ -142,25 +131,49 @@ menu {
142
131
  }
143
132
  }
144
133
 
134
+
135
+ main {
136
+ display: flex;
137
+ align-items: flex-start;
138
+ margin-top: 56px;
139
+
140
+ > table {
141
+ border-collapse: collapse;
142
+
143
+ th {
144
+ padding-top: 20px;
145
+ padding-bottom: 2px;
146
+ text-align: left;
147
+ }
148
+
149
+ tr {
150
+ border-bottom: 2px solid transparent;
151
+ }
152
+ }
153
+ }
154
+
155
+
145
156
  .PayloadViewer {
146
157
  position: sticky;
147
- top: 0;
158
+ top: 80px;
148
159
  width: 50%;
149
- margin-left: 16px;
160
+ margin-left: 20px;
150
161
 
151
162
  h2 {
152
163
  padding-top: 20px;
153
164
  }
154
165
 
155
166
  pre {
167
+ overflow: auto;
168
+ max-height: calc(100vh - 160px);
169
+ padding: 12px;
170
+ padding-left: 0;
171
+ margin-top: 6px;
172
+ border-radius: 4px;
173
+ white-space: pre;
156
174
  tab-size: 2;
157
175
 
158
- &:not(:empty) {
159
- overflow: auto;
160
- max-height: calc(100vh - 160px);
161
- padding: 12px;
162
- margin-top: 6px;
163
- background: var(--colorCodeBackground);
176
+ code * {
164
177
  font-family: monospace;
165
178
  }
166
179
  }
@@ -172,6 +185,7 @@ menu {
172
185
  display: inline-block;
173
186
  width: 280px;
174
187
  padding: 8px 6px;
188
+ border-radius: 4px;
175
189
  color: var(--colorAccent);
176
190
  text-decoration: none;
177
191
 
@@ -220,6 +234,7 @@ menu {
220
234
  fill: var(--colorText);
221
235
  border-radius: 50%;
222
236
  background: var(--colorSecondaryButtonBackground);
237
+ box-shadow: var(--boxShadow1);
223
238
 
224
239
  &:hover {
225
240
  background: var(--colorHover);
@@ -244,6 +259,7 @@ menu {
244
259
 
245
260
  > span {
246
261
  padding: 4px;
262
+ box-shadow: var(--boxShadow1);
247
263
  font-size: 10px;
248
264
  color: var(--colorText);
249
265
  border-radius: 2px;
@@ -256,6 +272,122 @@ menu {
256
272
  }
257
273
  }
258
274
 
275
+ .ProgressBar {
276
+ position: relative;
277
+ width: 100%;
278
+ height: 16px;
279
+ background: var(--colorComboBoxHeaderBackground);
280
+
281
+ div {
282
+ position: absolute;
283
+ top: 0;
284
+ left: 0;
285
+ height: 100%;
286
+ background: var(--colorAccent);
287
+ animation: _kfProgress;
288
+ /*animation-duration: It's in JavaScript */
289
+ }
290
+
291
+ }
292
+ @keyframes _kfProgress {
293
+ 0% {
294
+ width: 0;
295
+ }
296
+ 100% {
297
+ width: 100%;
298
+ }
299
+ }
300
+
259
301
  .bold {
260
302
  font-weight: bold;
261
303
  }
304
+
305
+
306
+ /*
307
+ * Prism
308
+ */
309
+
310
+ @media (prefers-color-scheme: dark) {
311
+ .token.cdata, .token.comment, .token.doctype, .token.prolog {
312
+ color: #8292a2
313
+ }
314
+ .token.punctuation {
315
+ color: #f8f8f2
316
+ }
317
+ .token.namespace {
318
+ opacity: .7
319
+ }
320
+ .token.constant, .token.deleted, .token.property, .token.symbol, .token.tag {
321
+ color: #f92672
322
+ }
323
+ .token.boolean, .token.number {
324
+ color: #ae81ff
325
+ }
326
+ .token.attr-name, .token.builtin, .token.char, .token.inserted, .token.selector, .token.string {
327
+ color: #a6e22e
328
+ }
329
+ .language-css .token.string, .style .token.string, .token.entity, .token.operator, .token.url, .token.variable {
330
+ color: #f8f8f2
331
+ }
332
+ .token.atrule, .token.attr-value, .token.class-name, .token.function {
333
+ color: #e6db74
334
+ }
335
+ .token.keyword {
336
+ color: #66d9ef
337
+ }
338
+ .token.important, .token.regex {
339
+ color: #fd971f
340
+ }
341
+ .token.bold, .token.important {
342
+ font-weight: 700
343
+ }
344
+ .token.italic {
345
+ font-style: italic
346
+ }
347
+ .token.entity {
348
+ cursor: help
349
+ }
350
+ }
351
+
352
+ @media (prefers-color-scheme: light) {
353
+ .token.cdata, .token.comment, .token.doctype, .token.prolog {
354
+ color: #708090
355
+ }
356
+ .token.punctuation {
357
+ color: #999
358
+ }
359
+ .token.namespace {
360
+ opacity: .7
361
+ }
362
+ .token.constant, .token.deleted, .token.property, .token.symbol, .token.tag {
363
+ color: #ed206a
364
+ }
365
+ .token.boolean, .token.number {
366
+ color: #9b71e8
367
+ }
368
+ .token.attr-name, .token.builtin, .token.char, .token.inserted, .token.selector, .token.string {
369
+ color: #459900
370
+ }
371
+ .language-css .token.string, .style .token.string, .token.entity, .token.operator, .token.url {
372
+ color: #9a6e3a;
373
+ background: hsla(0, 0%, 100%, .5)
374
+ }
375
+ .token.atrule, .token.attr-value, .token.keyword {
376
+ color: #07a
377
+ }
378
+ .token.class-name, .token.function {
379
+ color: #dd4a68
380
+ }
381
+ .token.important, .token.regex, .token.variable {
382
+ color: #e90
383
+ }
384
+ .token.bold, .token.important {
385
+ font-weight: 700
386
+ }
387
+ .token.italic {
388
+ font-style: italic
389
+ }
390
+ .token.entity {
391
+ cursor: help
392
+ }
393
+ }
@@ -1,12 +1,16 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en-US">
3
3
  <head>
4
+ <meta charset="UTF-8">
4
5
  <link rel="stylesheet" href="/Dashboard.css">
5
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
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