Browse Source

mocks: docs, examples, tests

master
Lloyd Brookes 9 years ago
parent
commit
c0a72dbaf2
  1. 106
      README.md
  2. 8
      example/mock/.local-web-server.json
  3. 7
      example/mock/css/style.css
  4. 8
      example/mock/index.html
  5. 9
      example/mock/index.js
  6. 3
      example/mock/mocks/data.json
  7. 5
      example/mock/mocks/five.js
  8. 4
      example/mock/mocks/four.js
  9. 106
      jsdoc2md/README.hbs
  10. 6
      lib/local-web-server.js
  11. 134
      test/test.js

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

8
example/mock/.local-web-server.json

@ -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>"
} }
}, },
{ {

7
example/mock/css/style.css

@ -1,7 +0,0 @@
body {
background-color: #AA3939;
color: #FFE2E2
}
svg {
fill: #000
}

8
example/mock/index.html

@ -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>

9
example/mock/index.js

@ -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

@ -0,0 +1,3 @@
{
"one": "static data"
}

5
example/mock/mocks/five.js

@ -1,8 +1,5 @@
module.exports = { module.exports = {
response: function (ctx, id, name) { response: function (ctx, id, name) {
this.body = {
id: id,
name: name
}
ctx.body = `<h1>id: ${id}, name: ${name}</h1>`
} }
} }

4
example/mock/mocks/four.js

@ -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)
} }
} }

106
jsdoc2md/README.hbs

@ -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

6
lib/local-web-server.js

@ -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) {
app.use(mw.mockResponses(mock.route, mock.targets))
if (mock.responses) {
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

@ -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))
})
})
Loading…
Cancel
Save