Skip to content

Commit

Permalink
Merge pull request #7 from cdcabrera/development
Browse files Browse the repository at this point in the history
feat(delay response): add ability to delay response time
  • Loading branch information
cdcabrera authored Aug 14, 2018
2 parents e871c84 + 9e008bc commit f68dbc0
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 24 deletions.
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ From there you should be able to navigate to
### More examples, and custom responses
Apidoc Mock adds in a few different custom flags to help you identify or demonstrate API responses
- @apiMock {Random|RandomResponse} - pull a random response from either success or error examples
- @apiMock {RandomSuccess} - pull a random success from success examples
- @apiMock {RandomError} - pull a random error from error examples
- @apiMock {ForceStatus} [HTTP STATUS] - force a specific http status
- @apiMock {DelayResponse} [MILLISECONDS] - force (in milliseconds) a delayed response
1. Get random responses from both `success` and `error` examples with the `@apiMock {RandomResponse}` annotation
```js
/**
Expand Down Expand Up @@ -176,3 +183,28 @@ From there you should be able to navigate to
*/
const getExample = () => {};
```
1. Delay a response status with the `@apiMock {DelayResponse} [MILLISECONDS GO HERE]` annotation.
```js
/**
* @api {get} /hello/world/
* @apiMock {DelayResponse} 3000
* @apiSuccess {String} foo
* @apiSuccess {String} bar
* @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK
* {
* "foo": "hello",
* "bar": "world",
* }
* @apiError {String} bad
* @apiError {String} request
* @apiErrorExample {json} Error-Response:
* HTTP/1.1 400 OK
* {
* "bad": "hello",
* "request": "world",
* }
*/
const getExample = () => {};
```
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "apidoc-mock",
"version": "1.0.2",
"version": "2.0.0",
"description": "Creates a mock server from apiDoc comments.",
"author": "cdcabrera",
"private": true,
Expand All @@ -13,7 +13,7 @@
"url": "https://github.com/cdcabrera/apidoc-mock/issues"
},
"engines": {
"node": ">=8.9.1"
"node": ">=8.11.3"
},
"main": "src/index.js",
"scripts": {
Expand All @@ -38,14 +38,14 @@
},
"devDependencies": {
"babel-eslint": "^8.2.6",
"eslint": "^5.2.0",
"eslint": "^5.3.0",
"eslint-config-esnext": "^3.0.0",
"eslint-config-node": "^3.0.0",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-babel": "^5.1.0",
"eslint-plugin-import": "^2.13.0",
"eslint-plugin-node": "^7.0.1",
"eslint-plugin-prettier": "^2.6.2",
"prettier": "^1.13.7"
"prettier": "^1.14.2"
}
}
8 changes: 6 additions & 2 deletions src/api_mock.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* Configure Apidoc output. Filter custom "apiMock" related key/value
* pairs such as randomResponse, forceStatus, or delayResponse.
*/
let group = '';

const parse = (content, source, defaultGroup) => {
Expand All @@ -8,7 +12,7 @@ const parse = (content, source, defaultGroup) => {
let key = (keyValue[0] || '').replace(/({|^\s+|\s+$)/, '');
const value = (keyValue[1] || '').replace(/(^\s+|\s+$)/, '');

key = key.replace(/(?:^\w|[A-Z]|\b\w)/g, function(letter, index) {
key = key.replace(/(?:^\w|[A-Z]|\b\w)/g, (letter, index) => {
return index === 0 ? letter.toLowerCase() : letter.toUpperCase();
});

Expand All @@ -22,6 +26,6 @@ const path = () => `local.mock.${getGroup()}`;
module.exports = {
parse,
path,
getGroup: getGroup,
getGroup,
method: 'push'
};
53 changes: 43 additions & 10 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,24 +78,41 @@ class LoadApi {
if (mockSettings.mock && mockSettings.mock.settings && mockSettings.mock.settings.length) {
mockSettings.mock.settings.forEach(val => {
const keys = Object.keys(val || {});
const key = keys[0] || null;
const key = keys[0] || '';

switch (key) {
case 'forceStatus':
switch (key.toLowerCase()) {
case 'delay':
case 'delayresponse':
settings.delay = parseInt(val[key], 10);

if (Number.isNaN(settings.delay)) {
settings.delay = 1000;
}

break;
case 'force':
case 'forcestatus':
case 'forcedstatus':
settings.forceStatus = parseInt(val[key], 10);

if (Number.isNaN(settings.forceStatus)) {
settings.forceStatus = 200;
}

break;
case 'response':
settings.response = 'response';
break;
case 'randomResponse':
case 'random':
case 'randomresponse':
settings.response = 'response';
settings.reload = true;
break;
case 'randomSuccess':
case 'randomsuccess':
settings.response = 'success';
settings.reload = true;
break;
case 'randomError':
case 'randomerror':
settings.response = 'error';
settings.reload = true;
break;
Expand Down Expand Up @@ -175,7 +192,7 @@ class LoadApi {
return;
}

console.info('ApiDoc finished...\tloading JSON');
console.info('ApiDoc finished...\tloading response');
return JSON.parse(fs.readFileSync(apiJsonFile, 'utf8'));
}

Expand Down Expand Up @@ -367,7 +384,16 @@ class LoadApi {
response.append('WWW-Authenticate', 'Spoof response');
response.status(401);
response.set('Content-Type', authObj.type);
response.end(authObj.content || 'Authorization Required');

if (mockSettings.delay > 0) {
setTimeout(
() => response.end(authObj.content || 'Authorization Required'),
mockSettings.delay
);
} else {
response.end(authObj.content || 'Authorization Required');
}

return;
}
}
Expand All @@ -379,7 +405,12 @@ class LoadApi {

response.set('Content-Type', type);
response.status(httpStatus);
response.send(content);

if (mockSettings.delay > 0) {
setTimeout(() => response.send(content), mockSettings.delay);
} else {
response.send(content);
}
});

routesLoaded += 1;
Expand All @@ -390,7 +421,9 @@ class LoadApi {

if (routesLoaded) {
this.app.listen(port, () =>
console.info(`JSON finished...\tloaded routes\nMock finished...\tforwarded port ${port}`)
console.info(
`Response finished...\tloaded routes\nMock finished...\tforwarded port ${port}`
)
);
} else {
console.info(`Mock waiting...`);
Expand Down
16 changes: 8 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -922,9 +922,9 @@ eslint@^4.19.1:
table "4.0.2"
text-table "~0.2.0"

eslint@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.2.0.tgz#3901ae249195d473e633c4acbc370068b1c964dc"
eslint@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.3.0.tgz#53695aca5213968aacdf970ccb231e42a2b285f8"
dependencies:
ajv "^6.5.0"
babel-code-frame "^6.26.0"
Expand Down Expand Up @@ -957,7 +957,7 @@ eslint@^5.2.0:
path-is-inside "^1.0.2"
pluralize "^7.0.0"
progress "^2.0.0"
regexpp "^1.1.0"
regexpp "^2.0.0"
require-uncached "^1.0.3"
semver "^5.5.0"
string.prototype.matchall "^2.0.0"
Expand Down Expand Up @@ -2327,9 +2327,9 @@ prepend-http@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"

prettier@^1.13.7:
version "1.13.7"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.7.tgz#850f3b8af784a49a6ea2d2eaa7ed1428a34b7281"
prettier@^1.14.2:
version "1.14.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.2.tgz#0ac1c6e1a90baa22a62925f41963c841983282f9"

process-nextick-args@~2.0.0:
version "2.0.0"
Expand Down Expand Up @@ -2441,7 +2441,7 @@ regexp.prototype.flags@^1.2.0:
dependencies:
define-properties "^1.1.2"

regexpp@^1.0.1, regexpp@^1.1.0:
regexpp@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab"

Expand Down

0 comments on commit f68dbc0

Please sign in to comment.