///
///
import configureStore from 'redux-mock-store'
import { middleware } from '../src';
const mockStore = configureStore([ middleware({}) ]);
const waitForResponse = () => new Promise((resolve, reject) => {
setTimeout(() => {
resolve({});
}, 10)
});
describe('redux-request-tracker middleware', () => {
it('should ignore actions that do not match the proper signature', () => {
const initialState = { request: {} };
const store = mockStore(initialState);
// Ignores other actions
const invalidAction1 = {
type: 'ANY_ACTION',
payload: 'Some non request tracker action'
};
// Ignores actions with proper named signature with improper values
const invalidAction2 = {
type: 'ANY_ACTION',
request: 5
};
// Ignores actions with that match but are not thenable (request must take a promise)
const invalidAction3 = {
type: 'ANY_ACTION',
request: () => {}
};
store.dispatch(invalidAction1);
store.dispatch(invalidAction2);
store.dispatch(invalidAction3);
// Equals the exact number of actions dispatched
expect(store.getActions().length).toEqual(3);
});
it('should process vaild request actions that match the proper signature', async () => {
const initialState = { request: {} };
const store = mockStore(initialState);
const validAction = {
type: 'ANY_ACTION',
request: Promise.resolve({
status: 200,
body: []
})
};
store.dispatch(validAction);
await waitForResponse();
// Equals track request + action + resolve request
expect(store.getActions().length).toEqual(3);
});
it('should trigger onFailure if the request failed', async () => {
const initialState = { request: {} };
const store = mockStore(initialState);
let onFailureTriggers = 0;
const action = {
type: 'ANY_ACTION',
request: new Promise((resolve, reject) => {
reject({ status: 401 });
}),
onFailure: (err) => { onFailureTriggers++; }
};
store.dispatch(action);
await waitForResponse();
expect(onFailureTriggers).toEqual(1);
});
it('should not trigger onSuccess if the request failed', async () => {
const initialState = { request: {} };
const store = mockStore(initialState);
let onFailureTriggers = 0;
let onSuccessTriggers = 0;
const action = {
type: 'ANY_ACTION',
request: new Promise((resolve, reject) => {
reject({ status: 401 });
}),
onSuccess: () => { onSuccessTriggers++; },
onFailure: (err) => { onFailureTriggers++; }
};
store.dispatch(action);
await waitForResponse();
expect(onFailureTriggers).toEqual(1);
expect(onSuccessTriggers).toEqual(0);
});
it('should trigger onSuccess if the request succeeded', async () => {
const initialState = { request: {} };
const store = mockStore(initialState);
let onSuccessTriggers = 0;
const action = {
type: 'ANY_ACTION',
request: new Promise((resolve, reject) => {
resolve({ status: 200 });
}),
onSuccess: () => { onSuccessTriggers++; }
};
store.dispatch(action);
await waitForResponse();
expect(onSuccessTriggers).toEqual(1);
});
it('should not trigger onFailure if the request succeeded', async () => {
const initialState = { request: {} };
const store = mockStore(initialState);
let onSuccessTriggers = 0;
let onFailureTriggers = 0;
const action = {
type: 'ANY_ACTION',
request: new Promise((resolve, reject) => {
resolve({ status: 200 });
}),
onSuccess: () => { onSuccessTriggers++; },
onFailure: () => { onFailureTriggers++; }
};
store.dispatch(action);
await waitForResponse();
expect(onSuccessTriggers).toEqual(1);
expect(onFailureTriggers).toEqual(0);
});
it('should trigger complete callback if the request succeeded or failed', async () => {
const initialState = { request: {} };
const store = mockStore(initialState);
let onSuccessTriggers = 0;
let onFailureTriggers = 0;
let completeTriggers = 0;
const actionSuccess = {
type: 'ANY_ACTION',
request: new Promise((resolve, reject) => {
resolve({ status: 200 });
}),
onSuccess: () => { onSuccessTriggers++; },
onFailure: () => { onFailureTriggers++; },
complete: () => { completeTriggers++ }
};
const actionFailure = {
type: 'ANY_ACTION',
request: new Promise((resolve, reject) => {
reject({ status: 401 });
}),
onSuccess: () => { onSuccessTriggers++; },
onFailure: () => { onFailureTriggers++; },
complete: () => { completeTriggers++ }
};
store.dispatch(actionSuccess);
await waitForResponse();
expect(onSuccessTriggers).toEqual(1);
expect(onFailureTriggers).toEqual(0);
expect(completeTriggers).toEqual(1);
store.dispatch(actionFailure);
await waitForResponse();
expect(onSuccessTriggers).toEqual(1);
expect(onFailureTriggers).toEqual(1);
expect(completeTriggers).toEqual(2);
});
it('should trigger onUnauthorized callback if the request failed with 401 and middle is built with onUnauthorized option', async () => {
let onFailureTriggers = 0;
let onUnauthorizedTriggers = 0;
const initialState = { request: {} };
const store = configureStore([ middleware({
onUnauthorized: () => { onUnauthorizedTriggers++; }
}) ])(initialState);
const action = {
type: 'ANY_ACTION',
request: new Promise((resolve, reject) => {
reject({ status: 401 });
}),
onFailure: () => { onFailureTriggers++; }
};
store.dispatch(action);
await waitForResponse();
expect(onFailureTriggers).toEqual(1);
expect(onUnauthorizedTriggers).toEqual(1);
});
});