Skip to content

Commit

Permalink
fix(core): Disconnect from all adapters when pause is called (#291)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Calling `polly.pause()` will now disconnect from all connected adapters instead of setting the mode to passthrough. Calling `polly.play()` will reconnect to the disconnected adapters before pause was called.
  • Loading branch information
offirgolan committed Jan 12, 2020
1 parent 92f05d2 commit 5c655bf
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 23 deletions.
41 changes: 32 additions & 9 deletions docs/api.md
Expand Up @@ -179,32 +179,55 @@ played back from a saved recording.
polly.replay();
```

### passthrough

Puts polly in pass-through mode. All requests going forward will pass-through
directly to the server without being recorded or replayed.

**Example**

```js
polly.passthrough();
```

### pause

Puts polly in a paused mode. All requests going forward will pass through
and will not be recorded or replayed. The previous mode will be saved and can
be restored by calling [play](api#play)
Disconnects the polly instance from all connected adapters. This ensures that
no requests will be handled by the polly instance until calling [play](api#play)
or manually connecting to a new adapter via [connectTo](api#connectTo). The
previously connected adapters will be saved and can be restored by
calling [play](api#play).

?> If using the [Puppeteer Adapter](adapters/puppeteer), you'll need to also
disable request interception via `await page.setRequestInterception(false)`.

**Example**

```js
// polly.mode === 'replay'
await fetch('/api/not-a-secret');
polly.pause();
// polly.mode === 'passthrough'
// This and all subsequent requests will no longer be handled by polly
await fetch('/api/secret');
```

### play

Restores the mode to the one before [pause](api#pause) was called.
Reconnects to the adapters that were disconnected when [pause](api#pause)
was called.

?> If using the [Puppeteer Adapter](adapters/puppeteer), you'll need to also
enable request interception via `await page.setRequestInterception(true)`.

**Example**

```js
// polly.mode === 'replay'
await fetch('/api/not-a-secret');
polly.pause();
// polly.mode === 'passthrough'
// This and all subsequent requests will no longer be handled by polly
await fetch('/api/secret');
polly.play();
// polly.mode === 'replay'
// This and all subsequent requests will again be handled by polly
await fetch('/api/not-a-secret');
```

### stop
Expand Down
Expand Up @@ -2,6 +2,7 @@ import { Polly, setupMocha as setupPolly } from '@pollyjs/core';
import { URL } from '@pollyjs/utils';
import setupFetchRecord from '@pollyjs-tests/helpers/setup-fetch-record';
import adapterTests from '@pollyjs-tests/integration/adapter-tests';
import adapterPollyTests from '@pollyjs-tests/integration/adapter-polly-tests';
import adapterBrowserTests from '@pollyjs-tests/integration/adapter-browser-tests';
import adapterIdentifierTests from '@pollyjs-tests/integration/adapter-identifier-tests';

Expand All @@ -19,6 +20,7 @@ describe('Integration | Fetch Adapter', function() {
setupPolly.afterEach();

adapterTests();
adapterPollyTests();
adapterBrowserTests();
adapterIdentifierTests();

Expand Down
Expand Up @@ -34,7 +34,7 @@ describe('Integration | Puppeteer Adapter', function() {
}
});

setupFetchRecord({ host: HOST });
setupFetchRecord.beforeEach({ host: HOST });

beforeEach(function() {
// Override this.fetch here since it needs access to the current context
Expand All @@ -55,6 +55,14 @@ describe('Integration | Puppeteer Adapter', function() {
});
});

afterEach(async function() {
// Turn off request interception before setupFetchRecord's afterEach so it
// can correctly do it's thing
await this.page.setRequestInterception(false);
});

setupFetchRecord.afterEach();

afterEach(async function() {
await this.page.close();
});
Expand Down
20 changes: 14 additions & 6 deletions packages/@pollyjs/core/src/polly.js
Expand Up @@ -14,7 +14,7 @@ import { validateRecordingName } from './utils/validators';

const RECORDING_NAME = Symbol();
const RECORDING_ID = Symbol();
const PAUSED_MODE = Symbol();
const PAUSED_ADAPTERS = Symbol();

const FACTORY_REGISTRATION = new WeakMap();
const EVENT_EMITTER = new EventEmitter({
Expand Down Expand Up @@ -202,19 +202,27 @@ export default class Polly {
* @public
* @memberof Polly
*/
pause() {
this[PAUSED_MODE] = this.mode;
passthrough() {
this.mode = MODES.PASSTHROUGH;
}

/**
* @public
* @memberof Polly
*/
pause() {
this[PAUSED_ADAPTERS] = [...this.adapters.keys()];
this.disconnect();
}

/**
* @public
* @memberof Polly
*/
play() {
if (this[PAUSED_MODE]) {
this.mode = this[PAUSED_MODE];
delete this[PAUSED_MODE];
if (this[PAUSED_ADAPTERS]) {
this[PAUSED_ADAPTERS].forEach(adapterName => this.connectTo(adapterName));
delete this[PAUSED_ADAPTERS];
}
}

Expand Down
49 changes: 42 additions & 7 deletions packages/@pollyjs/core/tests/unit/polly-test.js
Expand Up @@ -239,6 +239,21 @@ describe('Unit | Polly', function() {
describe('API', function() {
setupPolly();

class MockAdapterA extends Adapter {
static get name() {
return 'adapter-a';
}

onConnect() {}
onDisconnect() {}
}

class MockAdapterB extends MockAdapterA {
static get name() {
return 'adapter-b';
}
}

it('.record()', async function() {
this.polly.mode = MODES.REPLAY;

Expand All @@ -255,24 +270,44 @@ describe('Unit | Polly', function() {
expect(this.polly.mode).to.equal(MODES.REPLAY);
});

it('.pause()', async function() {
it('.passthrough()', async function() {
this.polly.mode = MODES.RECORD;

expect(this.polly.mode).to.equal(MODES.RECORD);
this.polly.pause();
this.polly.passthrough();
expect(this.polly.mode).to.equal(MODES.PASSTHROUGH);
});

it('.pause()', async function() {
this.polly.configure({ adapters: [MockAdapterA, MockAdapterB] });

expect([...this.polly.adapters.keys()]).to.deep.equal([
'adapter-a',
'adapter-b'
]);
this.polly.pause();
expect([...this.polly.adapters.keys()]).to.deep.equal([]);
});

it('.play()', async function() {
this.polly.mode = MODES.RECORD;
this.polly.configure({ adapters: [MockAdapterA, MockAdapterB] });

expect(this.polly.mode).to.equal(MODES.RECORD);
expect([...this.polly.adapters.keys()]).to.deep.equal([
'adapter-a',
'adapter-b'
]);
this.polly.play();
expect(this.polly.mode).to.equal(MODES.RECORD);
expect([...this.polly.adapters.keys()]).to.deep.equal([
'adapter-a',
'adapter-b'
]);
this.polly.pause();
expect(this.polly.mode).to.equal(MODES.PASSTHROUGH);
expect([...this.polly.adapters.keys()]).to.deep.equal([]);
this.polly.play();
expect(this.polly.mode).to.equal(MODES.RECORD);
expect([...this.polly.adapters.keys()]).to.deep.equal([
'adapter-a',
'adapter-b'
]);
});

it('.stop()', async function() {
Expand Down
22 changes: 22 additions & 0 deletions tests/integration/adapter-polly-tests.js
@@ -0,0 +1,22 @@
export default function pollyTests() {
it('should not handle any requests when paused', async function() {
const { server } = this.polly;
const requests = [];

server.any().on('request', req => requests.push(req));

await this.fetchRecord();
await this.fetchRecord();

this.polly.pause();
await this.fetchRecord();
await this.fetchRecord();

this.polly.play();
await this.fetchRecord();

expect(requests.length).to.equal(3);
expect(this.polly._requests.length).to.equal(3);
expect(requests.map(r => r.order)).to.deep.equal([0, 1, 2]);
});
}

0 comments on commit 5c655bf

Please sign in to comment.