Skip to content

Commit 9090a4e

Browse files
committed
Initial commit
1 parent fc2f7fb commit 9090a4e

File tree

5 files changed

+308
-0
lines changed

5 files changed

+308
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
npm-debug.log*
2+
node_modules

README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
## Installation
2+
3+
Using npm:
4+
5+
`$ npm install axios-mock-adapter`
6+
7+
## Example
8+
9+
Mocking a `GET` request
10+
11+
```js
12+
var axios = require('axios');
13+
var MockAdapter = require('axios-mock-adapter');
14+
15+
// This sets the mock adapter on the default instance
16+
var mock = new MockAdapter(axios);
17+
// which is the same as:
18+
// var mock = new MockAdapter();
19+
// axios.defaults.adapter = mock.adapter();
20+
21+
mock.onGet('/users').reply(200, {
22+
users: [
23+
{ id: 1, name: 'John Smith' }
24+
]
25+
});
26+
27+
axios.get('/users')
28+
.then(function(response) {
29+
console.log(response.data);
30+
});
31+
```
32+
33+
Passing a function to `reply`
34+
35+
```js
36+
mock.onGet('/users').reply(function(config) {
37+
// `config` is the axios config and contains things like the url
38+
39+
// return an array in the form of [status, data, headers]
40+
return [200, {
41+
users: [
42+
{ id: 1, name: 'John Smith' }
43+
]
44+
}];
45+
});
46+
```
47+
48+
Using a regex
49+
50+
```js
51+
mock.onGet(/\/users\/\d+/).reply(function(config) {
52+
// the actual id can be grabbed from config.url
53+
54+
return [200, {}];
55+
});
56+
```
57+
58+
### API
59+
60+
**mock.onGet(url)**
61+
62+
**mock.onHead(url)**
63+
64+
**mock.onPost(url)**
65+
66+
**mock.onPut(url)**
67+
68+
**mock.onPatch(url)**
69+
70+
**mock.onDelete(url)**
71+
72+
`url` can either be a string or a regex.
73+
74+
#### Sending a reply
75+
76+
**reply(status, data, headers)**
77+
78+
Or you can pass a function that returns an array in the shape of:
79+
[status, data, headers]
80+
81+
**reply(function)**
82+

index.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
var verbs = ['get', 'post', 'head', 'delete', 'patch', 'put'];
2+
3+
function findHandler(matchers, method, url) {
4+
return matchers[method].find(function(matcher) {
5+
if (typeof matcher[0] === 'string') {
6+
return url === matcher[0];
7+
} else if (matcher[0] instanceof RegExp) {
8+
return matcher[0].test(url);
9+
}
10+
});
11+
}
12+
13+
function adapter() {
14+
return function(resolve, reject, config) {
15+
var handler = findHandler(this.matchers, config.method, config.url);
16+
17+
if (handler) {
18+
var response = (handler[1] instanceof Function)
19+
? handler[1](config)
20+
: handler.slice(1);
21+
resolve({
22+
status: response[0],
23+
data: response[1],
24+
headers: response[2],
25+
config: config
26+
});
27+
} else {
28+
reject({ status: 404, config: config });
29+
}
30+
}.bind(this);
31+
}
32+
33+
function MockAdapter(axiosInstance) {
34+
this.matchers = verbs.reduce(function(previousValue, currentValue) {
35+
previousValue[currentValue] = [];
36+
return previousValue;
37+
}, {});
38+
39+
if (axiosInstance) {
40+
axiosInstance.defaults.adapter = adapter.call(this);
41+
}
42+
}
43+
44+
MockAdapter.prototype.adapter = adapter;
45+
46+
verbs.forEach(function(method) {
47+
var methodName = 'on' + method.charAt(0).toUpperCase() + method.slice(1);
48+
MockAdapter.prototype[methodName] = function(matcher) {
49+
var _this = this;
50+
return {
51+
reply: function reply(code, response, headers) {
52+
_this.matchers[method].push([matcher, code, response, headers]);
53+
}
54+
};
55+
};
56+
});
57+
58+
module.exports = MockAdapter;

package.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"name": "axios-mock-adapter",
3+
"version": "1.0.0",
4+
"description": "Axios adapter that allows to easily mock requests",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "mocha"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/ctimmerm/axios-mock-adapter.git"
12+
},
13+
"keywords": [
14+
"axios",
15+
"test",
16+
"mock",
17+
"request",
18+
"stub",
19+
"adapter"
20+
],
21+
"author": "Colin Timmermans <colintimmermans@gmail.com>",
22+
"license": "MIT",
23+
"bugs": {
24+
"url": "https://github.com/ctimmerm/axios-mock-adapter/issues"
25+
},
26+
"homepage": "https://github.com/ctimmerm/axios-mock-adapter#readme",
27+
"devDependencies": {
28+
"axios": "^0.9.1",
29+
"chai": "^3.5.0",
30+
"mocha": "^2.4.5"
31+
}
32+
}

test/mock_adapter_test.js

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
var axios = require('axios');
2+
var expect = require('chai').expect;
3+
4+
var MockAdapter = require('..');
5+
6+
describe('MockAdapter', function() {
7+
var instance;
8+
var mock;
9+
10+
beforeEach(function() {
11+
instance = axios.create();
12+
mock = new MockAdapter(instance);
13+
});
14+
15+
it('correctly sets the adapter on the axios instance', function() {
16+
expect(instance.defaults.adapter).to.exist;
17+
});
18+
19+
it('supports all verbs', function() {
20+
expect(mock.onGet).to.be.a('function');
21+
expect(mock.onPost).to.be.a('function');
22+
expect(mock.onPut).to.be.a('function');
23+
expect(mock.onHead).to.be.a('function');
24+
expect(mock.onDelete).to.be.a('function');
25+
expect(mock.onPatch).to.be.a('function');
26+
});
27+
28+
it('mocks requests', function(done) {
29+
mock.onGet('/foo').reply(200, {
30+
foo: 'bar'
31+
});
32+
33+
instance.get('/foo')
34+
.then(function(response) {
35+
expect(response.status).to.equal(200);
36+
expect(response.data.foo).to.equal('bar');
37+
done();
38+
});
39+
});
40+
41+
it('exposes the adapter', function() {
42+
expect(mock.adapter()).to.be.a('function');
43+
44+
instance.defaults.adapter = mock.adapter();
45+
46+
mock.onGet('/foo').reply(200, {
47+
foo: 'bar'
48+
});
49+
50+
instance.get('/foo')
51+
.then(function(response) {
52+
expect(response.status).to.equal(200);
53+
expect(response.data.foo).to.equal('bar');
54+
done();
55+
});
56+
});
57+
58+
it('can return headers', function(done) {
59+
mock.onGet('/foo').reply(200, {}, {
60+
foo: 'bar'
61+
});
62+
63+
instance.get('/foo')
64+
.then(function(response) {
65+
expect(response.status).to.equal(200);
66+
expect(response.headers.foo).to.equal('bar');
67+
done();
68+
});
69+
});
70+
71+
it('accepts a callback that returns a response', function(done) {
72+
mock.onGet('/foo').reply(function() {
73+
return [200, { foo: 'bar' }];
74+
});
75+
76+
instance.get('/foo')
77+
.then(function(response) {
78+
expect(response.status).to.equal(200);
79+
expect(response.data.foo).to.equal('bar');
80+
done();
81+
});
82+
});
83+
84+
it('matches on a regex', function(done) {
85+
mock.onGet(/\/fo+/).reply(200);
86+
87+
instance.get('/foooooooooo')
88+
.then(function() {
89+
done()
90+
});
91+
});
92+
93+
it('passes the config to the callback', function(done) {
94+
mock.onGet(/\/products\/\d+/).reply(function(config) {
95+
return [200, {}, { RequestedURL: config.url }];
96+
});
97+
98+
instance.get('/products/25')
99+
.then(function(response) {
100+
expect(response.headers.RequestedURL).to.equal('/products/25');
101+
done();
102+
});
103+
});
104+
105+
it('handles post requests', function(done) {
106+
mock.onPost('/foo').reply(function(config) {
107+
return [200, JSON.parse(config.data).bar];
108+
});
109+
110+
instance.post('/foo', { bar: 'baz' })
111+
.then(function(response) {
112+
expect(response.data).to.equal('baz');
113+
done();
114+
});
115+
});
116+
117+
context('on the default instance', function() {
118+
afterEach(function() {
119+
axios.defaults.adapter = undefined;
120+
});
121+
122+
it('mocks requests on the default instance', function(done) {
123+
var defaultMock = new MockAdapter(axios);
124+
125+
defaultMock.onGet('/foo').reply(200);
126+
127+
axios.get('/foo')
128+
.then(function(response) {
129+
expect(response.status).to.equal(200);
130+
done();
131+
});
132+
});
133+
});
134+
});

0 commit comments

Comments
 (0)