Skip to content

Commit

Permalink
refactor(mock-server): remove server events
Browse files Browse the repository at this point in the history
BREAKING CHANGE: server lifecycle events are not longer emmitted
  • Loading branch information
Rob McGuinness committed Apr 13, 2018
1 parent 8cc9242 commit 2cb477b
Show file tree
Hide file tree
Showing 12 changed files with 172 additions and 297 deletions.
248 changes: 142 additions & 106 deletions README.md

Large diffs are not rendered by default.

81 changes: 29 additions & 52 deletions packages/mock-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,31 @@

## Table of Contents

* [Intro](#intro)
* [Server Configuration](#server-configuration)
* [Route Configuration](#route-configuration)
* [Events](#events)
* [Contributing](#contributing)
* [Authors](#authors)
* [Disclaimer](#disclaimer)
* [License](#license)

* [Intro](#intro)
* [Server Configuration](#server-configuration)
* [Route Configuration](#route-configuration)
* [Contributing](#contributing)
* [Authors](#authors)
* [Disclaimer](#disclaimer)
* [License](#license)

## Intro

Develop web applications without heavy back-end services by running Express middleware or http server which can deliver mock responses.

Responses can be JSON or other formats to simulate REST services. Access-Control HTTP Headers are set by default to allow CORS requests. Mock services are configured in the [routes.json](./routes.json) file.

This server can return other file types besides XML or JSON (PDFs, images, etc). The appropriate response headers will be automatically set for different file types. For a complete list of file types supported view the [mime types here](https://github.com/jshttp/mime-db/blob/88d8b0424d93aefef4ef300dc35ad2c8d1e1f9d4/db.json).
This server can return other file types besides XML or JSON (PDFs, images, etc). The appropriate response headers will be automatically set for different file types. For a complete list of file types supported view the [mime types here](https://github.com/jshttp/mime-db/blob/88d8b0424d93aefef4ef300dc35ad2c8d1e1f9d4/db.json).

## Route Matching

`avality-mock-server` is designed to respond with the route configuration that matches the incoming request the closest by introspecting the request body, parameters and headers. `avality-mock-server` calculates which route scores the highest for each request and returns the appropriate mock response.
`avality-mock-server` is designed to respond with the route configuration that matches the incoming request the closest by introspecting the request body, parameters and headers. `avality-mock-server` calculates which route scores the highest for each request and returns the appropriate mock response.

## Configuration

### Standalone Server

The default server configuration can be found in [config.js](./config.js). Pass a different configuration file to the `avality-mock-server` server to override the defaults.
The default server configuration can be found in [config.js](./config.js). Pass a different configuration file to the `avality-mock-server` server to override the defaults.

```javascript
const path = require('path');
Expand All @@ -53,6 +51,7 @@ const = new MockServer();
```

### Express Middleware

```js
const express = require('express');
const app = express();
Expand All @@ -68,38 +67,37 @@ app.listen(3001);
## Options
- **latency**: Global delay for all reponses. The latency can be overridden per route configuration. Default is `250ms`.
- **limit**: Upload max size. Default is `50mb`,
- **host**: Server binds and listens for connections on the specified host. Default is `0.0.0.0`.
- **port**: Server binds and listens for connections on the specified port. Default is `9999`.
- **data**: Path to folder that contains the json mock responses.
- **routes**: Path(s) to configuration file that contains a mapping of the request/response routes. Multiple paths can be passed in with an array of strings.
- **plugins**: Array of NPM module names that enhance `@availity/mock-server` with additional data and routes. @See [@availity/mock-data](https://github.com/Availity/@availity/mock-data)
- **logProvider**: Function that returns a logger that is used in place of the default logger. Inspired by the log provider in [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware)
- **pluginContext**: A url context value which is used to rewrite every instance of `${context}` variable in mock data responses. This can be useful for HATEOS links.
* **latency**: Global delay for all reponses. The latency can be overridden per route configuration. Default is `250ms`.
* **limit**: Upload max size. Default is `50mb`,
* **host**: Server binds and listens for connections on the specified host. Default is `0.0.0.0`.
* **port**: Server binds and listens for connections on the specified port. Default is `9999`.
* **data**: Path to folder that contains the json mock responses.
* **routes**: Path(s) to configuration file that contains a mapping of the request/response routes. Multiple paths can be passed in with an array of strings.
* **plugins**: Array of NPM module names that enhance `@availity/mock-server` with additional data and routes. @See [@availity/mock-data](https://github.com/Availity/@availity/mock-data)
* **logProvider**: Function that returns a logger that is used in place of the default logger. Inspired by the log provider in [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware)
* **pluginContext**: A url context value which is used to rewrite every instance of `${context}` variable in mock data responses. This can be useful for HATEOS links.
**Simple**
```js
```js
function logProvider(provider) {
return require('winston');
}
```
**Advanced**
```js
```js
function logProvider(provider) {

var logger = new (require('winston').Logger)();
var logger = new (require('winston')).Logger();

var myCustomProvider = {
log: logger.log,
debug: logger.debug,
info: logger.info,
warn: logger.warn,
error: logger.error
}
};
return myCustomProvider;
}
```
Expand Down Expand Up @@ -158,8 +156,8 @@ The mock configuration supports deep nested introspection of JSON and multi-part
"a": "1",
"b": "2"
}
},
"put": {// all PUT requests
},
"put": {// all PUT requests
"file": "example1.json,
},
"post": "example3.json", // all POST requests
Expand Down Expand Up @@ -354,36 +352,15 @@ The mock configuration supports deep nested introspection of JSON and multi-part
If you omit the port, or set it to `0`, `@availity/mock-server` will let the OS assign a random open port.
This allows you to run multiple servers without keeping track of all ports being used. (see Example 2)
## Events
`@availity/mock-server` emits events to allow implementations to handle when specific events occur. Descriptions of the events are listed below.
* `av:start` - Triggered when the `@availity/mock-server` server has been started.
* `av:stop` - Triggered when the `@availity/mock-server` server has been stopped.
* `av:request` - Triggered when a request has been received.
* `av:response` - Triggered when a response file has been found for the requested route.
* `av:fileNotFound` - Triggered when a response file could not be found -- either as a of an undefined route or the route's response file could not be found.
* `av:redirect` - Triggered when a route specifies to redirect instead of responding with the contents of a file.
To add event handlers, register the events before starting the `@availity/mock-server` server.
```javascript
const server = new MockServer(configPath);

server.on('av:request', req => {
/* your logic here */
});

server.start();
```
## Acknowledgements
- [apimocker](https://github.com/gstroup/apimocker)
- [json-server](https://github.com/typicode/json-server)
* [apimocker](https://github.com/gstroup/apimocker)
* [json-server](https://github.com/typicode/json-server)
## Disclaimer
Open source software components distributed or made available in the Availity Materials are licensed to Company under the terms of the applicable open source license agreements, which may be found in text files included in the Availity Materials.
## License
[MIT](../../LICENSE)
12 changes: 0 additions & 12 deletions packages/mock-server/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,8 @@ class Configuration {
this.router = null;
this.routes = [];
this.cache = [];
this.events = null;
this.path = null;
this.addressInUse = null;

this.constants = {
EVENTS: {
START: 'av:started',
STOPPED: 'av:stopped',
REQUEST: 'av:request',
RESPONSE: 'av:response',
REDIRECT: 'av:redirect',
FILE_NOT_FOUND: 'av:fileNotFound'
}
};
}

/**
Expand Down
16 changes: 1 addition & 15 deletions packages/mock-server/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable promise/avoid-new */
const express = require('express');
const events = require('events');
const http = require('http');
const chalk = require('chalk');
const logger = require('./logger');
Expand All @@ -18,8 +17,6 @@ class Ekko {
this.middleware(ekkoConfig);
}
}

config.events = new events.EventEmitter();
}

middleware(options) {
Expand Down Expand Up @@ -47,11 +44,6 @@ class Ekko {
config.server.listen(config.options.port, host, () => {
const url = `http://${host}:${config.server.address().port}`;
logger.getInstance().info(`Ekko server started at ${chalk.green(url)}`);

config.events.emit(config.constants.EVENTS.START, {
options: config.options
});

resolve(true);
});

Expand All @@ -69,24 +61,18 @@ class Ekko {
});
}

stop() {
async stop() {
return new Promise(resolve => {
if (config.server && config.server.close) {
config.server.close(() => {
config.events.emit(config.constants.EVENTS.STOPPED);
resolve(true);
});
} else {
config.events.emit(config.constants.EVENTS.STOPPED);
resolve(true);
}
});
}

on(event, callback) {
return config.events.on(event, callback);
}

config() {
return config;
}
Expand Down
2 changes: 0 additions & 2 deletions packages/mock-server/middleware/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const config = require('../config');
const routes = require('../routes');
const logger = require('../logger').getInstance();

const requestHandler = require('./request');
const notFoundHandler = require('./not.found');

// Custom request logger
Expand All @@ -37,7 +36,6 @@ module.exports = function development() {
});
}

config.router.use(requestHandler());
config.router.use(errorhandler());
config.router.use(compression());
config.router.use(cors());
Expand Down
6 changes: 0 additions & 6 deletions packages/mock-server/middleware/not.found.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
const config = require('../config');

module.exports = function notfound() {
return (req, res) => {
res.status(404);

config.events.emit(config.constants.EVENTS.FILE_NOT_FOUND, {
req
});

const message = 'Not Found';

if (req.accepts('html')) {
Expand Down
11 changes: 0 additions & 11 deletions packages/mock-server/middleware/request.js

This file was deleted.

14 changes: 0 additions & 14 deletions packages/mock-server/middleware/tests/not.found.spec.js

This file was deleted.

14 changes: 0 additions & 14 deletions packages/mock-server/middleware/tests/request.spec.js

This file was deleted.

26 changes: 0 additions & 26 deletions packages/mock-server/response/result.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,13 @@ const result = {
if (err) {
logger.error(`NOT FOUND ${filePath} `);

config.events.emit(config.constants.EVENTS.FILE_NOT_FOUND, {
req
});

res.sendStatus(404);
} else {
const file = chalk.blue(filePath);
const relativeFile = path.relative(process.cwd(), file);

// Attach file path to response object for logging at the end of request cycle
res.avFile = relativeFile;

config.events.emit(config.constants.EVENTS.RESPONSE, {
req,
res: response,
file: filePath
});
}
});
},
Expand Down Expand Up @@ -58,19 +48,8 @@ const result = {
res.avFile = relativeFile;

res.status(status).json(json);

config.events.emit(config.constants.EVENTS.RESPONSE, {
req,
res: response,
file: filePath
});
} catch (err) {
logger.error(`NOT FOUND ${filePath} `);

config.events.emit(config.constants.EVENTS.FILE_NOT_FOUND, {
req
});

res.sendStatus(404);
}
},
Expand Down Expand Up @@ -106,11 +85,6 @@ const result = {
},

url(req, res, response) {
config.events.emit(config.constants.EVENTS.REDIRECT, {
req,
res: response
});

res.redirect(response.url);
},

Expand Down
18 changes: 0 additions & 18 deletions packages/mock-server/response/tests/behavior.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,4 @@ describe('Behavior', () => {
expect(err.status).toBe(404);
}
});

describe('Events', () => {
it('should emit file not found event when file does not exist', done => {
helper.ekko.on('av:fileNotFound', () => {
done();
});

request.get(helper.getUrl('/bad/file')).end();
});

it('should emit response event when file exists', done => {
helper.ekko.on('av:response', () => {
done();
});

request.get(helper.getUrl('/v1/route1')).end();
});
});
});
Loading

0 comments on commit 2cb477b

Please sign in to comment.