Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ctimmerm committed Mar 23, 2016
1 parent fc2f7fb commit 9090a4e
Show file tree
Hide file tree
Showing 5 changed files with 308 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
npm-debug.log*
node_modules
82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
## Installation

Using npm:

`$ npm install axios-mock-adapter`

## Example

Mocking a `GET` request

```js
var axios = require('axios');
var MockAdapter = require('axios-mock-adapter');

// This sets the mock adapter on the default instance
var mock = new MockAdapter(axios);
// which is the same as:
// var mock = new MockAdapter();
// axios.defaults.adapter = mock.adapter();

mock.onGet('/users').reply(200, {
users: [
{ id: 1, name: 'John Smith' }
]
});

axios.get('/users')
.then(function(response) {
console.log(response.data);
});
```

Passing a function to `reply`

```js
mock.onGet('/users').reply(function(config) {
// `config` is the axios config and contains things like the url

// return an array in the form of [status, data, headers]
return [200, {
users: [
{ id: 1, name: 'John Smith' }
]
}];
});
```

Using a regex

```js
mock.onGet(/\/users\/\d+/).reply(function(config) {
// the actual id can be grabbed from config.url

return [200, {}];
});
```

### API

**mock.onGet(url)**

**mock.onHead(url)**

**mock.onPost(url)**

**mock.onPut(url)**

**mock.onPatch(url)**

**mock.onDelete(url)**

`url` can either be a string or a regex.

#### Sending a reply

**reply(status, data, headers)**

Or you can pass a function that returns an array in the shape of:
[status, data, headers]

**reply(function)**

58 changes: 58 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
var verbs = ['get', 'post', 'head', 'delete', 'patch', 'put'];

function findHandler(matchers, method, url) {
return matchers[method].find(function(matcher) {
if (typeof matcher[0] === 'string') {
return url === matcher[0];
} else if (matcher[0] instanceof RegExp) {
return matcher[0].test(url);
}
});
}

function adapter() {
return function(resolve, reject, config) {
var handler = findHandler(this.matchers, config.method, config.url);

if (handler) {
var response = (handler[1] instanceof Function)
? handler[1](config)
: handler.slice(1);
resolve({
status: response[0],
data: response[1],
headers: response[2],
config: config
});
} else {
reject({ status: 404, config: config });
}
}.bind(this);
}

function MockAdapter(axiosInstance) {
this.matchers = verbs.reduce(function(previousValue, currentValue) {
previousValue[currentValue] = [];
return previousValue;
}, {});

if (axiosInstance) {
axiosInstance.defaults.adapter = adapter.call(this);
}
}

MockAdapter.prototype.adapter = adapter;

verbs.forEach(function(method) {
var methodName = 'on' + method.charAt(0).toUpperCase() + method.slice(1);
MockAdapter.prototype[methodName] = function(matcher) {
var _this = this;
return {
reply: function reply(code, response, headers) {
_this.matchers[method].push([matcher, code, response, headers]);
}
};
};
});

module.exports = MockAdapter;
32 changes: 32 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "axios-mock-adapter",
"version": "1.0.0",
"description": "Axios adapter that allows to easily mock requests",
"main": "index.js",
"scripts": {
"test": "mocha"
},
"repository": {
"type": "git",
"url": "git+https://github.com/ctimmerm/axios-mock-adapter.git"
},
"keywords": [
"axios",
"test",
"mock",
"request",
"stub",
"adapter"
],
"author": "Colin Timmermans <colintimmermans@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/ctimmerm/axios-mock-adapter/issues"
},
"homepage": "https://github.com/ctimmerm/axios-mock-adapter#readme",
"devDependencies": {
"axios": "^0.9.1",
"chai": "^3.5.0",
"mocha": "^2.4.5"
}
}
134 changes: 134 additions & 0 deletions test/mock_adapter_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
var axios = require('axios');
var expect = require('chai').expect;

var MockAdapter = require('..');

describe('MockAdapter', function() {
var instance;
var mock;

beforeEach(function() {
instance = axios.create();
mock = new MockAdapter(instance);
});

it('correctly sets the adapter on the axios instance', function() {
expect(instance.defaults.adapter).to.exist;
});

it('supports all verbs', function() {
expect(mock.onGet).to.be.a('function');
expect(mock.onPost).to.be.a('function');
expect(mock.onPut).to.be.a('function');
expect(mock.onHead).to.be.a('function');
expect(mock.onDelete).to.be.a('function');
expect(mock.onPatch).to.be.a('function');
});

it('mocks requests', function(done) {
mock.onGet('/foo').reply(200, {
foo: 'bar'
});

instance.get('/foo')
.then(function(response) {
expect(response.status).to.equal(200);
expect(response.data.foo).to.equal('bar');
done();
});
});

it('exposes the adapter', function() {
expect(mock.adapter()).to.be.a('function');

instance.defaults.adapter = mock.adapter();

mock.onGet('/foo').reply(200, {
foo: 'bar'
});

instance.get('/foo')
.then(function(response) {
expect(response.status).to.equal(200);
expect(response.data.foo).to.equal('bar');
done();
});
});

it('can return headers', function(done) {
mock.onGet('/foo').reply(200, {}, {
foo: 'bar'
});

instance.get('/foo')
.then(function(response) {
expect(response.status).to.equal(200);
expect(response.headers.foo).to.equal('bar');
done();
});
});

it('accepts a callback that returns a response', function(done) {
mock.onGet('/foo').reply(function() {
return [200, { foo: 'bar' }];
});

instance.get('/foo')
.then(function(response) {
expect(response.status).to.equal(200);
expect(response.data.foo).to.equal('bar');
done();
});
});

it('matches on a regex', function(done) {
mock.onGet(/\/fo+/).reply(200);

instance.get('/foooooooooo')
.then(function() {
done()
});
});

it('passes the config to the callback', function(done) {
mock.onGet(/\/products\/\d+/).reply(function(config) {
return [200, {}, { RequestedURL: config.url }];
});

instance.get('/products/25')
.then(function(response) {
expect(response.headers.RequestedURL).to.equal('/products/25');
done();
});
});

it('handles post requests', function(done) {
mock.onPost('/foo').reply(function(config) {
return [200, JSON.parse(config.data).bar];
});

instance.post('/foo', { bar: 'baz' })
.then(function(response) {
expect(response.data).to.equal('baz');
done();
});
});

context('on the default instance', function() {
afterEach(function() {
axios.defaults.adapter = undefined;
});

it('mocks requests on the default instance', function(done) {
var defaultMock = new MockAdapter(axios);

defaultMock.onGet('/foo').reply(200);

axios.get('/foo')
.then(function(response) {
expect(response.status).to.equal(200);
done();
});
});
});
});

0 comments on commit 9090a4e

Please # to comment.