Skip to content

Commit

Permalink
Merge pull request #514 from wheresrhys/any
Browse files Browse the repository at this point in the history
Any
  • Loading branch information
wheresrhys committed Mar 14, 2020
2 parents 6428186 + 11abf0e commit 2555933
Show file tree
Hide file tree
Showing 16 changed files with 171 additions and 111 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ Mock http requests made using [fetch](https://developer.mozilla.org/en-US/docs/W
Features include:

- helpers for all common http methods and for responding a limited number of times
- declarative matching for most aspects of a http request
- declarative matching for most aspects of a http request
- delayed responses
- spying on real network requests
- support for advanced fetch behaviours, such as streaming responses and aborting

*New* If using jest, try the new [fetch-mock-jest](https://www.npmjs.com/package/fetch-mock-jest) wrapper.
_New_ If using jest, try the new [fetch-mock-jest](https://www.npmjs.com/package/fetch-mock-jest) wrapper.

![node version](https://img.shields.io/node/v/fetch-mock.svg?style=flat-square)
[![licence](https://img.shields.io/npm/l/fetch-mock.svg?style=flat-square)](https://github.com/wheresrhys/fetch-mock/blob/master/LICENSE)
Expand Down
2 changes: 1 addition & 1 deletion docs/_api-mocking/catch.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: ".catch(response)"
navTitle: .catch()
position: 5
position: 8
description: |-
Specifies how to respond to calls to `fetch` that don't match any mocks.
parentMethodGroup: mocking
Expand Down
8 changes: 8 additions & 0 deletions docs/_api-mocking/getAnyOnce_postAnyOnce.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: ".getAnyOnce(), .postAnyOnce(), .putAnyOnce(), .deleteAnyOnce(), .headAnyOnce(), .patchAnyOnce()"
navTitle: .getAnyOnce(), .postAnyOnce() ...
position: 7
description: |-
Shorthands for `anyOnce()` that only respond to requests using a particular http method.
parentMethodGroup: mocking
---
8 changes: 8 additions & 0 deletions docs/_api-mocking/getAny_postAny.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: ".getAny(), .postAny(), .putAny(), .deleteAny(), .headAny(), .patchAny()"
navTitle: .getAny(), .postAny() ...
position: 5.5
description: |-
Shorthands for `any()` that only respond to requests using a particular http method.
parentMethodGroup: mocking
---
2 changes: 1 addition & 1 deletion docs/_api-mocking/get_post.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: ".get(), .post(), .put(), .delete(), .head(), .patch()"
navTitle: .get(), .post() ...
position: 3
position: 2
description: |-
Shorthands for `mock()` that create routes that only respond to requests using a particular http method.
parentMethodGroup: mocking
Expand Down
2 changes: 1 addition & 1 deletion docs/_api-mocking/mock.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: ".mock(matcher, response, options)"
navTitle: .mock()
position: 1.0
position: 1
description: |
Initialises or extends a stub implementation of fetch, applying a `route` that matches `matcher`, delivers a `Response` configured using `response`, and that respects the additional `options`. The stub will record its calls so they can be inspected later. If `.mock` is called on the top level `fetch-mock` instance, this stub function will also replace `fetch` globally. Calling `.mock()` with no arguments will carry out this stubbing without defining any mock responses.
Expand Down
8 changes: 8 additions & 0 deletions docs/_api-mocking/mock_any.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: ".any(response, options)"
navTitle: .any()
position: 5
description: |-
Shorthand for `mock()` which creates a route that will return a response to any fetch request.
parentMethodGroup: mocking
---
8 changes: 8 additions & 0 deletions docs/_api-mocking/mock_any_once.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: ".anyOnce(response, options)"
navTitle: .anyOnce()
position: 6
description: |-
Shorthand for `mock()` which creates a route that will return a response to any single fetch request.
parentMethodGroup: mocking
---
2 changes: 1 addition & 1 deletion docs/_api-mocking/mock_once.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: ".once()"
position: 2
position: 3
description: |-
Shorthand for `mock()` which creates a route that can only mock a single request. (see `repeat` option above)
parentMethodGroup: mocking
Expand Down
2 changes: 1 addition & 1 deletion docs/_api-mocking/spy.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: ".spy()"
navTitle: .spy()
position: 6
position: 9
description: |-
Records call history while passing each call on to `fetch` to be handled by the network
parentMethodGroup: mocking
Expand Down
11 changes: 11 additions & 0 deletions src/lib/set-up-and-tear-down.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,22 @@ const defineShorthand = (methodName, underlyingMethod, shorthandOptions) => {
);
};
};

const defineGreedyShorthand = (methodName, underlyingMethod) => {
FetchMock[methodName] = function(response, options) {
return this[underlyingMethod]({}, response, options);
};
};

defineShorthand('once', 'mock', { repeat: 1 });
defineGreedyShorthand('any', 'mock');
defineGreedyShorthand('anyOnce', 'once');

['get', 'post', 'put', 'delete', 'head', 'patch'].forEach(method => {
defineShorthand(method, 'mock', { method });
defineShorthand(`${method}Once`, 'once', { method });
defineGreedyShorthand(`${method}Any`, method);
defineGreedyShorthand(`${method}AnyOnce`, `${method}Once`);
});

FetchMock.resetBehavior = function() {
Expand Down
1 change: 1 addition & 0 deletions test/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ module.exports = (fetchMock, theGlobal, fetch, AbortController) => {
require('./specs/custom-implementations.test')(fetchMock);
require('./specs/options.test')(fetchMock, theGlobal, fetch);
require('./specs/abortable.test')(fetchMock, AbortController);
require('./specs/shorthands.test')(fetchMock);
});
};
58 changes: 0 additions & 58 deletions test/specs/repeat.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,63 +226,5 @@ module.exports = fetchMock => {
expect(sb.done(matcher2)).to.be.true;
});
});

describe('strict matching shorthands', () => {
it('has once shorthand method', () => {
sinon.spy(fm, 'compileRoute');
fm['once']('a', 'b');
fm['once']('c', 'd', { opt: 'e' });
expect(
fm.compileRoute.calledWith([
'a',
'b',
{
repeat: 1
}
])
).to.be.true;
expect(
fm.compileRoute.calledWith([
'c',
'd',
{
opt: 'e',
repeat: 1
}
])
).to.be.true;
fm.compileRoute.restore();
});

'get,post,put,delete,head,patch'.split(',').forEach(method => {
it(`has once shorthand for ${method.toUpperCase()}`, () => {
sinon.spy(fm, 'compileRoute');
fm[method + 'Once']('a', 'b');
fm[method + 'Once']('c', 'd', { opt: 'e' });
expect(
fm.compileRoute.calledWith([
'a',
'b',
{
method: method,
repeat: 1
}
])
).to.be.true;
expect(
fm.compileRoute.calledWith([
'c',
'd',
{
opt: 'e',
method: method,
repeat: 1
}
])
).to.be.true;
fm.compileRoute.restore();
});
});
});
});
};
13 changes: 0 additions & 13 deletions test/specs/routing.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -544,19 +544,6 @@ module.exports = fetchMock => {
await fm.fetchHandler('http://domain.com/person', { method: 'POST' });
expect(fm.calls(true).length).to.equal(1);
});

['get', 'post', 'put', 'delete', 'head', 'patch'].forEach(method => {
it(`have shorthand method for ${method}`, async () => {
fm[method]('http://it.at.there/', 200).catch();

await fm.fetchHandler('http://it.at.there/', {
method: 'bad-method'
});
expect(fm.calls(true).length).to.equal(0);
await fm.fetchHandler('http://it.at.there/', { method });
expect(fm.calls(true).length).to.equal(1);
});
});
});

describe('body matching', () => {
Expand Down
33 changes: 0 additions & 33 deletions test/specs/set-up-and-tear-down.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,39 +109,6 @@ module.exports = fetchMock => {
});
});

describe('method shorthands', () => {
'get,post,put,delete,head,patch'.split(',').forEach(method => {
testChainableMethod(() => fm, method, [/a/, 200]);

it(`has shorthand for ${method.toUpperCase()}`, () => {
sinon.spy(fm, 'compileRoute');
fm[method]('a', 'b');
fm[method]('c', 'd', { opt: 'e' });
expect(fm.compileRoute).calledWith([
'a',
'b',
{
method: method
}
]);
expect(fm.compileRoute).calledWith([
'c',
'd',
{
opt: 'e',
method: method
}
]);
fm.compileRoute.restore();
fm.restore();
});

testChainableMethod(() => fm, `${method}Once`, [/a/, 200]);

// tests for behaviour of 'once' shorthands are in repeat.test.js
});
});

describe('reset', () => {
testChainableMethod(() => fm, 'reset');

Expand Down
120 changes: 120 additions & 0 deletions test/specs/shorthands.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
const chai = require('chai');
chai.use(require('sinon-chai'));
const expect = chai.expect;
const sinon = require('sinon');

const testChainableMethod = (getFetchMock, method, args = []) => {
it(`${method}() is chainable`, () => {
expect(getFetchMock()[method](...args)).to.equal(getFetchMock());
});

it(`${method}() has "this"`, () => {
sinon.spy(getFetchMock(), method);
getFetchMock()[method](...args);
expect(getFetchMock()[method].lastCall.thisValue).to.equal(getFetchMock());
getFetchMock()[method].restore();
});
};

module.exports = fetchMock => {
describe('shorthands', () => {
let fm;
let expectRoute;
before(() => {
fm = fetchMock.createInstance();
sinon.spy(fm, 'compileRoute');
fm.config.warnOnUnmatched = false;
expectRoute = (...args) => expect(fm.compileRoute).calledWith(args);
});
afterEach(() => {
fm.compileRoute.resetHistory();
fm.restore();
});

after(() => fm.compileRoute.restore());

it('has once() shorthand method', () => {
fm.once('a', 'b');
fm.once('c', 'd', { opt: 'e' });
expectRoute('a', 'b', {
repeat: 1
});
expectRoute('c', 'd', {
opt: 'e',
repeat: 1
});
});

it('has any() shorthand method', () => {
fm.any('a', { opt: 'b' });
expectRoute({}, 'a', {
opt: 'b'
});
});

it('has anyOnce() shorthand method', () => {
fm.anyOnce('a', { opt: 'b' });
expectRoute({}, 'a', {
opt: 'b',
repeat: 1
});
});

describe('method shorthands', () => {
['get', 'post', 'put', 'delete', 'head', 'patch'].forEach(method => {
describe(method.toUpperCase(), () => {
it(`has ${method}() shorthand`, () => {
fm[method]('a', 'b');
fm[method]('c', 'd', { opt: 'e' });
expectRoute('a', 'b', {
method: method
});
expectRoute('c', 'd', {
opt: 'e',
method: method
});
});

testChainableMethod(() => fm, method, [/a/, 200]);

it(`has ${method}Once() shorthand`, () => {
fm[method + 'Once']('a', 'b');
fm[method + 'Once']('c', 'd', { opt: 'e' });
expectRoute('a', 'b', {
method: method,
repeat: 1
});
expectRoute('c', 'd', {
opt: 'e',
method: method,
repeat: 1
});
});

testChainableMethod(() => fm, `${method}Once`, [/a/, 200]);

it(`has ${method}Any() shorthand`, () => {
fm[method + 'Any']('a', { opt: 'b' });
expectRoute({}, 'a', {
opt: 'b',
method: method
});
});

testChainableMethod(() => fm, `${method}Any`, [200]);

it(`has ${method}AnyOnce() shorthand`, () => {
fm[method + 'AnyOnce']('a', { opt: 'b' });
expectRoute({}, 'a', {
opt: 'b',
method: method,
repeat: 1
});
});

testChainableMethod(() => fm, `${method}Any`, [200]);
});
});
});
});
};

0 comments on commit 2555933

Please sign in to comment.