mockaton 0.9.10 → 0.10.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/README.md +13 -16
- package/Tests.js +24 -10
- package/index.d.ts +1 -0
- package/package.json +2 -2
- package/src/Config.js +2 -0
- package/src/MockDispatcher.js +6 -2
- package/src/ProxyRelay.js +11 -0
package/README.md
CHANGED
|
@@ -5,9 +5,7 @@ It scans `Config.mocksDir` for files following a specific directory
|
|
|
5
5
|
and file name convention, which is similar to the URL paths. For
|
|
6
6
|
example, the following file will be served for `/api/user/1234`
|
|
7
7
|
```
|
|
8
|
-
|
|
9
|
-
|-- user/
|
|
10
|
-
|-- [user-id].GET.200.json
|
|
8
|
+
my-mocks-dir/api/user/[user-id].GET.200.json
|
|
11
9
|
```
|
|
12
10
|
|
|
13
11
|
By the way, [this browser
|
|
@@ -65,10 +63,9 @@ Create a `my-mockaton.js` file
|
|
|
65
63
|
import { resolve } from 'node:path'
|
|
66
64
|
import { Mockaton } from 'src/Mockaton'
|
|
67
65
|
|
|
68
|
-
|
|
69
66
|
Mockaton({ // Config options
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
port: 2345,
|
|
68
|
+
mocksDir: resolve('my-mocks-dir')
|
|
72
69
|
})
|
|
73
70
|
```
|
|
74
71
|
|
|
@@ -87,6 +84,7 @@ interface Config {
|
|
|
87
84
|
cookies?(): object
|
|
88
85
|
database?: object // for "Transforms"
|
|
89
86
|
skipOpen?: boolean // Prevents opening the dashboard in a browser
|
|
87
|
+
proxyFallback?: string // e.g. http://localhost:9999 For relaying routes without mocks
|
|
90
88
|
allowedExt?: RegExp // /\.(json|txt|md|mjs)$/ Just for excluding temporary editor files (e.g. JetBrains appends a ~)
|
|
91
89
|
}
|
|
92
90
|
```
|
|
@@ -95,14 +93,13 @@ interface Config {
|
|
|
95
93
|
```js
|
|
96
94
|
import { jwtCookie } from 'src/Mockaton'
|
|
97
95
|
|
|
98
|
-
|
|
99
96
|
Config.cookies = {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
97
|
+
'My Admin User': 'my-cookie=1;Path=/;SameSite=strict',
|
|
98
|
+
'My Normal User': 'my-cookie=0;Path=/;SameSite=strict',
|
|
99
|
+
'My JWT': jwtCookie('my-cookie', {
|
|
100
|
+
email: 'john.doe@example.com',
|
|
101
|
+
picture: 'https://cdn.auth0.com/avatars/jd.png'
|
|
102
|
+
})
|
|
106
103
|
}
|
|
107
104
|
```
|
|
108
105
|
|
|
@@ -179,9 +176,9 @@ with `.mjs` will process the mock before serving it.
|
|
|
179
176
|
|
|
180
177
|
For example, this handler will capitalize the mock body and increment a counter.
|
|
181
178
|
```js
|
|
182
|
-
export default function capitalizeAllText(mockAsText, requestBody,
|
|
183
|
-
|
|
184
|
-
|
|
179
|
+
export default function capitalizeAllText(mockAsText, requestBody, config) {
|
|
180
|
+
config.database.myCount ??= 0
|
|
181
|
+
config.database.myCount++
|
|
185
182
|
return mockAsText.toUpperCase()
|
|
186
183
|
}
|
|
187
184
|
```
|
package/Tests.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { tmpdir } from 'node:os'
|
|
4
4
|
import { dirname } from 'node:path'
|
|
5
5
|
import { describe, it } from 'node:test'
|
|
6
|
+
import { createServer } from 'node:http'
|
|
6
7
|
import { equal, deepEqual, match } from 'node:assert/strict'
|
|
7
8
|
import { writeFileSync, mkdtempSync, mkdirSync } from 'node:fs'
|
|
8
9
|
|
|
@@ -98,17 +99,22 @@ writeStatic('index.html', '<h1>Static</h1>')
|
|
|
98
99
|
writeStatic('assets/app.js', 'const app = 1')
|
|
99
100
|
writeStatic('another-entry/index.html', '<h1>Another</h1>')
|
|
100
101
|
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
102
|
+
let server
|
|
103
|
+
const fallbackServer = createServer((_, response) => {
|
|
104
|
+
response.end('From_Fallback_Server')
|
|
105
|
+
}).listen(0, 'localhost', function () {
|
|
106
|
+
server = Mockaton({
|
|
107
|
+
mocksDir: tmpDir,
|
|
108
|
+
staticDir: staticTmpDir,
|
|
109
|
+
skipOpen: true,
|
|
110
|
+
cookies: {
|
|
111
|
+
userA: 'CookieA',
|
|
112
|
+
userB: 'CookieB'
|
|
113
|
+
},
|
|
114
|
+
proxyFallback: `http://localhost:${fallbackServer.address().port}`
|
|
115
|
+
})
|
|
116
|
+
server.on('listening', runTests)
|
|
110
117
|
})
|
|
111
|
-
server.on('listening', runTests)
|
|
112
118
|
|
|
113
119
|
async function runTests() {
|
|
114
120
|
await testItRendersDashboard()
|
|
@@ -157,7 +163,9 @@ async function runTests() {
|
|
|
157
163
|
await testTransforms()
|
|
158
164
|
await testStaticFileServing()
|
|
159
165
|
await testInvalidFilenamesAreIgnored()
|
|
166
|
+
await testRouteWithoutMocksRelaysGetsProxied()
|
|
160
167
|
server.close()
|
|
168
|
+
fallbackServer.close()
|
|
161
169
|
}
|
|
162
170
|
|
|
163
171
|
async function reset() {
|
|
@@ -350,6 +358,12 @@ async function testInvalidFilenamesAreIgnored() {
|
|
|
350
358
|
})
|
|
351
359
|
}
|
|
352
360
|
|
|
361
|
+
async function testRouteWithoutMocksRelaysGetsProxied() {
|
|
362
|
+
await it('Fallback relay', async () => {
|
|
363
|
+
const res = await request('/non-existing-mock')
|
|
364
|
+
equal(await res.text(), 'From_Fallback_Server')
|
|
365
|
+
})
|
|
366
|
+
}
|
|
353
367
|
|
|
354
368
|
// Utils
|
|
355
369
|
|
package/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"name": "mockaton",
|
|
3
3
|
"description": "A deterministic server-side for developing and testing frontend clients",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.10.0",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"types": "index.d.ts",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"repository": "https://github.com/ericfortis/mockaton",
|
|
10
10
|
"scripts": {
|
|
11
11
|
"test": "./Tests.js",
|
|
12
|
-
"demo": "_usage_example.js"
|
|
12
|
+
"demo": "./_usage_example.js"
|
|
13
13
|
}
|
|
14
14
|
}
|
package/src/Config.js
CHANGED
|
@@ -11,6 +11,7 @@ export const Config = {
|
|
|
11
11
|
cookies: {}, // defaults to the first kv
|
|
12
12
|
database: {},
|
|
13
13
|
skipOpen: false,
|
|
14
|
+
proxyFallback: '', // e.g. http://localhost:9999
|
|
14
15
|
allowedExt: /\.(json|txt|md|mjs)$/ // Just for excluding temporary editor files (e.g. JetBrains appends a ~)
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -25,6 +26,7 @@ export function setup(options) {
|
|
|
25
26
|
cookies: is(Object),
|
|
26
27
|
database: is(Object),
|
|
27
28
|
skipOpen: is(Boolean),
|
|
29
|
+
proxyFallback: is(String),
|
|
28
30
|
allowedExt: is(RegExp)
|
|
29
31
|
})
|
|
30
32
|
}
|
package/src/MockDispatcher.js
CHANGED
|
@@ -2,6 +2,7 @@ import { join } from 'node:path'
|
|
|
2
2
|
import { readFileSync } from 'node:fs'
|
|
3
3
|
|
|
4
4
|
import { DF } from './ApiConstants.js'
|
|
5
|
+
import { proxy } from './ProxyRelay.js'
|
|
5
6
|
import { cookie } from './cookie.js'
|
|
6
7
|
import { Config } from './Config.js'
|
|
7
8
|
import { mimeFor } from './utils/mime.js'
|
|
@@ -19,10 +20,13 @@ export async function dispatchMock(req, response) {
|
|
|
19
20
|
|
|
20
21
|
const broker = mockBrokerCollection.getBrokerForUrl(req.method, req.url)
|
|
21
22
|
if (!broker) {
|
|
22
|
-
|
|
23
|
+
if (Config.proxyFallback)
|
|
24
|
+
await proxy(req, response)
|
|
25
|
+
else
|
|
26
|
+
sendNotFound(response) // TESTME
|
|
23
27
|
return
|
|
24
28
|
}
|
|
25
|
-
|
|
29
|
+
|
|
26
30
|
try {
|
|
27
31
|
const { file, status, delay, currentTransform } = broker
|
|
28
32
|
console.log('\n', req.url, '→\n ', file)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Config } from './Config.js'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export async function proxy(req, response) {
|
|
5
|
+
const proxyResponse = await fetch(Config.proxyFallback + req.url, {
|
|
6
|
+
method: req.method,
|
|
7
|
+
headers: req.headers
|
|
8
|
+
})
|
|
9
|
+
response.writeHead(proxyResponse.status, proxyResponse.headers)
|
|
10
|
+
response.end(await proxyResponse.text())
|
|
11
|
+
}
|