Skip to content

Commit

Permalink
feat(adapter-xhr): Support context option
Browse files Browse the repository at this point in the history
* feat(adapter-xhr): Support `context` option

* docs: Add the context option to the docs

* refactor: Use a WeakSet instead of IS_STUBBED
  • Loading branch information
offirgolan authored and jasonmit committed Jun 6, 2019
1 parent 7417627 commit 65b3c38
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 65 deletions.
22 changes: 22 additions & 0 deletions docs/adapters/xhr.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,25 @@ polly.connectTo('xhr');
// Disconnect using the `disconnectFrom` API
polly.disconnectFrom('xhr');
```

## Options

### context

_Type_: `Object`
_Default_: `global|self|window`

The context object which contains the XMLHttpRequest object. Typically this is `window` or `self` in the browser and `global` in node.

**Example**

```js
polly.configure({
adapters: ['xhr'],
adapterOptions: {
xhr: {
context: window
}
}
});
```
2 changes: 1 addition & 1 deletion packages/@pollyjs/adapter-xhr/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"dependencies": {
"@pollyjs/adapter": "^2.4.0",
"@pollyjs/utils": "^2.1.0",
"nise": "^1.4.6"
"nise": "^1.5.0"
},
"devDependencies": {
"@pollyjs/core": "^2.4.0",
Expand Down
30 changes: 20 additions & 10 deletions packages/@pollyjs/adapter-xhr/src/index.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
import FakeXHR from 'nise/lib/fake-xhr';
import fakeXhr from 'nise/lib/fake-xhr';
import Adapter from '@pollyjs/adapter';

import resolveXhr from './utils/resolve-xhr';
import serializeResponseHeaders from './utils/serialize-response-headers';

const SEND = Symbol();
const IS_STUBBED = Symbol();
const stubbedXhrs = new WeakSet();

export default class XHRAdapter extends Adapter {
static get name() {
return 'xhr';
}

get defaultOptions() {
return {
context: global
};
}

onConnect() {
this.assert('XHR global not found.', FakeXHR.xhr.supportsXHR);
const { context } = this.options;
const fakeXhrForContext = fakeXhr.fakeXMLHttpRequestFor(context);

this.assert('XHR global not found.', fakeXhrForContext.xhr.supportsXHR);
this.assert(
'Running concurrent XHR adapters is unsupported, stop any running Polly instances.',
!global.XMLHttpRequest[IS_STUBBED]
!stubbedXhrs.has(context.XMLHttpRequest)
);

this.native = global.XMLHttpRequest;
this.xhr = FakeXHR.useFakeXMLHttpRequest();
this.NativeXMLHttpRequest = context.XMLHttpRequest;
this.xhr = fakeXhrForContext.useFakeXMLHttpRequest();

this.xhr.onCreate = xhr => {
xhr[SEND] = xhr.send;
Expand All @@ -36,11 +45,13 @@ export default class XHRAdapter extends Adapter {
};
};

global.XMLHttpRequest[IS_STUBBED] = true;
stubbedXhrs.add(context.XMLHttpRequest);
}

onDisconnect() {
delete global.XMLHttpRequest[IS_STUBBED];
const { context } = this.options;

stubbedXhrs.delete(context.XMLHttpRequest);
this.xhr.restore();
}

Expand All @@ -62,8 +73,7 @@ export default class XHRAdapter extends Adapter {

async passthroughRequest(pollyRequest) {
const fakeXhr = pollyRequest.requestArguments.xhr;

const xhr = new this.native();
const xhr = new this.NativeXMLHttpRequest();

xhr.open(
pollyRequest.method,
Expand Down
85 changes: 65 additions & 20 deletions packages/@pollyjs/adapter-xhr/tests/integration/adapter-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import RESTPersister from '@pollyjs/persister-rest';
import xhrRequest from '../utils/xhr-request';
import XHRAdapter from '../../src';

class MockXMLHttpRequest {}

describe('Integration | XHR Adapter', function() {
setupPolly.beforeEach({
recordFailedRequests: true,
Expand All @@ -28,33 +30,76 @@ describe('Integration | XHR Adapter', function() {
adapterBrowserTests();
});

describe('Integration | XHR Adapter | Concurrency', function() {
it('should prevent concurrent XHR adapter instances', async function() {
const one = new Polly('one');
const two = new Polly('two');
describe('Integration | XHR Adapter | Init', function() {
describe('Context', function() {
it(`should assign context's XMLHttpRequest as the native XMLHttpRequest`, async function() {
const polly = new Polly('context', { adapters: [] });
const adapterOptions = {
xhr: {
context: { XMLHttpRequest: MockXMLHttpRequest }
}
};

polly.configure({
adapters: [XHRAdapter],
adapterOptions
});

one.connectTo(XHRAdapter);
expect(polly.adapters.get('xhr').NativeXMLHttpRequest).to.equal(
MockXMLHttpRequest
);
expect(polly.adapters.get('xhr').NativeXMLHttpRequest).to.not.equal(
adapterOptions.xhr.context.XMLHttpRequest
);

expect(function() {
two.connectTo(XHRAdapter);
}).to.throw(/Running concurrent XHR adapters is unsupported/);
expect(function() {
polly.configure({
adapterOptions: { xhr: { context: {} } }
});
}).to.throw(/XHR global not found/);

await one.stop();
await two.stop();
await polly.stop();
});
});

it('should allow you to register new instances once stopped', async function() {
const one = new Polly('one');
const two = new Polly('two');
describe('Concurrency', function() {
it('should prevent concurrent XHR adapter instances on the same context', async function() {
const one = new Polly('one');
const two = new Polly('two');
const three = new Polly('three', {
adapterOptions: {
xhr: {
context: { XMLHttpRequest: MockXMLHttpRequest }
}
}
});

one.connectTo(XHRAdapter);

expect(function() {
two.connectTo(XHRAdapter);
}).to.throw(/Running concurrent XHR adapters is unsupported/);

three.connectTo(XHRAdapter);

await one.stop();
await two.stop();
await three.stop();
});

it('should allow you to register new instances once stopped', async function() {
const one = new Polly('one');
const two = new Polly('two');

one.connectTo(XHRAdapter);
await one.stop();
one.connectTo(XHRAdapter);
await one.stop();

expect(function() {
two.connectTo(XHRAdapter);
}).to.not.throw();
expect(function() {
two.connectTo(XHRAdapter);
}).to.not.throw();

await one.stop();
await two.stop();
await one.stop();
await two.stop();
});
});
});
80 changes: 46 additions & 34 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1838,19 +1838,34 @@
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd"
integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==

"@sinonjs/formatio@3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.0.0.tgz#9d282d81030a03a03fa0c5ce31fd8786a4da311a"
integrity sha512-vdjoYLDptCgvtJs57ULshak3iJe4NW3sJ3g36xVDGff5AE8P30S6A093EIEPjdi2noGhfuNOEkbxt3J3awFW1w==
"@sinonjs/commons@^1", "@sinonjs/commons@^1.0.2":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.4.0.tgz#7b3ec2d96af481d7a0321252e7b1c94724ec5a78"
integrity sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==
dependencies:
"@sinonjs/samsam" "2.1.0"
type-detect "4.0.8"

"@sinonjs/[email protected]":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-2.1.0.tgz#b8b8f5b819605bd63601a6ede459156880f38ea3"
integrity sha512-5x2kFgJYupaF1ns/RmharQ90lQkd2ELS8A9X0ymkAAdemYHGtI2KiUHG8nX2WU0T1qgnOU5YMqnBM2V7NUanNw==
"@sinonjs/formatio@^3.1.0":
version "3.2.1"
resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.2.1.tgz#52310f2f9bcbc67bdac18c94ad4901b95fde267e"
integrity sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==
dependencies:
"@sinonjs/commons" "^1"
"@sinonjs/samsam" "^3.1.0"

"@sinonjs/samsam@^3.1.0":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.3.1.tgz#e88c53fbd9d91ad9f0f2b0140c16c7c107fe0d07"
integrity sha512-wRSfmyd81swH0hA1bxJZJ57xr22kC07a1N4zuIL47yTS04bDk6AoCkczcqHEjcRPmJ+FruGJ9WBQiJwMtIElFw==
dependencies:
"@sinonjs/commons" "^1.0.2"
array-from "^2.1.1"
lodash "^4.17.11"

"@sinonjs/text-encoding@^0.7.1":
version "0.7.1"
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==

"@types/[email protected]":
version "0.0.39"
Expand Down Expand Up @@ -9025,10 +9040,10 @@ jsx-ast-utils@^2.0.1:
dependencies:
array-includes "^3.0.3"

just-extend@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-3.0.0.tgz#cee004031eaabf6406da03a7b84e4fe9d78ef288"
integrity sha512-Fu3T6pKBuxjWT/p4DkqGHFRsysc8OauWr4ZRTY9dIx07Y9O0RkoR5jcv28aeD1vuAwhm3nLkDurwLXoALp4DpQ==
just-extend@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.0.2.tgz#f3f47f7dfca0f989c55410a7ebc8854b07108afc"
integrity sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==

[email protected]:
version "3.0.0"
Expand Down Expand Up @@ -9762,15 +9777,15 @@ lodash@^4.13.1, lodash@^4.17.10, lodash@^4.6.1:
version "4.17.10"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"

lodash@^4.17.4, lodash@^4.2.1, lodash@^4.3.0:
version "4.17.5"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"

lodash@^4.17.5:
lodash@^4.17.11, lodash@^4.17.5:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==

lodash@^4.17.4, lodash@^4.2.1, lodash@^4.3.0:
version "4.17.5"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"

log-symbols@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
Expand All @@ -9793,9 +9808,10 @@ log-update@^2.3.0:
cli-cursor "^2.0.0"
wrap-ansi "^3.0.1"

lolex@^2.3.2:
version "2.7.1"
resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.7.1.tgz#e40a8c4d1f14b536aa03e42a537c7adbaf0c20be"
lolex@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/lolex/-/lolex-4.1.0.tgz#ecdd7b86539391d8237947a3419aa8ac975f0fe1"
integrity sha512-BYxIEXiVq5lGIXeVHnsFzqa1TxN5acnKnPCdlZSpzm8viNEOhiigupA4vTQ9HEFQ6nLTQ9wQOgBknJgzUYQ9Aw==

[email protected]:
version "4.0.0"
Expand Down Expand Up @@ -10472,16 +10488,16 @@ nice-try@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4"

nise@^1.4.6:
version "1.4.6"
resolved "https://registry.yarnpkg.com/nise/-/nise-1.4.6.tgz#76cc3915925056ae6c405dd8ad5d12bde570c19f"
integrity sha512-1GedetLKzmqmgwabuMSqPsT7oumdR77SBpDfNNJhADRIeA3LN/2RVqR4fFqwvzhAqcTef6PPCzQwITE/YQ8S8A==
nise@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/nise/-/nise-1.5.0.tgz#d03ea0e6c1b75c638015aa3585eddc132949a50d"
integrity sha512-Z3sfYEkLFzFmL8KY6xnSJLRxwQwYBjOXi/24lb62ZnZiGA0JUzGGTI6TBIgfCSMIDl9Jlu8SRmHNACLTemDHww==
dependencies:
"@sinonjs/formatio" "3.0.0"
just-extend "^3.0.0"
lolex "^2.3.2"
"@sinonjs/formatio" "^3.1.0"
"@sinonjs/text-encoding" "^0.7.1"
just-extend "^4.0.2"
lolex "^4.1.0"
path-to-regexp "^1.7.0"
text-encoding "^0.6.4"

no-case@^2.2.0:
version "2.3.2"
Expand Down Expand Up @@ -13517,10 +13533,6 @@ testem@^2.14.0, testem@^2.9.2:
tmp "0.0.33"
xmldom "^0.1.19"

text-encoding@^0.6.4:
version "0.6.4"
resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19"

text-extensions@^1.0.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.7.0.tgz#faaaba2625ed746d568a23e4d0aacd9bf08a8b39"
Expand Down Expand Up @@ -13728,7 +13740,7 @@ type-check@~0.3.2:
dependencies:
prelude-ls "~1.1.2"

type-detect@^4.0.0, type-detect@^4.0.5:
type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5:
version "4.0.8"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"

Expand Down

0 comments on commit 65b3c38

Please sign in to comment.