diff options
Diffstat (limited to 'spec/javascripts/diffs/components/app_spec.js')
-rw-r--r-- | spec/javascripts/diffs/components/app_spec.js | 405 |
1 files changed, 382 insertions, 23 deletions
diff --git a/spec/javascripts/diffs/components/app_spec.js b/spec/javascripts/diffs/components/app_spec.js index 5abdfe695d0..1aabf3c2132 100644 --- a/spec/javascripts/diffs/components/app_spec.js +++ b/spec/javascripts/diffs/components/app_spec.js @@ -1,15 +1,24 @@ import Vuex from 'vuex'; import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { GlLoadingIcon } from '@gitlab/ui'; import { TEST_HOST } from 'spec/test_constants'; import App from '~/diffs/components/app.vue'; import NoChanges from '~/diffs/components/no_changes.vue'; import DiffFile from '~/diffs/components/diff_file.vue'; +import Mousetrap from 'mousetrap'; +import CompareVersions from '~/diffs/components/compare_versions.vue'; +import HiddenFilesWarning from '~/diffs/components/hidden_files_warning.vue'; +import CommitWidget from '~/diffs/components/commit_widget.vue'; +import TreeList from '~/diffs/components/tree_list.vue'; import createDiffsStore from '../create_diffs_store'; +import diffsMockData from '../mock_data/merge_request_diffs'; + +const mergeRequestDiff = { version_index: 1 }; describe('diffs/components/app', () => { const oldMrTabs = window.mrTabs; let store; - let vm; + let wrapper; function createComponent(props = {}, extendStore = () => {}) { const localVue = createLocalVue(); @@ -21,7 +30,7 @@ describe('diffs/components/app', () => { extendStore(store); - vm = shallowMount(localVue.extend(App), { + wrapper = shallowMount(localVue.extend(App), { localVue, propsData: { endpoint: `${TEST_HOST}/diff/endpoint`, @@ -38,7 +47,6 @@ describe('diffs/components/app', () => { // setup globals (needed for component to mount :/) window.mrTabs = jasmine.createSpyObj('mrTabs', ['resetViewContainer']); window.mrTabs.expandViewContainer = jasmine.createSpy(); - window.location.hash = 'ABC_123'; }); afterEach(() => { @@ -46,25 +54,85 @@ describe('diffs/components/app', () => { window.mrTabs = oldMrTabs; // reset component - vm.destroy(); + wrapper.destroy(); + }); + + it('adds container-limiting classes when showFileTree is false with inline diffs', () => { + createComponent({}, ({ state }) => { + state.diffs.showTreeList = false; + state.diffs.isParallelView = false; + }); + + expect(wrapper.contains('.container-limited.limit-container-width')).toBe(true); + }); + + it('does not add container-limiting classes when showFileTree is false with inline diffs', () => { + createComponent({}, ({ state }) => { + state.diffs.showTreeList = true; + state.diffs.isParallelView = false; + }); + + expect(wrapper.contains('.container-limited.limit-container-width')).toBe(false); + }); + + it('does not add container-limiting classes when isFluidLayout', () => { + createComponent({ isFluidLayout: true }, ({ state }) => { + state.diffs.isParallelView = false; + }); + + expect(wrapper.contains('.container-limited.limit-container-width')).toBe(false); + }); + + it('displays loading icon on loading', () => { + createComponent({}, ({ state }) => { + state.diffs.isLoading = true; + }); + + expect(wrapper.contains(GlLoadingIcon)).toBe(true); + }); + + it('displays diffs container when not loading', () => { + createComponent(); + + expect(wrapper.contains(GlLoadingIcon)).toBe(false); + expect(wrapper.contains('#diffs')).toBe(true); }); it('does not show commit info', () => { createComponent(); - expect(vm.contains('.blob-commit-info')).toBe(false); + expect(wrapper.contains('.blob-commit-info')).toBe(false); }); - it('sets highlighted row if hash exists in location object', done => { - createComponent({ - shouldShow: true, + describe('row highlighting', () => { + beforeEach(() => { + window.location.hash = 'ABC_123'; }); - // Component uses $nextTick so we wait until that has finished - setTimeout(() => { - expect(store.state.diffs.highlightedRow).toBe('ABC_123'); + it('sets highlighted row if hash exists in location object', done => { + createComponent({ + shouldShow: true, + }); - done(); + // Component uses $nextTick so we wait until that has finished + setTimeout(() => { + expect(store.state.diffs.highlightedRow).toBe('ABC_123'); + + done(); + }); + }); + + it('marks current diff file based on currently highlighted row', done => { + createComponent({ + shouldShow: true, + }); + + // Component uses $nextTick so we wait until that has finished + setTimeout(() => { + expect(store.state.diffs.currentDiffFileId).toBe('ABC'); + + done(); + }); }); }); @@ -76,7 +144,7 @@ describe('diffs/components/app', () => { it('sets initial width when no localStorage has been set', () => { createComponent(); - expect(vm.vm.treeWidth).toEqual(320); + expect(wrapper.vm.treeWidth).toEqual(320); }); it('sets initial width to localStorage size', () => { @@ -84,13 +152,26 @@ describe('diffs/components/app', () => { createComponent(); - expect(vm.vm.treeWidth).toEqual(200); + expect(wrapper.vm.treeWidth).toEqual(200); }); it('sets width of tree list', () => { createComponent(); - expect(vm.find('.js-diff-tree-list').element.style.width).toEqual('320px'); + expect(wrapper.find('.js-diff-tree-list').element.style.width).toEqual('320px'); + }); + }); + + it('marks current diff file based on currently highlighted row', done => { + createComponent({ + shouldShow: true, + }); + + // Component uses $nextTick so we wait until that has finished + setTimeout(() => { + expect(store.state.diffs.currentDiffFileId).toBe('ABC'); + + done(); }); }); @@ -98,27 +179,305 @@ describe('diffs/components/app', () => { it('renders empty state when no diff files exist', () => { createComponent(); - expect(vm.contains(NoChanges)).toBe(true); + expect(wrapper.contains(NoChanges)).toBe(true); }); it('does not render empty state when diff files exist', () => { - createComponent({}, () => { - store.state.diffs.diffFiles.push({ + createComponent({}, ({ state }) => { + state.diffs.diffFiles.push({ id: 1, }); }); - expect(vm.contains(NoChanges)).toBe(false); - expect(vm.findAll(DiffFile).length).toBe(1); + expect(wrapper.contains(NoChanges)).toBe(false); + expect(wrapper.findAll(DiffFile).length).toBe(1); }); it('does not render empty state when versions match', () => { + createComponent({}, ({ state }) => { + state.diffs.startVersion = mergeRequestDiff; + state.diffs.mergeRequestDiff = mergeRequestDiff; + }); + + expect(wrapper.contains(NoChanges)).toBe(false); + }); + }); + + describe('keyboard shortcut navigation', () => { + const mappings = { + '[': -1, + k: -1, + ']': +1, + j: +1, + }; + let spy; + + describe('visible app', () => { + beforeEach(() => { + spy = jasmine.createSpy('spy'); + + createComponent({ + shouldShow: true, + }); + wrapper.setMethods({ + jumpToFile: spy, + }); + }); + + it('calls `jumpToFile()` with correct parameter whenever pre-defined key is pressed', done => { + wrapper.vm + .$nextTick() + .then(() => { + Object.keys(mappings).forEach(function(key) { + Mousetrap.trigger(key); + + expect(spy.calls.mostRecent().args).toEqual([mappings[key]]); + }); + + expect(spy.calls.count()).toEqual(Object.keys(mappings).length); + }) + .then(done) + .catch(done.fail); + }); + + it('does not call `jumpToFile()` when unknown key is pressed', done => { + wrapper.vm + .$nextTick() + .then(() => { + Mousetrap.trigger('d'); + + expect(spy).not.toHaveBeenCalled(); + }) + .then(done) + .catch(done.fail); + }); + }); + + describe('hideen app', () => { + beforeEach(() => { + spy = jasmine.createSpy('spy'); + + createComponent({ + shouldShow: false, + }); + wrapper.setMethods({ + jumpToFile: spy, + }); + }); + + it('stops calling `jumpToFile()` when application is hidden', done => { + wrapper.vm + .$nextTick() + .then(() => { + Object.keys(mappings).forEach(function(key) { + Mousetrap.trigger(key); + + expect(spy).not.toHaveBeenCalled(); + }); + }) + .then(done) + .catch(done.fail); + }); + }); + }); + + describe('jumpToFile', () => { + let spy; + + beforeEach(() => { + spy = jasmine.createSpy(); + createComponent({}, () => { - store.state.diffs.startVersion = { version_index: 1 }; - store.state.diffs.mergeRequestDiff = { version_index: 1 }; + store.state.diffs.diffFiles = [ + { file_hash: '111', file_path: '111.js' }, + { file_hash: '222', file_path: '222.js' }, + { file_hash: '333', file_path: '333.js' }, + ]; + }); + + wrapper.setMethods({ + scrollToFile: spy, }); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('jumps to next and previous files in the list', done => { + wrapper.vm + .$nextTick() + .then(() => { + wrapper.vm.jumpToFile(+1); + + expect(spy.calls.mostRecent().args).toEqual(['222.js']); + store.state.diffs.currentDiffFileId = '222'; + wrapper.vm.jumpToFile(+1); + + expect(spy.calls.mostRecent().args).toEqual(['333.js']); + store.state.diffs.currentDiffFileId = '333'; + wrapper.vm.jumpToFile(-1); + + expect(spy.calls.mostRecent().args).toEqual(['222.js']); + }) + .then(done) + .catch(done.fail); + }); + + it('does not jump to previous file from the first one', done => { + wrapper.vm + .$nextTick() + .then(() => { + store.state.diffs.currentDiffFileId = '333'; + + expect(wrapper.vm.currentDiffIndex).toEqual(2); + + wrapper.vm.jumpToFile(+1); + + expect(wrapper.vm.currentDiffIndex).toEqual(2); + expect(spy).not.toHaveBeenCalled(); + }) + .then(done) + .catch(done.fail); + }); + + it('does not jump to next file from the last one', done => { + wrapper.vm + .$nextTick() + .then(() => { + expect(wrapper.vm.currentDiffIndex).toEqual(0); + + wrapper.vm.jumpToFile(-1); + + expect(wrapper.vm.currentDiffIndex).toEqual(0); + expect(spy).not.toHaveBeenCalled(); + }) + .then(done) + .catch(done.fail); + }); + }); + + describe('diffs', () => { + it('should render compare versions component', () => { + createComponent({}, ({ state }) => { + state.diffs.mergeRequestDiffs = diffsMockData; + state.diffs.targetBranchName = 'target-branch'; + state.diffs.mergeRequestDiff = mergeRequestDiff; + }); + + expect(wrapper.contains(CompareVersions)).toBe(true); + expect(wrapper.find(CompareVersions).props()).toEqual( + jasmine.objectContaining({ + targetBranch: { + branchName: 'target-branch', + versionIndex: -1, + path: '', + }, + mergeRequestDiffs: diffsMockData, + mergeRequestDiff, + }), + ); + }); + + it('should render hidden files warning if render overflow warning is present', () => { + createComponent({}, ({ state }) => { + state.diffs.renderOverflowWarning = true; + state.diffs.realSize = '5'; + state.diffs.plainDiffPath = 'plain diff path'; + state.diffs.emailPatchPath = 'email patch path'; + state.diffs.size = 1; + }); + + expect(wrapper.contains(HiddenFilesWarning)).toBe(true); + expect(wrapper.find(HiddenFilesWarning).props()).toEqual( + jasmine.objectContaining({ + total: '5', + plainDiffPath: 'plain diff path', + emailPatchPath: 'email patch path', + visible: 1, + }), + ); + }); + + it('should display commit widget if store has a commit', () => { + createComponent({}, () => { + store.state.diffs.commit = { + author: 'John Doe', + }; + }); + + expect(wrapper.contains(CommitWidget)).toBe(true); + }); + + it('should display diff file if there are diff files', () => { + createComponent({}, ({ state }) => { + state.diffs.diffFiles.push({ sha: '123' }); + }); + + expect(wrapper.contains(DiffFile)).toBe(true); + }); + + it('should render tree list', () => { + createComponent(); + + expect(wrapper.find(TreeList).exists()).toBe(true); + }); + }); + + describe('hideTreeListIfJustOneFile', () => { + let toggleShowTreeList; + + beforeEach(() => { + toggleShowTreeList = jasmine.createSpy('toggleShowTreeList'); + }); + + afterEach(() => { + localStorage.removeItem('mr_tree_show'); + }); + + it('calls toggleShowTreeList when only 1 file', () => { + createComponent({}, ({ state }) => { + state.diffs.diffFiles.push({ sha: '123' }); + }); + + wrapper.setMethods({ + toggleShowTreeList, + }); + + wrapper.vm.hideTreeListIfJustOneFile(); + + expect(toggleShowTreeList).toHaveBeenCalledWith(false); + }); + + it('does not call toggleShowTreeList when more than 1 file', () => { + createComponent({}, ({ state }) => { + state.diffs.diffFiles.push({ sha: '123' }); + state.diffs.diffFiles.push({ sha: '124' }); + }); + + wrapper.setMethods({ + toggleShowTreeList, + }); + + wrapper.vm.hideTreeListIfJustOneFile(); + + expect(toggleShowTreeList).not.toHaveBeenCalled(); + }); + + it('does not call toggleShowTreeList when localStorage is set', () => { + localStorage.setItem('mr_tree_show', 'true'); + + createComponent({}, ({ state }) => { + state.diffs.diffFiles.push({ sha: '123' }); + }); + + wrapper.setMethods({ + toggleShowTreeList, + }); + + wrapper.vm.hideTreeListIfJustOneFile(); - expect(vm.contains(NoChanges)).toBe(false); + expect(toggleShowTreeList).not.toHaveBeenCalled(); }); }); }); |