mockaton 0.10.7 → 0.10.8

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 CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { tmpdir } from 'node:os'
4
4
  import { dirname } from 'node:path'
5
+ import { promisify } from 'node:util'
5
6
  import { describe, it } from 'node:test'
6
7
  import { createServer } from 'node:http'
7
8
  import { equal, deepEqual, match } from 'node:assert/strict'
@@ -99,25 +100,20 @@ writeStatic('index.html', '<h1>Static</h1>')
99
100
  writeStatic('assets/app.js', 'const app = 1')
100
101
  writeStatic('another-entry/index.html', '<h1>Another</h1>')
101
102
 
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)
103
+ const server = Mockaton({
104
+ mocksDir: tmpDir,
105
+ staticDir: staticTmpDir,
106
+ skipOpen: true,
107
+ cookies: {
108
+ userA: 'CookieA',
109
+ userB: 'CookieB'
110
+ }
117
111
  })
112
+ server.on('listening', runTests)
118
113
 
119
114
  async function runTests() {
120
115
  await testItRendersDashboard()
116
+ await test404()
121
117
 
122
118
  for (const [url, file, body] of fixtures)
123
119
  await testMockDispatching(url, file, body)
@@ -163,9 +159,8 @@ async function runTests() {
163
159
  await testTransforms()
164
160
  await testStaticFileServing()
165
161
  await testInvalidFilenamesAreIgnored()
166
- await testRouteWithoutMocksRelaysGetsProxied()
162
+ await testEnableFallbackSoRoutesWithoutMocksGetRelayed()
167
163
  server.close()
168
- fallbackServer.close()
169
164
  }
170
165
 
171
166
  async function reset() {
@@ -179,6 +174,13 @@ async function testItRendersDashboard() {
179
174
  it('Renders HTML', () => match(body, new RegExp('<!DOCTYPE html>'))))
180
175
  }
181
176
 
177
+ async function test404() {
178
+ await it('Sends 404 when there is no mock', async () => {
179
+ const res = await request('/api/non-existing')
180
+ equal(res.status, 404)
181
+ })
182
+ }
183
+
182
184
  async function testMockDispatching(url, file, expectedBody, reqBody = void 0) {
183
185
  const { urlMask, method, status } = Route.parseFilename(file)
184
186
  const mime = mimeFor(file)
@@ -346,7 +348,7 @@ async function testInvalidFilenamesAreIgnored() {
346
348
  await it('Invalid filenames get skipped, so they don’t crash the server', async (t) => {
347
349
  const consoleErrorSpy = t.mock.method(console, 'error')
348
350
  consoleErrorSpy.mock.mockImplementation(() => {}) // so they don’t render in the test report
349
-
351
+
350
352
  // An extension is needed for testing because of `Config.allowedExt`
351
353
  write('api/_INVALID_FILENAME_CONVENTION_.json', '')
352
354
  write('api/bad-filename.GET._INVALID_STATUS_.json', '')
@@ -358,10 +360,24 @@ async function testInvalidFilenamesAreIgnored() {
358
360
  })
359
361
  }
360
362
 
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')
363
+ async function testEnableFallbackSoRoutesWithoutMocksGetRelayed() {
364
+ await describe('Fallback', async () => {
365
+ const fallbackServer = createServer((_, response) => {
366
+ response.statusCode = 423
367
+ response.end('From_Fallback_Server')
368
+ })
369
+ await promisify(fallbackServer.listen).bind(fallbackServer, 3330, '127.0.0.1')()
370
+
371
+ await request(API.fallback, { // Enable fallback
372
+ method: 'PATCH',
373
+ body: JSON.stringify(`http://localhost:${fallbackServer.address().port}`)
374
+ })
375
+ await it('Relays to fallback server', async () => {
376
+ const res = await request('/non-existing-mock')
377
+ equal(res.status, 423)
378
+ equal(await res.text(), 'From_Fallback_Server')
379
+ fallbackServer.close()
380
+ })
365
381
  })
366
382
  }
367
383
 
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": "0.10.7",
5
+ "version": "0.10.8",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "license": "MIT",
package/src/Api.js CHANGED
@@ -28,7 +28,8 @@ export const apiPatchRequests = new Map([
28
28
  [API.edit, updateBroker],
29
29
  [API.reset, reinitialize],
30
30
  [API.cookies, selectCookie],
31
- [API.transform, updateBrokerTransform]
31
+ [API.transform, updateBrokerTransform],
32
+ [API.fallback, updateProxyFallback]
32
33
  ])
33
34
 
34
35
  function serveDashboard(_, response) {
@@ -105,3 +106,14 @@ async function updateBrokerTransform(req, response) {
105
106
  sendBadRequest(response)
106
107
  }
107
108
  }
109
+
110
+ async function updateProxyFallback(req, response) {
111
+ try {
112
+ Config.proxyFallback = await parseJSON(req)
113
+ sendOK(response)
114
+ }
115
+ catch (error) {
116
+ console.error(error)
117
+ sendBadRequest(response)
118
+ }
119
+ }
@@ -7,7 +7,8 @@ export const API = {
7
7
  mocks: MOUNT + '/mocks',
8
8
  reset: MOUNT + '/reset',
9
9
  transform: MOUNT + '/transform',
10
- cookies: MOUNT + '/cookies'
10
+ cookies: MOUNT + '/cookies',
11
+ fallback: MOUNT + '/fallback'
11
12
  }
12
13
 
13
14
  export const DF = { // Dashboard Fields (XHR)
@@ -23,7 +23,7 @@ export async function dispatchMock(req, response) {
23
23
  if (Config.proxyFallback)
24
24
  await proxy(req, response)
25
25
  else
26
- sendNotFound(response) // TODO unit TESTME
26
+ sendNotFound(response)
27
27
  return
28
28
  }
29
29
 
@@ -61,6 +61,8 @@ export const getBrokerByFilename = file => {
61
61
  // BTW, `urlMasks` always start with "/", so there’s no need to
62
62
  // worry about the primacy of array-like keys when iterating.
63
63
  export function getBrokerForUrl(method, url) {
64
+ if (!method in collection)
65
+ return
64
66
  const brokers = Object.values(collection[method])
65
67
  for (let i = brokers.length - 1; i >= 0; i--)
66
68
  if (brokers[i].urlMaskMatches(url))