redux-observable-sans
Version:
Use redux without any boilerplate
264 lines (251 loc) • 9.22 kB
JavaScript
import { ActionsObservable, EPIC_END } from 'redux-observable';
import { Subject } from 'rxjs';
import { httpAction, httpEpic } from '../index';
import fetchMock from 'fetch-mock/es5/client';
describe('httpEpic', function () {
var dispatch = function dispatch(i) {
return i;
};
var url = 'localhost:3000';
var me = { token: 'key', name: 'AB Normal', userId: '3f43f' };
var state$ = { value: { me: me } };
var subject = void 0;
var action$ = void 0;
var testOutput = function testOutput(done, testFetch, expectedActions) {
var count = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
return function (action) {
expect(action).toEqual(expectedActions[count]);
count++;
if (count === expectedActions.length) {
testFetch();
done();
}
};
};
beforeEach(function () {
subject = new Subject();
action$ = new ActionsObservable(subject);
});
afterEach(function () {
fetchMock.restore();
});
it('basic GET', function (done) {
// values
var type = 'GET_WHAT';
var path = 'whats';
var method = 'GET';
var response = { what: 'evs'
// setup
};var httpAct = httpAction(dispatch)(type, path, method)();
var expectedActions = [{ type: type + '_REQUEST', payload: { body: undefined, method: method, url: url + '/' + path } }, { type: type + '_SUCCESS', payload: response }];
fetchMock.mock({
matcher: url + '/' + path,
method: method,
response: response
});
var testFetch = function testFetch() {
return expect(fetchMock.calls(url + '/' + path, method)).toEqual([[url + '/' + path, {
'headers': {
Accept: 'application/json',
'Content-Type': 'application/json'
},
method: method
}]]);
};
// run
var result$ = httpEpic({ url: url })(action$, state$);
result$.subscribe(testOutput(done, testFetch, expectedActions), console.error, console.error);
subject.next(httpAct);
});
it('POST with auth headers and id', function (done) {
// values
var id = 'GH'; // test addition of id
var setHeaders = function setHeaders(action$, deps) {
return {
Authorization: 'Bearer ' + action$.value.me.token
};
};
var type = 'SET_WHAT';
var path = 'whats';
var method = 'POST';
var body = { what: 'evs' };
var response = { yay: 'success'
// setup
};var httpAct = httpAction(dispatch, id)(type, path, method)(body);
var expectedActions = [{ type: type + '_REQUEST', payload: { body: body, method: method, url: url + '/' + path } }, { type: type + '_SUCCESS', payload: response }];
fetchMock.mock({
matcher: url + '/' + path,
method: method,
response: response
});
var testFetch = function testFetch() {
return expect(fetchMock.calls(url + '/' + path, method)).toEqual([[url + '/' + path, {
'headers': {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer key'
},
method: method,
body: JSON.stringify(body)
}]]);
};
// run
var options = { id: id, url: url, setHeaders: setHeaders };
var result$ = httpEpic(options)(action$, state$);
result$.subscribe(testOutput(done, testFetch, expectedActions), console.error, console.error);
subject.next(httpAct);
});
it('401 with extra action', function (done) {
// values
var id = 'LH';
var type = 'SET_WHAT';
var path = 'unauth';
var method = 'POST';
var body = { what: 'evs' };
var response = { status: 401, body: { error: 'no entry' }
// setup
};var httpAct = httpAction(dispatch, id)(type, path, method)(body);
var expectedActions = [{ type: type + '_REQUEST', payload: { body: body, method: method, url: url + '/' + path } }, { type: type + '_FAILURE', payload: response.body }, { type: 'HTTP_LH_UNAUTHORIZED', payload: { url: url + '/' + path, code: response.status, body: response.body } }];
fetchMock.mock({
matcher: url + '/' + path,
method: method,
response: response
});
var testFetch = function testFetch() {
return expect(fetchMock.calls(url + '/' + path, method)).toEqual([[url + '/' + path, {
'headers': {
Accept: 'application/json',
'Content-Type': 'application/json'
},
method: method,
body: JSON.stringify(body)
}]]);
};
// run
var result$ = httpEpic({ url: url, id: id })(action$, state$);
result$.subscribe(testOutput(done, testFetch, expectedActions), console.error, console.error);
subject.next(httpAct);
});
it('http error', function (done) {
// values
var id = 'LH';
var type = 'SET_WHAT';
var path = 'unauth';
var method = 'POST';
var body = { what: 'evs' };
var response = { status: 500, body: { error: 'no entry' }
// setup
};var httpAct = httpAction(dispatch, id)(type, path, method)(body);
var expectedActions = [{ type: type + '_REQUEST', payload: { body: body, method: method, url: url + '/' + path } }, { type: type + '_FAILURE', payload: response.body }, { type: 'HTTP_LH_ERROR', payload: { url: url + '/' + path, code: response.status, body: response.body } }];
fetchMock.mock({
matcher: url + '/' + path,
method: method,
response: response
});
var testFetch = function testFetch() {
return expect(fetchMock.calls(url + '/' + path, method)).toEqual([[url + '/' + path, {
'headers': {
Accept: 'application/json',
'Content-Type': 'application/json'
},
method: method,
body: JSON.stringify(body)
}]]);
};
// run
var result$ = httpEpic({ url: url, id: id })(action$, state$);
result$.subscribe(testOutput(done, testFetch, expectedActions), console.error, console.error);
subject.next(httpAct);
});
it('throws', function (done) {
// values
var type = 'SET_WHAT';
var path = 'throws';
var method = 'POST';
var body = { what: 'evs' };
var msg = 'none of that';
var response = function response() {
throw new Error(msg);
};
// setup
var httpAct = httpAction(dispatch)(type, path, method)(body);
var expectedActions = [{ type: type + '_REQUEST', payload: { body: body, method: method, url: url + '/' + path } }, { type: type + '_FAILURE' }, { type: 'HTTP_ERROR', payload: { url: url + '/' + path } }];
fetchMock.mock({
matcher: url + '/' + path,
method: method,
response: response
});
var testFetch = function testFetch() {
return expect(fetchMock.calls(url + '/' + path, method)).toEqual([[url + '/' + path, {
'headers': {
Accept: 'application/json',
'Content-Type': 'application/json'
},
method: method,
body: JSON.stringify(body)
}]]);
};
// run
var result$ = httpEpic({ url: url })(action$, state$);
result$.subscribe(testOutput(done, testFetch, expectedActions), console.error, console.error);
subject.next(httpAct);
});
it('EPIC_END causes _CANCELLED', function (done) {
// values
var type = 'GET_WHAT';
var path = 'whats';
var method = 'GET';
var response = { what: 'evs'
// setup
};var httpAct = httpAction(dispatch)(type, path, method)();
var expectedActions = [{ type: type + '_REQUEST', payload: { body: undefined, method: method, url: url + '/' + path } }, { type: type + '_CANCELLED' }];
fetchMock.mock({
matcher: url + '/' + path,
method: method,
response: response
});
var testFetch = function testFetch() {
return expect(fetchMock.calls(url + '/' + path, method)).toEqual([[url + '/' + path, {
'headers': {
Accept: 'application/json',
'Content-Type': 'application/json'
},
method: method
}]]);
};
// run
var result$ = httpEpic({ url: url })(action$, state$);
result$.subscribe(testOutput(done, testFetch, expectedActions), console.error, console.error);
subject.next(httpAct);
subject.next({ type: EPIC_END });
});
it('_CANCELLED', function (done) {
// values
var type = 'GET_WHAT';
var path = 'whats';
var method = 'GET';
var response = { what: 'evs'
// setup
};var httpAct = httpAction(dispatch)(type, path, method)();
var expectedActions = [{ type: type + '_REQUEST', payload: { body: undefined, method: method, url: url + '/' + path } }];
fetchMock.mock({
matcher: url + '/' + path,
method: method,
response: response
});
var testFetch = function testFetch() {
return expect(fetchMock.calls(url + '/' + path, method)).toEqual([[url + '/' + path, {
'headers': {
Accept: 'application/json',
'Content-Type': 'application/json'
},
method: method
}]]);
};
// run
var result$ = httpEpic({ url: url })(action$, state$);
result$.subscribe(testOutput(done, testFetch, expectedActions), console.error, console.error);
subject.next(httpAct);
subject.next({ type: type + '_CANLCELLED' });
});
});