mockaton 8.7.3 → 8.7.4

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/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.7.3",
5
+ "version": "8.7.4",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "license": "MIT",
package/src/Dashboard.js CHANGED
@@ -45,8 +45,6 @@ const CSS = {
45
45
  }
46
46
 
47
47
  const r = createElement
48
- const refPayloadViewer = useRef()
49
- const refPayloadViewerFileTitle = useRef()
50
48
 
51
49
  const mockaton = new Commander(window.location.origin)
52
50
 
@@ -59,10 +57,7 @@ function init() {
59
57
  mockaton.getProxyFallback(),
60
58
  mockaton.listStaticFiles()
61
59
  ].map(api => api.then(response => response.ok && response.json())))
62
- .then(data => {
63
- empty(document.body)
64
- document.body.append(...App(data))
65
- })
60
+ .then(data => document.body.replaceChildren(...App(data)))
66
61
  .catch(onError)
67
62
  }
68
63
  init()
@@ -118,9 +113,10 @@ function CookieSelector({ cookies }) {
118
113
  function BulkSelector({ comments }) {
119
114
  // UX wise this should be a menu instead of this `select`.
120
115
  // But this way is easier to implement, with a few hacks.
116
+ const firstOption = Strings.pick
121
117
  function onChange() {
122
118
  const value = this.value
123
- this.value = Strings.pick // Hack
119
+ this.value = firstOption // Hack
124
120
  mockaton.bulkSelectByComment(value)
125
121
  .then(init)
126
122
  .catch(onError)
@@ -128,7 +124,7 @@ function BulkSelector({ comments }) {
128
124
  const disabled = !comments.length
129
125
  const list = disabled
130
126
  ? []
131
- : [Strings.pick].concat(comments)
127
+ : [firstOption].concat(comments)
132
128
  return (
133
129
  r('label', { className: CSS.Field },
134
130
  r('span', null, Strings.bulk_select_by_comment),
@@ -144,14 +140,14 @@ function BulkSelector({ comments }) {
144
140
  }
145
141
 
146
142
  function ProxyFallbackField({ fallbackAddress = '', collectProxied }) {
147
- const refSaveProxiedCheckbox = useRef()
148
- function onChange(event) {
149
- const input = event.currentTarget
150
- refSaveProxiedCheckbox.current.disabled = !input.validity.valid || !input.value.trim()
151
- if (!input.validity.valid)
152
- input.reportValidity()
143
+ function onChange() {
144
+ const saveCheckbox = this.closest(`.${CSS.FallbackBackend}`).querySelector('[type=checkbox]')
145
+ saveCheckbox.disabled = !this.validity.valid || !this.value.trim()
146
+
147
+ if (!this.validity.valid)
148
+ this.reportValidity()
153
149
  else
154
- mockaton.setProxyFallback(input.value.trim()).catch(onError)
150
+ mockaton.setProxyFallback(this.value.trim()).catch(onError)
155
151
  }
156
152
  return (
157
153
  r('div', { className: cssClass(CSS.Field, CSS.FallbackBackend) },
@@ -166,20 +162,17 @@ function ProxyFallbackField({ fallbackAddress = '', collectProxied }) {
166
162
  })),
167
163
  r(SaveProxiedCheckbox, {
168
164
  collectProxied,
169
- disabled: !fallbackAddress,
170
- ref: refSaveProxiedCheckbox
165
+ disabled: !fallbackAddress
171
166
  })))
172
167
  }
173
168
 
174
- function SaveProxiedCheckbox({ ref, disabled, collectProxied }) {
175
- function onChange(event) {
176
- mockaton.setCollectProxied(event.currentTarget.checked)
177
- .catch(onError)
169
+ function SaveProxiedCheckbox({ disabled, collectProxied }) {
170
+ function onChange() {
171
+ mockaton.setCollectProxied(this.checked).catch(onError)
178
172
  }
179
173
  return (
180
174
  r('label', { className: CSS.SaveProxiedCheckbox },
181
175
  r('input', {
182
- ref,
183
176
  type: 'checkbox',
184
177
  disabled,
185
178
  checked: collectProxied,
@@ -238,14 +231,7 @@ function PreviewLink({ method, urlMask }) {
238
231
  async function onClick(event) {
239
232
  event.preventDefault()
240
233
  try {
241
- const preloader = setTimeout(() => {
242
- empty(refPayloadViewer.current)
243
- refPayloadViewer.current.append(PayloadViewerProgressBar())
244
- }, 180)
245
-
246
- const response = await fetch(this.href, { method })
247
- clearTimeout(preloader)
248
- await updatePayloadViewer(method, urlMask, this.href, response)
234
+ await previewMock(method, urlMask, this.href)
249
235
  document.querySelector(`.${CSS.PreviewLink}.${CSS.chosen}`)?.classList.remove(CSS.chosen)
250
236
  this.classList.add(CSS.chosen)
251
237
  }
@@ -306,9 +292,9 @@ function MockSelector({ broker }) {
306
292
 
307
293
 
308
294
  function DelayRouteToggler({ broker }) {
309
- function onChange(event) {
295
+ function onChange() {
310
296
  const { method, urlMask } = parseFilename(this.name)
311
- mockaton.setRouteIsDelayed(method, urlMask, event.currentTarget.checked)
297
+ mockaton.setRouteIsDelayed(method, urlMask, this.checked)
312
298
  .catch(onError)
313
299
  }
314
300
  return (
@@ -333,11 +319,12 @@ function DelayRouteToggler({ broker }) {
333
319
 
334
320
 
335
321
  function InternalServerErrorToggler({ broker }) {
336
- function onChange(event) {
322
+ function onChange() {
337
323
  const { urlMask, method } = parseFilename(broker.mocks[0])
338
- mockaton.select(event.currentTarget.checked
339
- ? broker.mocks.find(f => parseFilename(f).status === 500)
340
- : broker.mocks[0])
324
+ mockaton.select(
325
+ this.checked
326
+ ? broker.mocks.find(f => parseFilename(f).status === 500)
327
+ : broker.mocks[0])
341
328
  .then(init)
342
329
  .then(() => linkFor(method, urlMask)?.click())
343
330
  .catch(onError)
@@ -358,18 +345,24 @@ function InternalServerErrorToggler({ broker }) {
358
345
  )
359
346
  }
360
347
 
361
- function PayloadViewerProgressBar() {
362
- return (
363
- r('div', { className: CSS.ProgressBar },
364
- r('div', { style: { animationDuration: '1000ms' } }))) // TODO from Config.delay - 180
365
- }
348
+
349
+ // Payload Preview ===============
350
+
351
+ const payloadViewerTitleRef = useRef()
352
+ const payloadViewerRef = useRef()
366
353
 
367
354
  function PayloadViewer() {
368
355
  return (
369
356
  r('div', { className: CSS.PayloadViewer },
370
- r('h2', { ref: refPayloadViewerFileTitle }, Strings.mock),
357
+ r('h2', { ref: payloadViewerTitleRef }, Strings.mock),
371
358
  r('pre', null,
372
- r('code', { ref: refPayloadViewer }, Strings.click_link_to_preview))))
359
+ r('code', { ref: payloadViewerRef }, Strings.click_link_to_preview))))
360
+ }
361
+
362
+ function PayloadViewerProgressBar() {
363
+ return (
364
+ r('div', { className: CSS.ProgressBar },
365
+ r('div', { style: { animationDuration: '1000ms' } }))) // TODO from Config.delay - 180
373
366
  }
374
367
 
375
368
  function PayloadViewerTitle({ file }) {
@@ -381,27 +374,35 @@ function PayloadViewerTitle({ file }) {
381
374
  '.' + ext))
382
375
  }
383
376
 
384
- async function updatePayloadViewer(method, urlMask, imgSrc, response) {
385
- empty(refPayloadViewerFileTitle.current)
386
- refPayloadViewerFileTitle.current.append(PayloadViewerTitle({
387
- file: mockSelectorFor(method, urlMask).value
388
- }))
377
+ async function previewMock(method, urlMask, href) {
378
+ const timer = setTimeout(renderProgressBar, 180)
379
+ const response = await fetch(href, { method })
380
+ clearTimeout(timer)
381
+ await updatePayloadViewer(method, urlMask, response)
382
+
383
+ function renderProgressBar() {
384
+ payloadViewerRef.current.replaceChildren(PayloadViewerProgressBar())
385
+ }
386
+ }
387
+
388
+ async function updatePayloadViewer(method, urlMask, response) {
389
+ payloadViewerTitleRef.current.replaceChildren(
390
+ PayloadViewerTitle({ file: mockSelectorFor(method, urlMask).value }))
389
391
 
390
392
  const mime = response.headers.get('content-type') || ''
391
- if (mime.startsWith('image/')) // naively assumes GET.200
392
- renderPayloadImage(imgSrc) // TESTME in pixaton
393
- else
394
- renderPayloadBody(await response.text() || Strings.empty_response_body, mime)
395
-
396
- function renderPayloadImage(src) {
397
- empty(refPayloadViewer.current)
398
- refPayloadViewer.current.append(r('img', { src }))
393
+ if (mime.startsWith('image/')) { // Naively assumes GET.200
394
+ payloadViewerRef.current.replaceChildren(
395
+ r('img', {
396
+ src: URL.createObjectURL(await response.blob())
397
+ }))
399
398
  }
400
- function renderPayloadBody(body, mime) {
401
- if (mime === 'application/json' && window.Prism?.highlight && window.Prism?.languages)
402
- refPayloadViewer.current.innerHTML = window.Prism.highlight(body, window.Prism.languages.json, 'json')
399
+ else {
400
+ const prism = window.Prism
401
+ const body = await response.text() || Strings.empty_response_body
402
+ if (mime === 'application/json' && prism?.highlight && prism?.languages)
403
+ payloadViewerRef.current.innerHTML = prism.highlight(body, prism.languages.json, 'json')
403
404
  else
404
- refPayloadViewer.current.innerText = body
405
+ payloadViewerRef.current.innerText = body
405
406
  }
406
407
  }
407
408
 
@@ -453,11 +454,6 @@ function cssClass(...args) {
453
454
  return args.filter(a => a).join(' ')
454
455
  }
455
456
 
456
- function empty(node) {
457
- while (node.firstChild)
458
- node.removeChild(node.firstChild)
459
- }
460
-
461
457
 
462
458
  // These are simplified React-compatible implementations.
463
459
  // IOW, for switching to React, remove the `createRoot`, `createElement`, `useRef`
@@ -40,7 +40,7 @@ await describe('CORS', async () => {
40
40
 
41
41
  await describe('Identifies Preflight Requests', async () => {
42
42
  const requiredRequestHeaders = {
43
- [CH.Origin]: 'http://locahost:9999',
43
+ [CH.Origin]: 'http://localhost:9999',
44
44
  [CH.AccessControlRequestMethod]: 'POST'
45
45
  }
46
46