Skip to content

Commit

Permalink
feat: Custom persister support
Browse files Browse the repository at this point in the history
* feat: Custom persister support

* Create a @pollyjs/persister package
* Move out shared utils into their own @pollyjs/utils package
* Add support to register a custom persister (same way as an adapter)
* Add more tests

* docs: Custom adapter & persister docs

* test: Add custom persister test
  • Loading branch information
offirgolan authored and jasonmit committed Jun 16, 2018
1 parent 46bc3a2 commit 8bb313c
Show file tree
Hide file tree
Showing 50 changed files with 3,193 additions and 142 deletions.
2 changes: 2 additions & 0 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
- Adapters
- [XHR](adapters/xhr.md)
- [Fetch](adapters/fetch.md)
- [Custom](adapters/custom.md)

- Persisters
- [REST](persisters/rest.md)
- [Local Storage](persisters/local-storage.md)
- [Custom](persisters/custom.md)

- Frameworks
- [Ember CLI](frameworks/ember-cli.md)
Expand Down
99 changes: 99 additions & 0 deletions docs/adapters/custom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Custom Adapter

If you need to create your own adapter or modify an pre-existing one, you've come
to the right page!

## Creating a Custom Adapter

The `@pollyjs/adapter` package provides an extendable base adapter class that
contains core logic dependent on by the [Fetch](adapters/fetch)
& [XHR](adapters/xhr) adapters.

### Installation

_Note that you must have node (and npm) installed._

```bash
npm install @pollyjs/adapter -D
```

If you want to install it with [yarn](https://yarnpkg.com):

```bash
yarn add @pollyjs/adapter -D
```

### Usage

```js
import Adapter from '@pollyjs/adapter';

class CustomAdapter extends Adapter {
onConnect() {
/* Do something when the adapter is connect to */
}

onDisconnect() {
/* Do something when the adapter is disconnected from */
}

toString() {
return '[Adapter: CustomAdapter]';
}
}
```

For better usage examples, please refer to the source code for
the [Fetch](https://github.com/Netflix/pollyjs/blob/master/packages/%40pollyjs/core/src/adapters/fetch/index.js) & [XHR](https://github.com/Netflix/pollyjs/blob/master/packages/%40pollyjs/core/src/adapters/xhr/index.js) adapters.

## Extending from an Existing Adapter

The `@pollyjs/core` package exports the `XHRAdapter` and `FetchAdapter` classes,
allowing you to modify them as needed.

```js
import { XHRAdapter, FetchAdapter } from '@pollyjs/core';

class CustomXHRAdapter extends XHRAdapter {}
class CustomFetchAdapter extends FetchAdapter {}
```

## Registering & Connecting to a Custom Adapter

You can register and connect to a custom adapter by passing an array to the `adapters`
config where the first element is the name of your adapter and the second is the
adapter class.

```js
// Register and connect to a custom adapter:
new Polly('Custom Adapter', {
adapters: [
['my-custom-adapter', MyCustomAdapterClass]
]
});

// Register and connect to the default adapters + a custom adapter:
new Polly('Defaults + Custom Adapter', {
adapters: [
'fetch',
'xhr',
['my-custom-adapter', MyCustomAdapterClass]
]
});

// Register and connect to a custom fetch adapter:
new Polly('Custom Fetch Adapter', {
adapters: [
['fetch', MyCustomFetchAdapterClass]
]
});

// Register and connect to a custom adapter via .configure():
const polly = new Polly('Custom Adapter');

polly.configure({
adapters: [
['my-custom-adapter', MyCustomAdapterClass]
]
});
```
9 changes: 0 additions & 9 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,6 @@ polly.record();
polly.mode // → 'record'
```

### Modes

_Type_: `Object`

A static object of all the possible modes a polly can be in.

[modes.js](https://raw.githubusercontent.com/Netflix/pollyjs/master/packages/@pollyjs/core/src/defaults/modes.js ':include :type=code')


### persister

_Type_: `Persister`
Expand Down
75 changes: 75 additions & 0 deletions docs/persisters/custom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Custom Persister

If you need to create your own persister or modify an pre-existing one, you've come
to the right page!

## Creating a Custom Persister

The `@pollyjs/persister` package provides an extendable base persister class that
contains core logic dependent on by the [REST](persisters/rest)
& [Local Storage](persisters/local-storage) persisters.

### Installation

_Note that you must have node (and npm) installed._

```bash
npm install @pollyjs/persister -D
```

If you want to install it with [yarn](https://yarnpkg.com):

```bash
yarn add @pollyjs/persister -D
```

### Usage

```js
import Persister from '@pollyjs/persister';

class CustomPersister extends Persister {
findRecordingEntry() {}

findRecording() {}

saveRecording() {}

deleteRecording() {}
}
```

For better usage examples, please refer to the source code for
the [REST](https://github.com/Netflix/pollyjs/blob/master/packages/%40pollyjs/core/src/persisters/rest/index.js) & [Local Storage](https://github.com/Netflix/pollyjs/blob/master/packages/%40pollyjs/core/src/persisters/local-storage/index.js) persisters.

## Extending from an Existing Persister

The `@pollyjs/core` package exports the `RESTPersister` and `LocalStoragePersister` classes,
allowing you to modify them as needed.

```js
import { RESTPersister, LocalStoragePersister } from '@pollyjs/core';

class CustomRESTPersister extends RESTPersister {}
class CustomLocalStoragePersister extends LocalStoragePersister {}
```

## Registering & Connecting to a Custom Persister

You can register and connect to a custom persister by passing an array to the `persister`
config where the first element is the name of your persister and the second is the
persister class.

```js
// Register and connect to a custom persister:
new Polly('Custom Persister', {
persister: ['my-custom-persister', MyCustomPersisterClass]
});

// Register and connect to a custom persister via .configure():
const polly = new Polly('Custom Persister');

polly.configure({
persister: ['my-custom-persister', MyCustomPersisterClass]
});
```
2 changes: 1 addition & 1 deletion docs/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ yarn add @pollyjs/core -D

## Setup

In order write to disk, Polly makes networks requests to a local server which
In order to write to disk, Polly makes networks requests to a local server which
does all the heavy lifting. If you don't want to use the CLI and you have your
own express server, see the [Express Integrations](node-server/express-integrations)
documentation on integrating with your existing server.
Expand Down
2 changes: 1 addition & 1 deletion docs/test-helpers/mocha.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ stopped and destroyed produces the following error:
!> _You are trying to access an instance of Polly that is no longer available._
If you need do some work before the polly instance gets destroyed or just need more control on when each of the test hooks are called, `setupMocha` can be invoked as a function or accessed as an object with two methods: `setupMocha.beforeEach` and `setupMocha.afterEach`.
If you need to do some work before the polly instance gets destroyed or just need more control on when each of the test hooks are called, `setupMocha` can be invoked as a function or accessed as an object with two methods: `setupMocha.beforeEach` and `setupMocha.afterEach`.
Instead of calling `setupMocha()`, register these two hooks separately in the order that fits within your test.
Expand Down
2 changes: 1 addition & 1 deletion docs/test-helpers/qunit.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ stopped and destroyed produces the following error:
!> _You are trying to access an instance of Polly that is no longer available._
If you need do some work before the polly instance gets destroyed or just need more control on when each of the test hooks are called, `setupQunit` can be invoked as a function or accessed as an object with two methods: `setupQunit.beforeEach` and `setupQunit.afterEach`.
If you need to do some work before the polly instance gets destroyed or just need more control on when each of the test hooks are called, `setupQunit` can be invoked as a function or accessed as an object with two methods: `setupQunit.beforeEach` and `setupQunit.afterEach`.
Instead of calling `setupQunit()`, register these two hooks separately in the order that fits within your test.
Expand Down
7 changes: 6 additions & 1 deletion packages/@pollyjs/adapter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ If you want to install it with [yarn](https://yarnpkg.com):
yarn add @pollyjs/adapter -D
```

## Documentation

Check out the [Custom Adapter](https://netflix.github.io/pollyjs/#/adapters/custom)
documentation for more details.

## Usage

```js
Expand All @@ -45,7 +50,7 @@ class CustomAdapter extends Adapter {
}
```

For better usage details, please refer to the source code for
For better usage examples, please refer to the source code for
the [Fetch](https://github.com/Netflix/pollyjs/blob/master/packages/%40pollyjs/core/src/adapters/fetch/index.js) & [XHR](https://github.com/Netflix/pollyjs/blob/master/packages/%40pollyjs/core/src/adapters/xhr/index.js) adapters.

## License
Expand Down
3 changes: 3 additions & 0 deletions packages/@pollyjs/adapter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
}
],
"license": "Apache-2.0",
"dependencies": {
"@pollyjs/utils": "0.0.0"
},
"devDependencies": {
"eslint": "^4.19.1",
"npm-run-all": "^4.1.2",
Expand Down
19 changes: 7 additions & 12 deletions packages/@pollyjs/adapter/src/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import isExpired from './utils/is-expired';
import { ACTIONS, MODES, assert } from '@pollyjs/utils';

const REQUEST_HANDLER = Symbol();
const ACTIONS = {
RECORD: 'record',
REPLAY: 'replay',
INTERCEPT: 'intercept',
PASSTHROUGH: 'passthrough'
};

export default class Adapter {
constructor(polly) {
Expand Down Expand Up @@ -75,24 +70,24 @@ export default class Adapter {
}

async [REQUEST_HANDLER](request) {
const { mode, Modes } = this.polly;
const { mode } = this.polly;
const pollyRequest = this.polly.registerRequest(request);

await pollyRequest.setup();

if (mode === Modes.PASSTHROUGH || pollyRequest.shouldPassthrough) {
if (mode === MODES.PASSTHROUGH || pollyRequest.shouldPassthrough) {
return this.passthrough(pollyRequest);
}

if (pollyRequest.shouldIntercept) {
return this.intercept(pollyRequest);
}

if (mode === Modes.RECORD) {
if (mode === MODES.RECORD) {
return this.record(pollyRequest);
}

if (mode === Modes.REPLAY) {
if (mode === MODES.REPLAY) {
return this.replay(pollyRequest);
}

Expand Down Expand Up @@ -153,12 +148,12 @@ export default class Adapter {
}

assert(message, ...args) {
this.polly.assert(`${this} ${message}`, ...args);
assert(`${this} ${message}`, ...args);
}

toString() {
/* cannot use this.assert since `this` calls toString */
this.polly.assert('Must implement the the `toString` hook.', false);
assert('Must implement the the `toString` hook.', false);
}

onConnect() {
Expand Down
7 changes: 7 additions & 0 deletions packages/@pollyjs/adapter/tests/unit/adapter-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Adapter from '../../src';

describe('Unit | Adapter', function() {
it('should exist', function() {
expect(Adapter).to.be.a('function');
});
});
2 changes: 2 additions & 0 deletions packages/@pollyjs/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
"license": "Apache-2.0",
"dependencies": {
"@pollyjs/adapter": "^0.1.0",
"@pollyjs/persister": "0.0.0",
"@pollyjs/utils": "0.0.0",
"@sindresorhus/fnv1a": "^1.0.0",
"blueimp-md5": "^2.10.0",
"json-stable-stringify": "^1.0.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/@pollyjs/core/src/-private/container.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import assert from '../utils/assert';
import { assert } from '@pollyjs/utils';

export default class Container extends Map {
set(name, Type) {
Expand Down
18 changes: 10 additions & 8 deletions packages/@pollyjs/core/src/-private/logger.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
const ACTIONS = {
record: 'Recorded',
replay: 'Replayed',
intercept: 'Intercepted',
passthrough: 'Passthrough'
import { ACTIONS } from '@pollyjs/utils';

const FORMATTED_ACTIONS = {
[ACTIONS.RECORD]: 'Recorded',
[ACTIONS.REPLAY]: 'Replayed',
[ACTIONS.INTERCEPT]: 'Intercepted',
[ACTIONS.PASSTHROUGH]: 'Passthrough'
};

export default class Logger {
Expand Down Expand Up @@ -57,9 +59,9 @@ export default class Logger {

logRequest(request) {
this.log(
`${ACTIONS[request.action]}${request.method} ${request.url} ${
request.response.statusCode
}${request.responseTime}ms`,
`${FORMATTED_ACTIONS[request.action]}${request.method} ${
request.url
} ${request.response.statusCode} ${request.responseTime}ms`,
request
);
}
Expand Down
3 changes: 1 addition & 2 deletions packages/@pollyjs/core/src/-private/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ import URL from 'url-parse';
import stringify from 'json-stable-stringify';
import PollyResponse from './response';
import NormalizeRequest from '../utils/normalize-request';
import assert from '../utils/assert';
import timestamp from '../utils/timestamp';
import removeHostFromUrl from '../utils/remove-host-from-url';
import serializeRequestBody from '../utils/serialize-request-body';
import { assert, timestamp } from '@pollyjs/utils';

const { keys, freeze } = Object;

Expand Down
2 changes: 1 addition & 1 deletion packages/@pollyjs/core/src/-private/response.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import stringify from 'json-stable-stringify';
import assert from '../utils/assert';
import { assert } from '@pollyjs/utils';

const { freeze } = Object;

Expand Down
Loading

0 comments on commit 8bb313c

Please sign in to comment.