mockaton 8.11.6 → 8.11.7
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 +12 -4
- package/TODO.md +5 -0
- package/package.json +1 -1
- package/src/Api.js +8 -8
- package/src/MockBroker.js +11 -7
- package/src/Mockaton.test.js +5 -5
- package/src/Watcher.js +16 -21
- package/src/config.js +2 -1
- package/src/utils/http-cors.js +17 -17
- package/src/utils/http-cors.test.js +47 -47
package/README.md
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|

|
|
4
4
|

|
|
5
5
|
|
|
6
|
+
Mockaton is an HTTP mock server for enhancing the development and testing experience.
|
|
7
|
+
|
|
8
|
+
## Convention over Code
|
|
6
9
|
|
|
7
10
|
With Mockaton you don’t need to write code for wiring mocks. Instead, it scans a
|
|
8
11
|
given directory for filenames following a convention similar to the URLs.
|
|
@@ -13,8 +16,10 @@ For example, for <code>/<b>api/user</b>/1234</code> the filename would be:
|
|
|
13
16
|
</pre>
|
|
14
17
|
|
|
15
18
|
|
|
19
|
+
## Dashboard
|
|
20
|
+
|
|
16
21
|
On the dashboard you can select a mock variant for a particular route, delaying responses,
|
|
17
|
-
|
|
22
|
+
or triggering an autogenerated `500` (Internal Server Error), among other features.
|
|
18
23
|
|
|
19
24
|
Nonetheless, there’s a programmatic API, which is handy
|
|
20
25
|
for setting up tests. See **Commander API** section.
|
|
@@ -148,7 +153,10 @@ filename, such as `(demo-part1)`, `(demo-part2)`.
|
|
|
148
153
|
## Alternatives
|
|
149
154
|
- Chrome DevTools allows for [overriding responses](https://developer.chrome.com/docs/devtools/overrides)
|
|
150
155
|
- Reverse Proxies such as [Burp](https://portswigger.net/burp) are also handy for overriding responses.
|
|
151
|
-
- [Mock Server Worker](https://mswjs.io)
|
|
156
|
+
- [MSW (Mock Server Worker)](https://mswjs.io)
|
|
157
|
+
- [Nock](https://github.com/nock/nock)
|
|
158
|
+
- [Fetch Mock](https://github.com/wheresrhys/fetch-mock)
|
|
159
|
+
- [Mentoss](https://github.com/humanwhocodes/mentoss)
|
|
152
160
|
|
|
153
161
|
---
|
|
154
162
|
|
|
@@ -364,8 +372,8 @@ Mockaton’s predefined list. For that, you can add it to <code>config.extraMime
|
|
|
364
372
|
- Use Case 2: For a standalone demo server. For example,
|
|
365
373
|
build your frontend bundle, and serve it from Mockaton.
|
|
366
374
|
|
|
367
|
-
Files under `config.staticDir` don’t use the filename convention
|
|
368
|
-
|
|
375
|
+
Files under `config.staticDir` don’t use the filename convention, and
|
|
376
|
+
they take precedence over `GET` mocks in `config.mocksDir`.
|
|
369
377
|
For example, if you have two files for `GET /foo/bar.jpg`
|
|
370
378
|
|
|
371
379
|
<pre>
|
package/TODO.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# TODO
|
|
2
2
|
|
|
3
3
|
- Refactor tests
|
|
4
|
+
- Group By Route/Method localstorage
|
|
5
|
+
- openapi
|
|
6
|
+
- parsing it for examples?
|
|
7
|
+
- displaying documentation (.openapi)
|
|
8
|
+
- perhaps instead using .js functions `export const doc`
|
|
4
9
|
- Preserve focus when refreshing dashboard `init()`
|
|
5
10
|
- More real-time updates. Currently, it's only for add/remove mock but not for
|
|
6
11
|
static files and changes from another client (Browser, or Commander).
|
package/package.json
CHANGED
package/src/Api.js
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
import { join } from 'node:path'
|
|
7
7
|
import { cookie } from './cookie.js'
|
|
8
8
|
import { config } from './config.js'
|
|
9
|
+
import { arEvents } from './Watcher.js'
|
|
9
10
|
import { parseJSON } from './utils/http-request.js'
|
|
10
11
|
import { listFilesRecursively } from './utils/fs.js'
|
|
11
12
|
import * as mockBrokersCollection from './mockBrokersCollection.js'
|
|
12
13
|
import { DF, API, LONG_POLL_SERVER_TIMEOUT } from './ApiConstants.js'
|
|
13
|
-
import { countAR_Events, subscribeAR_EventListener, unsubscribeAR_EventListener } from './Watcher.js'
|
|
14
14
|
import { sendOK, sendJSON, sendUnprocessableContent, sendDashboardFile, sendForbidden } from './utils/http-response.js'
|
|
15
15
|
|
|
16
16
|
|
|
@@ -82,22 +82,22 @@ function listStaticFiles(req, response) {
|
|
|
82
82
|
|
|
83
83
|
function longPollAR_Events(req, response) {
|
|
84
84
|
// e.g. tab was hidden while new mocks were added or removed
|
|
85
|
-
const clientIsOutOfSync = parseInt(req.headers[DF.lastReceived_nAR], 10) !==
|
|
85
|
+
const clientIsOutOfSync = parseInt(req.headers[DF.lastReceived_nAR], 10) !== arEvents.count
|
|
86
86
|
if (clientIsOutOfSync) {
|
|
87
|
-
sendJSON(response,
|
|
87
|
+
sendJSON(response, arEvents.count)
|
|
88
88
|
return
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
function onAddOrRemoveMock() {
|
|
92
|
-
|
|
93
|
-
sendJSON(response,
|
|
92
|
+
arEvents.unsubscribe(onAddOrRemoveMock)
|
|
93
|
+
sendJSON(response, arEvents.count)
|
|
94
94
|
}
|
|
95
95
|
response.setTimeout(LONG_POLL_SERVER_TIMEOUT, onAddOrRemoveMock)
|
|
96
96
|
req.on('error', () => {
|
|
97
|
-
|
|
97
|
+
arEvents.unsubscribe(onAddOrRemoveMock)
|
|
98
98
|
response.destroy()
|
|
99
99
|
})
|
|
100
|
-
|
|
100
|
+
arEvents.subscribe(onAddOrRemoveMock)
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
|
|
@@ -123,7 +123,7 @@ async function selectMock(req, response) {
|
|
|
123
123
|
if (!broker || !broker.hasMock(file))
|
|
124
124
|
sendUnprocessableContent(response, `Missing Mock: ${file}`)
|
|
125
125
|
else {
|
|
126
|
-
broker.
|
|
126
|
+
broker.selectFile(file)
|
|
127
127
|
sendOK(response)
|
|
128
128
|
}
|
|
129
129
|
}
|
package/src/MockBroker.js
CHANGED
|
@@ -26,16 +26,20 @@ export class MockBroker {
|
|
|
26
26
|
register(file) {
|
|
27
27
|
if (parseFilename(file).status === 500) {
|
|
28
28
|
if (this.temp500IsSelected)
|
|
29
|
-
this.
|
|
29
|
+
this.selectFile(file)
|
|
30
30
|
this.#deleteTemp500()
|
|
31
31
|
}
|
|
32
32
|
this.mocks.push(file)
|
|
33
33
|
this.#sortMocks()
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
#deleteTemp500() {
|
|
36
|
+
#deleteTemp500() {
|
|
37
|
+
this.mocks = this.mocks.filter(file => !this.#isTemp500(file))
|
|
38
|
+
}
|
|
37
39
|
|
|
38
|
-
#isTemp500(file) {
|
|
40
|
+
#isTemp500(file) {
|
|
41
|
+
return includesComment(file, DEFAULT_500_COMMENT)
|
|
42
|
+
}
|
|
39
43
|
|
|
40
44
|
#sortMocks() {
|
|
41
45
|
this.mocks.sort()
|
|
@@ -69,10 +73,10 @@ export class MockBroker {
|
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
selectDefaultFile() {
|
|
72
|
-
this.
|
|
76
|
+
this.selectFile(this.mocks[0])
|
|
73
77
|
}
|
|
74
78
|
|
|
75
|
-
|
|
79
|
+
selectFile(filename) {
|
|
76
80
|
this.currentMock.file = filename
|
|
77
81
|
}
|
|
78
82
|
|
|
@@ -82,7 +86,7 @@ export class MockBroker {
|
|
|
82
86
|
|
|
83
87
|
updateProxied(proxied) {
|
|
84
88
|
if (proxied)
|
|
85
|
-
this.
|
|
89
|
+
this.selectFile('')
|
|
86
90
|
else
|
|
87
91
|
this.selectDefaultFile()
|
|
88
92
|
}
|
|
@@ -90,7 +94,7 @@ export class MockBroker {
|
|
|
90
94
|
setByMatchingComment(comment) {
|
|
91
95
|
for (const file of this.mocks)
|
|
92
96
|
if (includesComment(file, comment)) {
|
|
93
|
-
this.
|
|
97
|
+
this.selectFile(file)
|
|
94
98
|
break
|
|
95
99
|
}
|
|
96
100
|
}
|
package/src/Mockaton.test.js
CHANGED
|
@@ -607,12 +607,12 @@ async function testCorsAllowed() {
|
|
|
607
607
|
method: 'OPTIONS',
|
|
608
608
|
headers: {
|
|
609
609
|
[CorsHeader.Origin]: 'http://example.com',
|
|
610
|
-
[CorsHeader.
|
|
610
|
+
[CorsHeader.AcRequestMethod]: 'GET'
|
|
611
611
|
}
|
|
612
612
|
})
|
|
613
613
|
equal(res.status, 204)
|
|
614
|
-
equal(res.headers.get(CorsHeader.
|
|
615
|
-
equal(res.headers.get(CorsHeader.
|
|
614
|
+
equal(res.headers.get(CorsHeader.AcAllowOrigin), 'http://example.com')
|
|
615
|
+
equal(res.headers.get(CorsHeader.AcAllowMethods), 'GET')
|
|
616
616
|
})
|
|
617
617
|
await it('cors actual response', async () => {
|
|
618
618
|
const res = await request(fixtureDefaultInName[0], {
|
|
@@ -621,8 +621,8 @@ async function testCorsAllowed() {
|
|
|
621
621
|
}
|
|
622
622
|
})
|
|
623
623
|
equal(res.status, 200)
|
|
624
|
-
equal(res.headers.get(CorsHeader.
|
|
625
|
-
equal(res.headers.get(CorsHeader.
|
|
624
|
+
equal(res.headers.get(CorsHeader.AcAllowOrigin), 'http://example.com')
|
|
625
|
+
equal(res.headers.get(CorsHeader.AcExposeHeaders), 'Content-Encoding')
|
|
626
626
|
})
|
|
627
627
|
}
|
|
628
628
|
|
package/src/Watcher.js
CHANGED
|
@@ -7,25 +7,20 @@ import { isFile } from './utils/fs.js'
|
|
|
7
7
|
import * as mockBrokerCollection from './mockBrokersCollection.js'
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function emitAddOrRemoveMock() {
|
|
27
|
-
nAR_Events++
|
|
28
|
-
emitter.emit('AR')
|
|
10
|
+
// AR = Add or Remove Mock
|
|
11
|
+
export const arEvents = new class extends EventEmitter {
|
|
12
|
+
count = 0
|
|
13
|
+
|
|
14
|
+
emit() {
|
|
15
|
+
this.count++
|
|
16
|
+
super.emit('AR')
|
|
17
|
+
}
|
|
18
|
+
subscribe(listener) {
|
|
19
|
+
this.on('AR', listener)
|
|
20
|
+
}
|
|
21
|
+
unsubscribe(listener) {
|
|
22
|
+
this.removeListener('AR', listener)
|
|
23
|
+
}
|
|
29
24
|
}
|
|
30
25
|
|
|
31
26
|
export function watchMocksDir() {
|
|
@@ -35,11 +30,11 @@ export function watchMocksDir() {
|
|
|
35
30
|
return
|
|
36
31
|
if (isFile(join(dir, file))) {
|
|
37
32
|
if (mockBrokerCollection.registerMock(file, 'isFromWatcher'))
|
|
38
|
-
|
|
33
|
+
arEvents.emit()
|
|
39
34
|
}
|
|
40
35
|
else {
|
|
41
36
|
mockBrokerCollection.unregisterMock(file)
|
|
42
|
-
|
|
37
|
+
arEvents.emit()
|
|
43
38
|
}
|
|
44
39
|
})
|
|
45
40
|
}
|
package/src/config.js
CHANGED
package/src/utils/http-cors.js
CHANGED
|
@@ -18,16 +18,16 @@ export function validateCorsAllowedMethods(arr) {
|
|
|
18
18
|
export const CorsHeader = {
|
|
19
19
|
// Request
|
|
20
20
|
Origin: 'origin',
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
AcRequestMethod: 'access-control-request-method',
|
|
22
|
+
AcRequestHeaders: 'access-control-request-headers', // Comma separated
|
|
23
23
|
|
|
24
24
|
// Response
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
AcMaxAge: 'Access-Control-Max-Age',
|
|
26
|
+
AcAllowOrigin: 'Access-Control-Allow-Origin', // '*' | Space delimited | null
|
|
27
|
+
AcAllowMethods: 'Access-Control-Allow-Methods', // '*' | Comma delimited
|
|
28
|
+
AcAllowHeaders: 'Access-Control-Allow-Headers', // '*' | Comma delimited
|
|
29
|
+
AcExposeHeaders: 'Access-Control-Expose-Headers', // '*' | Comma delimited (headers client-side JS can read)
|
|
30
|
+
AcAllowCredentials: 'Access-Control-Allow-Credentials' // 'true'
|
|
31
31
|
}
|
|
32
32
|
const CH = CorsHeader
|
|
33
33
|
|
|
@@ -35,7 +35,7 @@ const CH = CorsHeader
|
|
|
35
35
|
export function isPreflight(req) {
|
|
36
36
|
return req.method === 'OPTIONS'
|
|
37
37
|
&& URL.canParse(req.headers[CH.Origin])
|
|
38
|
-
&& methodIsSupported(req.headers[CH.
|
|
38
|
+
&& methodIsSupported(req.headers[CH.AcRequestMethod])
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
|
|
@@ -51,23 +51,23 @@ export function setCorsHeaders(req, response, {
|
|
|
51
51
|
const hasWildcard = corsOrigins.some(ao => ao === '*')
|
|
52
52
|
if (!reqOrigin || (!hasWildcard && !corsOrigins.includes(reqOrigin)))
|
|
53
53
|
return
|
|
54
|
-
response.setHeader(CH.
|
|
54
|
+
response.setHeader(CH.AcAllowOrigin, reqOrigin) // Never '*', so no need to `Vary` it
|
|
55
55
|
|
|
56
56
|
if (corsCredentials)
|
|
57
|
-
response.setHeader(CH.
|
|
57
|
+
response.setHeader(CH.AcAllowCredentials, 'true')
|
|
58
58
|
|
|
59
|
-
if (req.headers[CH.
|
|
59
|
+
if (req.headers[CH.AcRequestMethod])
|
|
60
60
|
setPreflightSpecificHeaders(req, response, corsMethods, corsHeaders, corsMaxAge)
|
|
61
61
|
else if (corsExposedHeaders.length)
|
|
62
|
-
response.setHeader(CH.
|
|
62
|
+
response.setHeader(CH.AcExposeHeaders, corsExposedHeaders.join(','))
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
function setPreflightSpecificHeaders(req, response, methods, headers, maxAge) {
|
|
66
|
-
const methodAskingFor = req.headers[CH.
|
|
66
|
+
const methodAskingFor = req.headers[CH.AcRequestMethod]
|
|
67
67
|
if (!methods.includes(methodAskingFor))
|
|
68
68
|
return
|
|
69
|
-
response.setHeader(CH.
|
|
70
|
-
response.setHeader(CH.
|
|
69
|
+
response.setHeader(CH.AcMaxAge, maxAge)
|
|
70
|
+
response.setHeader(CH.AcAllowMethods, methodAskingFor)
|
|
71
71
|
if (headers.length)
|
|
72
|
-
response.setHeader(CH.
|
|
72
|
+
response.setHeader(CH.AcAllowHeaders, headers.join(','))
|
|
73
73
|
}
|
|
@@ -41,7 +41,7 @@ await describe('CORS', async () => {
|
|
|
41
41
|
await describe('Identifies Preflight Requests', async () => {
|
|
42
42
|
const requiredRequestHeaders = {
|
|
43
43
|
[CH.Origin]: 'http://localhost:9999',
|
|
44
|
-
[CH.
|
|
44
|
+
[CH.AcRequestMethod]: 'POST'
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
await it('Ignores non-OPTIONS requests', async () => {
|
|
@@ -58,17 +58,17 @@ await describe('CORS', async () => {
|
|
|
58
58
|
equal(await res.text(), 'NON_PREFLIGHT')
|
|
59
59
|
})
|
|
60
60
|
|
|
61
|
-
await it(`Ignores missing method in ${CH.
|
|
61
|
+
await it(`Ignores missing method in ${CH.AcRequestMethod} header`, async () => {
|
|
62
62
|
const headers = { ...requiredRequestHeaders }
|
|
63
|
-
delete headers[CH.
|
|
63
|
+
delete headers[CH.AcRequestMethod]
|
|
64
64
|
const res = await preflight(headers)
|
|
65
65
|
equal(await res.text(), 'NON_PREFLIGHT')
|
|
66
66
|
})
|
|
67
67
|
|
|
68
|
-
await it(`Ignores non-standard method in ${CH.
|
|
68
|
+
await it(`Ignores non-standard method in ${CH.AcRequestMethod} header`, async () => {
|
|
69
69
|
const headers = {
|
|
70
70
|
...requiredRequestHeaders,
|
|
71
|
-
[CH.
|
|
71
|
+
[CH.AcRequestMethod]: 'NON_STANDARD'
|
|
72
72
|
}
|
|
73
73
|
const res = await preflight(headers)
|
|
74
74
|
equal(await res.text(), 'NON_PREFLIGHT')
|
|
@@ -88,13 +88,13 @@ await describe('CORS', async () => {
|
|
|
88
88
|
}
|
|
89
89
|
const p = await preflight({
|
|
90
90
|
[CH.Origin]: FooDotCom,
|
|
91
|
-
[CH.
|
|
91
|
+
[CH.AcRequestMethod]: 'GET'
|
|
92
92
|
})
|
|
93
|
-
headerIs(p, CH.
|
|
94
|
-
headerIs(p, CH.
|
|
95
|
-
headerIs(p, CH.
|
|
96
|
-
headerIs(p, CH.
|
|
97
|
-
headerIs(p, CH.
|
|
93
|
+
headerIs(p, CH.AcAllowOrigin, null)
|
|
94
|
+
headerIs(p, CH.AcAllowMethods, null)
|
|
95
|
+
headerIs(p, CH.AcAllowCredentials, null)
|
|
96
|
+
headerIs(p, CH.AcAllowHeaders, null)
|
|
97
|
+
headerIs(p, CH.AcMaxAge, null)
|
|
98
98
|
})
|
|
99
99
|
|
|
100
100
|
await it('not in allowed origins', async () => {
|
|
@@ -104,12 +104,12 @@ await describe('CORS', async () => {
|
|
|
104
104
|
}
|
|
105
105
|
const p = await preflight({
|
|
106
106
|
[CH.Origin]: NotAllowedDotCom,
|
|
107
|
-
[CH.
|
|
107
|
+
[CH.AcRequestMethod]: 'GET'
|
|
108
108
|
})
|
|
109
|
-
headerIs(p, CH.
|
|
110
|
-
headerIs(p, CH.
|
|
111
|
-
headerIs(p, CH.
|
|
112
|
-
headerIs(p, CH.
|
|
109
|
+
headerIs(p, CH.AcAllowOrigin, null)
|
|
110
|
+
headerIs(p, CH.AcAllowMethods, null)
|
|
111
|
+
headerIs(p, CH.AcAllowCredentials, null)
|
|
112
|
+
headerIs(p, CH.AcAllowHeaders, null)
|
|
113
113
|
})
|
|
114
114
|
|
|
115
115
|
await it('origin and method match', async () => {
|
|
@@ -119,12 +119,12 @@ await describe('CORS', async () => {
|
|
|
119
119
|
}
|
|
120
120
|
const p = await preflight({
|
|
121
121
|
[CH.Origin]: AllowedDotCom,
|
|
122
|
-
[CH.
|
|
122
|
+
[CH.AcRequestMethod]: 'GET'
|
|
123
123
|
})
|
|
124
|
-
headerIs(p, CH.
|
|
125
|
-
headerIs(p, CH.
|
|
126
|
-
headerIs(p, CH.
|
|
127
|
-
headerIs(p, CH.
|
|
124
|
+
headerIs(p, CH.AcAllowOrigin, AllowedDotCom)
|
|
125
|
+
headerIs(p, CH.AcAllowMethods, 'GET')
|
|
126
|
+
headerIs(p, CH.AcAllowCredentials, null)
|
|
127
|
+
headerIs(p, CH.AcAllowHeaders, null)
|
|
128
128
|
})
|
|
129
129
|
|
|
130
130
|
await it('origin matches from multiple', async () => {
|
|
@@ -134,12 +134,12 @@ await describe('CORS', async () => {
|
|
|
134
134
|
}
|
|
135
135
|
const p = await preflight({
|
|
136
136
|
[CH.Origin]: AllowedDotCom,
|
|
137
|
-
[CH.
|
|
137
|
+
[CH.AcRequestMethod]: 'GET'
|
|
138
138
|
})
|
|
139
|
-
headerIs(p, CH.
|
|
140
|
-
headerIs(p, CH.
|
|
141
|
-
headerIs(p, CH.
|
|
142
|
-
headerIs(p, CH.
|
|
139
|
+
headerIs(p, CH.AcAllowOrigin, AllowedDotCom)
|
|
140
|
+
headerIs(p, CH.AcAllowMethods, 'GET')
|
|
141
|
+
headerIs(p, CH.AcAllowCredentials, null)
|
|
142
|
+
headerIs(p, CH.AcAllowHeaders, null)
|
|
143
143
|
})
|
|
144
144
|
|
|
145
145
|
await it('wildcard origin', async () => {
|
|
@@ -149,12 +149,12 @@ await describe('CORS', async () => {
|
|
|
149
149
|
}
|
|
150
150
|
const p = await preflight({
|
|
151
151
|
[CH.Origin]: FooDotCom,
|
|
152
|
-
[CH.
|
|
152
|
+
[CH.AcRequestMethod]: 'GET'
|
|
153
153
|
})
|
|
154
|
-
headerIs(p, CH.
|
|
155
|
-
headerIs(p, CH.
|
|
156
|
-
headerIs(p, CH.
|
|
157
|
-
headerIs(p, CH.
|
|
154
|
+
headerIs(p, CH.AcAllowOrigin, FooDotCom)
|
|
155
|
+
headerIs(p, CH.AcAllowMethods, 'GET')
|
|
156
|
+
headerIs(p, CH.AcAllowCredentials, null)
|
|
157
|
+
headerIs(p, CH.AcAllowHeaders, null)
|
|
158
158
|
})
|
|
159
159
|
|
|
160
160
|
await it(`wildcard and credentials`, async () => {
|
|
@@ -165,12 +165,12 @@ await describe('CORS', async () => {
|
|
|
165
165
|
}
|
|
166
166
|
const p = await preflight({
|
|
167
167
|
[CH.Origin]: FooDotCom,
|
|
168
|
-
[CH.
|
|
168
|
+
[CH.AcRequestMethod]: 'GET'
|
|
169
169
|
})
|
|
170
|
-
headerIs(p, CH.
|
|
171
|
-
headerIs(p, CH.
|
|
172
|
-
headerIs(p, CH.
|
|
173
|
-
headerIs(p, CH.
|
|
170
|
+
headerIs(p, CH.AcAllowOrigin, FooDotCom)
|
|
171
|
+
headerIs(p, CH.AcAllowMethods, 'GET')
|
|
172
|
+
headerIs(p, CH.AcAllowCredentials, 'true')
|
|
173
|
+
headerIs(p, CH.AcAllowHeaders, null)
|
|
174
174
|
})
|
|
175
175
|
|
|
176
176
|
await it(`wildcard, credentials, and headers`, async () => {
|
|
@@ -182,12 +182,12 @@ await describe('CORS', async () => {
|
|
|
182
182
|
}
|
|
183
183
|
const p = await preflight({
|
|
184
184
|
[CH.Origin]: FooDotCom,
|
|
185
|
-
[CH.
|
|
185
|
+
[CH.AcRequestMethod]: 'GET'
|
|
186
186
|
})
|
|
187
|
-
headerIs(p, CH.
|
|
188
|
-
headerIs(p, CH.
|
|
189
|
-
headerIs(p, CH.
|
|
190
|
-
headerIs(p, CH.
|
|
187
|
+
headerIs(p, CH.AcAllowOrigin, FooDotCom)
|
|
188
|
+
headerIs(p, CH.AcAllowMethods, 'GET')
|
|
189
|
+
headerIs(p, CH.AcAllowCredentials, 'true')
|
|
190
|
+
headerIs(p, CH.AcAllowHeaders, 'content-type,my-header')
|
|
191
191
|
})
|
|
192
192
|
})
|
|
193
193
|
|
|
@@ -201,9 +201,9 @@ await describe('CORS', async () => {
|
|
|
201
201
|
[CH.Origin]: NotAllowedDotCom
|
|
202
202
|
})
|
|
203
203
|
equal(p.status, 200)
|
|
204
|
-
headerIs(p, CH.
|
|
205
|
-
headerIs(p, CH.
|
|
206
|
-
headerIs(p, CH.
|
|
204
|
+
headerIs(p, CH.AcAllowOrigin, null)
|
|
205
|
+
headerIs(p, CH.AcAllowCredentials, null)
|
|
206
|
+
headerIs(p, CH.AcExposeHeaders, null)
|
|
207
207
|
})
|
|
208
208
|
|
|
209
209
|
await it('origin allowed', async () => {
|
|
@@ -217,9 +217,9 @@ await describe('CORS', async () => {
|
|
|
217
217
|
[CH.Origin]: AllowedDotCom
|
|
218
218
|
})
|
|
219
219
|
equal(p.status, 200)
|
|
220
|
-
headerIs(p, CH.
|
|
221
|
-
headerIs(p, CH.
|
|
222
|
-
headerIs(p, CH.
|
|
220
|
+
headerIs(p, CH.AcAllowOrigin, AllowedDotCom)
|
|
221
|
+
headerIs(p, CH.AcAllowCredentials, 'true')
|
|
222
|
+
headerIs(p, CH.AcExposeHeaders, 'x-h1,x-h2')
|
|
223
223
|
})
|
|
224
224
|
})
|
|
225
225
|
})
|