mockaton 6.3.8 → 6.3.10
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/Tests.js +5 -4
- package/package.json +1 -1
- package/src/Api.js +4 -8
- package/src/Filename.js +19 -10
- package/src/MockBroker.js +3 -1
- package/src/MockDispatcher.js +2 -3
- package/src/mockBrokersCollection.js +7 -14
- package/src/utils/fs.js +5 -1
- package/src/utils/http-response.js +5 -4
- package/src/utils/openInBrowser.js +8 -2
package/Tests.js
CHANGED
|
@@ -17,6 +17,7 @@ import { API, DF, DEFAULT_500_COMMENT } from './src/ApiConstants.js'
|
|
|
17
17
|
|
|
18
18
|
const tmpDir = mkdtempSync(tmpdir()) + '/'
|
|
19
19
|
const staticTmpDir = mkdtempSync(tmpdir()) + '/'
|
|
20
|
+
console.log(tmpDir)
|
|
20
21
|
|
|
21
22
|
const fixtureCustomMime = [
|
|
22
23
|
'/api/custom-mime',
|
|
@@ -380,12 +381,12 @@ async function testInvalidFilenamesAreIgnored() {
|
|
|
380
381
|
consoleErrorSpy.mock.mockImplementation(() => {}) // so they don’t render in the test report
|
|
381
382
|
|
|
382
383
|
write('api/_INVALID_FILENAME_CONVENTION_.json', '')
|
|
383
|
-
write('api/bad-filename.
|
|
384
|
-
write('api/bad-filename.
|
|
384
|
+
write('api/bad-filename-method._INVALID_METHOD_.200.json', '')
|
|
385
|
+
write('api/bad-filename-status.GET._INVALID_STATUS_.json', '')
|
|
385
386
|
await reset()
|
|
386
387
|
equal(consoleErrorSpy.mock.calls[0].arguments[0], 'Invalid Filename Convention')
|
|
387
|
-
equal(consoleErrorSpy.mock.calls[1].arguments[0], '
|
|
388
|
-
equal(consoleErrorSpy.mock.calls[2].arguments[0], '
|
|
388
|
+
equal(consoleErrorSpy.mock.calls[1].arguments[0], 'Unrecognized HTTP Method: "_INVALID_METHOD_"')
|
|
389
|
+
equal(consoleErrorSpy.mock.calls[2].arguments[0], 'Invalid HTTP Response Status: "NaN"')
|
|
389
390
|
})
|
|
390
391
|
}
|
|
391
392
|
|
package/package.json
CHANGED
package/src/Api.js
CHANGED
|
@@ -50,8 +50,7 @@ async function selectCookie(req, response) {
|
|
|
50
50
|
sendOK(response)
|
|
51
51
|
}
|
|
52
52
|
catch (error) {
|
|
53
|
-
|
|
54
|
-
sendBadRequest(response)
|
|
53
|
+
sendBadRequest(response, error)
|
|
55
54
|
}
|
|
56
55
|
}
|
|
57
56
|
|
|
@@ -69,8 +68,7 @@ async function updateBroker(req, response) {
|
|
|
69
68
|
sendOK(response)
|
|
70
69
|
}
|
|
71
70
|
catch (error) {
|
|
72
|
-
|
|
73
|
-
sendBadRequest(response)
|
|
71
|
+
sendBadRequest(response, error)
|
|
74
72
|
}
|
|
75
73
|
}
|
|
76
74
|
|
|
@@ -80,8 +78,7 @@ async function updateProxyFallback(req, response) {
|
|
|
80
78
|
sendOK(response)
|
|
81
79
|
}
|
|
82
80
|
catch (error) {
|
|
83
|
-
|
|
84
|
-
sendBadRequest(response)
|
|
81
|
+
sendBadRequest(response, error)
|
|
85
82
|
}
|
|
86
83
|
}
|
|
87
84
|
|
|
@@ -91,7 +88,6 @@ async function bulkUpdateBrokersByCommentTag(req, response) {
|
|
|
91
88
|
sendOK(response)
|
|
92
89
|
}
|
|
93
90
|
catch (error) {
|
|
94
|
-
|
|
95
|
-
sendBadRequest(response)
|
|
91
|
+
sendBadRequest(response, error)
|
|
96
92
|
}
|
|
97
93
|
}
|
package/src/Filename.js
CHANGED
|
@@ -14,24 +14,33 @@ export const includesComment = (filename, search) =>
|
|
|
14
14
|
extractComments(filename).some(comment => comment.includes(search))
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
export function
|
|
17
|
+
export function filenameIsValid(file) {
|
|
18
|
+
const error = validateFilename(file)
|
|
19
|
+
if (error)
|
|
20
|
+
console.error(error, file)
|
|
21
|
+
return !error
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function validateFilename(file) {
|
|
18
25
|
const tokens = file.replace(reComments, '').split('.')
|
|
19
26
|
if (tokens.length < 4)
|
|
20
|
-
return
|
|
27
|
+
return 'Invalid Filename Convention'
|
|
21
28
|
|
|
22
|
-
const method =
|
|
23
|
-
const status = Number(tokens.at(-2))
|
|
24
|
-
|
|
25
|
-
if (!httpMethods.includes(method))
|
|
26
|
-
return { error: `Unrecognized HTTP Method: "${method}"` }
|
|
29
|
+
const { status, method } = parseFilename(file)
|
|
27
30
|
|
|
28
31
|
if (!responseStatusIsValid(status))
|
|
29
|
-
return
|
|
32
|
+
return `Invalid HTTP Response Status: "${status}"`
|
|
30
33
|
|
|
34
|
+
if (!httpMethods.includes(method))
|
|
35
|
+
return `Unrecognized HTTP Method: "${method}"`
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function parseFilename(file) {
|
|
39
|
+
const tokens = file.replace(reComments, '').split('.')
|
|
31
40
|
return {
|
|
32
41
|
urlMask: '/' + removeTrailingSlash(tokens.slice(0, -3).join('.')),
|
|
33
|
-
method,
|
|
34
|
-
status
|
|
42
|
+
method: tokens.at(-3),
|
|
43
|
+
status: Number(tokens.at(-2))
|
|
35
44
|
}
|
|
36
45
|
}
|
|
37
46
|
|
package/src/MockBroker.js
CHANGED
|
@@ -41,7 +41,6 @@ export class MockBroker {
|
|
|
41
41
|
get file() { return this.currentMock.file }
|
|
42
42
|
get delay() { return this.currentMock.delay }
|
|
43
43
|
get status() { return parseFilename(this.file).status }
|
|
44
|
-
get isTemp500() { return includesComment(this.file, DEFAULT_500_COMMENT) }
|
|
45
44
|
|
|
46
45
|
updateFile(filename) {
|
|
47
46
|
this.currentMock.file = filename
|
|
@@ -78,6 +77,9 @@ export class MockBroker {
|
|
|
78
77
|
const file = urlMask.replace(/^\//, '') // Removes leading slash TESTME
|
|
79
78
|
this.register(`${file}${DEFAULT_500_COMMENT}.${method}.500.txt`)
|
|
80
79
|
}
|
|
80
|
+
get isTemp500() {
|
|
81
|
+
return includesComment(this.file, DEFAULT_500_COMMENT)
|
|
82
|
+
}
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
// Stars out (for regex) all the paths that are in square brackets
|
package/src/MockDispatcher.js
CHANGED
|
@@ -41,13 +41,12 @@ export async function dispatchMock(req, response) {
|
|
|
41
41
|
setTimeout(() => response.end(mockText), delay)
|
|
42
42
|
}
|
|
43
43
|
catch (error) {
|
|
44
|
-
console.error(error)
|
|
45
44
|
if (error instanceof JsonBodyParserError)
|
|
46
|
-
sendBadRequest(response)
|
|
45
|
+
sendBadRequest(response, error)
|
|
47
46
|
else if (error.code === 'ENOENT')
|
|
48
47
|
sendNotFound(response) // file has been deleted
|
|
49
48
|
else
|
|
50
|
-
sendInternalServerError(response)
|
|
49
|
+
sendInternalServerError(response, error)
|
|
51
50
|
}
|
|
52
51
|
}
|
|
53
52
|
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import { join } from 'node:path'
|
|
2
|
-
import { readdirSync as readDir } from 'node:fs'
|
|
3
|
-
|
|
4
1
|
import { Config } from './Config.js'
|
|
5
2
|
import { cookie } from './cookie.js'
|
|
6
|
-
import { isFile } from './utils/fs.js'
|
|
7
3
|
import { MockBroker } from './MockBroker.js'
|
|
8
|
-
import {
|
|
4
|
+
import { listFilesRecursively } from './utils/fs.js'
|
|
5
|
+
import { parseFilename, filenameIsValid } from './Filename.js'
|
|
9
6
|
|
|
10
7
|
|
|
11
8
|
/**
|
|
@@ -24,16 +21,12 @@ export function init() {
|
|
|
24
21
|
collection = {}
|
|
25
22
|
cookie.init(Config.cookies)
|
|
26
23
|
|
|
27
|
-
const files =
|
|
28
|
-
.filter(f => !Config.ignore.test(f) && isFile(join(Config.mocksDir, f)))
|
|
24
|
+
const files = listFilesRecursively(Config.mocksDir)
|
|
29
25
|
.sort()
|
|
26
|
+
.filter(f => !Config.ignore.test(f) && filenameIsValid(f))
|
|
30
27
|
|
|
31
28
|
for (const file of files) {
|
|
32
|
-
const {
|
|
33
|
-
if (error) {
|
|
34
|
-
console.error(error, file)
|
|
35
|
-
continue
|
|
36
|
-
}
|
|
29
|
+
const { method, urlMask } = parseFilename(file)
|
|
37
30
|
collection[method] ??= {}
|
|
38
31
|
if (!collection[method][urlMask])
|
|
39
32
|
collection[method][urlMask] = new MockBroker(file)
|
|
@@ -74,8 +67,8 @@ export function getBrokerForUrl(method, url) {
|
|
|
74
67
|
export function extractAllComments() {
|
|
75
68
|
const comments = new Set()
|
|
76
69
|
forEachBroker(broker => {
|
|
77
|
-
for (const
|
|
78
|
-
comments.add(
|
|
70
|
+
for (const c of broker.extractComments())
|
|
71
|
+
comments.add(c)
|
|
79
72
|
})
|
|
80
73
|
return Array.from(comments)
|
|
81
74
|
}
|
package/src/utils/fs.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { join } from 'node:path'
|
|
2
|
+
import { lstatSync, readFileSync, readdirSync } from 'node:fs'
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
export const isFile = path => lstatSync(path, { throwIfNoEntry: false })?.isFile()
|
|
5
6
|
export const isDirectory = path => lstatSync(path, { throwIfNoEntry: false })?.isDirectory()
|
|
6
7
|
|
|
7
8
|
export const read = path => readFileSync(path)
|
|
9
|
+
|
|
10
|
+
export const listFilesRecursively = dir => readdirSync(dir, { recursive: true })
|
|
11
|
+
.filter(f => isFile(join(dir, f)))
|
|
@@ -42,14 +42,14 @@ export async function sendPartialContent(response, range, file) {
|
|
|
42
42
|
this.pipe(response)
|
|
43
43
|
})
|
|
44
44
|
reader.on('error', function (error) {
|
|
45
|
-
|
|
46
|
-
sendInternalServerError(response)
|
|
45
|
+
sendInternalServerError(response, error)
|
|
47
46
|
})
|
|
48
47
|
}
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
|
|
52
|
-
export function sendBadRequest(response) {
|
|
51
|
+
export function sendBadRequest(response, error) {
|
|
52
|
+
console.error(error);
|
|
53
53
|
response.statusCode = 400
|
|
54
54
|
response.end()
|
|
55
55
|
}
|
|
@@ -64,7 +64,8 @@ export function sendUnprocessableContent(response) {
|
|
|
64
64
|
response.end()
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
export function sendInternalServerError(response) {
|
|
67
|
+
export function sendInternalServerError(response, error) {
|
|
68
|
+
console.error(error);
|
|
68
69
|
response.statusCode = 500
|
|
69
70
|
response.end()
|
|
70
71
|
}
|
|
@@ -2,7 +2,13 @@ import { exec } from 'node:child_process'
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
export function openInBrowser(address) {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
switch (process.platform) {
|
|
6
|
+
case 'darwin':
|
|
7
|
+
exec(`open ${address}`)
|
|
8
|
+
break
|
|
9
|
+
case 'win32': // TESTME
|
|
10
|
+
exec(`start ${address}`)
|
|
11
|
+
break
|
|
12
|
+
}
|
|
7
13
|
}
|
|
8
14
|
|