From a5f4bba440d7f9ea47046a0a561d49adf0a1e6d4 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 16 Jun 2021 18:25:58 +0000 Subject: Add latest changes from gitlab-org/gitlab@14-0-stable-ee --- .../frontend/diffs/components/diff_content_spec.js | 1 + spec/frontend/diffs/components/diff_stats_spec.js | 53 +++- .../diffs/components/settings_dropdown_spec.js | 1 - spec/frontend/diffs/mock_data/diff_file.js | 2 + spec/frontend/diffs/store/actions_spec.js | 62 ++-- spec/frontend/diffs/store/utils_spec.js | 328 --------------------- spec/frontend/diffs/utils/diff_file_spec.js | 78 ++++- spec/frontend/diffs/utils/workers_spec.js | 309 +++++++++++++++++++ 8 files changed, 465 insertions(+), 369 deletions(-) create mode 100644 spec/frontend/diffs/utils/workers_spec.js (limited to 'spec/frontend/diffs') diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js index db4d69f0176..7012889440c 100644 --- a/spec/frontend/diffs/components/diff_content_spec.js +++ b/spec/frontend/diffs/components/diff_content_spec.js @@ -73,6 +73,7 @@ describe('DiffContent', () => { isParallelView: isParallelViewGetterMock, getCommentFormForDiffFile: getCommentFormForDiffFileGetterMock, diffLines: () => () => [...diffFileMockData.parallel_diff_lines], + fileLineCodequality: () => () => [], }, actions: { saveDiffDiscussion: saveDiffDiscussionMock, diff --git a/spec/frontend/diffs/components/diff_stats_spec.js b/spec/frontend/diffs/components/diff_stats_spec.js index 504158fb7fc..4ef1ec55cb0 100644 --- a/spec/frontend/diffs/components/diff_stats_spec.js +++ b/spec/frontend/diffs/components/diff_stats_spec.js @@ -1,6 +1,9 @@ import { GlIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; + import DiffStats from '~/diffs/components/diff_stats.vue'; +import mockDiffFile from '../mock_data/diff_file'; const TEST_ADDED_LINES = 100; const TEST_REMOVED_LINES = 200; @@ -11,13 +14,15 @@ describe('diff_stats', () => { let wrapper; const createComponent = (props = {}) => { - wrapper = shallowMount(DiffStats, { - propsData: { - addedLines: TEST_ADDED_LINES, - removedLines: TEST_REMOVED_LINES, - ...props, - }, - }); + wrapper = extendedWrapper( + shallowMount(DiffStats, { + propsData: { + addedLines: TEST_ADDED_LINES, + removedLines: TEST_REMOVED_LINES, + ...props, + }, + }), + ); }; describe('diff stats group', () => { @@ -38,15 +43,43 @@ describe('diff_stats', () => { }); }); + describe('bytes changes', () => { + let file; + const getBytesContainer = () => wrapper.find('.diff-stats > div:first-child'); + + beforeEach(() => { + file = { + ...mockDiffFile, + viewer: { + ...mockDiffFile.viewer, + name: 'not_diffable', + }, + }; + + createComponent({ diffFile: file }); + }); + + it("renders the bytes changes instead of line changes when the file isn't diffable", () => { + const content = getBytesContainer(); + + expect(content.classes('gl-text-green-600')).toBe(true); + expect(content.text()).toBe('+1.00 KiB (+100%)'); + }); + }); + describe('line changes', () => { - const findFileLine = (name) => wrapper.find(name); + const findFileLine = (name) => wrapper.findByTestId(name); + + beforeEach(() => { + createComponent(); + }); it('shows the amount of lines added', () => { - expect(findFileLine('.js-file-addition-line').text()).toBe(TEST_ADDED_LINES.toString()); + expect(findFileLine('js-file-addition-line').text()).toBe(TEST_ADDED_LINES.toString()); }); it('shows the amount of lines removed', () => { - expect(findFileLine('.js-file-deletion-line').text()).toBe(TEST_REMOVED_LINES.toString()); + expect(findFileLine('js-file-deletion-line').text()).toBe(TEST_REMOVED_LINES.toString()); }); }); diff --git a/spec/frontend/diffs/components/settings_dropdown_spec.js b/spec/frontend/diffs/components/settings_dropdown_spec.js index feac88cb802..43b9c5871a6 100644 --- a/spec/frontend/diffs/components/settings_dropdown_spec.js +++ b/spec/frontend/diffs/components/settings_dropdown_spec.js @@ -142,7 +142,6 @@ describe('Diff settings dropdown component', () => { expect(store.dispatch).toHaveBeenCalledWith('diffs/setShowWhitespace', { showWhitespace: !checked, - pushState: true, }); }); }); diff --git a/spec/frontend/diffs/mock_data/diff_file.js b/spec/frontend/diffs/mock_data/diff_file.js index cef776c885a..9ebcd5ef26b 100644 --- a/spec/frontend/diffs/mock_data/diff_file.js +++ b/spec/frontend/diffs/mock_data/diff_file.js @@ -19,6 +19,8 @@ export default { renamed_file: false, old_path: 'CHANGELOG', new_path: 'CHANGELOG', + old_size: 1024, + new_size: 2048, mode_changed: false, a_mode: '100644', b_mode: '100644', diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js index f46a42fae7a..14f8e090be9 100644 --- a/spec/frontend/diffs/store/actions_spec.js +++ b/spec/frontend/diffs/store/actions_spec.js @@ -9,8 +9,6 @@ import { INLINE_DIFF_VIEW_TYPE, PARALLEL_DIFF_VIEW_TYPE, DIFFS_PER_PAGE, - DIFF_WHITESPACE_COOKIE_NAME, - SHOW_WHITESPACE, } from '~/diffs/constants'; import { setBaseConfig, @@ -54,7 +52,8 @@ import { } from '~/diffs/store/actions'; import * as types from '~/diffs/store/mutation_types'; import * as utils from '~/diffs/store/utils'; -import { deprecatedCreateFlash as createFlash } from '~/flash'; +import * as workerUtils from '~/diffs/utils/workers'; +import createFlash from '~/flash'; import axios from '~/lib/utils/axios_utils'; import * as commonUtils from '~/lib/utils/common_utils'; import { mergeUrlParams } from '~/lib/utils/url_utility'; @@ -252,7 +251,10 @@ describe('DiffsStoreActions', () => { { type: types.SET_MERGE_REQUEST_DIFFS, payload: diffMetadata.merge_request_diffs }, { type: types.SET_DIFF_METADATA, payload: noFilesData }, // Workers are synchronous in Jest environment (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58805) - { type: types.SET_TREE_DATA, payload: utils.generateTreeList(diffMetadata.diff_files) }, + { + type: types.SET_TREE_DATA, + payload: workerUtils.generateTreeList(diffMetadata.diff_files), + }, ], [], () => { @@ -293,7 +295,9 @@ describe('DiffsStoreActions', () => { testAction(fetchCoverageFiles, {}, { endpointCoverage }, [], [], () => { expect(createFlash).toHaveBeenCalledTimes(1); - expect(createFlash).toHaveBeenCalledWith(expect.stringMatching('Something went wrong')); + expect(createFlash).toHaveBeenCalledWith({ + message: expect.stringMatching('Something went wrong'), + }); done(); }); }); @@ -1013,14 +1017,26 @@ describe('DiffsStoreActions', () => { }); describe('setShowWhitespace', () => { + const endpointUpdateUser = 'user/prefs'; + let putSpy; + let mock; + beforeEach(() => { + mock = new MockAdapter(axios); + putSpy = jest.spyOn(axios, 'put'); + + mock.onPut(endpointUpdateUser).reply(200, {}); jest.spyOn(eventHub, '$emit').mockImplementation(); }); + afterEach(() => { + mock.restore(); + }); + it('commits SET_SHOW_WHITESPACE', (done) => { testAction( setShowWhitespace, - { showWhitespace: true }, + { showWhitespace: true, updateDatabase: false }, {}, [{ type: types.SET_SHOW_WHITESPACE, payload: true }], [], @@ -1028,32 +1044,20 @@ describe('DiffsStoreActions', () => { ); }); - it('sets cookie', () => { - setShowWhitespace({ commit() {} }, { showWhitespace: true }); - - expect(Cookies.get(DIFF_WHITESPACE_COOKIE_NAME)).toEqual(SHOW_WHITESPACE); - }); - - it('calls history pushState', () => { - setShowWhitespace({ commit() {} }, { showWhitespace: true, pushState: true }); - - expect(window.history.pushState).toHaveBeenCalled(); - }); - - it('calls history pushState with merged params', () => { - window.history.pushState({}, '', '?test=1'); - - setShowWhitespace({ commit() {} }, { showWhitespace: true, pushState: true }); - - expect( - window.history.pushState.mock.calls[window.history.pushState.mock.calls.length - 1][2], - ).toMatch(/(.*)\?test=1&w=0/); + it('saves to the database', async () => { + await setShowWhitespace( + { state: { endpointUpdateUser }, commit() {} }, + { showWhitespace: true, updateDatabase: true }, + ); - window.history.pushState({}, '', '?'); + expect(putSpy).toHaveBeenCalledWith(endpointUpdateUser, { show_whitespace_in_diffs: true }); }); - it('emits eventHub event', () => { - setShowWhitespace({ commit() {} }, { showWhitespace: true, pushState: true }); + it('emits eventHub event', async () => { + await setShowWhitespace( + { state: {}, commit() {} }, + { showWhitespace: true, updateDatabase: false }, + ); expect(eventHub.$emit).toHaveBeenCalledWith('refetchDiffData'); }); diff --git a/spec/frontend/diffs/store/utils_spec.js b/spec/frontend/diffs/store/utils_spec.js index 6af38590610..73de0a6d381 100644 --- a/spec/frontend/diffs/store/utils_spec.js +++ b/spec/frontend/diffs/store/utils_spec.js @@ -685,141 +685,6 @@ describe('DiffsStoreUtils', () => { }); }); - describe('generateTreeList', () => { - let files; - - beforeAll(() => { - files = [ - { - new_path: 'app/index.js', - deleted_file: false, - new_file: false, - removed_lines: 10, - added_lines: 0, - file_hash: 'test', - }, - { - new_path: 'app/test/index.js', - deleted_file: false, - new_file: true, - removed_lines: 0, - added_lines: 0, - file_hash: 'test', - }, - { - new_path: 'app/test/filepathneedstruncating.js', - deleted_file: false, - new_file: true, - removed_lines: 0, - added_lines: 0, - file_hash: 'test', - }, - { - new_path: 'package.json', - deleted_file: true, - new_file: false, - removed_lines: 0, - added_lines: 0, - file_hash: 'test', - }, - ]; - }); - - it('creates a tree of files', () => { - const { tree } = utils.generateTreeList(files); - - expect(tree).toEqual([ - { - key: 'app', - path: 'app', - name: 'app', - type: 'tree', - tree: [ - { - addedLines: 0, - changed: true, - deleted: false, - fileHash: 'test', - key: 'app/index.js', - name: 'index.js', - parentPath: 'app/', - path: 'app/index.js', - removedLines: 10, - tempFile: false, - type: 'blob', - tree: [], - }, - { - key: 'app/test', - path: 'app/test', - name: 'test', - type: 'tree', - opened: true, - tree: [ - { - addedLines: 0, - changed: true, - deleted: false, - fileHash: 'test', - key: 'app/test/index.js', - name: 'index.js', - parentPath: 'app/test/', - path: 'app/test/index.js', - removedLines: 0, - tempFile: true, - type: 'blob', - tree: [], - }, - { - addedLines: 0, - changed: true, - deleted: false, - fileHash: 'test', - key: 'app/test/filepathneedstruncating.js', - name: 'filepathneedstruncating.js', - parentPath: 'app/test/', - path: 'app/test/filepathneedstruncating.js', - removedLines: 0, - tempFile: true, - type: 'blob', - tree: [], - }, - ], - }, - ], - opened: true, - }, - { - key: 'package.json', - parentPath: '/', - path: 'package.json', - name: 'package.json', - type: 'blob', - changed: true, - tempFile: false, - deleted: true, - fileHash: 'test', - addedLines: 0, - removedLines: 0, - tree: [], - }, - ]); - }); - - it('creates flat list of blobs & folders', () => { - const { treeEntries } = utils.generateTreeList(files); - - expect(Object.keys(treeEntries)).toEqual([ - 'app', - 'app/index.js', - 'app/test', - 'app/test/index.js', - 'app/test/filepathneedstruncating.js', - 'package.json', - ]); - }); - }); - describe('getDiffMode', () => { it('returns mode when matched in file', () => { expect( @@ -842,177 +707,6 @@ describe('DiffsStoreUtils', () => { }); }); - describe('getLowestSingleFolder', () => { - it('returns path and tree of lowest single folder tree', () => { - const folder = { - name: 'app', - type: 'tree', - tree: [ - { - name: 'javascripts', - type: 'tree', - tree: [ - { - type: 'blob', - name: 'index.js', - }, - ], - }, - ], - }; - const { path, treeAcc } = utils.getLowestSingleFolder(folder); - - expect(path).toEqual('app/javascripts'); - expect(treeAcc).toEqual([ - { - type: 'blob', - name: 'index.js', - }, - ]); - }); - - it('returns passed in folders path & tree when more than tree exists', () => { - const folder = { - name: 'app', - type: 'tree', - tree: [ - { - name: 'spec', - type: 'blob', - tree: [], - }, - ], - }; - const { path, treeAcc } = utils.getLowestSingleFolder(folder); - - expect(path).toEqual('app'); - expect(treeAcc).toBeNull(); - }); - }); - - describe('flattenTree', () => { - it('returns flattened directory structure', () => { - const tree = [ - { - type: 'tree', - name: 'app', - tree: [ - { - type: 'tree', - name: 'javascripts', - tree: [ - { - type: 'blob', - name: 'index.js', - tree: [], - }, - ], - }, - ], - }, - { - type: 'tree', - name: 'ee', - tree: [ - { - type: 'tree', - name: 'lib', - tree: [ - { - type: 'tree', - name: 'ee', - tree: [ - { - type: 'tree', - name: 'gitlab', - tree: [ - { - type: 'tree', - name: 'checks', - tree: [ - { - type: 'tree', - name: 'longtreenametomakepath', - tree: [ - { - type: 'blob', - name: 'diff_check.rb', - tree: [], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - type: 'tree', - name: 'spec', - tree: [ - { - type: 'tree', - name: 'javascripts', - tree: [], - }, - { - type: 'blob', - name: 'index_spec.js', - tree: [], - }, - ], - }, - ]; - const flattened = utils.flattenTree(tree); - - expect(flattened).toEqual([ - { - type: 'tree', - name: 'app/javascripts', - tree: [ - { - type: 'blob', - name: 'index.js', - tree: [], - }, - ], - }, - { - type: 'tree', - name: 'ee/lib/…/…/…/longtreenametomakepath', - tree: [ - { - name: 'diff_check.rb', - tree: [], - type: 'blob', - }, - ], - }, - { - type: 'tree', - name: 'spec', - tree: [ - { - type: 'tree', - name: 'javascripts', - tree: [], - }, - { - type: 'blob', - name: 'index_spec.js', - tree: [], - }, - ], - }, - ]); - }); - }); - describe('convertExpandLines', () => { it('converts expanded lines to normal lines', () => { const diffLines = [ @@ -1058,28 +752,6 @@ describe('DiffsStoreUtils', () => { }); }); - describe('getDefaultWhitespace', () => { - it('defaults to true if querystring and cookie are undefined', () => { - expect(utils.getDefaultWhitespace()).toBe(true); - }); - - it('returns false if querystring is `1`', () => { - expect(utils.getDefaultWhitespace('1', '0')).toBe(false); - }); - - it('returns true if querystring is `0`', () => { - expect(utils.getDefaultWhitespace('0', undefined)).toBe(true); - }); - - it('returns false if cookie is `1`', () => { - expect(utils.getDefaultWhitespace(undefined, '1')).toBe(false); - }); - - it('returns true if cookie is `0`', () => { - expect(utils.getDefaultWhitespace(undefined, '0')).toBe(true); - }); - }); - describe('isAdded', () => { it.each` type | expected diff --git a/spec/frontend/diffs/utils/diff_file_spec.js b/spec/frontend/diffs/utils/diff_file_spec.js index c6cfdfced65..3223b6c2dab 100644 --- a/spec/frontend/diffs/utils/diff_file_spec.js +++ b/spec/frontend/diffs/utils/diff_file_spec.js @@ -1,4 +1,11 @@ -import { prepareRawDiffFile, getShortShaFromFile } from '~/diffs/utils/diff_file'; +import { + prepareRawDiffFile, + getShortShaFromFile, + stats, + isNotDiffable, +} from '~/diffs/utils/diff_file'; +import { diffViewerModes } from '~/ide/constants'; +import mockDiffFile from '../mock_data/diff_file'; function getDiffFiles() { const loadFull = 'namespace/project/-/merge_requests/12345/diff_for_path?file_identifier=abc'; @@ -154,4 +161,73 @@ describe('diff_file utilities', () => { expect(getShortShaFromFile({ content_sha: cs })).toBe(response); }); }); + + describe('stats', () => { + const noFile = [ + "returns empty stats when the file isn't provided", + undefined, + { + text: '', + percent: 0, + changed: 0, + classes: '', + sign: '', + valid: false, + }, + ]; + const validFile = [ + 'computes the correct stats from a file', + mockDiffFile, + { + changed: 1024, + percent: 100, + classes: 'gl-text-green-600', + sign: '+', + text: '+1.00 KiB (+100%)', + valid: true, + }, + ]; + const negativeChange = [ + 'computed the correct states from a file with a negative size change', + { + ...mockDiffFile, + new_size: 0, + old_size: 1024, + }, + { + changed: -1024, + percent: -100, + classes: 'gl-text-red-500', + sign: '', + text: '-1.00 KiB (-100%)', + valid: true, + }, + ]; + + it.each([noFile, validFile, negativeChange])('%s', (_, file, output) => { + expect(stats(file)).toEqual(output); + }); + }); + + describe('isNotDiffable', () => { + it.each` + bool | vw + ${true} | ${diffViewerModes.not_diffable} + ${false} | ${diffViewerModes.text} + ${false} | ${diffViewerModes.image} + `('returns $bool when the viewer is $vw', ({ bool, vw }) => { + expect(isNotDiffable({ viewer: { name: vw } })).toBe(bool); + }); + + it.each` + file + ${undefined} + ${null} + ${{}} + ${{ viewer: undefined }} + ${{ viewer: null }} + `('reports `false` when the file is `$file`', ({ file }) => { + expect(isNotDiffable(file)).toBe(false); + }); + }); }); diff --git a/spec/frontend/diffs/utils/workers_spec.js b/spec/frontend/diffs/utils/workers_spec.js new file mode 100644 index 00000000000..25d8183b777 --- /dev/null +++ b/spec/frontend/diffs/utils/workers_spec.js @@ -0,0 +1,309 @@ +import { generateTreeList, getLowestSingleFolder, flattenTree } from '~/diffs/utils/workers'; + +describe('~/diffs/utils/workers', () => { + describe('generateTreeList', () => { + let files; + + beforeAll(() => { + files = [ + { + new_path: 'app/index.js', + deleted_file: false, + new_file: false, + removed_lines: 10, + added_lines: 0, + file_hash: 'test', + }, + { + new_path: 'app/test/index.js', + deleted_file: false, + new_file: true, + removed_lines: 0, + added_lines: 0, + file_hash: 'test', + }, + { + new_path: 'app/test/filepathneedstruncating.js', + deleted_file: false, + new_file: true, + removed_lines: 0, + added_lines: 0, + file_hash: 'test', + }, + { + new_path: 'package.json', + deleted_file: true, + new_file: false, + removed_lines: 0, + added_lines: 0, + file_hash: 'test', + }, + ]; + }); + + it('creates a tree of files', () => { + const { tree } = generateTreeList(files); + + expect(tree).toEqual([ + { + key: 'app', + path: 'app', + name: 'app', + type: 'tree', + tree: [ + { + addedLines: 0, + changed: true, + deleted: false, + fileHash: 'test', + key: 'app/index.js', + name: 'index.js', + parentPath: 'app/', + path: 'app/index.js', + removedLines: 10, + tempFile: false, + type: 'blob', + tree: [], + }, + { + key: 'app/test', + path: 'app/test', + name: 'test', + type: 'tree', + opened: true, + tree: [ + { + addedLines: 0, + changed: true, + deleted: false, + fileHash: 'test', + key: 'app/test/index.js', + name: 'index.js', + parentPath: 'app/test/', + path: 'app/test/index.js', + removedLines: 0, + tempFile: true, + type: 'blob', + tree: [], + }, + { + addedLines: 0, + changed: true, + deleted: false, + fileHash: 'test', + key: 'app/test/filepathneedstruncating.js', + name: 'filepathneedstruncating.js', + parentPath: 'app/test/', + path: 'app/test/filepathneedstruncating.js', + removedLines: 0, + tempFile: true, + type: 'blob', + tree: [], + }, + ], + }, + ], + opened: true, + }, + { + key: 'package.json', + parentPath: '/', + path: 'package.json', + name: 'package.json', + type: 'blob', + changed: true, + tempFile: false, + deleted: true, + fileHash: 'test', + addedLines: 0, + removedLines: 0, + tree: [], + }, + ]); + }); + + it('creates flat list of blobs & folders', () => { + const { treeEntries } = generateTreeList(files); + + expect(Object.keys(treeEntries)).toEqual([ + 'app', + 'app/index.js', + 'app/test', + 'app/test/index.js', + 'app/test/filepathneedstruncating.js', + 'package.json', + ]); + }); + }); + + describe('getLowestSingleFolder', () => { + it('returns path and tree of lowest single folder tree', () => { + const folder = { + name: 'app', + type: 'tree', + tree: [ + { + name: 'javascripts', + type: 'tree', + tree: [ + { + type: 'blob', + name: 'index.js', + }, + ], + }, + ], + }; + const { path, treeAcc } = getLowestSingleFolder(folder); + + expect(path).toEqual('app/javascripts'); + expect(treeAcc).toEqual([ + { + type: 'blob', + name: 'index.js', + }, + ]); + }); + + it('returns passed in folders path & tree when more than tree exists', () => { + const folder = { + name: 'app', + type: 'tree', + tree: [ + { + name: 'spec', + type: 'blob', + tree: [], + }, + ], + }; + const { path, treeAcc } = getLowestSingleFolder(folder); + + expect(path).toEqual('app'); + expect(treeAcc).toBeNull(); + }); + }); + + describe('flattenTree', () => { + it('returns flattened directory structure', () => { + const tree = [ + { + type: 'tree', + name: 'app', + tree: [ + { + type: 'tree', + name: 'javascripts', + tree: [ + { + type: 'blob', + name: 'index.js', + tree: [], + }, + ], + }, + ], + }, + { + type: 'tree', + name: 'ee', + tree: [ + { + type: 'tree', + name: 'lib', + tree: [ + { + type: 'tree', + name: 'ee', + tree: [ + { + type: 'tree', + name: 'gitlab', + tree: [ + { + type: 'tree', + name: 'checks', + tree: [ + { + type: 'tree', + name: 'longtreenametomakepath', + tree: [ + { + type: 'blob', + name: 'diff_check.rb', + tree: [], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + type: 'tree', + name: 'spec', + tree: [ + { + type: 'tree', + name: 'javascripts', + tree: [], + }, + { + type: 'blob', + name: 'index_spec.js', + tree: [], + }, + ], + }, + ]; + const flattened = flattenTree(tree); + + expect(flattened).toEqual([ + { + type: 'tree', + name: 'app/javascripts', + tree: [ + { + type: 'blob', + name: 'index.js', + tree: [], + }, + ], + }, + { + type: 'tree', + name: 'ee/lib/…/…/…/longtreenametomakepath', + tree: [ + { + name: 'diff_check.rb', + tree: [], + type: 'blob', + }, + ], + }, + { + type: 'tree', + name: 'spec', + tree: [ + { + type: 'tree', + name: 'javascripts', + tree: [], + }, + { + type: 'blob', + name: 'index_spec.js', + tree: [], + }, + ], + }, + ]); + }); + }); +}); -- cgit v1.2.3