Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(delay response): add ability to delay response time #7

Merged
merged 2 commits into from
Aug 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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