mocks: docs, examples, tests
This commit is contained in:
106
README.md
106
README.md
@ -47,16 +47,6 @@ By default, typical SPA urls (e.g. `/user/1`, `/login`) would return `404 Not Fo
|
|||||||
|
|
||||||
[Example](https://github.com/75lb/local-web-server/tree/master/example/spa).
|
[Example](https://github.com/75lb/local-web-server/tree/master/example/spa).
|
||||||
|
|
||||||
### Access Control
|
|
||||||
|
|
||||||
By default, access to all files is allowed (including dot files). Use `--forbid` to establish a blacklist:
|
|
||||||
```sh
|
|
||||||
$ ws --forbid '*.json' '*.yml'
|
|
||||||
serving at http://localhost:8000
|
|
||||||
```
|
|
||||||
|
|
||||||
[Example](https://github.com/75lb/local-web-server/tree/master/example/forbid).
|
|
||||||
|
|
||||||
### URL rewriting
|
### URL rewriting
|
||||||
|
|
||||||
Your application requested `/css/style.css` but it's stored at `/build/css/style.css`. To avoid a 404 you need a rewrite rule:
|
Your application requested `/css/style.css` but it's stored at `/build/css/style.css`. To avoid a 404 you need a rewrite rule:
|
||||||
@ -79,7 +69,6 @@ $ ws --rewrite '/css/* -> /build/css/$1'
|
|||||||
|
|
||||||
this rewrites `/css/a` as `/build/css/a`, `/css/a/b/c` as `/build/css/a/b/c` etc.
|
this rewrites `/css/a` as `/build/css/a`, `/css/a/b/c` as `/build/css/a/b/c` etc.
|
||||||
|
|
||||||
|
|
||||||
#### Proxied requests
|
#### Proxied requests
|
||||||
|
|
||||||
If the `to` URL contains a remote host, local-web-server will act as a proxy - fetching and responding with the remote resource.
|
If the `to` URL contains a remote host, local-web-server will act as a proxy - fetching and responding with the remote resource.
|
||||||
@ -96,6 +85,91 @@ $ ws --rewrite '/:user/repos/:name -> https://api.github.com/repos/:user/:name'
|
|||||||
|
|
||||||
[Example](https://github.com/75lb/local-web-server/tree/master/example/rewrite).
|
[Example](https://github.com/75lb/local-web-server/tree/master/example/rewrite).
|
||||||
|
|
||||||
|
### Mock Responses
|
||||||
|
|
||||||
|
Mock a data service, serve any custom/dynamic content.
|
||||||
|
|
||||||
|
A mock definition maps a route to a response. Mock a home page.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mocks": [
|
||||||
|
{
|
||||||
|
"route": "/",
|
||||||
|
"response": {
|
||||||
|
"body": "<h1>Welcome to the Mock Responses example</h1>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Conditional response, depending on the request.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mocks": [
|
||||||
|
{
|
||||||
|
"route": "/two",
|
||||||
|
"request": { "accepts": "xml" },
|
||||||
|
"response": {
|
||||||
|
"body": "<result id='2' name='whatever' />"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Multiple potential responses. First request to match.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mocks": [
|
||||||
|
{
|
||||||
|
"route": "/three",
|
||||||
|
"responses": [
|
||||||
|
{
|
||||||
|
"request": { "method": "GET" },
|
||||||
|
"response": {
|
||||||
|
"body": "<h1>Mock response for 'GET' request on /three</h1>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"request": { "method": "POST" },
|
||||||
|
"response": {
|
||||||
|
"status": 400,
|
||||||
|
"body": { "message": "That method is not allowed." }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
More dynamic response.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mocks": [
|
||||||
|
{
|
||||||
|
"route": "/four",
|
||||||
|
"module": "/mocks/four.js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Tokens in the route are passed to the response.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mocks": [
|
||||||
|
{
|
||||||
|
"route": "/five/:id\\?name=:name",
|
||||||
|
"module": "/mocks/five.js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[Example](https://github.com/75lb/local-web-server/tree/master/example/mock).
|
||||||
|
|
||||||
### Stored config
|
### Stored config
|
||||||
|
|
||||||
Use the same port and blacklist every time? Persist it to `package.json`:
|
Use the same port and blacklist every time? Persist it to `package.json`:
|
||||||
@ -136,6 +210,16 @@ serving at http://localhost:8000
|
|||||||
|
|
||||||
The format value supplied is passed directly to [morgan](https://github.com/expressjs/morgan). The exception is `--log-format none` which disables all output.
|
The format value supplied is passed directly to [morgan](https://github.com/expressjs/morgan). The exception is `--log-format none` which disables all output.
|
||||||
|
|
||||||
|
### Access Control
|
||||||
|
|
||||||
|
By default, access to all files is allowed (including dot files). Use `--forbid` to establish a blacklist:
|
||||||
|
```sh
|
||||||
|
$ ws --forbid '*.json' '*.yml'
|
||||||
|
serving at http://localhost:8000
|
||||||
|
```
|
||||||
|
|
||||||
|
[Example](https://github.com/75lb/local-web-server/tree/master/example/forbid).
|
||||||
|
|
||||||
### Other usage
|
### Other usage
|
||||||
|
|
||||||
#### Debugging
|
#### Debugging
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"mocks": [
|
"mocks": [
|
||||||
{
|
{
|
||||||
"route": "/one",
|
"route": "/",
|
||||||
"response": {
|
"response": {
|
||||||
"body": { "id": 1, "name": "whatever" }
|
"body": "<h1>Welcome to the Mock Responses example</h1>"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -15,11 +15,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"route": "/three",
|
"route": "/three",
|
||||||
"targets": [
|
"responses": [
|
||||||
{
|
{
|
||||||
"request": { "method": "GET" },
|
"request": { "method": "GET" },
|
||||||
"response": {
|
"response": {
|
||||||
"body": { "id": 1, "name": "whatever" }
|
"body": "<h1>Mock response for 'GET' request on /three</h1>"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
body {
|
|
||||||
background-color: #AA3939;
|
|
||||||
color: #FFE2E2
|
|
||||||
}
|
|
||||||
svg {
|
|
||||||
fill: #000
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
<head>
|
|
||||||
<link rel="stylesheet" href="css/style.css">
|
|
||||||
</head>
|
|
||||||
<h1>Mock responses</h1>
|
|
||||||
<ul>
|
|
||||||
<li>list data</li>
|
|
||||||
</ul>
|
|
||||||
<script src="bundle.js"></script>
|
|
@ -1,9 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
const request = require('req-then')
|
|
||||||
const $ = document.querySelector.bind(document)
|
|
||||||
|
|
||||||
request('http://localhost:8000/tree').then(response => {
|
|
||||||
$('ul').innerHTML = JSON.parse(response.data).map(tree => {
|
|
||||||
return `<li>${tree.name}</li>`
|
|
||||||
}).join('')
|
|
||||||
})
|
|
3
example/mock/mocks/data.json
Normal file
3
example/mock/mocks/data.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"one": "static data"
|
||||||
|
}
|
@ -1,8 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
response: function (ctx, id, name) {
|
response: function (ctx, id, name) {
|
||||||
this.body = {
|
ctx.body = `<h1>id: ${id}, name: ${name}</h1>`
|
||||||
id: id,
|
|
||||||
name: name
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
const fs = require('fs')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
response: {
|
response: {
|
||||||
body: { id: 2, name: 'eucalyptus', maxHeight: 210 }
|
body: fs.createReadStream(__filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,16 +47,6 @@ By default, typical SPA urls (e.g. `/user/1`, `/login`) would return `404 Not Fo
|
|||||||
|
|
||||||
[Example](https://github.com/75lb/local-web-server/tree/master/example/spa).
|
[Example](https://github.com/75lb/local-web-server/tree/master/example/spa).
|
||||||
|
|
||||||
### Access Control
|
|
||||||
|
|
||||||
By default, access to all files is allowed (including dot files). Use `--forbid` to establish a blacklist:
|
|
||||||
```sh
|
|
||||||
$ ws --forbid '*.json' '*.yml'
|
|
||||||
serving at http://localhost:8000
|
|
||||||
```
|
|
||||||
|
|
||||||
[Example](https://github.com/75lb/local-web-server/tree/master/example/forbid).
|
|
||||||
|
|
||||||
### URL rewriting
|
### URL rewriting
|
||||||
|
|
||||||
Your application requested `/css/style.css` but it's stored at `/build/css/style.css`. To avoid a 404 you need a rewrite rule:
|
Your application requested `/css/style.css` but it's stored at `/build/css/style.css`. To avoid a 404 you need a rewrite rule:
|
||||||
@ -79,7 +69,6 @@ $ ws --rewrite '/css/* -> /build/css/$1'
|
|||||||
|
|
||||||
this rewrites `/css/a` as `/build/css/a`, `/css/a/b/c` as `/build/css/a/b/c` etc.
|
this rewrites `/css/a` as `/build/css/a`, `/css/a/b/c` as `/build/css/a/b/c` etc.
|
||||||
|
|
||||||
|
|
||||||
#### Proxied requests
|
#### Proxied requests
|
||||||
|
|
||||||
If the `to` URL contains a remote host, local-web-server will act as a proxy - fetching and responding with the remote resource.
|
If the `to` URL contains a remote host, local-web-server will act as a proxy - fetching and responding with the remote resource.
|
||||||
@ -96,6 +85,91 @@ $ ws --rewrite '/:user/repos/:name -> https://api.github.com/repos/:user/:name'
|
|||||||
|
|
||||||
[Example](https://github.com/75lb/local-web-server/tree/master/example/rewrite).
|
[Example](https://github.com/75lb/local-web-server/tree/master/example/rewrite).
|
||||||
|
|
||||||
|
### Mock Responses
|
||||||
|
|
||||||
|
Mock a data service, serve any custom/dynamic content.
|
||||||
|
|
||||||
|
A mock definition maps a route to a response. Mock a home page.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mocks": [
|
||||||
|
{
|
||||||
|
"route": "/",
|
||||||
|
"response": {
|
||||||
|
"body": "<h1>Welcome to the Mock Responses example</h1>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Conditional response, depending on the request.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mocks": [
|
||||||
|
{
|
||||||
|
"route": "/two",
|
||||||
|
"request": { "accepts": "xml" },
|
||||||
|
"response": {
|
||||||
|
"body": "<result id='2' name='whatever' />"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Multiple potential responses. First request to match.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mocks": [
|
||||||
|
{
|
||||||
|
"route": "/three",
|
||||||
|
"responses": [
|
||||||
|
{
|
||||||
|
"request": { "method": "GET" },
|
||||||
|
"response": {
|
||||||
|
"body": "<h1>Mock response for 'GET' request on /three</h1>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"request": { "method": "POST" },
|
||||||
|
"response": {
|
||||||
|
"status": 400,
|
||||||
|
"body": { "message": "That method is not allowed." }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
More dynamic response.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mocks": [
|
||||||
|
{
|
||||||
|
"route": "/four",
|
||||||
|
"module": "/mocks/four.js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Tokens in the route are passed to the response.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mocks": [
|
||||||
|
{
|
||||||
|
"route": "/five/:id\\?name=:name",
|
||||||
|
"module": "/mocks/five.js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[Example](https://github.com/75lb/local-web-server/tree/master/example/mock).
|
||||||
|
|
||||||
### Stored config
|
### Stored config
|
||||||
|
|
||||||
Use the same port and blacklist every time? Persist it to `package.json`:
|
Use the same port and blacklist every time? Persist it to `package.json`:
|
||||||
@ -136,6 +210,16 @@ serving at http://localhost:8000
|
|||||||
|
|
||||||
The format value supplied is passed directly to [morgan](https://github.com/expressjs/morgan). The exception is `--log-format none` which disables all output.
|
The format value supplied is passed directly to [morgan](https://github.com/expressjs/morgan). The exception is `--log-format none` which disables all output.
|
||||||
|
|
||||||
|
### Access Control
|
||||||
|
|
||||||
|
By default, access to all files is allowed (including dot files). Use `--forbid` to establish a blacklist:
|
||||||
|
```sh
|
||||||
|
$ ws --forbid '*.json' '*.yml'
|
||||||
|
serving at http://localhost:8000
|
||||||
|
```
|
||||||
|
|
||||||
|
[Example](https://github.com/75lb/local-web-server/tree/master/example/forbid).
|
||||||
|
|
||||||
### Other usage
|
### Other usage
|
||||||
|
|
||||||
#### Debugging
|
#### Debugging
|
||||||
|
@ -148,11 +148,11 @@ function localWebServer (options) {
|
|||||||
/* Mock Responses */
|
/* Mock Responses */
|
||||||
options.mocks.forEach(mock => {
|
options.mocks.forEach(mock => {
|
||||||
if (mock.module) {
|
if (mock.module) {
|
||||||
mock.targets = require(path.join(options.static.root, mock.module))
|
mock.responses = require(path.join(options.static.root, mock.module))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mock.targets) {
|
if (mock.responses) {
|
||||||
app.use(mw.mockResponses(mock.route, mock.targets))
|
app.use(mw.mockResponses(mock.route, mock.responses))
|
||||||
} else if (mock.response) {
|
} else if (mock.response) {
|
||||||
mock.target = {
|
mock.target = {
|
||||||
request: mock.request,
|
request: mock.request,
|
||||||
|
134
test/test.js
134
test/test.js
@ -17,6 +17,13 @@ function launchServer (app, options) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkResponse (t, status, body) {
|
||||||
|
return function (response) {
|
||||||
|
if (status) t.strictEqual(response.res.statusCode, status)
|
||||||
|
if (body) t.ok(body.test(response.data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test('static', function (t) {
|
test('static', function (t) {
|
||||||
t.plan(1)
|
t.plan(1)
|
||||||
const app = localWebServer({
|
const app = localWebServer({
|
||||||
@ -201,3 +208,130 @@ test('rewrite: proxy with port', function (t) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('mock: simple response', function (t) {
|
||||||
|
t.plan(2)
|
||||||
|
const app = localWebServer({
|
||||||
|
log: { format: 'none' },
|
||||||
|
mocks: [
|
||||||
|
{ route: '/test', response: { body: 'test' } }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
launchServer(app, { path: '/test', onSuccess: response => {
|
||||||
|
t.strictEqual(response.res.statusCode, 200)
|
||||||
|
t.ok(/test/.test(response.data))
|
||||||
|
}})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('mock: method request filter', function (t) {
|
||||||
|
t.plan(3)
|
||||||
|
const app = localWebServer({
|
||||||
|
log: { format: 'none' },
|
||||||
|
mocks: [
|
||||||
|
{
|
||||||
|
route: '/test',
|
||||||
|
request: { method: 'POST' },
|
||||||
|
response: { body: 'test' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
const server = http.createServer(app.callback())
|
||||||
|
server.listen(8100, () => {
|
||||||
|
request('http://localhost:8100/test')
|
||||||
|
.then(checkResponse(t, 404))
|
||||||
|
.then(() => request('http://localhost:8100/test', { data: 'something' }))
|
||||||
|
.then(checkResponse(t, 200, /test/))
|
||||||
|
.then(server.close.bind(server))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('mock: accepts request filter', function (t) {
|
||||||
|
t.plan(3)
|
||||||
|
const app = localWebServer({
|
||||||
|
log: { format: 'none' },
|
||||||
|
mocks: [
|
||||||
|
{
|
||||||
|
route: '/test',
|
||||||
|
request: { accepts: 'text' },
|
||||||
|
response: { body: 'test' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
const server = http.createServer(app.callback())
|
||||||
|
server.listen(8100, () => {
|
||||||
|
request('http://localhost:8100/test', { headers: { Accept: '*/json' }})
|
||||||
|
.then(checkResponse(t, 404))
|
||||||
|
.then(() => request('http://localhost:8100/test', { headers: { Accept: 'text/plain' }}))
|
||||||
|
.then(checkResponse(t, 200, /test/))
|
||||||
|
.then(server.close.bind(server))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('mock: responses array', function (t) {
|
||||||
|
t.plan(4)
|
||||||
|
const app = localWebServer({
|
||||||
|
log: { format: 'none' },
|
||||||
|
mocks: [
|
||||||
|
{
|
||||||
|
route: '/test',
|
||||||
|
responses: [
|
||||||
|
{ request: { method: 'GET' }, response: { body: 'get' } },
|
||||||
|
{ request: { method: 'POST' }, response: { body: 'post' } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
const server = http.createServer(app.callback())
|
||||||
|
server.listen(8100, () => {
|
||||||
|
request('http://localhost:8100/test')
|
||||||
|
.then(checkResponse(t, 200, /get/))
|
||||||
|
.then(() => request('http://localhost:8100/test', { method: 'POST' }))
|
||||||
|
.then(checkResponse(t, 200, /post/))
|
||||||
|
.then(server.close.bind(server))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('mock: response function', function (t) {
|
||||||
|
t.plan(4)
|
||||||
|
const app = localWebServer({
|
||||||
|
log: { format: 'none' },
|
||||||
|
mocks: [
|
||||||
|
{
|
||||||
|
route: '/test',
|
||||||
|
responses: [
|
||||||
|
{ request: { method: 'GET' }, response: ctx => ctx.body = 'get' },
|
||||||
|
{ request: { method: 'POST' }, response: ctx => ctx.body = 'post' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
const server = http.createServer(app.callback())
|
||||||
|
server.listen(8100, () => {
|
||||||
|
request('http://localhost:8100/test')
|
||||||
|
.then(checkResponse(t, 200, /get/))
|
||||||
|
.then(() => request('http://localhost:8100/test', { method: 'POST' }))
|
||||||
|
.then(checkResponse(t, 200, /post/))
|
||||||
|
.then(server.close.bind(server))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('mock: response function args', function (t) {
|
||||||
|
t.plan(2)
|
||||||
|
const app = localWebServer({
|
||||||
|
log: { format: 'none' },
|
||||||
|
mocks: [
|
||||||
|
{
|
||||||
|
route: '/test/:one',
|
||||||
|
responses: [
|
||||||
|
{ request: { method: 'GET' }, response: (ctx, one) => ctx.body = one }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
const server = http.createServer(app.callback())
|
||||||
|
server.listen(8100, () => {
|
||||||
|
request('http://localhost:8100/test/yeah')
|
||||||
|
.then(checkResponse(t, 200, /yeah/))
|
||||||
|
.then(server.close.bind(server))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Reference in New Issue
Block a user