mockaton 13.10.0 → 13.11.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/ApiCommander.js +2 -0
- package/src/client/ApiConstants.js +1 -0
- package/src/client/app-header.js +26 -20
- package/src/client/app.css +2 -3
- package/src/server/Api.js +8 -2
- package/src/server/Mockaton.test.js +13 -0
- package/src/server/utils/HttpServerResponse.js +7 -3
- package/www/src/assets/openapi.json +12 -0
package/package.json
CHANGED
package/src/client/app-header.js
CHANGED
|
@@ -31,7 +31,7 @@ function GlobalDelayField() {
|
|
|
31
31
|
function onChange() {
|
|
32
32
|
store.setGlobalDelay(this.valueAsNumber)
|
|
33
33
|
}
|
|
34
|
-
return
|
|
34
|
+
return SlidableNumberField({
|
|
35
35
|
className: CSS.GlobalDelay,
|
|
36
36
|
label: t`Delay (ms)`,
|
|
37
37
|
min: 0,
|
|
@@ -50,7 +50,7 @@ function GlobalDelayJitterField() {
|
|
|
50
50
|
this.value = Math.min(300, this.valueAsNumber)
|
|
51
51
|
store.setGlobalDelayJitter(this.valueAsNumber / 100)
|
|
52
52
|
}
|
|
53
|
-
return
|
|
53
|
+
return SlidableNumberField({
|
|
54
54
|
className: CSS.GlobalDelayJitter,
|
|
55
55
|
label: t`Max Jitter %`,
|
|
56
56
|
min: 0,
|
|
@@ -140,38 +140,44 @@ function HelpLink() {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
|
|
143
|
-
function
|
|
143
|
+
function SlidableNumberField({ className, label, onChange, min, max, step, value }) {
|
|
144
144
|
function onPointerDown(event) {
|
|
145
|
-
const input = event.target
|
|
146
145
|
let lastX = event.clientX
|
|
146
|
+
const input = event.target
|
|
147
147
|
input.setPointerCapture(event.pointerId)
|
|
148
|
+
window.addEventListener('pointerup', onPointerUp, { once: true })
|
|
149
|
+
window.addEventListener('pointermove', onPointerMove)
|
|
148
150
|
|
|
149
|
-
function onPointerMove(ev) {
|
|
150
|
-
const diff = ev.clientX - lastX
|
|
151
|
-
if (Math.abs(diff) > 10) {
|
|
152
|
-
const v = input.value
|
|
153
|
-
if (diff > 0)
|
|
154
|
-
input.stepUp()
|
|
155
|
-
else
|
|
156
|
-
input.stepDown()
|
|
157
|
-
if (v !== input.value)
|
|
158
|
-
input.dispatchEvent(new Event('change'))
|
|
159
|
-
lastX = ev.clientX
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
151
|
function onPointerUp(ev) {
|
|
163
|
-
window.removeEventListener('pointermove', onPointerMove)
|
|
164
152
|
input.releasePointerCapture(ev.pointerId)
|
|
153
|
+
window.removeEventListener('pointermove', onPointerMove)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function onPointerMove(ev) {
|
|
157
|
+
const diff = ev.clientX - lastX
|
|
158
|
+
if (Math.abs(diff) < 10)
|
|
159
|
+
return
|
|
160
|
+
|
|
161
|
+
lastX = ev.clientX
|
|
162
|
+
const v = input.value
|
|
163
|
+
|
|
164
|
+
if (diff > 0)
|
|
165
|
+
input.stepUp()
|
|
166
|
+
else
|
|
167
|
+
input.stepDown()
|
|
168
|
+
|
|
169
|
+
if (v !== input.value)
|
|
170
|
+
input.dispatchEvent(new Event('change'))
|
|
165
171
|
}
|
|
166
|
-
window.addEventListener('pointermove', onPointerMove)
|
|
167
|
-
window.addEventListener('pointerup', onPointerUp, { once: true })
|
|
168
172
|
}
|
|
173
|
+
|
|
169
174
|
return (
|
|
170
175
|
r('label', { className },
|
|
171
176
|
r('span', null, label),
|
|
172
177
|
r('input', {
|
|
173
178
|
type: 'number',
|
|
174
179
|
autocomplete: 'none',
|
|
180
|
+
style: { cursor: 'col-resize' },
|
|
175
181
|
min,
|
|
176
182
|
max,
|
|
177
183
|
step,
|
package/src/client/app.css
CHANGED
|
@@ -59,7 +59,8 @@ body {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
label,
|
|
62
|
-
button
|
|
62
|
+
button,
|
|
63
|
+
select {
|
|
63
64
|
user-select: none;
|
|
64
65
|
}
|
|
65
66
|
|
|
@@ -260,8 +261,6 @@ header {
|
|
|
260
261
|
&.GlobalDelay,
|
|
261
262
|
&.GlobalDelayJitter {
|
|
262
263
|
input {
|
|
263
|
-
cursor: col-resize;
|
|
264
|
-
|
|
265
264
|
&&::selection {
|
|
266
265
|
background-color: transparent;
|
|
267
266
|
}
|
package/src/server/Api.js
CHANGED
|
@@ -63,6 +63,12 @@ const patchReqs = new Map([
|
|
|
63
63
|
|
|
64
64
|
export async function handleApiRequest(req, response) {
|
|
65
65
|
const url = removeQueryStringAndFragment(req.url)
|
|
66
|
+
|
|
67
|
+
if ((req.method === 'GET' || req.method === 'HEAD') && url === API.health) {
|
|
68
|
+
response.ok()
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
66
72
|
const handler = (
|
|
67
73
|
req.method === 'GET' && getReqs.get(url) ||
|
|
68
74
|
req.method === 'PATCH' && patchReqs.get(url))
|
|
@@ -80,8 +86,8 @@ function serveDashboard(_, response) {
|
|
|
80
86
|
}
|
|
81
87
|
|
|
82
88
|
function serveDashboardAsset(f) {
|
|
83
|
-
return (_, response) => {
|
|
84
|
-
response.file(join(CLIENT_ASSETS, f))
|
|
89
|
+
return async (_, response) => {
|
|
90
|
+
await response.file(join(CLIENT_ASSETS, f))
|
|
85
91
|
}
|
|
86
92
|
}
|
|
87
93
|
|
|
@@ -161,6 +161,19 @@ describe('Filename Convention', () => {
|
|
|
161
161
|
})
|
|
162
162
|
|
|
163
163
|
|
|
164
|
+
describe('Health Check', () => {
|
|
165
|
+
test('HEAD', async () => {
|
|
166
|
+
const r = await request(API.health, { method: 'HEAD' })
|
|
167
|
+
equal(r.status, 200)
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
test('GET', async () => {
|
|
171
|
+
const r = await request(API.health)
|
|
172
|
+
equal(r.status, 200)
|
|
173
|
+
})
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
|
|
164
177
|
describe('CORS', () => {
|
|
165
178
|
describe('Set CORS allowed', () => {
|
|
166
179
|
test('422 for non boolean', async () => {
|
|
@@ -39,7 +39,9 @@ export class ServerResponse extends http.ServerResponse {
|
|
|
39
39
|
await pipeline(fs.createReadStream(file), this)
|
|
40
40
|
}
|
|
41
41
|
catch (err) {
|
|
42
|
-
if (this.headersSent
|
|
42
|
+
if (this.headersSent
|
|
43
|
+
|| err.code === 'ERR_STREAM_PREMATURE_CLOSE'
|
|
44
|
+
|| err.code === 'ERR_STREAM_UNABLE_TO_PIPE')
|
|
43
45
|
this.destroy()
|
|
44
46
|
else if (err.code === 'ENOENT')
|
|
45
47
|
this.notFound()
|
|
@@ -76,7 +78,9 @@ export class ServerResponse extends http.ServerResponse {
|
|
|
76
78
|
await pipeline(fs.createReadStream(file, { start, end }), this)
|
|
77
79
|
}
|
|
78
80
|
catch (err) {
|
|
79
|
-
if (this.headersSent
|
|
81
|
+
if (this.headersSent
|
|
82
|
+
|| err.code === 'ERR_STREAM_PREMATURE_CLOSE'
|
|
83
|
+
|| err.code === 'ERR_STREAM_UNABLE_TO_PIPE')
|
|
80
84
|
this.destroy()
|
|
81
85
|
else if (err.code === 'ENOENT')
|
|
82
86
|
this.notFound()
|
|
@@ -84,7 +88,7 @@ export class ServerResponse extends http.ServerResponse {
|
|
|
84
88
|
throw err
|
|
85
89
|
}
|
|
86
90
|
}
|
|
87
|
-
|
|
91
|
+
|
|
88
92
|
|
|
89
93
|
badRequest() {
|
|
90
94
|
this.statusCode = 400
|
|
@@ -525,6 +525,18 @@
|
|
|
525
525
|
}
|
|
526
526
|
}
|
|
527
527
|
}
|
|
528
|
+
},
|
|
529
|
+
"/mockaton/health": {
|
|
530
|
+
"get": {
|
|
531
|
+
"summary": "Health check",
|
|
532
|
+
"description": "Returns 200 OK if the server is running. Accepts both GET and HEAD.",
|
|
533
|
+
"x-js-client-example": "await mockaton.health()",
|
|
534
|
+
"responses": {
|
|
535
|
+
"200": {
|
|
536
|
+
"description": "OK"
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
528
540
|
}
|
|
529
541
|
},
|
|
530
542
|
"components": {
|