Skip to content

Commit

Permalink
beginning work on adding support for glob, path, end and begin (#145)
Browse files Browse the repository at this point in the history
* added end: and begin: keywords

* finished globa nad express path implementations

* documentation

* deprecation warning

* dryer
  • Loading branch information
wheresrhys authored Dec 18, 2016
1 parent 6ba388b commit d6b3d34
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 10 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,12 @@ Replaces `fetch()` with a stub which records its calls, grouped by route, and op
* `matcher`: Condition for selecting which requests to mock Accepts any of the following
* `string`: Either
* an exact url to match e.g. 'http://www.site.com/page.html'
* if the string begins with a `^`, the string following the `^` must begin the url e.g. '^http://www.site.com' would match 'http://www.site.com' or 'http://www.site.com/page.html'
* '*' to match any url
* `begin:http://www.site.com/` to match urls beginning with a string
* `end:.jpg` to match urls ending with a string
* `glob:http://*.*` to match glob patterns
* `express:/user/:user` to match [express style paths](https://www.npmjs.com/package/path-to-regexp)
* [deprecated] if the string begins with a `^`, the string following the `^` must begin the url e.g. '^http://www.site.com' would match 'http://www.site.com' or 'http://www.site.com/page.html'
* `RegExp`: A regular expression to test the url against
* `Function(url, opts)`: A function (returning a Boolean) that is passed the url and opts `fetch()` is called with (or, if `fetch()` was called with one, the `Request` instance)
* `response`: Configures the http response returned by the mock. Can take any of the following values (or be a `Promise` for any of them, enabling full control when testing race conditions etc.)
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
},
"homepage": "https://github.com/wheresrhys/fetch-mock",
"dependencies": {
"node-fetch": "^1.3.3"
"glob-to-regexp": "^0.3.0",
"node-fetch": "^1.3.3",
"path-to-regexp": "^1.7.0"
},
"devDependencies": {
"babel": "^6.0.15",
Expand Down
45 changes: 37 additions & 8 deletions src/compile-route.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
'use strict';
const glob = require('glob-to-regexp')
const express = require('path-to-regexp');

const stringMatchers = {
begin: targetString => {
return url => url.indexOf(targetString) === 0
},
end: targetString => {
return url => url.substr(-targetString.length) === targetString
},
glob: targetString => {
const urlRX = glob(targetString.replace(/^glob:/, ''))
return url => urlRX.test(url)
},
express: targetString => {
const urlRX = express(targetString.replace(/^express:/, ''))
return url => urlRX.test(url)
}
}

function getHeaderMatcher (expectedHeaders) {
const expectation = Object.keys(expectedHeaders).map(k => {
Expand Down Expand Up @@ -72,14 +91,24 @@ module.exports = function (route, Request) {

if (typeof route.matcher === 'string') {

if (route.matcher === '*') {
matchUrl = () => true;
} else if (route.matcher.indexOf('^') === 0) {
const expectedUrl = route.matcher.substr(1);
matchUrl = url => url.indexOf(expectedUrl) === 0;
} else {
const expectedUrl = route.matcher;
matchUrl = url => url === expectedUrl;
Object.keys(stringMatchers).some(name => {
if (route.matcher.indexOf(name + ':') === 0) {
const url = route.matcher.replace(new RegExp(`^${name}:`), '')
matchUrl = stringMatchers[name](url);
return true
}
})
if (!matchUrl) {
if (route.matcher === '*') {
matchUrl = () => true;
} else if (route.matcher.indexOf('^') === 0) {
console.warn('Using \'^\' to denote the start of a url is deprecated. Use \'begin:\' instead');
const expectedUrl = route.matcher.substr(1);
matchUrl = url => url.indexOf(expectedUrl) === 0;
} else {
const expectedUrl = route.matcher;
matchUrl = url => url === expectedUrl;
}
}
} else if (route.matcher instanceof RegExp) {
const urlRX = route.matcher;
Expand Down
76 changes: 76 additions & 0 deletions test/spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,82 @@ module.exports = (fetchMock, theGlobal, Request, Response) => {
});
});

describe('string matcher keywords', () => {
it('match begin: keyword', () => {
fetchMock.mock({
name: 'route',
matcher: 'begin:http://it.at.there',
response: 'ok'
}).catch();
return Promise.all([
fetch('http://it.at.there'),
fetch('http://it.at.thereabouts'),
fetch('http://it.at.hereabouts')
])
.then(function () {
expect(fetchMock.called('route')).to.be.true;
expect(fetchMock.calls('route').length).to.equal(2);
expect(fetchMock.calls('route')[0][0]).to.equal('http://it.at.there');
});
});

it('match end: keyword', () => {
fetchMock.mock({
name: 'route',
matcher: 'end:hereabouts',
response: 'ok'
}).catch();
return Promise.all([
fetch('http://it.at.there'),
fetch('http://it.at.thereabouts'),
fetch('http://it.at.hereabouts')
])
.then(function () {
expect(fetchMock.called('route')).to.be.true;
expect(fetchMock.calls('route').length).to.equal(2);
expect(fetchMock.calls('route')[0][0]).to.equal('http://it.at.thereabouts');
});
});

it('match glob: keyword', () => {
fetchMock.mock({
name: 'route',
matcher: 'glob:/its/*/*',
response: 'ok'
}).catch();
return Promise.all([
fetch('/its/a/boy'),
fetch('/its/a/girl'),
fetch('/its/alive')
])
.then(function () {
expect(fetchMock.called('route')).to.be.true;
expect(fetchMock.calls('route').length).to.equal(2);
expect(fetchMock.calls('route')[0][0]).to.equal('/its/a/boy');
});
});

it('match express: keyword', () => {
fetchMock.mock({
name: 'route',
matcher: 'express:/its/:word',
response: 'ok'
}).catch();
return Promise.all([
fetch('/its/a/boy'),
fetch('/its/a/girl'),
fetch('/its/alive')
])
.then(function () {
expect(fetchMock.called('route')).to.be.true;
expect(fetchMock.calls('route').length).to.equal(1);
expect(fetchMock.calls('route')[0][0]).to.equal('/its/alive');
});
});

});


it('match wildcard string', () => {
fetchMock.mock({
name: 'route',
Expand Down

0 comments on commit d6b3d34

Please sign in to comment.