import axios from '~/lib/utils/axios_utils'; import MockAdapter from 'axios-mock-adapter'; import actions, { transformBackendBadge } from '~/badges/store/actions'; import mutationTypes from '~/badges/store/mutation_types'; import createState from '~/badges/store/state'; import { DUMMY_IMAGE_URL, TEST_HOST } from 'spec/test_constants'; import { createDummyBadge, createDummyBadgeResponse } from '../dummy_badge'; fdescribe('Badges store actions', () => { const dummyEndpointUrl = `${TEST_HOST}/badges/endpoint`; const dummyBadges = [{ ...createDummyBadge(), id: 5 }, { ...createDummyBadge(), id: 6 }]; let axiosMock; let badgeCount; let badgeId; let store; beforeEach(() => { axiosMock = new MockAdapter(axios); store = { commit: jasmine.createSpy('commit'), dispatch: jasmine.createSpy('dispatch'), state: { ...createState(), apiEndpointUrl: dummyEndpointUrl, badges: dummyBadges, }, }; badgeCount = store.state.badges.length; badgeId = store.state.badges[0].id; }); afterEach(() => { axiosMock.restore(); }); describe('requestNewBadge', () => { it('commits REQUEST_NEW_BADGE', () => { actions.requestNewBadge(store); expect(store.commit).toHaveBeenCalledWith(mutationTypes.REQUEST_NEW_BADGE); }); }); describe('receiveNewBadge', () => { it('commits RECEIVE_NEW_BADGE', () => { const newBadge = createDummyBadge(); actions.receiveNewBadge(store, newBadge); expect(store.commit).toHaveBeenCalledWith(mutationTypes.RECEIVE_NEW_BADGE, newBadge); }); }); describe('receiveNewBadgeError', () => { it('commits RECEIVE_NEW_BADGE_ERROR', () => { actions.receiveNewBadgeError(store); expect(store.commit).toHaveBeenCalledWith(mutationTypes.RECEIVE_NEW_BADGE_ERROR); }); }); describe('addBadge', () => { let badgeInAddForm; let endpointMock; beforeEach(() => { badgeInAddForm = createDummyBadge(); endpointMock = axiosMock.onPost(dummyEndpointUrl); store.state = { ...store.state, badgeInAddForm, }; }); it('dispatches requestNewBadge and receiveNewBadge for successful response', done => { const dummyResponse = createDummyBadgeResponse(); endpointMock.replyOnce(req => { expect(req.data).toBe( JSON.stringify({ image_url: badgeInAddForm.imageUrl, link_url: badgeInAddForm.linkUrl, }), ); expect(store.dispatch).toHaveBeenCalledWith('requestNewBadge'); store.dispatch.calls.reset(); return [200, dummyResponse]; }); actions .addBadge(store) .then(() => { const dummyBadge = transformBackendBadge(dummyResponse); expect(store.dispatch).toHaveBeenCalledWith('receiveNewBadge', dummyBadge); }) .then(done) .catch(done.fail); }); it('dispatches requestNewBadge and receiveNewBadgeError for error response', done => { endpointMock.replyOnce(req => { expect(req.data).toBe( JSON.stringify({ image_url: badgeInAddForm.imageUrl, link_url: badgeInAddForm.linkUrl, }), ); expect(store.dispatch).toHaveBeenCalledWith('requestNewBadge'); store.dispatch.calls.reset(); return [500, '']; }); actions .addBadge(store) .then(() => done.fail('Promise should have thrown')) .catch(() => { expect(store.dispatch).toHaveBeenCalledWith('receiveNewBadgeError'); }) .then(done) .catch(done.fail); }); }); // TODO: describe('deleteBadge', () => { let deleteRequestMock; const findBadge = () => store.state.badges.find(b => b.id === badgeId); beforeEach(() => { deleteRequestMock = axiosMock.onDelete(`${dummyEndpointUrl}/${badgeId}`); }); it('removes badge on successful response', done => { expect(findBadge().isDeleting).toBe(false); deleteRequestMock.replyOnce(() => { expect(findBadge().isDeleting).toBe(true); return [204, '']; }); store .dispatch('deleteBadge', { id: badgeId }) .then(() => { const badges = store.state.badges; expect(badges.length).toBe(badgeCount - 1); expect(badges[0].id).not.toBe(badgeId); expect(findBadge()).toBe(undefined); }) .then(done) .catch(done.fail); }); it('does not remove badge on error response', done => { expect(findBadge().isDeleting).toBe(false); deleteRequestMock.replyOnce(() => { expect(findBadge().isDeleting).toBe(true); return [500, '']; }); store .dispatch('deleteBadge', { id: badgeId }) .then(() => done.fail('Promise should have thrown')) .catch(() => { const badges = store.state.badges; expect(badges.length).toBe(badgeCount); expect(badges[0].id).toBe(badgeId); expect(findBadge().isDeleting).toBe(false); }) .then(done) .catch(done.fail); }); }); describe('editBadge', () => { it('copies selected badge into edit form and sets isEditing to true', () => { expect(store.state.badgeInEditForm.id).not.toBe(badgeId); expect(store.state.isEditing).toBe(false); store.dispatch('editBadge', { id: badgeId }); expect(store.state.badgeInEditForm.id).toBe(badgeId); expect(store.state.isEditing).toBe(true); }); }); describe('stopEditing', () => { it('sets isEditing to false', () => { store.state.isEditing = true; store.dispatch('stopEditing'); expect(store.state.isEditing).toBe(false); }); }); describe('renderBadge', () => { beforeEach(() => { store.state.badgeInAddForm = createDummyBadge(); }); it('returns immediately if link_url is empty', done => { spyOn(axios, 'get'); store.state.badgeInAddForm.linkUrl = ''; store .dispatch('renderBadge') .then(done) .catch(done.fail); expect(axios.get).not.toHaveBeenCalled(); expect(store.state.isRendering).toBe(false); }); it('returns immediately if image_url is empty', done => { spyOn(axios, 'get'); store.state.badgeInAddForm.imageUrl = ''; store .dispatch('renderBadge') .then(done) .catch(done.fail); expect(axios.get).not.toHaveBeenCalled(); expect(store.state.isRendering).toBe(false); }); it('makes a request with escaped user values', done => { const dummyReponse = { ...createDummyBadgeResponse(), rendered_link_url: 'new badger', rendered_image_url: 'new image', }; const badge = store.state.badgeInAddForm; const renderUrl = `${dummyEndpointUrl}/render?link_url=${encodeURIComponent( badge.linkUrl, )}&image_url=${encodeURIComponent(badge.imageUrl)}`; axiosMock.onGet(renderUrl).replyOnce(() => { expect(store.state.isRendering).toBe(true); return [200, dummyReponse]; }); store .dispatch('renderBadge') .then(() => { const renderedBadge = store.state.renderedBadge; expect(renderedBadge.renderedLinkUrl).toEqual(dummyReponse.rendered_link_url); expect(renderedBadge.renderedImageUrl).toEqual(dummyReponse.rendered_image_url); expect(store.state.isRendering).toBe(false); }) .then(done) .catch(done.fail); }); }); describe('saveBadge', () => { const newImageUrl = `${DUMMY_IMAGE_URL}#new`; const oldImageUrl = `${DUMMY_IMAGE_URL}#old`; beforeEach(() => { store.state.badges[0].image_url = oldImageUrl; }); it('updates badge on successful response', done => { expect(store.state.badges.length).toBe(dummyBadges.length); expect(store.state.isSaving).toBe(false); expect(store.state.badges[0].image_url).toBe(oldImageUrl); store.state.badgeInEditForm = { ...store.state.badges[0], imageUrl: newImageUrl, }; axiosMock.onPut(`${dummyEndpointUrl}/${badgeId}`).replyOnce(req => { expect(store.state.isSaving).toBe(true); const requestData = JSON.parse(req.data); expect(requestData.image_url).toBe(newImageUrl); return [200, { ...createDummyBadgeResponse(), ...requestData, id: badgeId }]; }); store .dispatch('saveBadge', { id: badgeId }) .then(() => { expect(store.state.isSaving).toBe(false); expect(store.state.badges.length).toBe(dummyBadges.length); expect(store.state.badges[0].id).toBe(badgeId); expect(store.state.badges[0].imageUrl).toBe(newImageUrl); }) .then(done) .catch(done.fail); }); it('does not update on error response', done => { expect(store.state.badges.length).toBe(dummyBadges.length); expect(store.state.isSaving).toBe(false); expect(store.state.badges[0].id).toBe(badgeId); expect(store.state.badges[0].image_url).toBe(oldImageUrl); store.state.badgeInEditForm = { ...store.state.badges[0], image_url: newImageUrl, }; axiosMock.onPut(`${dummyEndpointUrl}/${badgeId}`).replyOnce(() => [500, '']); store .dispatch('saveBadge', { id: badgeId }) .then(() => done.fail('Promise should have thrown')) .catch(() => { expect(store.state.isSaving).toBe(false); expect(store.state.badges.length).toBe(dummyBadges.length); expect(store.state.badges[0].id).toBe(badgeId); expect(store.state.badges[0].image_url).toBe(oldImageUrl); done(); }); }); }); describe('loadBadges', () => { const docsUrl = `${TEST_HOST}/api/badges/new/url`; const newEndpointUrl = `${TEST_HOST}/docs/badges/new/url`; it('sets parameters and updates badges on successful response', done => { expect(store.state.badges.length).toBe(dummyBadges.length); expect(store.state.isLoading).toBe(false); expect(store.state.apiEndpointUrl).toBe(dummyEndpointUrl); const newBadges = [ { ...createDummyBadgeResponse(), id: 42 }, { ...createDummyBadgeResponse(), id: 43 }, { ...createDummyBadgeResponse(), id: 44 }, ]; axiosMock.onGet(newEndpointUrl).replyOnce(200, newBadges); store .dispatch('loadBadges', { kind: 'foo', apiEndpointUrl: newEndpointUrl, docsUrl, }) .then(() => { expect(store.state.isSaving).toBe(false); expect(store.state.badges.length).toBe(newBadges.length); expect(store.state.apiEndpointUrl).toBe(newEndpointUrl); expect(store.state.docsUrl).toBe(docsUrl); expect(store.state.kind).toBe('foo'); }) .then(done) .catch(done.fail); }); it('sets parameters and does not update badges on error response', done => { expect(store.state.badges.length).toBe(dummyBadges.length); expect(store.state.isLoading).toBe(false); expect(store.state.apiEndpointUrl).toBe(dummyEndpointUrl); axiosMock.onGet(newEndpointUrl).replyOnce(404, ''); store .dispatch('loadBadges', { kind: 'foo', apiEndpointUrl: newEndpointUrl, docsUrl, }) .then(() => done.fail('Promise should have thrown')) .catch(() => { expect(store.state.isSaving).toBe(false); expect(store.state.badges.length).toBe(dummyBadges.length); expect(store.state.apiEndpointUrl).toBe(newEndpointUrl); expect(store.state.docsUrl).toBe(docsUrl); expect(store.state.kind).toBe('foo'); done(); }); }); }); describe('updateBadgeInForm', () => { const dummyBadge = 'this is not a badge'; it('replaces badgeInAddForm if isEditing is false', () => { store.replaceState({ ...store.state, isEditing: false, badgeInAddForm: 'initial value', }); store.dispatch('updateBadgeInForm', dummyBadge); expect(store.state.badgeInAddForm).toBe(dummyBadge); }); it('replaces badgeInEditForm if isEditing is true', () => { store.replaceState({ ...store.state, isEditing: true, badgeInEditForm: 'initial value', }); store.dispatch('updateBadgeInForm', dummyBadge); expect(store.state.badgeInEditForm).toBe(dummyBadge); }); }); });