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';
|
2020-04-08 14:13:33 +05:30
|
|
|
import MockAdapter from 'axios-mock-adapter';
|
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';
|
2020-03-13 15:44:24 +05:30
|
|
|
import { INLINE_DIFF_VIEW_TYPE, PARALLEL_DIFF_VIEW_TYPE } from '~/diffs/constants';
|
2018-12-05 23:21:45 +05:30
|
|
|
import createDiffsStore from '../create_diffs_store';
|
2020-04-08 14:13:33 +05:30
|
|
|
import axios from '~/lib/utils/axios_utils';
|
2019-07-07 11:18:12 +05:30
|
|
|
import diffsMockData from '../mock_data/merge_request_diffs';
|
|
|
|
|
|
|
|
const mergeRequestDiff = { version_index: 1 };
|
2020-04-08 14:13:33 +05:30
|
|
|
const TEST_ENDPOINT = `${TEST_HOST}/diff/endpoint`;
|
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;
|
2020-04-08 14:13:33 +05:30
|
|
|
let mock;
|
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: {
|
2020-04-08 14:13:33 +05:30
|
|
|
endpoint: TEST_ENDPOINT,
|
2020-01-01 13:55:28 +05:30
|
|
|
endpointMetadata: `${TEST_HOST}/diff/endpointMetadata`,
|
|
|
|
endpointBatch: `${TEST_HOST}/diff/endpointBatch`,
|
2020-04-08 14:13:33 +05:30
|
|
|
endpointCoverage: `${TEST_HOST}/diff/endpointCoverage`,
|
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,
|
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
|
|
|
}
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
function getOppositeViewType(currentViewType) {
|
|
|
|
return currentViewType === INLINE_DIFF_VIEW_TYPE
|
|
|
|
? PARALLEL_DIFF_VIEW_TYPE
|
|
|
|
: INLINE_DIFF_VIEW_TYPE;
|
|
|
|
}
|
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
beforeEach(() => {
|
|
|
|
// setup globals (needed for component to mount :/)
|
2020-04-08 14:13:33 +05:30
|
|
|
window.mrTabs = {
|
|
|
|
resetViewContainer: jest.fn(),
|
|
|
|
};
|
|
|
|
window.mrTabs.expandViewContainer = jest.fn();
|
|
|
|
mock = new MockAdapter(axios);
|
|
|
|
mock.onGet(TEST_ENDPOINT).reply(200, {});
|
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-04-08 14:13:33 +05:30
|
|
|
|
|
|
|
mock.restore();
|
2019-07-07 11:18:12 +05:30
|
|
|
});
|
|
|
|
|
2020-01-01 13:55:28 +05:30
|
|
|
describe('fetch diff methods', () => {
|
2020-03-13 15:44:24 +05:30
|
|
|
beforeEach(done => {
|
|
|
|
const fetchResolver = () => {
|
|
|
|
store.state.diffs.retrievingBatches = false;
|
|
|
|
store.state.notes.discussions = 'test';
|
|
|
|
return Promise.resolve({ real_size: 100 });
|
|
|
|
};
|
2020-04-08 14:13:33 +05:30
|
|
|
jest.spyOn(window, 'requestIdleCallback').mockImplementation(fn => fn());
|
2020-01-01 13:55:28 +05:30
|
|
|
createComponent();
|
2020-04-08 14:13:33 +05:30
|
|
|
jest.spyOn(wrapper.vm, 'fetchDiffFiles').mockImplementation(fetchResolver);
|
|
|
|
jest.spyOn(wrapper.vm, 'fetchDiffFilesMeta').mockImplementation(fetchResolver);
|
|
|
|
jest.spyOn(wrapper.vm, 'fetchDiffFilesBatch').mockImplementation(fetchResolver);
|
|
|
|
jest.spyOn(wrapper.vm, 'fetchCoverageFiles').mockImplementation(fetchResolver);
|
|
|
|
jest.spyOn(wrapper.vm, 'setDiscussions').mockImplementation(() => {});
|
|
|
|
jest.spyOn(wrapper.vm, 'startRenderDiffsQueue').mockImplementation(() => {});
|
|
|
|
jest.spyOn(wrapper.vm, 'unwatchDiscussions').mockImplementation(() => {});
|
|
|
|
jest.spyOn(wrapper.vm, 'unwatchRetrievingBatches').mockImplementation(() => {});
|
2020-03-13 15:44:24 +05:30
|
|
|
store.state.diffs.retrievingBatches = true;
|
|
|
|
store.state.diffs.diffFiles = [];
|
|
|
|
wrapper.vm.$nextTick(done);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when the diff view type changes and it should load a single diff view style', () => {
|
|
|
|
const noLinesDiff = {
|
|
|
|
highlighted_diff_lines: [],
|
|
|
|
parallel_diff_lines: [],
|
|
|
|
};
|
|
|
|
const parallelLinesDiff = {
|
|
|
|
highlighted_diff_lines: [],
|
|
|
|
parallel_diff_lines: ['line'],
|
|
|
|
};
|
|
|
|
const inlineLinesDiff = {
|
|
|
|
highlighted_diff_lines: ['line'],
|
|
|
|
parallel_diff_lines: [],
|
|
|
|
};
|
|
|
|
const fullDiff = {
|
|
|
|
highlighted_diff_lines: ['line'],
|
|
|
|
parallel_diff_lines: ['line'],
|
|
|
|
};
|
|
|
|
|
|
|
|
function expectFetchToOccur({
|
|
|
|
vueInstance,
|
|
|
|
done = () => {},
|
|
|
|
batch = false,
|
|
|
|
existingFiles = 1,
|
|
|
|
} = {}) {
|
|
|
|
vueInstance.$nextTick(() => {
|
|
|
|
expect(vueInstance.diffFiles.length).toEqual(existingFiles);
|
|
|
|
|
|
|
|
if (!batch) {
|
|
|
|
expect(vueInstance.fetchDiffFiles).toHaveBeenCalled();
|
|
|
|
expect(vueInstance.fetchDiffFilesBatch).not.toHaveBeenCalled();
|
|
|
|
} else {
|
|
|
|
expect(vueInstance.fetchDiffFiles).not.toHaveBeenCalled();
|
|
|
|
expect(vueInstance.fetchDiffFilesBatch).toHaveBeenCalled();
|
|
|
|
}
|
|
|
|
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
wrapper.vm.glFeatures.singleMrDiffView = true;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('fetches diffs if it has none', done => {
|
|
|
|
wrapper.vm.isLatestVersion = () => false;
|
|
|
|
|
|
|
|
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
|
|
|
|
|
|
|
|
expectFetchToOccur({ vueInstance: wrapper.vm, batch: false, existingFiles: 0, done });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('fetches diffs if it has both view styles, but no lines in either', done => {
|
|
|
|
wrapper.vm.isLatestVersion = () => false;
|
|
|
|
|
|
|
|
store.state.diffs.diffFiles.push(noLinesDiff);
|
|
|
|
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
|
|
|
|
|
|
|
|
expectFetchToOccur({ vueInstance: wrapper.vm, done });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('fetches diffs if it only has inline view style', done => {
|
|
|
|
wrapper.vm.isLatestVersion = () => false;
|
|
|
|
|
|
|
|
store.state.diffs.diffFiles.push(inlineLinesDiff);
|
|
|
|
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
|
|
|
|
|
|
|
|
expectFetchToOccur({ vueInstance: wrapper.vm, done });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('fetches diffs if it only has parallel view style', done => {
|
|
|
|
wrapper.vm.isLatestVersion = () => false;
|
|
|
|
|
|
|
|
store.state.diffs.diffFiles.push(parallelLinesDiff);
|
|
|
|
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
|
|
|
|
|
|
|
|
expectFetchToOccur({ vueInstance: wrapper.vm, done });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('fetches batch diffs if it has none', done => {
|
|
|
|
wrapper.vm.glFeatures.diffsBatchLoad = true;
|
|
|
|
|
|
|
|
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
|
|
|
|
|
|
|
|
expectFetchToOccur({ vueInstance: wrapper.vm, batch: true, existingFiles: 0, done });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('fetches batch diffs if it has both view styles, but no lines in either', done => {
|
|
|
|
wrapper.vm.glFeatures.diffsBatchLoad = true;
|
|
|
|
|
|
|
|
store.state.diffs.diffFiles.push(noLinesDiff);
|
|
|
|
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
|
|
|
|
|
|
|
|
expectFetchToOccur({ vueInstance: wrapper.vm, batch: true, done });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('fetches batch diffs if it only has inline view style', done => {
|
|
|
|
wrapper.vm.glFeatures.diffsBatchLoad = true;
|
|
|
|
|
|
|
|
store.state.diffs.diffFiles.push(inlineLinesDiff);
|
|
|
|
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
|
|
|
|
|
|
|
|
expectFetchToOccur({ vueInstance: wrapper.vm, batch: true, done });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('fetches batch diffs if it only has parallel view style', done => {
|
|
|
|
wrapper.vm.glFeatures.diffsBatchLoad = true;
|
|
|
|
|
|
|
|
store.state.diffs.diffFiles.push(parallelLinesDiff);
|
|
|
|
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
|
|
|
|
|
|
|
|
expectFetchToOccur({ vueInstance: wrapper.vm, batch: true, done });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('does not fetch diffs if it has already fetched both styles of diff', () => {
|
|
|
|
wrapper.vm.glFeatures.diffsBatchLoad = false;
|
|
|
|
|
|
|
|
store.state.diffs.diffFiles.push(fullDiff);
|
|
|
|
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
|
|
|
|
|
|
|
|
expect(wrapper.vm.diffFiles.length).toEqual(1);
|
|
|
|
expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
|
|
|
|
expect(wrapper.vm.fetchDiffFilesBatch).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('does not fetch batch diffs if it has already fetched both styles of diff', () => {
|
|
|
|
wrapper.vm.glFeatures.diffsBatchLoad = true;
|
|
|
|
|
|
|
|
store.state.diffs.diffFiles.push(fullDiff);
|
|
|
|
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
|
|
|
|
|
|
|
|
expect(wrapper.vm.diffFiles.length).toEqual(1);
|
|
|
|
expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
|
|
|
|
expect(wrapper.vm.fetchDiffFilesBatch).not.toHaveBeenCalled();
|
|
|
|
});
|
2020-01-01 13:55:28 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
it('calls fetchDiffFiles if diffsBatchLoad is not enabled', done => {
|
2020-03-13 15:44:24 +05:30
|
|
|
expect(wrapper.vm.diffFilesLength).toEqual(0);
|
2020-01-01 13:55:28 +05:30
|
|
|
wrapper.vm.glFeatures.diffsBatchLoad = false;
|
|
|
|
wrapper.vm.fetchData(false);
|
|
|
|
|
|
|
|
expect(wrapper.vm.fetchDiffFiles).toHaveBeenCalled();
|
2020-04-08 14:13:33 +05:30
|
|
|
setImmediate(() => {
|
2020-01-01 13:55:28 +05:30
|
|
|
expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
|
|
|
|
expect(wrapper.vm.fetchDiffFilesMeta).not.toHaveBeenCalled();
|
|
|
|
expect(wrapper.vm.fetchDiffFilesBatch).not.toHaveBeenCalled();
|
2020-04-08 14:13:33 +05:30
|
|
|
expect(wrapper.vm.fetchCoverageFiles).toHaveBeenCalled();
|
2020-03-13 15:44:24 +05:30
|
|
|
expect(wrapper.vm.unwatchDiscussions).toHaveBeenCalled();
|
|
|
|
expect(wrapper.vm.diffFilesLength).toEqual(100);
|
|
|
|
expect(wrapper.vm.unwatchRetrievingBatches).toHaveBeenCalled();
|
2020-01-01 13:55:28 +05:30
|
|
|
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
it('calls batch methods if diffsBatchLoad is enabled, and not latest version', done => {
|
|
|
|
expect(wrapper.vm.diffFilesLength).toEqual(0);
|
2020-01-01 13:55:28 +05:30
|
|
|
wrapper.vm.glFeatures.diffsBatchLoad = true;
|
|
|
|
wrapper.vm.isLatestVersion = () => false;
|
|
|
|
wrapper.vm.fetchData(false);
|
|
|
|
|
|
|
|
expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
|
2020-04-08 14:13:33 +05:30
|
|
|
setImmediate(() => {
|
2020-01-01 13:55:28 +05:30
|
|
|
expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
|
|
|
|
expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
|
|
|
|
expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
|
2020-04-08 14:13:33 +05:30
|
|
|
expect(wrapper.vm.fetchCoverageFiles).toHaveBeenCalled();
|
2020-03-13 15:44:24 +05:30
|
|
|
expect(wrapper.vm.unwatchDiscussions).toHaveBeenCalled();
|
|
|
|
expect(wrapper.vm.diffFilesLength).toEqual(100);
|
|
|
|
expect(wrapper.vm.unwatchRetrievingBatches).toHaveBeenCalled();
|
|
|
|
done();
|
2020-01-01 13:55:28 +05:30
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
it('calls batch methods if diffsBatchLoad is enabled, and latest version', done => {
|
|
|
|
expect(wrapper.vm.diffFilesLength).toEqual(0);
|
2020-01-01 13:55:28 +05:30
|
|
|
wrapper.vm.glFeatures.diffsBatchLoad = true;
|
|
|
|
wrapper.vm.fetchData(false);
|
|
|
|
|
|
|
|
expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
|
2020-04-08 14:13:33 +05:30
|
|
|
setImmediate(() => {
|
2020-01-01 13:55:28 +05:30
|
|
|
expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
|
|
|
|
expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
|
|
|
|
expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
|
2020-04-08 14:13:33 +05:30
|
|
|
expect(wrapper.vm.fetchCoverageFiles).toHaveBeenCalled();
|
2020-03-13 15:44:24 +05:30
|
|
|
expect(wrapper.vm.unwatchDiscussions).toHaveBeenCalled();
|
|
|
|
expect(wrapper.vm.diffFilesLength).toEqual(100);
|
|
|
|
expect(wrapper.vm.unwatchRetrievingBatches).toHaveBeenCalled();
|
|
|
|
done();
|
2020-01-01 13:55:28 +05:30
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
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
|
2020-04-08 14:13:33 +05:30
|
|
|
setImmediate(() => {
|
2019-07-07 11:18:12 +05:30
|
|
|
expect(store.state.diffs.highlightedRow).toBe('ABC_123');
|
|
|
|
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
it('marks current diff file based on currently highlighted row', () => {
|
2019-07-07 11:18:12 +05:30
|
|
|
createComponent({
|
|
|
|
shouldShow: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
// Component uses $nextTick so we wait until that has finished
|
2020-04-08 14:13:33 +05:30
|
|
|
return wrapper.vm.$nextTick().then(() => {
|
2019-07-07 11:18:12 +05:30
|
|
|
expect(store.state.diffs.currentDiffFileId).toBe('ABC');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
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
|
2020-04-08 14:13:33 +05:30
|
|
|
setImmediate(() => {
|
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(() => {
|
2020-04-08 14:13:33 +05:30
|
|
|
spy = jest.fn();
|
2019-07-07 11:18:12 +05:30
|
|
|
|
|
|
|
createComponent({
|
|
|
|
shouldShow: true,
|
|
|
|
});
|
|
|
|
wrapper.setMethods({
|
|
|
|
jumpToFile: spy,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
it.each(Object.keys(mappings))(
|
|
|
|
'calls `jumpToFile()` with correct parameter whenever pre-defined %s is pressed',
|
|
|
|
key => {
|
|
|
|
return wrapper.vm.$nextTick().then(() => {
|
|
|
|
expect(spy).not.toHaveBeenCalled();
|
2019-07-07 11:18:12 +05:30
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
Mousetrap.trigger(key);
|
2019-07-07 11:18:12 +05:30
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
expect(spy).toHaveBeenCalledWith(mappings[key]);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
);
|
2019-07-07 11:18:12 +05:30
|
|
|
|
|
|
|
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(() => {
|
2020-04-08 14:13:33 +05:30
|
|
|
spy = jest.fn();
|
2019-07-07 11:18:12 +05:30
|
|
|
|
|
|
|
createComponent({
|
|
|
|
shouldShow: false,
|
|
|
|
});
|
|
|
|
wrapper.setMethods({
|
|
|
|
jumpToFile: spy,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('stops calling `jumpToFile()` when application is hidden', done => {
|
|
|
|
wrapper.vm
|
|
|
|
.$nextTick()
|
|
|
|
.then(() => {
|
2020-04-08 14:13:33 +05:30
|
|
|
Object.keys(mappings).forEach(key => {
|
2019-07-07 11:18:12 +05:30
|
|
|
Mousetrap.trigger(key);
|
|
|
|
|
|
|
|
expect(spy).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.then(done)
|
|
|
|
.catch(done.fail);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('jumpToFile', () => {
|
|
|
|
let spy;
|
|
|
|
|
|
|
|
beforeEach(() => {
|
2020-04-08 14:13:33 +05:30
|
|
|
spy = jest.fn();
|
2019-07-07 11:18:12 +05:30
|
|
|
|
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);
|
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['222.js']);
|
2019-07-07 11:18:12 +05:30
|
|
|
store.state.diffs.currentDiffFileId = '222';
|
|
|
|
wrapper.vm.jumpToFile(+1);
|
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['333.js']);
|
2019-07-07 11:18:12 +05:30
|
|
|
store.state.diffs.currentDiffFileId = '333';
|
|
|
|
wrapper.vm.jumpToFile(-1);
|
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['222.js']);
|
2019-07-07 11:18:12 +05:30
|
|
|
})
|
|
|
|
.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(
|
2020-04-08 14:13:33 +05:30
|
|
|
expect.objectContaining({
|
2019-07-07 11:18:12 +05:30
|
|
|
mergeRequestDiffs: diffsMockData,
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
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(
|
2020-04-08 14:13:33 +05:30
|
|
|
expect.objectContaining({
|
2019-07-07 11:18:12 +05:30
|
|
|
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(() => {
|
2020-04-08 14:13:33 +05:30
|
|
|
toggleShowTreeList = jest.fn();
|
2019-07-07 11:18:12 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
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
|
|
|
});
|
|
|
|
});
|