diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-20 09:55:51 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-20 09:55:51 +0000 |
commit | e8d2c2579383897a1dd7f9debd359abe8ae8373d (patch) | |
tree | c42be41678c2586d49a75cabce89322082698334 /spec/frontend/diffs | |
parent | fc845b37ec3a90aaa719975f607740c22ba6a113 (diff) | |
download | gitlab-ce-e8d2c2579383897a1dd7f9debd359abe8ae8373d.tar.gz |
Add latest changes from gitlab-org/gitlab@14-1-stable-eev14.1.0-rc42
Diffstat (limited to 'spec/frontend/diffs')
13 files changed, 206 insertions, 1040 deletions
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js index 8a1c5547581..b5eb3e1713c 100644 --- a/spec/frontend/diffs/components/app_spec.js +++ b/spec/frontend/diffs/components/app_spec.js @@ -6,14 +6,19 @@ import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { TEST_HOST } from 'spec/test_constants'; import App from '~/diffs/components/app.vue'; -import CollapsedFilesWarning from '~/diffs/components/collapsed_files_warning.vue'; import CommitWidget from '~/diffs/components/commit_widget.vue'; import CompareVersions from '~/diffs/components/compare_versions.vue'; import DiffFile from '~/diffs/components/diff_file.vue'; -import HiddenFilesWarning from '~/diffs/components/hidden_files_warning.vue'; import NoChanges from '~/diffs/components/no_changes.vue'; import TreeList from '~/diffs/components/tree_list.vue'; +/* eslint-disable import/order */ +/* You know what: sometimes alphabetical isn't the best order */ +import CollapsedFilesWarning from '~/diffs/components/collapsed_files_warning.vue'; +import HiddenFilesWarning from '~/diffs/components/hidden_files_warning.vue'; +import MergeConflictWarning from '~/diffs/components/merge_conflict_warning.vue'; +/* eslint-enable import/order */ + import axios from '~/lib/utils/axios_utils'; import * as urlUtils from '~/lib/utils/url_utility'; import createDiffsStore from '../create_diffs_store'; @@ -541,6 +546,43 @@ describe('diffs/components/app', () => { expect(getCollapsedFilesWarning(wrapper).exists()).toBe(false); }); }); + + describe('merge conflicts', () => { + it('should render the merge conflicts banner if viewing the whole changeset and there are conflicts', () => { + createComponent({}, ({ state }) => { + Object.assign(state.diffs, { + latestDiff: true, + startVersion: null, + hasConflicts: true, + canMerge: false, + conflictResolutionPath: 'path', + }); + }); + + expect(wrapper.find(MergeConflictWarning).exists()).toBe(true); + }); + + it.each` + prop | value + ${'latestDiff'} | ${false} + ${'startVersion'} | ${'notnull'} + ${'hasConflicts'} | ${false} + `( + "should not render if any of the MR properties aren't correct - like $prop: $value", + ({ prop, value }) => { + createComponent({}, ({ state }) => { + Object.assign(state.diffs, { + latestDiff: true, + startVersion: null, + hasConflicts: true, + [prop]: value, + }); + }); + + expect(wrapper.find(MergeConflictWarning).exists()).toBe(false); + }, + ); + }); }); it('should display commit widget if store has a commit', () => { diff --git a/spec/frontend/diffs/components/collapsed_files_warning_spec.js b/spec/frontend/diffs/components/collapsed_files_warning_spec.js index 77c2e19cb68..46caeb01132 100644 --- a/spec/frontend/diffs/components/collapsed_files_warning_spec.js +++ b/spec/frontend/diffs/components/collapsed_files_warning_spec.js @@ -1,10 +1,13 @@ import { shallowMount, mount, createLocalVue } from '@vue/test-utils'; +import { nextTick } from 'vue'; import Vuex from 'vuex'; import CollapsedFilesWarning from '~/diffs/components/collapsed_files_warning.vue'; import { CENTERED_LIMITED_CONTAINER_CLASSES, EVT_EXPAND_ALL_FILES } from '~/diffs/constants'; import eventHub from '~/diffs/event_hub'; import createStore from '~/diffs/store/modules'; +import file from '../mock_data/diff_file'; + const propsData = { limited: true, mergeable: true, @@ -12,6 +15,13 @@ const propsData = { }; const limitedClasses = CENTERED_LIMITED_CONTAINER_CLASSES.split(' '); +async function files(store, count) { + const copies = Array(count).fill(file); + store.state.diffs.diffFiles.push(...copies); + + return nextTick(); +} + describe('CollapsedFilesWarning', () => { const localVue = createLocalVue(); let store; @@ -42,48 +52,63 @@ describe('CollapsedFilesWarning', () => { wrapper.destroy(); }); - it.each` - limited | containerClasses - ${true} | ${limitedClasses} - ${false} | ${[]} - `( - 'has the correct container classes when limited is $limited', - ({ limited, containerClasses }) => { - createComponent({ limited }); - - expect(wrapper.classes()).toEqual(['col-12'].concat(containerClasses)); - }, - ); - - it.each` - present | dismissed - ${false} | ${true} - ${true} | ${false} - `('toggles the alert when dismissed is $dismissed', ({ present, dismissed }) => { - createComponent({ dismissed }); - - expect(wrapper.find('[data-testid="root"]').exists()).toBe(present); - }); + describe('when there is more than one file', () => { + it.each` + limited | containerClasses + ${true} | ${limitedClasses} + ${false} | ${[]} + `( + 'has the correct container classes when limited is $limited', + async ({ limited, containerClasses }) => { + createComponent({ limited }); + await files(store, 2); + + expect(wrapper.classes()).toEqual(['col-12'].concat(containerClasses)); + }, + ); - it('dismisses the component when the alert "x" is clicked', async () => { - createComponent({}, { full: true }); + it.each` + present | dismissed + ${false} | ${true} + ${true} | ${false} + `('toggles the alert when dismissed is $dismissed', async ({ present, dismissed }) => { + createComponent({ dismissed }); + await files(store, 2); - expect(wrapper.find('[data-testid="root"]').exists()).toBe(true); + expect(wrapper.find('[data-testid="root"]').exists()).toBe(present); + }); - getAlertCloseButton().element.click(); + it('dismisses the component when the alert "x" is clicked', async () => { + createComponent({}, { full: true }); + await files(store, 2); - await wrapper.vm.$nextTick(); + expect(wrapper.find('[data-testid="root"]').exists()).toBe(true); - expect(wrapper.find('[data-testid="root"]').exists()).toBe(false); - }); + getAlertCloseButton().element.click(); - it(`emits the \`${EVT_EXPAND_ALL_FILES}\` event when the alert action button is clicked`, () => { - createComponent({}, { full: true }); + await wrapper.vm.$nextTick(); - jest.spyOn(eventHub, '$emit'); + expect(wrapper.find('[data-testid="root"]').exists()).toBe(false); + }); - getAlertActionButton().vm.$emit('click'); + it(`emits the \`${EVT_EXPAND_ALL_FILES}\` event when the alert action button is clicked`, async () => { + createComponent({}, { full: true }); + await files(store, 2); - expect(eventHub.$emit).toHaveBeenCalledWith(EVT_EXPAND_ALL_FILES); + jest.spyOn(eventHub, '$emit'); + + getAlertActionButton().vm.$emit('click'); + + expect(eventHub.$emit).toHaveBeenCalledWith(EVT_EXPAND_ALL_FILES); + }); + }); + + describe('when there is a single file', () => { + it('should not display', async () => { + createComponent(); + await files(store, 1); + + expect(wrapper.find('[data-testid="root"]').exists()).toBe(false); + }); }); }); diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js index 7012889440c..0a7dfc02c65 100644 --- a/spec/frontend/diffs/components/diff_content_spec.js +++ b/spec/frontend/diffs/components/diff_content_spec.js @@ -4,8 +4,6 @@ import Vuex from 'vuex'; import DiffContentComponent from '~/diffs/components/diff_content.vue'; import DiffDiscussions from '~/diffs/components/diff_discussions.vue'; import DiffView from '~/diffs/components/diff_view.vue'; -import InlineDiffView from '~/diffs/components/inline_diff_view.vue'; -import ParallelDiffView from '~/diffs/components/parallel_diff_view.vue'; import { IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants'; import { diffViewerModes } from '~/ide/constants'; import NoteForm from '~/notes/components/note_form.vue'; @@ -107,25 +105,10 @@ describe('DiffContent', () => { }); const textDiffFile = { ...defaultProps.diffFile, viewer: { name: diffViewerModes.text } }; - it('should render diff inline view if `isInlineView` is true', () => { - isInlineViewGetterMock.mockReturnValue(true); - createComponent({ props: { diffFile: textDiffFile } }); - - expect(wrapper.find(InlineDiffView).exists()).toBe(true); - }); - - it('should render parallel view if `isParallelView` getter is true', () => { - isParallelViewGetterMock.mockReturnValue(true); - createComponent({ props: { diffFile: textDiffFile } }); - - expect(wrapper.find(ParallelDiffView).exists()).toBe(true); - }); it('should render diff view if `unifiedDiffComponents` are true', () => { - isParallelViewGetterMock.mockReturnValue(true); createComponent({ props: { diffFile: textDiffFile }, - provide: { glFeatures: { unifiedDiffComponents: true } }, }); expect(wrapper.find(DiffView).exists()).toBe(true); diff --git a/spec/frontend/diffs/components/diff_file_spec.js b/spec/frontend/diffs/components/diff_file_spec.js index 1e8ad9344f2..99dda8d5deb 100644 --- a/spec/frontend/diffs/components/diff_file_spec.js +++ b/spec/frontend/diffs/components/diff_file_spec.js @@ -110,7 +110,6 @@ const findLoader = (wrapper) => wrapper.find('[data-testid="loader-icon"]'); const findToggleButton = (wrapper) => wrapper.find('[data-testid="expand-button"]'); const toggleFile = (wrapper) => findDiffHeader(wrapper).vm.$emit('toggleFile'); -const isDisplayNone = (element) => element.style.display === 'none'; const getReadableFile = () => JSON.parse(JSON.stringify(diffFileMockDataReadable)); const getUnreadableFile = () => JSON.parse(JSON.stringify(diffFileMockDataUnreadable)); @@ -305,9 +304,7 @@ describe('DiffFile', () => { it('should not have any content at all', async () => { await wrapper.vm.$nextTick(); - Array.from(findDiffContentArea(wrapper).element.children).forEach((child) => { - expect(isDisplayNone(child)).toBe(true); - }); + expect(findDiffContentArea(wrapper).element.children.length).toBe(0); }); it('should not have the class `has-body` to present the header differently', () => { diff --git a/spec/frontend/diffs/components/diff_row_spec.js b/spec/frontend/diffs/components/diff_row_spec.js index 137cc7e3f86..c0c92908701 100644 --- a/spec/frontend/diffs/components/diff_row_spec.js +++ b/spec/frontend/diffs/components/diff_row_spec.js @@ -8,6 +8,12 @@ import diffsModule from '~/diffs/store/modules'; import { findInteropAttributes } from '../find_interop_attributes'; import diffFileMockData from '../mock_data/diff_file'; +const showCommentForm = jest.fn(); +const enterdragging = jest.fn(); +const stopdragging = jest.fn(); +const setHighlightedRow = jest.fn(); +let wrapper; + describe('DiffRow', () => { const testLines = [ { @@ -29,7 +35,7 @@ describe('DiffRow', () => { }, ]; - const createWrapper = ({ props, state, actions, isLoggedIn = true }) => { + const createWrapper = ({ props, state = {}, actions, isLoggedIn = true }) => { Vue.use(Vuex); const diffs = diffsModule(); @@ -43,11 +49,25 @@ describe('DiffRow', () => { getters, }); + window.gon = { current_user_id: isLoggedIn ? 1 : 0 }; + const coverageFileData = state.coverageFiles?.files ? state.coverageFiles.files : {}; + const propsData = { fileHash: 'abc', filePath: 'abc', line: {}, index: 0, + isHighlighted: false, + fileLineCoverage: (file, line) => { + const hits = coverageFileData[file]?.[line]; + if (hits) { + return { text: `Test coverage: ${hits} hits`, class: 'coverage' }; + } else if (hits === 0) { + return { text: 'No test coverage', class: 'no-coverage' }; + } + + return {}; + }, ...props, }; @@ -55,49 +75,37 @@ describe('DiffRow', () => { glFeatures: { dragCommentSelection: true }, }; - return shallowMount(DiffRow, { propsData, store, provide }); + return shallowMount(DiffRow, { + propsData, + store, + provide, + listeners: { + enterdragging, + stopdragging, + setHighlightedRow, + showCommentForm, + }, + }); }; - it('isHighlighted returns true given line.left', () => { - const props = { - line: { - left: { - line_code: 'abc', - }, - }, - }; - const state = { highlightedRow: 'abc' }; - const wrapper = createWrapper({ props, state }); - expect(wrapper.vm.isHighlighted).toBe(true); - }); + afterEach(() => { + wrapper.destroy(); + wrapper = null; - it('isHighlighted returns true given line.right', () => { - const props = { - line: { - right: { - line_code: 'abc', - }, - }, - }; - const state = { highlightedRow: 'abc' }; - const wrapper = createWrapper({ props, state }); - expect(wrapper.vm.isHighlighted).toBe(true); - }); + window.gon = {}; + showCommentForm.mockReset(); + enterdragging.mockReset(); + stopdragging.mockReset(); + setHighlightedRow.mockReset(); - it('isHighlighted returns false given line.left', () => { - const props = { - line: { - left: { - line_code: 'abc', - }, - }, - }; - const wrapper = createWrapper({ props }); - expect(wrapper.vm.isHighlighted).toBe(false); + Object.values(DiffRow).forEach(({ cache }) => { + if (cache) { + cache.clear(); + } + }); }); - const getCommentButton = (wrapper, side) => - wrapper.find(`[data-testid="${side}-comment-button"]`); + const getCommentButton = (side) => wrapper.find(`[data-testid="${side}-comment-button"]`); describe.each` side @@ -105,33 +113,30 @@ describe('DiffRow', () => { ${'right'} `('$side side', ({ side }) => { it(`renders empty cells if ${side} is unavailable`, () => { - const wrapper = createWrapper({ props: { line: testLines[2], inline: false } }); + wrapper = createWrapper({ props: { line: testLines[2], inline: false } }); expect(wrapper.find(`[data-testid="${side}-line-number"]`).exists()).toBe(false); expect(wrapper.find(`[data-testid="${side}-empty-cell"]`).exists()).toBe(true); }); describe('comment button', () => { - const showCommentForm = jest.fn(); let line; beforeEach(() => { - showCommentForm.mockReset(); // https://eslint.org/docs/rules/prefer-destructuring#when-not-to-use-it // eslint-disable-next-line prefer-destructuring line = testLines[3]; }); it('renders', () => { - const wrapper = createWrapper({ props: { line, inline: false } }); - expect(getCommentButton(wrapper, side).exists()).toBe(true); + wrapper = createWrapper({ props: { line, inline: false } }); + expect(getCommentButton(side).exists()).toBe(true); }); it('responds to click and keyboard events', async () => { - const wrapper = createWrapper({ + wrapper = createWrapper({ props: { line, inline: false }, - actions: { showCommentForm }, }); - const commentButton = getCommentButton(wrapper, side); + const commentButton = getCommentButton(side); await commentButton.trigger('click'); await commentButton.trigger('keydown.enter'); @@ -142,11 +147,10 @@ describe('DiffRow', () => { it('ignores click and keyboard events when comments are disabled', async () => { line[side].commentsDisabled = true; - const wrapper = createWrapper({ + wrapper = createWrapper({ props: { line, inline: false }, - actions: { showCommentForm }, }); - const commentButton = getCommentButton(wrapper, side); + const commentButton = getCommentButton(side); await commentButton.trigger('click'); await commentButton.trigger('keydown.enter'); @@ -157,19 +161,20 @@ describe('DiffRow', () => { }); it('renders avatars', () => { - const wrapper = createWrapper({ props: { line: testLines[0], inline: false } }); + wrapper = createWrapper({ props: { line: testLines[0], inline: false } }); + expect(wrapper.find(`[data-testid="${side}-discussions"]`).exists()).toBe(true); }); }); it('renders left line numbers', () => { - const wrapper = createWrapper({ props: { line: testLines[0] } }); + wrapper = createWrapper({ props: { line: testLines[0] } }); const lineNumber = testLines[0].left.old_line; expect(wrapper.find(`[data-linenumber="${lineNumber}"]`).exists()).toBe(true); }); it('renders right line numbers', () => { - const wrapper = createWrapper({ props: { line: testLines[0] } }); + wrapper = createWrapper({ props: { line: testLines[0] } }); const lineNumber = testLines[0].right.new_line; expect(wrapper.find(`[data-linenumber="${lineNumber}"]`).exists()).toBe(true); }); @@ -186,12 +191,10 @@ describe('DiffRow', () => { ${'left'} ${'right'} `('emits `enterdragging` onDragEnter $side side', ({ side }) => { - const expectation = { ...line[side], index: 0 }; - const wrapper = createWrapper({ props: { line } }); + wrapper = createWrapper({ props: { line } }); fireEvent.dragEnter(getByTestId(wrapper.element, `${side}-side`)); - expect(wrapper.emitted().enterdragging).toBeTruthy(); - expect(wrapper.emitted().enterdragging[0]).toEqual([expectation]); + expect(enterdragging).toHaveBeenCalledWith({ ...line[side], index: 0 }); }); it.each` @@ -199,10 +202,10 @@ describe('DiffRow', () => { ${'left'} ${'right'} `('emits `stopdragging` onDrop $side side', ({ side }) => { - const wrapper = createWrapper({ props: { line } }); + wrapper = createWrapper({ props: { line } }); fireEvent.dragEnd(getByTestId(wrapper.element, `${side}-side`)); - expect(wrapper.emitted().stopdragging).toBeTruthy(); + expect(stopdragging).toHaveBeenCalled(); }); }); @@ -231,7 +234,7 @@ describe('DiffRow', () => { it('for lines with coverage', () => { const coverageFiles = { files: { [name]: { [line]: 5 } } }; - const wrapper = createWrapper({ props, state: { coverageFiles } }); + wrapper = createWrapper({ props, state: { coverageFiles } }); const coverage = wrapper.find('.line-coverage.right-side'); expect(coverage.attributes('title')).toContain('Test coverage: 5 hits'); @@ -240,7 +243,7 @@ describe('DiffRow', () => { it('for lines without coverage', () => { const coverageFiles = { files: { [name]: { [line]: 0 } } }; - const wrapper = createWrapper({ props, state: { coverageFiles } }); + wrapper = createWrapper({ props, state: { coverageFiles } }); const coverage = wrapper.find('.line-coverage.right-side'); expect(coverage.attributes('title')).toContain('No test coverage'); @@ -249,7 +252,7 @@ describe('DiffRow', () => { it('for unknown lines', () => { const coverageFiles = {}; - const wrapper = createWrapper({ props, state: { coverageFiles } }); + wrapper = createWrapper({ props, state: { coverageFiles } }); const coverage = wrapper.find('.line-coverage.right-side'); expect(coverage.attributes('title')).toBeFalsy(); @@ -267,7 +270,7 @@ describe('DiffRow', () => { ${'with parallel and no left side'} | ${{ right: { old_line: 3, new_line: 5 } }} | ${false} | ${null} | ${{ type: 'new', line: '5', newLine: '5' }} ${'with parallel and right side'} | ${{ left: { old_line: 3 }, right: { new_line: 5 } }} | ${false} | ${{ type: 'old', line: '3', oldLine: '3' }} | ${{ type: 'new', line: '5', newLine: '5' }} `('$desc, sets interop data attributes', ({ line, inline, leftSide, rightSide }) => { - const wrapper = createWrapper({ props: { line, inline } }); + wrapper = createWrapper({ props: { line, inline } }); expect(findInteropAttributes(wrapper, '[data-testid="left-side"]')).toEqual(leftSide); expect(findInteropAttributes(wrapper, '[data-testid="right-side"]')).toEqual(rightSide); diff --git a/spec/frontend/diffs/components/diff_row_utils_spec.js b/spec/frontend/diffs/components/diff_row_utils_spec.js index 47ae3cd5867..930b8bcdb08 100644 --- a/spec/frontend/diffs/components/diff_row_utils_spec.js +++ b/spec/frontend/diffs/components/diff_row_utils_spec.js @@ -11,24 +11,21 @@ const LINE_CODE = 'abc123'; describe('isHighlighted', () => { it('should return true if line is highlighted', () => { - const state = { diffs: { highlightedRow: LINE_CODE } }; const line = { line_code: LINE_CODE }; const isCommented = false; - expect(utils.isHighlighted(state, line, isCommented)).toBe(true); + expect(utils.isHighlighted(LINE_CODE, line, isCommented)).toBe(true); }); it('should return false if line is not highlighted', () => { - const state = { diffs: { highlightedRow: 'xxx' } }; const line = { line_code: LINE_CODE }; const isCommented = false; - expect(utils.isHighlighted(state, line, isCommented)).toBe(false); + expect(utils.isHighlighted('xxx', line, isCommented)).toBe(false); }); it('should return true if isCommented is true', () => { - const state = { diffs: { highlightedRow: 'xxx' } }; const line = { line_code: LINE_CODE }; const isCommented = true; - expect(utils.isHighlighted(state, line, isCommented)).toBe(true); + expect(utils.isHighlighted('xxx', line, isCommented)).toBe(true); }); }); @@ -143,19 +140,14 @@ describe('addCommentTooltip', () => { 'Commenting on symbolic links that replace or are replaced by files is currently not supported.'; const brokenRealTooltip = 'Commenting on files that replace or are replaced by symbolic links is currently not supported.'; - const commentTooltip = 'Add a comment to this line'; const dragTooltip = 'Add a comment to this line or drag for multiple lines'; it('should return default tooltip', () => { expect(utils.addCommentTooltip()).toBeUndefined(); }); - it('should return comment tooltip', () => { - expect(utils.addCommentTooltip({})).toEqual(commentTooltip); - }); - it('should return drag comment tooltip when dragging is enabled', () => { - expect(utils.addCommentTooltip({}, true)).toEqual(dragTooltip); + expect(utils.addCommentTooltip({})).toEqual(dragTooltip); }); it('should return broken symlink tooltip', () => { @@ -258,30 +250,3 @@ describe('mapParallel', () => { expect(mapped.right).toMatchObject(rightExpectation); }); }); - -describe('mapInline', () => { - it('should assign computed properties to the line object', () => { - const content = { - diffFile: {}, - shouldRenderDraftRow: () => false, - }; - const line = { - discussions: [{}], - discussionsExpanded: true, - hasForm: true, - }; - const expectation = { - commentRowClasses: '', - hasDiscussions: true, - isContextLine: false, - isMatchLine: false, - isMetaLine: false, - renderDiscussion: true, - hasDraft: false, - hasCommentForm: true, - }; - const mapped = utils.mapInline(content)(line); - - expect(mapped).toMatchObject(expectation); - }); -}); diff --git a/spec/frontend/diffs/components/diff_view_spec.js b/spec/frontend/diffs/components/diff_view_spec.js index 83b173c1f5d..3af66526050 100644 --- a/spec/frontend/diffs/components/diff_view_spec.js +++ b/spec/frontend/diffs/components/diff_view_spec.js @@ -28,7 +28,7 @@ describe('DiffView', () => { }; const diffs = { actions: { showCommentForm }, - getters: { commitId: () => 'abc123' }, + getters: { commitId: () => 'abc123', fileLineCoverage: () => ({}) }, namespaced: true, }; const notes = { @@ -41,7 +41,7 @@ describe('DiffView', () => { }); const propsData = { - diffFile: {}, + diffFile: { file_hash: '123' }, diffLines: [], ...props, }; @@ -84,15 +84,15 @@ describe('DiffView', () => { it('sets `dragStart` onStartDragging', () => { const wrapper = createWrapper({ diffLines: [{}] }); - wrapper.findComponent(DiffRow).vm.$emit('startdragging', { test: true }); - expect(wrapper.vm.dragStart).toEqual({ test: true }); + wrapper.findComponent(DiffRow).vm.$emit('startdragging', { line: { test: true } }); + expect(wrapper.vm.idState.dragStart).toEqual({ test: true }); }); it('does not call `setSelectedCommentPosition` on different chunks onDragOver', () => { const wrapper = createWrapper({ diffLines: [{}] }); const diffRow = getDiffRow(wrapper); - diffRow.$emit('startdragging', { chunk: 0 }); + diffRow.$emit('startdragging', { line: { chunk: 0 } }); diffRow.$emit('enterdragging', { chunk: 1 }); expect(setSelectedCommentPosition).not.toHaveBeenCalled(); @@ -109,7 +109,7 @@ describe('DiffView', () => { const wrapper = createWrapper({ diffLines: [{}] }); const diffRow = getDiffRow(wrapper); - diffRow.$emit('startdragging', { chunk: 1, index: start }); + diffRow.$emit('startdragging', { line: { chunk: 1, index: start } }); diffRow.$emit('enterdragging', { chunk: 1, index: end }); const arg = setSelectedCommentPosition.mock.calls[0][1]; @@ -122,11 +122,11 @@ describe('DiffView', () => { const wrapper = createWrapper({ diffLines: [{}] }); const diffRow = getDiffRow(wrapper); - diffRow.$emit('startdragging', { test: true }); - expect(wrapper.vm.dragStart).toEqual({ test: true }); + diffRow.$emit('startdragging', { line: { test: true } }); + expect(wrapper.vm.idState.dragStart).toEqual({ test: true }); diffRow.$emit('stopdragging'); - expect(wrapper.vm.dragStart).toBeNull(); + expect(wrapper.vm.idState.dragStart).toBeNull(); expect(showCommentForm).toHaveBeenCalled(); }); }); diff --git a/spec/frontend/diffs/components/inline_diff_table_row_spec.js b/spec/frontend/diffs/components/inline_diff_table_row_spec.js deleted file mode 100644 index 9c3e00cd6cf..00000000000 --- a/spec/frontend/diffs/components/inline_diff_table_row_spec.js +++ /dev/null @@ -1,325 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import DiffGutterAvatars from '~/diffs/components/diff_gutter_avatars.vue'; -import { mapInline } from '~/diffs/components/diff_row_utils'; -import InlineDiffTableRow from '~/diffs/components/inline_diff_table_row.vue'; -import { createStore } from '~/mr_notes/stores'; -import { findInteropAttributes } from '../find_interop_attributes'; -import discussionsMockData from '../mock_data/diff_discussions'; -import diffFileMockData from '../mock_data/diff_file'; - -const TEST_USER_ID = 'abc123'; -const TEST_USER = { id: TEST_USER_ID }; - -describe('InlineDiffTableRow', () => { - let wrapper; - let store; - const mockDiffContent = { - diffFile: diffFileMockData, - shouldRenderDraftRow: jest.fn(), - hasParallelDraftLeft: jest.fn(), - hasParallelDraftRight: jest.fn(), - draftForLine: jest.fn(), - }; - - const applyMap = mapInline(mockDiffContent); - const thisLine = applyMap(diffFileMockData.highlighted_diff_lines[0]); - - const createComponent = (props = {}, propsStore = store) => { - wrapper = shallowMount(InlineDiffTableRow, { - store: propsStore, - propsData: { - line: thisLine, - fileHash: diffFileMockData.file_hash, - filePath: diffFileMockData.file_path, - contextLinesPath: 'contextLinesPath', - isHighlighted: false, - ...props, - }, - }); - }; - - beforeEach(() => { - store = createStore(); - store.state.notes.userData = TEST_USER; - }); - - afterEach(() => { - wrapper.destroy(); - }); - - it('does not add hll class to line content when line does not match highlighted row', () => { - createComponent(); - expect(wrapper.find('.line_content').classes('hll')).toBe(false); - }); - - it('adds hll class to lineContent when line is the highlighted row', () => { - store.state.diffs.highlightedRow = thisLine.line_code; - createComponent({}, store); - expect(wrapper.find('.line_content').classes('hll')).toBe(true); - }); - - it('adds hll class to lineContent when line is part of a multiline comment', () => { - createComponent({ isCommented: true }); - expect(wrapper.find('.line_content').classes('hll')).toBe(true); - }); - - describe('sets coverage title and class', () => { - it('for lines with coverage', () => { - const name = diffFileMockData.file_path; - const line = thisLine.new_line; - - store.state.diffs.coverageFiles = { files: { [name]: { [line]: 5 } } }; - createComponent({}, store); - const coverage = wrapper.find('.line-coverage'); - - expect(coverage.attributes('title')).toContain('Test coverage: 5 hits'); - expect(coverage.classes('coverage')).toBe(true); - }); - - it('for lines without coverage', () => { - const name = diffFileMockData.file_path; - const line = thisLine.new_line; - - store.state.diffs.coverageFiles = { files: { [name]: { [line]: 0 } } }; - createComponent({}, store); - const coverage = wrapper.find('.line-coverage'); - - expect(coverage.attributes('title')).toContain('No test coverage'); - expect(coverage.classes('no-coverage')).toBe(true); - }); - - it('for unknown lines', () => { - store.state.diffs.coverageFiles = {}; - createComponent({}, store); - - const coverage = wrapper.find('.line-coverage'); - - expect(coverage.attributes('title')).toBeUndefined(); - expect(coverage.classes('coverage')).toBe(false); - expect(coverage.classes('no-coverage')).toBe(false); - }); - }); - - describe('Table Cells', () => { - const findNewTd = () => wrapper.find({ ref: 'newTd' }); - const findOldTd = () => wrapper.find({ ref: 'oldTd' }); - - describe('td', () => { - it('highlights when isHighlighted true', () => { - store.state.diffs.highlightedRow = thisLine.line_code; - createComponent({}, store); - - expect(findNewTd().classes()).toContain('hll'); - expect(findOldTd().classes()).toContain('hll'); - }); - - it('does not highlight when isHighlighted false', () => { - createComponent(); - - expect(findNewTd().classes()).not.toContain('hll'); - expect(findOldTd().classes()).not.toContain('hll'); - }); - }); - - describe('comment button', () => { - const findNoteButton = () => wrapper.find({ ref: 'addDiffNoteButton' }); - - it.each` - userData | expectation - ${TEST_USER} | ${true} - ${null} | ${false} - `('exists is $expectation - with userData ($userData)', ({ userData, expectation }) => { - store.state.notes.userData = userData; - createComponent({}, store); - - expect(findNoteButton().exists()).toBe(expectation); - }); - - it.each` - isHover | line | expectation - ${true} | ${{ ...thisLine, discussions: [] }} | ${true} - ${false} | ${{ ...thisLine, discussions: [] }} | ${false} - ${true} | ${{ ...thisLine, type: 'context', discussions: [] }} | ${false} - ${true} | ${{ ...thisLine, type: 'old-nonewline', discussions: [] }} | ${false} - ${true} | ${{ ...thisLine, discussions: [{}] }} | ${false} - `('visible is $expectation - line ($line)', ({ isHover, line, expectation }) => { - createComponent({ line: applyMap(line) }); - wrapper.setData({ isHover }); - - return wrapper.vm.$nextTick().then(() => { - expect(findNoteButton().isVisible()).toBe(expectation); - }); - }); - - it.each` - disabled | commentsDisabled - ${'disabled'} | ${true} - ${undefined} | ${false} - `( - 'has attribute disabled=$disabled when the outer component has prop commentsDisabled=$commentsDisabled', - ({ disabled, commentsDisabled }) => { - createComponent({ - line: applyMap({ ...thisLine, commentsDisabled }), - }); - - wrapper.setData({ isHover: true }); - - return wrapper.vm.$nextTick().then(() => { - expect(findNoteButton().attributes('disabled')).toBe(disabled); - }); - }, - ); - - const symlinkishFileTooltip = - 'Commenting on symbolic links that replace or are replaced by files is currently not supported.'; - const realishFileTooltip = - 'Commenting on files that replace or are replaced by symbolic links is currently not supported.'; - const otherFileTooltip = 'Add a comment to this line'; - const findTooltip = () => wrapper.find({ ref: 'addNoteTooltip' }); - - it.each` - tooltip | commentsDisabled - ${symlinkishFileTooltip} | ${{ wasSymbolic: true }} - ${symlinkishFileTooltip} | ${{ isSymbolic: true }} - ${realishFileTooltip} | ${{ wasReal: true }} - ${realishFileTooltip} | ${{ isReal: true }} - ${otherFileTooltip} | ${false} - `( - 'has the correct tooltip when commentsDisabled=$commentsDisabled', - ({ tooltip, commentsDisabled }) => { - createComponent({ - line: applyMap({ ...thisLine, commentsDisabled }), - }); - - wrapper.setData({ isHover: true }); - - return wrapper.vm.$nextTick().then(() => { - expect(findTooltip().attributes('title')).toBe(tooltip); - }); - }, - ); - }); - - describe('line number', () => { - const findLineNumberOld = () => wrapper.find({ ref: 'lineNumberRefOld' }); - const findLineNumberNew = () => wrapper.find({ ref: 'lineNumberRefNew' }); - - it('renders line numbers in correct cells', () => { - createComponent(); - - expect(findLineNumberOld().exists()).toBe(false); - expect(findLineNumberNew().exists()).toBe(true); - }); - - describe('with lineNumber prop', () => { - const TEST_LINE_CODE = 'LC_42'; - const TEST_LINE_NUMBER = 1; - - describe.each` - lineProps | findLineNumber | expectedHref | expectedClickArg - ${{ line_code: TEST_LINE_CODE, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${`#${TEST_LINE_CODE}`} | ${TEST_LINE_CODE} - ${{ line_code: undefined, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${'#'} | ${undefined} - ${{ line_code: undefined, left: { line_code: TEST_LINE_CODE }, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${'#'} | ${TEST_LINE_CODE} - ${{ line_code: undefined, right: { line_code: TEST_LINE_CODE }, new_line: TEST_LINE_NUMBER }} | ${findLineNumberNew} | ${'#'} | ${TEST_LINE_CODE} - `( - 'with line ($lineProps)', - ({ lineProps, findLineNumber, expectedHref, expectedClickArg }) => { - beforeEach(() => { - jest.spyOn(store, 'dispatch').mockImplementation(); - createComponent({ - line: applyMap({ ...thisLine, ...lineProps }), - }); - }); - - it('renders', () => { - expect(findLineNumber().exists()).toBe(true); - expect(findLineNumber().attributes()).toEqual({ - href: expectedHref, - 'data-linenumber': TEST_LINE_NUMBER.toString(), - }); - }); - - it('on click, dispatches setHighlightedRow', () => { - expect(store.dispatch).toHaveBeenCalledTimes(1); - - findLineNumber().trigger('click'); - - expect(store.dispatch).toHaveBeenCalledWith( - 'diffs/setHighlightedRow', - expectedClickArg, - ); - expect(store.dispatch).toHaveBeenCalledTimes(2); - }); - }, - ); - }); - }); - - describe('diff-gutter-avatars', () => { - const TEST_LINE_CODE = 'LC_42'; - const TEST_FILE_HASH = diffFileMockData.file_hash; - const findAvatars = () => wrapper.find(DiffGutterAvatars); - let line; - - beforeEach(() => { - jest.spyOn(store, 'dispatch').mockImplementation(); - - line = { - line_code: TEST_LINE_CODE, - type: 'new', - old_line: null, - new_line: 1, - discussions: [{ ...discussionsMockData }], - discussionsExpanded: true, - text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n', - rich_text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n', - meta_data: null, - }; - }); - - describe('with showCommentButton', () => { - it('renders if line has discussions', () => { - createComponent({ line: applyMap(line) }); - - expect(findAvatars().props()).toEqual({ - discussions: line.discussions, - discussionsExpanded: line.discussionsExpanded, - }); - }); - - it('does notrender if line has no discussions', () => { - line.discussions = []; - createComponent({ line: applyMap(line) }); - - expect(findAvatars().exists()).toEqual(false); - }); - - it('toggles line discussion', () => { - createComponent({ line: applyMap(line) }); - - expect(store.dispatch).toHaveBeenCalledTimes(1); - - findAvatars().vm.$emit('toggleLineDiscussions'); - - expect(store.dispatch).toHaveBeenCalledWith('diffs/toggleLineDiscussions', { - lineCode: TEST_LINE_CODE, - fileHash: TEST_FILE_HASH, - expanded: !line.discussionsExpanded, - }); - }); - }); - }); - }); - - describe('interoperability', () => { - it.each` - desc | line | expectation - ${'with type old'} | ${{ ...thisLine, type: 'old', old_line: 3, new_line: 5 }} | ${{ type: 'old', line: '3', oldLine: '3', newLine: '5' }} - ${'with type new'} | ${{ ...thisLine, type: 'new', old_line: 3, new_line: 5 }} | ${{ type: 'new', line: '5', oldLine: '3', newLine: '5' }} - `('$desc, sets interop data attributes', ({ line, expectation }) => { - createComponent({ line }); - - expect(findInteropAttributes(wrapper)).toEqual(expectation); - }); - }); -}); diff --git a/spec/frontend/diffs/components/inline_diff_view_spec.js b/spec/frontend/diffs/components/inline_diff_view_spec.js deleted file mode 100644 index 27834804f77..00000000000 --- a/spec/frontend/diffs/components/inline_diff_view_spec.js +++ /dev/null @@ -1,57 +0,0 @@ -import '~/behaviors/markdown/render_gfm'; -import { getByText } from '@testing-library/dom'; -import { mount } from '@vue/test-utils'; -import { mapInline } from '~/diffs/components/diff_row_utils'; -import InlineDiffView from '~/diffs/components/inline_diff_view.vue'; -import { createStore } from '~/mr_notes/stores'; -import discussionsMockData from '../mock_data/diff_discussions'; -import diffFileMockData from '../mock_data/diff_file'; - -describe('InlineDiffView', () => { - let wrapper; - const getDiffFileMock = () => ({ ...diffFileMockData }); - const getDiscussionsMockData = () => [{ ...discussionsMockData }]; - const notesLength = getDiscussionsMockData()[0].notes.length; - - const setup = (diffFile, diffLines) => { - const mockDiffContent = { - diffFile, - shouldRenderDraftRow: jest.fn(), - }; - - const store = createStore(); - - store.dispatch('diffs/setInlineDiffViewType'); - wrapper = mount(InlineDiffView, { - store, - propsData: { - diffFile, - diffLines: diffLines.map(mapInline(mockDiffContent)), - }, - }); - }; - - describe('template', () => { - it('should have rendered diff lines', () => { - const diffFile = getDiffFileMock(); - setup(diffFile, diffFile.highlighted_diff_lines); - - expect(wrapper.findAll('tr.line_holder').length).toEqual(8); - expect(wrapper.findAll('tr.line_holder.new').length).toEqual(4); - expect(wrapper.findAll('tr.line_expansion.match').length).toEqual(1); - getByText(wrapper.element, /Bad dates/i); - }); - - it('should render discussions', () => { - const diffFile = getDiffFileMock(); - diffFile.highlighted_diff_lines[1].discussions = getDiscussionsMockData(); - diffFile.highlighted_diff_lines[1].discussionsExpanded = true; - setup(diffFile, diffFile.highlighted_diff_lines); - - expect(wrapper.findAll('.notes_holder').length).toEqual(1); - expect(wrapper.findAll('.notes_holder .note').length).toEqual(notesLength + 1); - getByText(wrapper.element, 'comment 5'); - wrapper.vm.$store.dispatch('setInitialNotes', []); - }); - }); -}); diff --git a/spec/frontend/diffs/components/parallel_diff_table_row_spec.js b/spec/frontend/diffs/components/parallel_diff_table_row_spec.js deleted file mode 100644 index ed191d849fd..00000000000 --- a/spec/frontend/diffs/components/parallel_diff_table_row_spec.js +++ /dev/null @@ -1,445 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; -import { createComponentWithStore } from 'helpers/vue_mount_component_helper'; -import DiffGutterAvatars from '~/diffs/components/diff_gutter_avatars.vue'; -import { mapParallel } from '~/diffs/components/diff_row_utils'; -import ParallelDiffTableRow from '~/diffs/components/parallel_diff_table_row.vue'; -import { createStore } from '~/mr_notes/stores'; -import { findInteropAttributes } from '../find_interop_attributes'; -import discussionsMockData from '../mock_data/diff_discussions'; -import diffFileMockData from '../mock_data/diff_file'; - -describe('ParallelDiffTableRow', () => { - const mockDiffContent = { - diffFile: diffFileMockData, - shouldRenderDraftRow: jest.fn(), - hasParallelDraftLeft: jest.fn(), - hasParallelDraftRight: jest.fn(), - draftForLine: jest.fn(), - }; - - const applyMap = mapParallel(mockDiffContent); - - describe('when one side is empty', () => { - let wrapper; - let vm; - const thisLine = diffFileMockData.parallel_diff_lines[0]; - const rightLine = diffFileMockData.parallel_diff_lines[0].right; - - beforeEach(() => { - wrapper = shallowMount(ParallelDiffTableRow, { - store: createStore(), - propsData: { - line: applyMap(thisLine), - fileHash: diffFileMockData.file_hash, - filePath: diffFileMockData.file_path, - contextLinesPath: 'contextLinesPath', - isHighlighted: false, - }, - }); - - vm = wrapper.vm; - }); - - it('does not highlight non empty line content when line does not match highlighted row', (done) => { - vm.$nextTick() - .then(() => { - expect(vm.$el.querySelector('.line_content.right-side').classList).not.toContain('hll'); - }) - .then(done) - .catch(done.fail); - }); - - it('highlights nonempty line content when line is the highlighted row', (done) => { - vm.$nextTick() - .then(() => { - vm.$store.state.diffs.highlightedRow = rightLine.line_code; - - return vm.$nextTick(); - }) - .then(() => { - expect(vm.$el.querySelector('.line_content.right-side').classList).toContain('hll'); - }) - .then(done) - .catch(done.fail); - }); - - it('highlights nonempty line content when line is part of a multiline comment', () => { - wrapper.setProps({ isCommented: true }); - return vm.$nextTick().then(() => { - expect(vm.$el.querySelector('.line_content.right-side').classList).toContain('hll'); - }); - }); - }); - - describe('when both sides have content', () => { - let vm; - const thisLine = diffFileMockData.parallel_diff_lines[2]; - const rightLine = diffFileMockData.parallel_diff_lines[2].right; - - beforeEach(() => { - vm = createComponentWithStore(Vue.extend(ParallelDiffTableRow), createStore(), { - line: applyMap(thisLine), - fileHash: diffFileMockData.file_hash, - filePath: diffFileMockData.file_path, - contextLinesPath: 'contextLinesPath', - isHighlighted: false, - }).$mount(); - }); - - it('does not highlight either line when line does not match highlighted row', (done) => { - vm.$nextTick() - .then(() => { - expect(vm.$el.querySelector('.line_content.right-side').classList).not.toContain('hll'); - expect(vm.$el.querySelector('.line_content.left-side').classList).not.toContain('hll'); - }) - .then(done) - .catch(done.fail); - }); - - it('adds hll class to lineContent when line is the highlighted row', (done) => { - vm.$nextTick() - .then(() => { - vm.$store.state.diffs.highlightedRow = rightLine.line_code; - - return vm.$nextTick(); - }) - .then(() => { - expect(vm.$el.querySelector('.line_content.right-side').classList).toContain('hll'); - expect(vm.$el.querySelector('.line_content.left-side').classList).toContain('hll'); - }) - .then(done) - .catch(done.fail); - }); - - describe('sets coverage title and class', () => { - it('for lines with coverage', (done) => { - vm.$nextTick() - .then(() => { - const name = diffFileMockData.file_path; - const line = rightLine.new_line; - - vm.$store.state.diffs.coverageFiles = { files: { [name]: { [line]: 5 } } }; - - return vm.$nextTick(); - }) - .then(() => { - const coverage = vm.$el.querySelector('.line-coverage.right-side'); - - expect(coverage.title).toContain('Test coverage: 5 hits'); - expect(coverage.classList).toContain('coverage'); - }) - .then(done) - .catch(done.fail); - }); - - it('for lines without coverage', (done) => { - vm.$nextTick() - .then(() => { - const name = diffFileMockData.file_path; - const line = rightLine.new_line; - - vm.$store.state.diffs.coverageFiles = { files: { [name]: { [line]: 0 } } }; - - return vm.$nextTick(); - }) - .then(() => { - const coverage = vm.$el.querySelector('.line-coverage.right-side'); - - expect(coverage.title).toContain('No test coverage'); - expect(coverage.classList).toContain('no-coverage'); - }) - .then(done) - .catch(done.fail); - }); - - it('for unknown lines', (done) => { - vm.$nextTick() - .then(() => { - vm.$store.state.diffs.coverageFiles = {}; - - return vm.$nextTick(); - }) - .then(() => { - const coverage = vm.$el.querySelector('.line-coverage.right-side'); - - expect(coverage.title).not.toContain('Coverage'); - expect(coverage.classList).not.toContain('coverage'); - expect(coverage.classList).not.toContain('no-coverage'); - }) - .then(done) - .catch(done.fail); - }); - }); - }); - - describe('Table Cells', () => { - let wrapper; - let store; - let thisLine; - const TEST_USER_ID = 'abc123'; - const TEST_USER = { id: TEST_USER_ID }; - - const createComponent = (props = {}, propsStore = store, data = {}) => { - wrapper = shallowMount(ParallelDiffTableRow, { - store: propsStore, - propsData: { - line: thisLine, - fileHash: diffFileMockData.file_hash, - filePath: diffFileMockData.file_path, - contextLinesPath: 'contextLinesPath', - isHighlighted: false, - ...props, - }, - data() { - return data; - }, - }); - }; - - beforeEach(() => { - // eslint-disable-next-line prefer-destructuring - thisLine = diffFileMockData.parallel_diff_lines[2]; - store = createStore(); - store.state.notes.userData = TEST_USER; - }); - - afterEach(() => { - wrapper.destroy(); - }); - - const findNewTd = () => wrapper.find({ ref: 'newTd' }); - const findOldTd = () => wrapper.find({ ref: 'oldTd' }); - - describe('td', () => { - it('highlights when isHighlighted true', () => { - store.state.diffs.highlightedRow = thisLine.left.line_code; - createComponent({}, store); - - expect(findNewTd().classes()).toContain('hll'); - expect(findOldTd().classes()).toContain('hll'); - }); - - it('does not highlight when isHighlighted false', () => { - createComponent(); - - expect(findNewTd().classes()).not.toContain('hll'); - expect(findOldTd().classes()).not.toContain('hll'); - }); - }); - - describe('comment button', () => { - const findNoteButton = () => wrapper.find({ ref: 'addDiffNoteButtonLeft' }); - - it.each` - hover | line | userData | expectation - ${true} | ${{}} | ${TEST_USER} | ${true} - ${true} | ${{ line: { left: null } }} | ${TEST_USER} | ${false} - ${true} | ${{}} | ${null} | ${false} - ${false} | ${{}} | ${TEST_USER} | ${false} - `( - 'exists is $expectation - with userData ($userData)', - async ({ hover, line, userData, expectation }) => { - store.state.notes.userData = userData; - createComponent(line, store); - if (hover) await wrapper.find('.line_holder').trigger('mouseover'); - - expect(findNoteButton().exists()).toBe(expectation); - }, - ); - - it.each` - line | expectation - ${{ ...thisLine, left: { discussions: [] } }} | ${true} - ${{ ...thisLine, left: { type: 'context', discussions: [] } }} | ${false} - ${{ ...thisLine, left: { type: 'old-nonewline', discussions: [] } }} | ${false} - ${{ ...thisLine, left: { discussions: [{}] } }} | ${false} - `('visible is $expectation - line ($line)', async ({ line, expectation }) => { - createComponent({ line: applyMap(line) }, store, { - isLeftHover: true, - isCommentButtonRendered: true, - }); - - expect(findNoteButton().isVisible()).toBe(expectation); - }); - - it.each` - disabled | commentsDisabled - ${'disabled'} | ${true} - ${undefined} | ${false} - `( - 'has attribute disabled=$disabled when the outer component has prop commentsDisabled=$commentsDisabled', - ({ disabled, commentsDisabled }) => { - thisLine.left.commentsDisabled = commentsDisabled; - createComponent({ line: { ...thisLine } }, store, { - isLeftHover: true, - isCommentButtonRendered: true, - }); - - expect(findNoteButton().attributes('disabled')).toBe(disabled); - }, - ); - - const symlinkishFileTooltip = - 'Commenting on symbolic links that replace or are replaced by files is currently not supported.'; - const realishFileTooltip = - 'Commenting on files that replace or are replaced by symbolic links is currently not supported.'; - const otherFileTooltip = 'Add a comment to this line'; - const findTooltip = () => wrapper.find({ ref: 'addNoteTooltipLeft' }); - - it.each` - tooltip | commentsDisabled - ${symlinkishFileTooltip} | ${{ wasSymbolic: true }} - ${symlinkishFileTooltip} | ${{ isSymbolic: true }} - ${realishFileTooltip} | ${{ wasReal: true }} - ${realishFileTooltip} | ${{ isReal: true }} - ${otherFileTooltip} | ${false} - `( - 'has the correct tooltip when commentsDisabled=$commentsDisabled', - ({ tooltip, commentsDisabled }) => { - thisLine.left.commentsDisabled = commentsDisabled; - createComponent({ line: { ...thisLine } }, store, { - isLeftHover: true, - isCommentButtonRendered: true, - }); - - expect(findTooltip().attributes('title')).toBe(tooltip); - }, - ); - }); - - describe('line number', () => { - const findLineNumberOld = () => wrapper.find({ ref: 'lineNumberRefOld' }); - const findLineNumberNew = () => wrapper.find({ ref: 'lineNumberRefNew' }); - - it('renders line numbers in correct cells', () => { - createComponent(); - - expect(findLineNumberOld().exists()).toBe(true); - expect(findLineNumberNew().exists()).toBe(true); - }); - - describe('with lineNumber prop', () => { - const TEST_LINE_CODE = 'LC_42'; - const TEST_LINE_NUMBER = 1; - - describe.each` - lineProps | findLineNumber | expectedHref | expectedClickArg - ${{ line_code: TEST_LINE_CODE, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${`#${TEST_LINE_CODE}`} | ${TEST_LINE_CODE} - ${{ line_code: undefined, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${'#'} | ${undefined} - `( - 'with line ($lineProps)', - ({ lineProps, findLineNumber, expectedHref, expectedClickArg }) => { - beforeEach(() => { - jest.spyOn(store, 'dispatch').mockImplementation(); - Object.assign(thisLine.left, lineProps); - Object.assign(thisLine.right, lineProps); - createComponent({ - line: applyMap({ ...thisLine }), - }); - }); - - it('renders', () => { - expect(findLineNumber().exists()).toBe(true); - expect(findLineNumber().attributes()).toEqual({ - href: expectedHref, - 'data-linenumber': TEST_LINE_NUMBER.toString(), - }); - }); - - it('on click, dispatches setHighlightedRow', () => { - expect(store.dispatch).toHaveBeenCalledTimes(1); - - findLineNumber().trigger('click'); - - expect(store.dispatch).toHaveBeenCalledWith( - 'diffs/setHighlightedRow', - expectedClickArg, - ); - expect(store.dispatch).toHaveBeenCalledTimes(2); - }); - }, - ); - }); - }); - - describe('diff-gutter-avatars', () => { - const TEST_LINE_CODE = 'LC_42'; - const TEST_FILE_HASH = diffFileMockData.file_hash; - const findAvatars = () => wrapper.find(DiffGutterAvatars); - let line; - - beforeEach(() => { - jest.spyOn(store, 'dispatch').mockImplementation(); - - line = applyMap({ - left: { - line_code: TEST_LINE_CODE, - type: 'new', - old_line: null, - new_line: 1, - discussions: [{ ...discussionsMockData }], - discussionsExpanded: true, - text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n', - rich_text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n', - meta_data: null, - }, - }); - }); - - describe('with showCommentButton', () => { - it('renders if line has discussions', () => { - createComponent({ line }); - - expect(findAvatars().props()).toEqual({ - discussions: line.left.discussions, - discussionsExpanded: line.left.discussionsExpanded, - }); - }); - - it('does notrender if line has no discussions', () => { - line.left.discussions = []; - createComponent({ line: applyMap(line) }); - - expect(findAvatars().exists()).toEqual(false); - }); - - it('toggles line discussion', () => { - createComponent({ line }); - - expect(store.dispatch).toHaveBeenCalledTimes(1); - - findAvatars().vm.$emit('toggleLineDiscussions'); - - expect(store.dispatch).toHaveBeenCalledWith('diffs/toggleLineDiscussions', { - lineCode: TEST_LINE_CODE, - fileHash: TEST_FILE_HASH, - expanded: !line.left.discussionsExpanded, - }); - }); - }); - }); - - describe('interoperability', () => { - beforeEach(() => { - createComponent(); - }); - - it('adds old side interoperability data attributes', () => { - expect(findInteropAttributes(wrapper, '.line_content.left-side')).toEqual({ - type: 'old', - line: thisLine.left.old_line.toString(), - oldLine: thisLine.left.old_line.toString(), - }); - }); - - it('adds new side interoperability data attributes', () => { - expect(findInteropAttributes(wrapper, '.line_content.right-side')).toEqual({ - type: 'new', - line: thisLine.right.new_line.toString(), - newLine: thisLine.right.new_line.toString(), - }); - }); - }); - }); -}); diff --git a/spec/frontend/diffs/components/parallel_diff_view_spec.js b/spec/frontend/diffs/components/parallel_diff_view_spec.js deleted file mode 100644 index 452e1f58551..00000000000 --- a/spec/frontend/diffs/components/parallel_diff_view_spec.js +++ /dev/null @@ -1,37 +0,0 @@ -import { shallowMount, createLocalVue } from '@vue/test-utils'; -import Vuex from 'vuex'; -import parallelDiffTableRow from '~/diffs/components/parallel_diff_table_row.vue'; -import ParallelDiffView from '~/diffs/components/parallel_diff_view.vue'; -import { createStore } from '~/mr_notes/stores'; -import diffFileMockData from '../mock_data/diff_file'; - -let wrapper; -const localVue = createLocalVue(); - -localVue.use(Vuex); - -function factory() { - const diffFile = { ...diffFileMockData }; - const store = createStore(); - - wrapper = shallowMount(ParallelDiffView, { - localVue, - store, - propsData: { - diffFile, - diffLines: diffFile.parallel_diff_lines, - }, - }); -} - -describe('ParallelDiffView', () => { - afterEach(() => { - wrapper.destroy(); - }); - - it('renders diff lines', () => { - factory(); - - expect(wrapper.findAll(parallelDiffTableRow).length).toBe(8); - }); -}); diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js index 14f8e090be9..c2e5d07bcfd 100644 --- a/spec/frontend/diffs/store/actions_spec.js +++ b/spec/frontend/diffs/store/actions_spec.js @@ -8,7 +8,6 @@ import { DIFF_VIEW_COOKIE_NAME, INLINE_DIFF_VIEW_TYPE, PARALLEL_DIFF_VIEW_TYPE, - DIFFS_PER_PAGE, } from '~/diffs/constants'; import { setBaseConfig, @@ -154,16 +153,16 @@ describe('DiffsStoreActions', () => { it('should fetch batch diff files', (done) => { const endpointBatch = '/fetch/diffs_batch'; - const res1 = { diff_files: [{ file_hash: 'test' }], pagination: { next_page: 2 } }; - const res2 = { diff_files: [{ file_hash: 'test2' }], pagination: {} }; + const res1 = { diff_files: [{ file_hash: 'test' }], pagination: { total_pages: 7 } }; + const res2 = { diff_files: [{ file_hash: 'test2' }], pagination: { total_pages: 7 } }; mock .onGet( mergeUrlParams( { w: '1', view: 'inline', - page: 1, - per_page: DIFFS_PER_PAGE, + page: 0, + per_page: 5, }, endpointBatch, ), @@ -174,8 +173,8 @@ describe('DiffsStoreActions', () => { { w: '1', view: 'inline', - page: 2, - per_page: DIFFS_PER_PAGE, + page: 5, + per_page: 7, }, endpointBatch, ), @@ -1020,10 +1019,12 @@ describe('DiffsStoreActions', () => { const endpointUpdateUser = 'user/prefs'; let putSpy; let mock; + let gon; beforeEach(() => { mock = new MockAdapter(axios); putSpy = jest.spyOn(axios, 'put'); + gon = window.gon; mock.onPut(endpointUpdateUser).reply(200, {}); jest.spyOn(eventHub, '$emit').mockImplementation(); @@ -1031,6 +1032,7 @@ describe('DiffsStoreActions', () => { afterEach(() => { mock.restore(); + window.gon = gon; }); it('commits SET_SHOW_WHITESPACE', (done) => { @@ -1044,7 +1046,9 @@ describe('DiffsStoreActions', () => { ); }); - it('saves to the database', async () => { + it('saves to the database when the user is logged in', async () => { + window.gon = { current_user_id: 12345 }; + await setShowWhitespace( { state: { endpointUpdateUser }, commit() {} }, { showWhitespace: true, updateDatabase: true }, @@ -1053,6 +1057,17 @@ describe('DiffsStoreActions', () => { expect(putSpy).toHaveBeenCalledWith(endpointUpdateUser, { show_whitespace_in_diffs: true }); }); + it('does not try to save to the API if the user is not logged in', async () => { + window.gon = {}; + + await setShowWhitespace( + { state: { endpointUpdateUser }, commit() {} }, + { showWhitespace: true, updateDatabase: true }, + ); + + expect(putSpy).not.toHaveBeenCalled(); + }); + it('emits eventHub event', async () => { await setShowWhitespace( { state: {}, commit() {} }, diff --git a/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js b/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js index dbef547c297..99f13a1c84c 100644 --- a/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js +++ b/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js @@ -54,7 +54,7 @@ describe('Compare diff version dropdowns', () => { Object.defineProperty(window, 'location', { writable: true, - value: { href: `https://example.gitlab.com${diffHeadParam}` }, + value: { search: diffHeadParam }, }); expectedFirstVersion = { |