debian-mirror-gitlab/spec/javascripts/diffs/components/app_spec.js

553 lines
15 KiB
JavaScript
Raw Normal View History

2019-02-15 15:39:39 +05:30
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
2019-07-07 11:18:12 +05:30
import { GlLoadingIcon } from '@gitlab/ui';
2018-12-05 23:21:45 +05:30
import { TEST_HOST } from 'spec/test_constants';
2020-01-01 13:55:28 +05:30
import Mousetrap from 'mousetrap';
2018-12-05 23:21:45 +05:30
import App from '~/diffs/components/app.vue';
2019-02-15 15:39:39 +05:30
import NoChanges from '~/diffs/components/no_changes.vue';
import DiffFile from '~/diffs/components/diff_file.vue';
2019-07-07 11:18:12 +05:30
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';
2018-12-05 23:21:45 +05:30
import createDiffsStore from '../create_diffs_store';
2019-07-07 11:18:12 +05:30
import diffsMockData from '../mock_data/merge_request_diffs';
const mergeRequestDiff = { version_index: 1 };
2018-12-05 23:21:45 +05:30
describe('diffs/components/app', () => {
const oldMrTabs = window.mrTabs;
2019-02-15 15:39:39 +05:30
let store;
2019-07-07 11:18:12 +05:30
let wrapper;
2018-12-05 23:21:45 +05:30
2019-02-15 15:39:39 +05:30
function createComponent(props = {}, extendStore = () => {}) {
const localVue = createLocalVue();
localVue.use(Vuex);
2018-12-05 23:21:45 +05:30
2019-02-15 15:39:39 +05:30
store = createDiffsStore();
2018-12-05 23:21:45 +05:30
store.state.diffs.isLoading = false;
2019-02-15 15:39:39 +05:30
extendStore(store);
2019-07-07 11:18:12 +05:30
wrapper = shallowMount(localVue.extend(App), {
2019-02-15 15:39:39 +05:30
localVue,
propsData: {
2018-12-05 23:21:45 +05:30
endpoint: `${TEST_HOST}/diff/endpoint`,
2020-01-01 13:55:28 +05:30
endpointMetadata: `${TEST_HOST}/diff/endpointMetadata`,
endpointBatch: `${TEST_HOST}/diff/endpointBatch`,
2018-12-05 23:21:45 +05:30
projectPath: 'namespace/project',
currentUser: {},
2019-02-15 15:39:39 +05:30
changesEmptyStateIllustration: '',
2019-09-04 21:01:54 +05:30
dismissEndpoint: '',
showSuggestPopover: true,
2020-01-01 13:55:28 +05:30
useSingleDiffStyle: false,
2019-02-15 15:39:39 +05:30
...props,
2018-12-05 23:21:45 +05:30
},
2019-02-15 15:39:39 +05:30
store,
2020-01-01 13:55:28 +05:30
methods: {
isLatestVersion() {
return true;
},
},
2018-12-05 23:21:45 +05:30
});
2019-02-15 15:39:39 +05:30
}
beforeEach(() => {
// setup globals (needed for component to mount :/)
window.mrTabs = jasmine.createSpyObj('mrTabs', ['resetViewContainer']);
window.mrTabs.expandViewContainer = jasmine.createSpy();
2018-12-05 23:21:45 +05:30
});
afterEach(() => {
// reset globals
window.mrTabs = oldMrTabs;
// reset component
2019-07-07 11:18:12 +05:30
wrapper.destroy();
});
2020-01-01 13:55:28 +05:30
describe('fetch diff methods', () => {
beforeEach(() => {
spyOn(window, 'requestIdleCallback').and.callFake(fn => fn());
createComponent();
spyOn(wrapper.vm, 'fetchDiffFiles').and.callFake(() => Promise.resolve());
spyOn(wrapper.vm, 'fetchDiffFilesMeta').and.callFake(() => Promise.resolve());
spyOn(wrapper.vm, 'fetchDiffFilesBatch').and.callFake(() => Promise.resolve());
spyOn(wrapper.vm, 'setDiscussions');
spyOn(wrapper.vm, 'startRenderDiffsQueue');
});
it('calls fetchDiffFiles if diffsBatchLoad is not enabled', done => {
wrapper.vm.glFeatures.diffsBatchLoad = false;
wrapper.vm.fetchData(false);
expect(wrapper.vm.fetchDiffFiles).toHaveBeenCalled();
setTimeout(() => {
expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesMeta).not.toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesBatch).not.toHaveBeenCalled();
done();
});
});
it('calls batch methods if diffsBatchLoad is enabled, and not latest version', () => {
wrapper.vm.glFeatures.diffsBatchLoad = true;
wrapper.vm.isLatestVersion = () => false;
wrapper.vm.fetchData(false);
expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
wrapper.vm.$nextTick(() => {
expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
});
});
it('calls batch methods if diffsBatchLoad is enabled, and latest version', () => {
wrapper.vm.glFeatures.diffsBatchLoad = true;
wrapper.vm.fetchData(false);
expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
wrapper.vm.$nextTick(() => {
expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
});
});
});
2019-07-07 11:18:12 +05:30
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;
2020-01-01 13:55:28 +05:30
});
expect(wrapper.contains(GlLoadingIcon)).toBe(true);
});
it('displays loading icon on batch loading', () => {
createComponent({}, ({ state }) => {
state.diffs.isBatchLoading = true;
2019-07-07 11:18:12 +05:30
});
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);
2018-12-05 23:21:45 +05:30
});
it('does not show commit info', () => {
2019-02-15 15:39:39 +05:30
createComponent();
2019-07-07 11:18:12 +05:30
expect(wrapper.contains('.blob-commit-info')).toBe(false);
});
describe('row highlighting', () => {
beforeEach(() => {
window.location.hash = 'ABC_123';
});
it('sets highlighted row if hash exists in location object', done => {
createComponent({
shouldShow: true,
});
// 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();
});
});
});
describe('resizable', () => {
afterEach(() => {
localStorage.removeItem('mr_tree_list_width');
});
it('sets initial width when no localStorage has been set', () => {
createComponent();
expect(wrapper.vm.treeWidth).toEqual(320);
});
it('sets initial width to localStorage size', () => {
localStorage.setItem('mr_tree_list_width', '200');
createComponent();
expect(wrapper.vm.treeWidth).toEqual(200);
});
it('sets width of tree list', () => {
createComponent();
expect(wrapper.find('.js-diff-tree-list').element.style.width).toEqual('320px');
});
2018-12-05 23:21:45 +05:30
});
2019-07-07 11:18:12 +05:30
it('marks current diff file based on currently highlighted row', done => {
2019-02-15 15:39:39 +05:30
createComponent({
shouldShow: true,
});
2018-12-05 23:21:45 +05:30
2019-02-15 15:39:39 +05:30
// Component uses $nextTick so we wait until that has finished
setTimeout(() => {
2019-07-07 11:18:12 +05:30
expect(store.state.diffs.currentDiffFileId).toBe('ABC');
2019-01-03 12:48:30 +05:30
2019-02-15 15:39:39 +05:30
done();
});
2019-01-03 12:48:30 +05:30
});
2019-02-15 15:39:39 +05:30
describe('empty state', () => {
it('renders empty state when no diff files exist', () => {
createComponent();
2019-07-07 11:18:12 +05:30
expect(wrapper.contains(NoChanges)).toBe(true);
2019-02-15 15:39:39 +05:30
});
it('does not render empty state when diff files exist', () => {
2019-07-07 11:18:12 +05:30
createComponent({}, ({ state }) => {
state.diffs.diffFiles.push({
2019-02-15 15:39:39 +05:30
id: 1,
});
});
2019-07-07 11:18:12 +05:30
expect(wrapper.contains(NoChanges)).toBe(false);
expect(wrapper.findAll(DiffFile).length).toBe(1);
2019-02-15 15:39:39 +05:30
});
it('does not render empty state when versions match', () => {
2019-07-07 11:18:12 +05:30
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();
2019-02-15 15:39:39 +05:30
createComponent({}, () => {
2019-07-07 11:18:12 +05:30
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;
2019-02-15 15:39:39 +05:30
});
2019-07-07 11:18:12 +05:30
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(toggleShowTreeList).not.toHaveBeenCalled();
2019-02-15 15:39:39 +05:30
});
2018-12-05 23:21:45 +05:30
});
});