import Vuex from 'vuex'; import { createLocalVue, shallowMount, mount } from '@vue/test-utils'; import Renamed from '~/vue_shared/components/diff_viewer/viewers/renamed.vue'; import { TRANSITION_LOAD_START, TRANSITION_LOAD_ERROR, TRANSITION_LOAD_SUCCEED, TRANSITION_ACKNOWLEDGE_ERROR, STATE_IDLING, STATE_LOADING, STATE_ERRORED, } from '~/diffs/constants'; const localVue = createLocalVue(); localVue.use(Vuex); function createRenamedComponent({ props = {}, methods = {}, store = new Vuex.Store({}), deep = false, }) { const mnt = deep ? mount : shallowMount; return mnt(Renamed, { propsData: { ...props }, localVue, store, methods, }); } describe('Renamed Diff Viewer', () => { const DIFF_FILE_COMMIT_SHA = 'commitsha'; const DIFF_FILE_SHORT_SHA = 'commitsh'; const DIFF_FILE_VIEW_PATH = `blob/${DIFF_FILE_COMMIT_SHA}/filename.ext`; let diffFile; let wrapper; beforeEach(() => { diffFile = { content_sha: DIFF_FILE_COMMIT_SHA, view_path: DIFF_FILE_VIEW_PATH, alternate_viewer: { name: 'text', }, }; }); afterEach(() => { if (wrapper) { wrapper.destroy(); wrapper = null; } }); describe('is', () => { beforeEach(() => { wrapper = createRenamedComponent({ props: { diffFile } }); }); it.each` state | request | result ${'idle'} | ${'idle'} | ${true} ${'idle'} | ${'loading'} | ${false} ${'idle'} | ${'errored'} | ${false} ${'loading'} | ${'loading'} | ${true} ${'loading'} | ${'idle'} | ${false} ${'loading'} | ${'errored'} | ${false} ${'errored'} | ${'errored'} | ${true} ${'errored'} | ${'idle'} | ${false} ${'errored'} | ${'loading'} | ${false} `( 'returns the $result for "$request" when the state is "$state"', ({ request, result, state }) => { wrapper.vm.state = state; expect(wrapper.vm.is(request)).toEqual(result); }, ); }); describe('transition', () => { beforeEach(() => { wrapper = createRenamedComponent({ props: { diffFile } }); }); it.each` state | transition | result ${'idle'} | ${TRANSITION_LOAD_START} | ${STATE_LOADING} ${'idle'} | ${TRANSITION_LOAD_ERROR} | ${STATE_IDLING} ${'idle'} | ${TRANSITION_LOAD_SUCCEED} | ${STATE_IDLING} ${'idle'} | ${TRANSITION_ACKNOWLEDGE_ERROR} | ${STATE_IDLING} ${'loading'} | ${TRANSITION_LOAD_START} | ${STATE_LOADING} ${'loading'} | ${TRANSITION_LOAD_ERROR} | ${STATE_ERRORED} ${'loading'} | ${TRANSITION_LOAD_SUCCEED} | ${STATE_IDLING} ${'loading'} | ${TRANSITION_ACKNOWLEDGE_ERROR} | ${STATE_LOADING} ${'errored'} | ${TRANSITION_LOAD_START} | ${STATE_LOADING} ${'errored'} | ${TRANSITION_LOAD_ERROR} | ${STATE_ERRORED} ${'errored'} | ${TRANSITION_LOAD_SUCCEED} | ${STATE_ERRORED} ${'errored'} | ${TRANSITION_ACKNOWLEDGE_ERROR} | ${STATE_IDLING} `( 'correctly updates the state to "$result" when it starts as "$state" and the transition is "$transition"', ({ state, transition, result }) => { wrapper.vm.state = state; wrapper.vm.transition(transition); expect(wrapper.vm.state).toEqual(result); }, ); }); describe('switchToFull', () => { let store; beforeEach(() => { store = new Vuex.Store({ modules: { diffs: { namespaced: true, actions: { switchToFullDiffFromRenamedFile: () => {} }, }, }, }); jest.spyOn(store, 'dispatch'); wrapper = createRenamedComponent({ props: { diffFile }, store }); }); afterEach(() => { store = null; }); it('calls the switchToFullDiffFromRenamedFile action when the method is triggered', () => { store.dispatch.mockResolvedValue(); wrapper.vm.switchToFull(); return wrapper.vm.$nextTick().then(() => { expect(store.dispatch).toHaveBeenCalledWith('diffs/switchToFullDiffFromRenamedFile', { diffFile, }); }); }); it.each` after | resolvePromise | resolution ${STATE_IDLING} | ${'mockResolvedValue'} | ${'successful'} ${STATE_ERRORED} | ${'mockRejectedValue'} | ${'rejected'} `( 'moves through the correct states during a $resolution request', ({ after, resolvePromise }) => { store.dispatch[resolvePromise](); expect(wrapper.vm.state).toEqual(STATE_IDLING); wrapper.vm.switchToFull(); expect(wrapper.vm.state).toEqual(STATE_LOADING); return ( wrapper.vm // This tick is needed for when the action (promise) finishes .$nextTick() // This tick waits for the state change in the promise .then/.catch to bubble into the component .then(() => wrapper.vm.$nextTick()) .then(() => { expect(wrapper.vm.state).toEqual(after); }) ); }, ); }); describe('clickLink', () => { let event; beforeEach(() => { event = { preventDefault: jest.fn(), }; }); it.each` alternateViewer | stops | handled ${'text'} | ${true} | ${'should'} ${'nottext'} | ${false} | ${'should not'} `( 'given { alternate_viewer: { name: "$alternateViewer" } }, the click event $handled be handled in the component', ({ alternateViewer, stops }) => { wrapper = createRenamedComponent({ props: { diffFile: { ...diffFile, alternate_viewer: { name: alternateViewer }, }, }, }); jest.spyOn(wrapper.vm, 'switchToFull').mockImplementation(() => {}); wrapper.vm.clickLink(event); if (stops) { expect(event.preventDefault).toHaveBeenCalled(); expect(wrapper.vm.switchToFull).toHaveBeenCalled(); } else { expect(event.preventDefault).not.toHaveBeenCalled(); expect(wrapper.vm.switchToFull).not.toHaveBeenCalled(); } }, ); }); describe('dismissError', () => { let transitionSpy; beforeEach(() => { wrapper = createRenamedComponent({ props: { diffFile } }); transitionSpy = jest.spyOn(wrapper.vm, 'transition'); }); it(`transitions the component with "${TRANSITION_ACKNOWLEDGE_ERROR}"`, () => { wrapper.vm.dismissError(); expect(transitionSpy).toHaveBeenCalledWith(TRANSITION_ACKNOWLEDGE_ERROR); }); }); describe('output', () => { it.each` altViewer | nameDisplay ${'text'} | ${'"text"'} ${'nottext'} | ${'"nottext"'} ${undefined} | ${undefined} ${null} | ${null} `( 'with { alternate_viewer: { name: $nameDisplay } }, renders the component', ({ altViewer }) => { const file = { ...diffFile }; file.alternate_viewer.name = altViewer; wrapper = createRenamedComponent({ props: { diffFile: file } }); expect(wrapper.find('[test-id="plaintext"]').text()).toEqual( 'File renamed with no changes.', ); }, ); it.each` altType | linkText ${'text'} | ${'Show file contents'} ${'nottext'} | ${`View file @ ${DIFF_FILE_SHORT_SHA}`} `( 'includes a link to the full file for alternate viewer type "$altType"', ({ altType, linkText }) => { const file = { ...diffFile }; const clickMock = jest.fn().mockImplementation(() => {}); file.alternate_viewer.name = altType; wrapper = createRenamedComponent({ deep: true, props: { diffFile: file }, methods: { clickLink: clickMock, }, }); const link = wrapper.find('a'); expect(link.text()).toEqual(linkText); expect(link.attributes('href')).toEqual(DIFF_FILE_VIEW_PATH); link.vm.$emit('click'); expect(clickMock).toHaveBeenCalled(); }, ); }); });