Skip to content

Commit

Permalink
feat: Cleanup event handler logic + rename some event names
Browse files Browse the repository at this point in the history
  • Loading branch information
offirgolan committed Jun 13, 2018
1 parent 35ace6f commit 78dbb5d
Show file tree
Hide file tree
Showing 17 changed files with 134 additions and 149 deletions.
10 changes: 5 additions & 5 deletions docs/server/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ you can use to pass-through, intercept, and attach events to.
```js
server.get('/ping').passthrough();
server.put('/ping').intercept((req, res) => res.sendStatus(200));
server.post('/ping').on('beforeRequest', (req) => { /* Do Something */ });
server.patch('/ping').off('beforeRequest');
server.post('/ping').on('request', (req) => { /* Do Something */ });
server.patch('/ping').off('request');
```

## any
Expand All @@ -35,7 +35,7 @@ __Example__
```js
server
.any('/session/:id')
.on('beforeRequest', (req, res) => {
.on('request', (req, res) => {
req.query.email = '[email protected]';
});
```
Expand All @@ -51,7 +51,7 @@ server.host('http://netflix.com', () => {
// Middleware will be attached to the host
server
.any()
.on('beforeRequest', (req) => {});
.on('request', (req) => {});

server.get('/session').intercept(() => {}); // → http://netflix.com/session
});
Expand All @@ -68,7 +68,7 @@ server.namespace('/api', () => {
// Middleware will be attached to the namespace
server
.any()
.on('beforeRequest', (req) => {});
.on('request', (req) => {});

server.get('/session').intercept(() => {}); // → /api/session

Expand Down
24 changes: 12 additions & 12 deletions docs/server/events-and-middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ or a `Promise` can be returned.
// Events
server
.get('/')
.on('beforeRequest', req => {})
.off('beforeRequest');
.on('request', req => {})
.off('request');

// Passthrough w/ Events
server
Expand All @@ -25,17 +25,17 @@ server
// Intercept w/ Events
server
.get('/', (req, res) => {})
.on('beforeRequest', req => {})
.on('request', req => {})
.on('beforeResponse', (req, res) => {});

// Middleware w/ Events
server
.any('/')
.on('beforeRequest', req => {})
.on('request', req => {})
.on('beforeResponse', (req, res) => {});
```

### beforeRequest
### request

Fires right before the request goes out.

Expand All @@ -48,7 +48,7 @@ __Example__
```js
server
.get('/session')
.on('beforeRequest', req => {
.on('request', req => {
req.headers['X-AUTH'] = '<ACCESS_TOKEN>';
req.query.email = '[email protected]';
});
Expand All @@ -73,7 +73,7 @@ server
});
```

### afterResponse
### response

Fires right after the response has been finalized for the request but before
the response materializes and the promise resolves.
Expand All @@ -88,12 +88,12 @@ __Example__
```js
server
.get('/session')
.on('afterResponse', (req, res) => {
.on('response', (req, res) => {
console.log(`${req.url} took ${req.responseTime}ms with a status of ${res.statusCode}.`);
});
```

### beforeRecord
### beforePersist

Fires before the request/response gets persisted.

Expand All @@ -107,7 +107,7 @@ __Example__
```js
server
.any()
.on('beforeRecord', (req, recording) => {
.on('beforePersist', (req, recording) => {
recording.request = encrypt(recording.request);
recording.response = encrypt(recording.response);
});
Expand Down Expand Up @@ -149,7 +149,7 @@ routes. This middleware in specific overrides the `X-Auth-Token` with a test tok
```js
server
.any()
.on('beforeRequest', (req, res) => {
.on('request', (req, res) => {
req.headers['X-Auth-Token'] = 'abc123';
});
```
Expand All @@ -163,7 +163,7 @@ the email query param with that of a test email.
```js
server
.any('/session/:id')
.on('beforeRequest', (req, res) => {
.on('request', (req, res) => {
req.query.email = '[email protected]';
});
```
4 changes: 2 additions & 2 deletions docs/server/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const { server } = polly;
// Events & Middleware
server
.any()
.on('beforeRequest', (req, res) => {
.on('request', (req, res) => {
req.headers['X-Auth-Token'] = 'abc123';
});

Expand Down Expand Up @@ -65,5 +65,5 @@ __Example__
server.get(['/api/v2/users', '/api/v2/users/*path']).passthrough();

// Register the same event handler on both '/session' and '/users/session'
server.any(['/session', '/users/session']).on('beforeRequest', () => {});
server.any(['/session', '/users/session']).on('request', () => {});
```
12 changes: 6 additions & 6 deletions docs/server/route-handler.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ __Example__
```js
server
.get('/session')
.on('beforeRequest', req => {
.on('request', req => {
req.headers['X-AUTH'] = '<ACCESS_TOKEN>';
req.query.email = '[email protected]';
})
.on('beforeRequest', () => {/* Do something else */});
.on('request', () => {/* Do something else */});
```

### off
Expand All @@ -49,10 +49,10 @@ const handler = () => {};

server
.get('/session')
.on('beforeRequest', , handler)
.on('beforeRequest', () => {})
.off('beforeRequest', handler) /* Un-register the specified event/handler pair */
.off('beforeRequest'); /* Un-register all handlers */
.on('request', , handler)
.on('request', () => {})
.off('request', handler) /* Un-register the specified event/handler pair */
.off('request'); /* Un-register all handlers */
```

### intercept
Expand Down
4 changes: 2 additions & 2 deletions packages/@pollyjs/core/src/-private/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ export default class Logger {
connect() {
this._middleware = this.polly.server
.any()
.on('afterResponse', (...args) => this.logRequest(...args));
.on('response', (...args) => this.logRequest(...args));
}

disconnect() {
this.groupEnd();
this._middleware.off('afterResponse');
this._middleware.off('response');
}

console(method, ...args) {
Expand Down
12 changes: 6 additions & 6 deletions packages/@pollyjs/core/src/-private/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ export default class PollyRequest {
}

async setup() {
// Trigger the `beforeRequest` event
await this._trigger('beforeRequest');
// Trigger the `request` event
await this._trigger('request');

// Setup the response
this.response = new PollyResponse();
Expand Down Expand Up @@ -156,8 +156,8 @@ export default class PollyRequest {

this.didRespond = true;

// Trigger the `afterResponse` event
await this._trigger('afterResponse', this.response);
// Trigger the `response` event
await this._trigger('response', this.response);

freeze(this);
}
Expand All @@ -170,8 +170,8 @@ export default class PollyRequest {
return this[ROUTE].invoke(methodName, this, ...args);
}

_trigger(methodName, ...args) {
return this[ROUTE].trigger(methodName, this, ...args);
_trigger(eventName, ...args) {
return this[ROUTE].trigger(eventName, this, ...args);
}

_identify() {
Expand Down
4 changes: 2 additions & 2 deletions packages/@pollyjs/core/src/persisters/persister.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ export default class Persister {
entry.created_at = createdAt;

/*
Trigger the `beforeRecord` hook on each new recorded entry.
Trigger the `beforePersist` event on each new recorded entry.
NOTE: This must be triggered last as this entry can be used to
modify the payload (i.e. encrypting the request & response).
*/
await request._trigger('beforeRecord', entry);
await request._trigger('beforePersist', entry);
}

if (recording) {
Expand Down
2 changes: 1 addition & 1 deletion packages/@pollyjs/core/src/persisters/rest/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default class RestPersister extends Persister {

_normalize({ xhr, body }) {
/**
* 204 - No Content. Polly uses this status code in place of 404
* 204 - No Content. Polly uses this status code in place of 404
* when interacting with our Rest server to prevent throwing
* request errors in consumer's stdout (console.log)
*/
Expand Down
6 changes: 3 additions & 3 deletions packages/@pollyjs/core/src/server/events.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export default [
'beforeRequest',
'request',
'beforeReplay',
'beforeRecord',
'beforePersist',
'beforeResponse',
'afterResponse'
'response'
];
35 changes: 26 additions & 9 deletions packages/@pollyjs/core/src/server/handler.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import assert from '../utils/assert';
import Events from './events';

const EVENTS = Symbol();

function assertEventName(eventName) {
assert(
`Invalid event name provided. Expected string, received: "${typeof eventName}".`,
Expand All @@ -16,38 +18,53 @@ function assertEventName(eventName) {
}

export default class Handler extends Map {
constructor() {
super(...arguments);
this.set(EVENTS, new Map());
}

on(eventName, handler) {
assertEventName(eventName);

assert(
`Attempted to register ${eventName} but invalid handler provided. Expected function, received: "${typeof handler}".`,
`Attempted to register "${eventName}" but invalid handler provided. Expected function, received: "${typeof handler}".`,
typeof handler === 'function'
);

if (!this.has(eventName)) {
this.set(eventName, []);
const events = this.get(EVENTS);

if (!events.has(eventName)) {
events.set(eventName, []);
}

this.get(eventName).push(handler);
events.get(eventName).push(handler);

return this;
}

off(eventName, handler) {
assertEventName(eventName);

if (this.hasEvent(eventName)) {
const events = this.get(EVENTS);

if (this._hasEventHandlers(eventName)) {
if (typeof handler === 'function') {
this.set(eventName, this.get(eventName).filter(l => l !== handler));
events.set(eventName, events.get(eventName).filter(h => h !== handler));
} else {
this.delete(eventName);
events.delete(eventName);
}
}

return this;
}

hasEvent(eventName) {
return this.has(eventName) && this.get(eventName).length > 0;
_hasEventHandlers(eventName) {
return this._getEventHandlers(eventName).length > 0;
}

_getEventHandlers(eventName) {
const events = this.get(EVENTS);

return events.has(eventName) ? events.get(eventName) : [];
}
}
10 changes: 3 additions & 7 deletions packages/@pollyjs/core/src/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import buildUrl from '../utils/build-url';
import assert from '../utils/assert';
import timeout from '../utils/timeout';
import removeHostFromUrl from '../utils/remove-host-from-url';
import castArray from 'lodash-es/castArray';

const HOST = Symbol();
const NAMESPACES = Symbol();
Expand All @@ -19,7 +20,6 @@ const STAR = '*';
const METHODS = ['GET', 'PUT', 'POST', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];

const { keys } = Object;
const { isArray } = Array;

function parseUrl(url) {
const path = new URL(url);
Expand All @@ -33,10 +33,6 @@ function parseUrl(url) {
return { host, path: href };
}

function makeArray(a) {
return isArray(a) ? a : [a];
}

export default class Server {
constructor() {
this[HOST] = '';
Expand Down Expand Up @@ -112,7 +108,7 @@ export default class Server {
_register(method, routes) {
const handler = new RouteHandler();

makeArray(routes).forEach(route => {
castArray(routes).forEach(route => {
const { host, path } = parseUrl(this._buildUrl(route));
const registry = this._registryForHost(host);

Expand All @@ -126,7 +122,7 @@ export default class Server {
const handler = new Handler();
const pathsByHost = {};

makeArray(routes).forEach(route => {
castArray(routes).forEach(route => {
/*
If the route is a '*' or '' and there is no host or namespace
specified, treat the middleware as global so it will match all routes.
Expand Down
Loading

0 comments on commit 78dbb5d

Please sign in to comment.