Commit 2e9a1608 authored by Simon Knox's avatar Simon Knox Committed by Andrew Fontaine

Allow passing named parameters to testAction function

This might need a better docstring update, could also
be done in a nicer way
parent 72fdd799
...@@ -4,7 +4,7 @@ const noop = () => {}; ...@@ -4,7 +4,7 @@ const noop = () => {};
* Helper for testing action with expected mutations inspired in * Helper for testing action with expected mutations inspired in
* https://vuex.vuejs.org/en/testing.html * https://vuex.vuejs.org/en/testing.html
* *
* @param {Function} action to be tested * @param {(Function|Object)} action to be tested, or object of named parameters
* @param {Object} payload will be provided to the action * @param {Object} payload will be provided to the action
* @param {Object} state will be provided to the action * @param {Object} state will be provided to the action
* @param {Array} [expectedMutations=[]] mutations expected to be committed * @param {Array} [expectedMutations=[]] mutations expected to be committed
...@@ -39,15 +39,42 @@ const noop = () => {}; ...@@ -39,15 +39,42 @@ const noop = () => {};
* [], // expected actions * [], // expected actions
* ).then(done) * ).then(done)
* .catch(done.fail); * .catch(done.fail);
*
* @example
* await testAction({
* action: actions.actionName,
* payload: { deleteListId: 1 },
* state: { lists: [1, 2, 3] },
* expectedMutations: [ { type: types.MUTATION} ],
* expectedActions: [],
* })
*/ */
export default ( export default (
action, actionArg,
payload, payloadArg,
state, stateArg,
expectedMutations = [], expectedMutationsArg = [],
expectedActions = [], expectedActionsArg = [],
done = noop, doneArg = noop,
) => { ) => {
let action = actionArg;
let payload = payloadArg;
let state = stateArg;
let expectedMutations = expectedMutationsArg;
let expectedActions = expectedActionsArg;
let done = doneArg;
if (typeof actionArg !== 'function') {
({
action,
payload,
state,
expectedMutations = [],
expectedActions = [],
done = noop,
} = actionArg);
}
const mutations = []; const mutations = [];
const actions = []; const actions = [];
......
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants'; import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import testAction from './vuex_action_helper'; import testActionFn from './vuex_action_helper';
describe('VueX test helper (testAction)', () => {
let originalExpect;
let assertion;
let mock;
const noop = () => {};
beforeEach(() => {
mock = new MockAdapter(axios);
/**
* In order to test the helper properly, we need to overwrite the Jest
* `expect` helper. We test that the testAction helper properly passes the
* dispatched actions/committed mutations to the Jest helper.
*/
originalExpect = expect;
assertion = null;
global.expect = actual => ({
toEqual: () => {
originalExpect(actual).toEqual(assertion);
},
});
});
afterEach(() => { const testActionFnWithOptionsArg = (...args) => {
mock.restore(); const [action, payload, state, expectedMutations, expectedActions, done] = args;
global.expect = originalExpect; return testActionFn({ action, payload, state, expectedMutations, expectedActions, done });
}); };
it('properly passes state and payload to action', () => { describe.each([testActionFn, testActionFnWithOptionsArg])(
const exampleState = { FOO: 12, BAR: 3 }; 'VueX test helper (testAction)',
const examplePayload = { BAZ: 73, BIZ: 55 }; testAction => {
let originalExpect;
let assertion;
let mock;
const noop = () => {};
const action = ({ state }, payload) => { beforeEach(() => {
originalExpect(state).toEqual(exampleState); mock = new MockAdapter(axios);
originalExpect(payload).toEqual(examplePayload); /**
}; * In order to test the helper properly, we need to overwrite the Jest
* `expect` helper. We test that the testAction helper properly passes the
* dispatched actions/committed mutations to the Jest helper.
*/
originalExpect = expect;
assertion = null;
global.expect = actual => ({
toEqual: () => {
originalExpect(actual).toEqual(assertion);
},
});
});
assertion = { mutations: [], actions: [] }; afterEach(() => {
mock.restore();
global.expect = originalExpect;
});
testAction(action, examplePayload, exampleState); it('properly passes state and payload to action', () => {
}); const exampleState = { FOO: 12, BAR: 3 };
const examplePayload = { BAZ: 73, BIZ: 55 };
describe('given a sync action', () => { const action = ({ state }, payload) => {
it('mocks committing mutations', () => { originalExpect(state).toEqual(exampleState);
const action = ({ commit }) => { originalExpect(payload).toEqual(examplePayload);
commit('MUTATION');
}; };
assertion = { mutations: [{ type: 'MUTATION' }], actions: [] }; assertion = { mutations: [], actions: [] };
testAction(action, null, {}, assertion.mutations, assertion.actions, noop); testAction(action, examplePayload, exampleState);
}); });
it('mocks dispatching actions', () => { describe('given a sync action', () => {
const action = ({ dispatch }) => { it('mocks committing mutations', () => {
dispatch('ACTION'); const action = ({ commit }) => {
}; commit('MUTATION');
};
assertion = { actions: [{ type: 'ACTION' }], mutations: [] }; assertion = { mutations: [{ type: 'MUTATION' }], actions: [] };
testAction(action, null, {}, assertion.mutations, assertion.actions, noop); testAction(action, null, {}, assertion.mutations, assertion.actions, noop);
}); });
it('works with done callback once finished', done => { it('mocks dispatching actions', () => {
assertion = { mutations: [], actions: [] }; const action = ({ dispatch }) => {
dispatch('ACTION');
};
testAction(noop, null, {}, assertion.mutations, assertion.actions, done); assertion = { actions: [{ type: 'ACTION' }], mutations: [] };
});
it('returns a promise', done => { testAction(action, null, {}, assertion.mutations, assertion.actions, noop);
assertion = { mutations: [], actions: [] }; });
testAction(noop, null, {}, assertion.mutations, assertion.actions) it('works with done callback once finished', done => {
.then(done) assertion = { mutations: [], actions: [] };
.catch(done.fail);
});
});
describe('given an async action (returning a promise)', () => {
let lastError;
const data = { FOO: 'BAR' };
const asyncAction = ({ commit, dispatch }) => {
dispatch('ACTION');
return axios
.get(TEST_HOST)
.catch(error => {
commit('ERROR');
lastError = error;
throw error;
})
.then(() => {
commit('SUCCESS');
return data;
});
};
beforeEach(() => { testAction(noop, null, {}, assertion.mutations, assertion.actions, done);
lastError = null; });
it('returns a promise', done => {
assertion = { mutations: [], actions: [] };
testAction(noop, null, {}, assertion.mutations, assertion.actions)
.then(done)
.catch(done.fail);
});
}); });
it('works with done callback once finished', done => { describe('given an async action (returning a promise)', () => {
mock.onGet(TEST_HOST).replyOnce(200, 42); let lastError;
const data = { FOO: 'BAR' };
assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] }; const asyncAction = ({ commit, dispatch }) => {
dispatch('ACTION');
testAction(asyncAction, null, {}, assertion.mutations, assertion.actions, done); return axios
}); .get(TEST_HOST)
.catch(error => {
commit('ERROR');
lastError = error;
throw error;
})
.then(() => {
commit('SUCCESS');
return data;
});
};
it('returns original data of successful promise while checking actions/mutations', done => { beforeEach(() => {
mock.onGet(TEST_HOST).replyOnce(200, 42); lastError = null;
});
assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] }; it('works with done callback once finished', done => {
mock.onGet(TEST_HOST).replyOnce(200, 42);
testAction(asyncAction, null, {}, assertion.mutations, assertion.actions) assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] };
.then(res => {
originalExpect(res).toEqual(data); testAction(asyncAction, null, {}, assertion.mutations, assertion.actions, done);
done(); });
})
.catch(done.fail); it('returns original data of successful promise while checking actions/mutations', done => {
}); mock.onGet(TEST_HOST).replyOnce(200, 42);
it('returns original error of rejected promise while checking actions/mutations', done => { assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] };
mock.onGet(TEST_HOST).replyOnce(500, '');
assertion = { mutations: [{ type: 'ERROR' }], actions: [{ type: 'ACTION' }] }; testAction(asyncAction, null, {}, assertion.mutations, assertion.actions)
.then(res => {
originalExpect(res).toEqual(data);
done();
})
.catch(done.fail);
});
testAction(asyncAction, null, {}, assertion.mutations, assertion.actions) it('returns original error of rejected promise while checking actions/mutations', done => {
.then(done.fail) mock.onGet(TEST_HOST).replyOnce(500, '');
.catch(error => {
originalExpect(error).toBe(lastError); assertion = { mutations: [{ type: 'ERROR' }], actions: [{ type: 'ACTION' }] };
done();
}); testAction(asyncAction, null, {}, assertion.mutations, assertion.actions)
.then(done.fail)
.catch(error => {
originalExpect(error).toBe(lastError);
done();
});
});
}); });
});
it('works with async actions not returning promises', done => { it('works with async actions not returning promises', done => {
const data = { FOO: 'BAR' }; const data = { FOO: 'BAR' };
const asyncAction = ({ commit, dispatch }) => { const asyncAction = ({ commit, dispatch }) => {
dispatch('ACTION'); dispatch('ACTION');
axios axios
.get(TEST_HOST) .get(TEST_HOST)
.then(() => { .then(() => {
commit('SUCCESS'); commit('SUCCESS');
return data; return data;
}) })
.catch(error => { .catch(error => {
commit('ERROR'); commit('ERROR');
throw error; throw error;
}); });
}; };
mock.onGet(TEST_HOST).replyOnce(200, 42); mock.onGet(TEST_HOST).replyOnce(200, 42);
assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] }; assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] };
testAction(asyncAction, null, {}, assertion.mutations, assertion.actions, done); testAction(asyncAction, null, {}, assertion.mutations, assertion.actions, done);
}); });
}); },
);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment