mockaton 12.6.1 → 12.7.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/package.json +1 -1
- package/src/client/app-store.js +11 -13
- package/src/client/app.js +37 -6
- package/src/server/cli.test.js +8 -7
- package/src/server/utils/mime.js +2 -5
- package/src/server/utils/mime.test.js +1 -8
package/package.json
CHANGED
package/src/client/app-store.js
CHANGED
|
@@ -252,26 +252,24 @@ function togglePreference(param, nextVal) {
|
|
|
252
252
|
* @param {string[]} paths - sorted
|
|
253
253
|
*/
|
|
254
254
|
export function dittoSplitPaths(paths) {
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const prev = pathsInParts[i - 1]
|
|
260
|
-
const curr = pathsInParts[i]
|
|
255
|
+
const pParts = paths.map(p => p.split('/').filter(Boolean))
|
|
256
|
+
return paths.map((p, i) => {
|
|
257
|
+
if (i === 0)
|
|
258
|
+
return ['', p]
|
|
261
259
|
|
|
260
|
+
const prev = pParts[i - 1]
|
|
261
|
+
const curr = pParts[i]
|
|
262
262
|
const min = Math.min(curr.length, prev.length)
|
|
263
263
|
let j = 0
|
|
264
264
|
while (j < min && curr[j] === prev[j])
|
|
265
265
|
j++
|
|
266
266
|
|
|
267
267
|
if (!j) // no common dirs
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
return result
|
|
268
|
+
return ['', p]
|
|
269
|
+
|
|
270
|
+
const ditto = '/' + curr.slice(0, j).join('/') + '/'
|
|
271
|
+
return [ditto, p.slice(ditto.length)]
|
|
272
|
+
})
|
|
275
273
|
}
|
|
276
274
|
|
|
277
275
|
|
package/src/client/app.js
CHANGED
|
@@ -481,13 +481,38 @@ function DelayToggler({ checked, commit, optClassName }) {
|
|
|
481
481
|
function ClickDragToggler({ checked, commit, className, title, body }) {
|
|
482
482
|
function onPointerEnter(event) {
|
|
483
483
|
if (event.buttons === 1)
|
|
484
|
-
onPointerDown.call(this)
|
|
484
|
+
onPointerDown.call(this, event)
|
|
485
485
|
}
|
|
486
|
-
|
|
486
|
+
|
|
487
|
+
function onPointerDown(event) {
|
|
488
|
+
if (event.altKey) {
|
|
489
|
+
onExclusiveClick.call(this)
|
|
490
|
+
return
|
|
491
|
+
}
|
|
487
492
|
this.checked = !this.checked
|
|
488
493
|
this.focus()
|
|
489
494
|
commit(this.checked)
|
|
490
495
|
}
|
|
496
|
+
|
|
497
|
+
function onExclusiveClick() {
|
|
498
|
+
const selector = selectorForColumnOf(this)
|
|
499
|
+
if (!selector)
|
|
500
|
+
return
|
|
501
|
+
|
|
502
|
+
// Uncheck all other in the column.
|
|
503
|
+
for (const elem of leftSideRef.elem.querySelectorAll(selector))
|
|
504
|
+
if (elem !== this && elem.checked && !elem.disabled) {
|
|
505
|
+
elem.checked = false
|
|
506
|
+
elem.dispatchEvent(new Event('change'))
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if (!this.checked) {
|
|
510
|
+
this.checked = true
|
|
511
|
+
this.dispatchEvent(new Event('change'))
|
|
512
|
+
}
|
|
513
|
+
this.focus()
|
|
514
|
+
}
|
|
515
|
+
|
|
491
516
|
function onClick(event) {
|
|
492
517
|
if (event.pointerType === 'mouse')
|
|
493
518
|
event.preventDefault()
|
|
@@ -667,18 +692,24 @@ function initRealTimeUpdates() {
|
|
|
667
692
|
}
|
|
668
693
|
}
|
|
669
694
|
|
|
695
|
+
function selectorForColumnOf(elem) {
|
|
696
|
+
return columnSelectors().find(s => elem?.matches(s))
|
|
697
|
+
}
|
|
670
698
|
|
|
671
|
-
function
|
|
672
|
-
|
|
699
|
+
function columnSelectors() {
|
|
700
|
+
return [
|
|
673
701
|
`.${CSS.TableRow} .${CSS.ProxyToggler} input`,
|
|
674
702
|
`.${CSS.TableRow} .${CSS.DelayToggler} input`,
|
|
675
703
|
`.${CSS.TableRow} .${CSS.StatusCodeToggler} input`,
|
|
676
704
|
`.${CSS.TableRow} .${CSS.PreviewLink}`,
|
|
677
705
|
// No .MockSelector because down/up arrows have native behavior on them
|
|
678
706
|
]
|
|
707
|
+
}
|
|
679
708
|
|
|
709
|
+
|
|
710
|
+
function initKeyboardNavigation() {
|
|
680
711
|
const rowSelectors = [
|
|
681
|
-
...columnSelectors,
|
|
712
|
+
...columnSelectors(),
|
|
682
713
|
`.${CSS.TableRow} .${CSS.MockSelector}:enabled`,
|
|
683
714
|
]
|
|
684
715
|
|
|
@@ -687,7 +718,7 @@ function initKeyboardNavigation() {
|
|
|
687
718
|
case 'ArrowDown':
|
|
688
719
|
case 'ArrowUp': {
|
|
689
720
|
const pivot = document.activeElement
|
|
690
|
-
const sel =
|
|
721
|
+
const sel = selectorForColumnOf(pivot)
|
|
691
722
|
if (sel) {
|
|
692
723
|
const offset = key === 'ArrowDown' ? +1 : -1
|
|
693
724
|
const siblings = leftSideRef.elem.querySelectorAll(sel)
|
package/src/server/cli.test.js
CHANGED
|
@@ -5,34 +5,35 @@ import { describe, test } from 'node:test'
|
|
|
5
5
|
|
|
6
6
|
import pkgJSON from '../../package.json' with { type: 'json' }
|
|
7
7
|
|
|
8
|
-
const
|
|
9
|
-
|
|
8
|
+
const cli = (...args) => spawnSync(join(import.meta.dirname, 'cli.js'), args, {
|
|
9
|
+
encoding: 'utf8'
|
|
10
|
+
})
|
|
10
11
|
|
|
11
12
|
describe('CLI', () => {
|
|
12
13
|
test('--invalid-flag', () => {
|
|
13
|
-
const { stderr, status } = cli(
|
|
14
|
+
const { stderr, status } = cli('--invalid-flag')
|
|
14
15
|
equal(stderr.trim(), `Unknown option '--invalid-flag'`)
|
|
15
16
|
equal(status, 1)
|
|
16
17
|
})
|
|
17
18
|
|
|
18
19
|
test('invalid config file', () => {
|
|
19
|
-
const { stderr, status } = cli(
|
|
20
|
+
const { stderr, status } = cli('--config', 'non-existing-file.js')
|
|
20
21
|
equal(stderr.trim(), `Invalid config file: non-existing-file.js`)
|
|
21
22
|
equal(status, 1)
|
|
22
23
|
})
|
|
23
24
|
|
|
24
25
|
test('-v outputs version from package.json', () => {
|
|
25
|
-
const { stdout, status } = cli(
|
|
26
|
+
const { stdout, status } = cli('-v')
|
|
26
27
|
equal(stdout.trim(), pkgJSON.version)
|
|
27
28
|
equal(status, 0)
|
|
28
29
|
})
|
|
29
30
|
|
|
30
31
|
test('-h outputs usage message', () => {
|
|
31
|
-
const { stdout, status } = cli(
|
|
32
|
+
const { stdout, status } = cli('-h')
|
|
32
33
|
equal(stdout.split('\n')[0], 'Usage: mockaton [options]')
|
|
33
34
|
equal(status, 0)
|
|
34
35
|
})
|
|
35
|
-
|
|
36
|
+
|
|
36
37
|
// Mockaton.test.js tests the remaining cli branch
|
|
37
38
|
})
|
|
38
39
|
|
package/src/server/utils/mime.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MIMEType } from 'node:util'
|
|
1
2
|
import { config } from '../config.js'
|
|
2
3
|
import { EXT_UNKNOWN_MIME, EXT_EMPTY } from '../../client/ApiConstants.js'
|
|
3
4
|
|
|
@@ -146,12 +147,8 @@ export function extFor(mime) {
|
|
|
146
147
|
: EXT_EMPTY
|
|
147
148
|
}
|
|
148
149
|
function findExt(rawMime) {
|
|
149
|
-
const m =
|
|
150
|
+
const m = new MIMEType(rawMime).essence
|
|
150
151
|
const extraMimeToExt = mapMimeToExt(config.extraMimes)
|
|
151
152
|
return extraMimeToExt[m] || mimeToExt[m] || EXT_UNKNOWN_MIME
|
|
152
153
|
}
|
|
153
154
|
|
|
154
|
-
export function parseMime(mime) {
|
|
155
|
-
return mime.split(';')[0].toLowerCase()
|
|
156
|
-
// RFC 9110 §8.3.1
|
|
157
|
-
}
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
import { test } from 'node:test'
|
|
2
2
|
import { equal } from 'node:assert/strict'
|
|
3
|
-
import {
|
|
3
|
+
import { extFor, mimeFor } from './mime.js'
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
test('parseMime', () => [
|
|
7
|
-
'text/html',
|
|
8
|
-
'TEXT/html',
|
|
9
|
-
'text/html; charset=utf-8'
|
|
10
|
-
].map(input =>
|
|
11
|
-
equal(parseMime(input), 'text/html')))
|
|
12
|
-
|
|
13
6
|
test('extFor', () => [
|
|
14
7
|
'text/html',
|
|
15
8
|
'Text/html',
|