diff options
Diffstat (limited to 'spec/frontend/diffs/components')
18 files changed, 267 insertions, 175 deletions
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js index fb5cf4dfd0a..c1f0966f9c6 100644 --- a/spec/frontend/diffs/components/app_spec.js +++ b/spec/frontend/diffs/components/app_spec.js @@ -2,6 +2,7 @@ import { GlLoadingIcon, GlPagination } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import Vue, { nextTick } from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import setWindowLocation from 'helpers/set_window_location_helper'; import { TEST_HOST } from 'spec/test_constants'; @@ -11,7 +12,7 @@ import CompareVersions from '~/diffs/components/compare_versions.vue'; import DiffFile from '~/diffs/components/diff_file.vue'; import NoChanges from '~/diffs/components/no_changes.vue'; import findingsDrawer from '~/diffs/components/shared/findings_drawer.vue'; -import TreeList from '~/diffs/components/tree_list.vue'; +import DiffsFileTree from '~/diffs/components/diffs_file_tree.vue'; import CollapsedFilesWarning from '~/diffs/components/collapsed_files_warning.vue'; import HiddenFilesWarning from '~/diffs/components/hidden_files_warning.vue'; @@ -252,34 +253,6 @@ describe('diffs/components/app', () => { }); }); - 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({}, ({ state }) => { - state.diffs.treeEntries = { 111: { type: 'blob', fileHash: '111', path: '111.js' } }; - }); - - expect(wrapper.find('.js-diff-tree-list').element.style.width).toEqual('320px'); - }); - }); - it('marks current diff file based on currently highlighted row', async () => { window.location.hash = 'ABC_123'; @@ -596,18 +569,21 @@ describe('diffs/components/app', () => { ); }); - it("doesn't render tree list when no changes exist", () => { + it('should always render diffs file tree', () => { createComponent(); - - expect(wrapper.findComponent(TreeList).exists()).toBe(false); + expect(wrapper.findComponent(DiffsFileTree).exists()).toBe(true); }); - it('should render tree list', () => { + it('should pass renderDiffFiles to file tree as true when files are present', () => { createComponent({}, ({ state }) => { state.diffs.treeEntries = { 111: { type: 'blob', fileHash: '111', path: '111.js' } }; }); + expect(wrapper.findComponent(DiffsFileTree).props('renderDiffFiles')).toBe(true); + }); - expect(wrapper.findComponent(TreeList).exists()).toBe(true); + it('should pass renderDiffFiles to file tree as false without files', () => { + createComponent(); + expect(wrapper.findComponent(DiffsFileTree).props('renderDiffFiles')).toBe(false); }); }); diff --git a/spec/frontend/diffs/components/collapsed_files_warning_spec.js b/spec/frontend/diffs/components/collapsed_files_warning_spec.js index ae40f6c898d..4e34691f72b 100644 --- a/spec/frontend/diffs/components/collapsed_files_warning_spec.js +++ b/spec/frontend/diffs/components/collapsed_files_warning_spec.js @@ -1,5 +1,6 @@ import { shallowMount, mount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import CollapsedFilesWarning from '~/diffs/components/collapsed_files_warning.vue'; import { EVT_EXPAND_ALL_FILES } from '~/diffs/constants'; diff --git a/spec/frontend/diffs/components/compare_versions_spec.js b/spec/frontend/diffs/components/compare_versions_spec.js index cbbfd88260b..3601f0cc7b0 100644 --- a/spec/frontend/diffs/components/compare_versions_spec.js +++ b/spec/frontend/diffs/components/compare_versions_spec.js @@ -84,7 +84,7 @@ describe('CompareVersions', () => { const treeListBtn = wrapper.find('.js-toggle-tree-list'); expect(treeListBtn.exists()).toBe(true); - expect(treeListBtn.attributes('title')).toBe('Hide file browser'); + expect(treeListBtn.attributes('title')).toBe('Hide file browser (or press F)'); expect(treeListBtn.props('icon')).toBe('file-tree'); }); diff --git a/spec/frontend/diffs/components/diff_code_quality_spec.js b/spec/frontend/diffs/components/diff_code_quality_spec.js deleted file mode 100644 index 73976ebd713..00000000000 --- a/spec/frontend/diffs/components/diff_code_quality_spec.js +++ /dev/null @@ -1,61 +0,0 @@ -import { mountExtended } from 'helpers/vue_test_utils_helper'; -import DiffCodeQuality from '~/diffs/components/diff_code_quality.vue'; -import DiffInlineFindings from '~/diffs/components/diff_inline_findings.vue'; -import { NEW_CODE_QUALITY_FINDINGS, NEW_SAST_FINDINGS } from '~/diffs/i18n'; -import { - multipleCodeQualityNoSast, - multipleSastNoCodeQuality, -} from '../mock_data/diff_code_quality'; - -let wrapper; - -const diffInlineFindings = () => wrapper.findComponent(DiffInlineFindings); -const allDiffInlineFindings = () => wrapper.findAllComponents(DiffInlineFindings); - -describe('DiffCodeQuality', () => { - const createWrapper = (findings) => { - return mountExtended(DiffCodeQuality, { - propsData: { - expandedLines: [], - codeQuality: findings.codeQuality, - sast: findings.sast, - }, - }); - }; - - it('hides details and throws hideCodeQualityFindings event on close click', async () => { - wrapper = createWrapper(multipleCodeQualityNoSast); - expect(wrapper.findByTestId('diff-codequality').exists()).toBe(true); - - await wrapper.findByTestId('diff-codequality-close').trigger('click'); - expect(wrapper.emitted('hideCodeQualityFindings')).toHaveLength(1); - }); - - it('renders diff inline findings component with correct props for codequality array', () => { - wrapper = createWrapper(multipleCodeQualityNoSast); - - expect(diffInlineFindings().props('title')).toBe(NEW_CODE_QUALITY_FINDINGS); - expect(diffInlineFindings().props('findings')).toBe(multipleCodeQualityNoSast.codeQuality); - }); - - it('does not render codeQuality section when codeQuality array is empty', () => { - wrapper = createWrapper(multipleSastNoCodeQuality); - - expect(diffInlineFindings().props('title')).toBe(NEW_SAST_FINDINGS); - expect(allDiffInlineFindings()).toHaveLength(1); - }); - - it('renders heading and correct amount of list items for sast array and their description', () => { - wrapper = createWrapper(multipleSastNoCodeQuality); - - expect(diffInlineFindings().props('title')).toBe(NEW_SAST_FINDINGS); - expect(diffInlineFindings().props('findings')).toBe(multipleSastNoCodeQuality.sast); - }); - - it('does not render sast section when sast array is empty', () => { - wrapper = createWrapper(multipleCodeQualityNoSast); - - expect(diffInlineFindings().props('title')).toBe(NEW_CODE_QUALITY_FINDINGS); - expect(allDiffInlineFindings()).toHaveLength(1); - }); -}); diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js index 3b37edbcb1d..be085ba1525 100644 --- a/spec/frontend/diffs/components/diff_content_spec.js +++ b/spec/frontend/diffs/components/diff_content_spec.js @@ -1,11 +1,11 @@ import { GlLoadingIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import waitForPromises from 'helpers/wait_for_promises'; import { sprintf } from '~/locale'; import { createAlert } from '~/alert'; -import * as diffRowUtils from 'ee_else_ce/diffs/components/diff_row_utils'; import DiffContentComponent from '~/diffs/components/diff_content.vue'; import DiffDiscussions from '~/diffs/components/diff_discussions.vue'; import DiffView from '~/diffs/components/diff_view.vue'; @@ -120,32 +120,6 @@ describe('DiffContent', () => { expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true); }); - - it('should include Sast findings when sastReportsInInlineDiff flag is true', () => { - const mapParallelSpy = jest.spyOn(diffRowUtils, 'mapParallel'); - const mapParallelNoSastSpy = jest.spyOn(diffRowUtils, 'mapParallelNoSast'); - createComponent({ - provide: { - glFeatures: { - sastReportsInInlineDiff: true, - }, - }, - props: { diffFile: { ...textDiffFile, renderingLines: true } }, - }); - - expect(mapParallelSpy).toHaveBeenCalled(); - expect(mapParallelNoSastSpy).not.toHaveBeenCalled(); - }); - - it('should not include Sast findings when sastReportsInInlineDiff flag is false', () => { - const mapParallelSpy = jest.spyOn(diffRowUtils, 'mapParallel'); - const mapParallelNoSastSpy = jest.spyOn(diffRowUtils, 'mapParallelNoSast'); - - createComponent({ props: { diffFile: { ...textDiffFile, renderingLines: true } } }); - - expect(mapParallelNoSastSpy).toHaveBeenCalled(); - expect(mapParallelSpy).not.toHaveBeenCalled(); - }); }); describe('with whitespace only change', () => { diff --git a/spec/frontend/diffs/components/diff_discussion_reply_spec.js b/spec/frontend/diffs/components/diff_discussion_reply_spec.js index 348439d6006..1e542c413b2 100644 --- a/spec/frontend/diffs/components/diff_discussion_reply_spec.js +++ b/spec/frontend/diffs/components/diff_discussion_reply_spec.js @@ -1,6 +1,7 @@ import { shallowMount } from '@vue/test-utils'; import { GlButton } from '@gitlab/ui'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import DiffDiscussionReply from '~/diffs/components/diff_discussion_reply.vue'; import NoteSignedOutWidget from '~/notes/components/note_signed_out_widget.vue'; diff --git a/spec/frontend/diffs/components/diff_file_header_spec.js b/spec/frontend/diffs/components/diff_file_header_spec.js index d3afaab492d..b089825090b 100644 --- a/spec/frontend/diffs/components/diff_file_header_spec.js +++ b/spec/frontend/diffs/components/diff_file_header_spec.js @@ -1,6 +1,7 @@ import { shallowMount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import { cloneDeep } from 'lodash'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { mockTracking, triggerEvent } from 'helpers/tracking_helper'; diff --git a/spec/frontend/diffs/components/diff_file_spec.js b/spec/frontend/diffs/components/diff_file_spec.js index db6cde883f3..53f135471b7 100644 --- a/spec/frontend/diffs/components/diff_file_spec.js +++ b/spec/frontend/diffs/components/diff_file_spec.js @@ -1,5 +1,6 @@ import MockAdapter from 'axios-mock-adapter'; import Vue, { nextTick } from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; @@ -42,6 +43,7 @@ jest.mock('~/notes/mixins/diff_line_note_form', () => ({ Vue.use(Vuex); const saveDiffDiscussionMock = jest.fn(); +const prefetchFileNeighborsMock = jest.fn(); function changeViewer(store, index, { automaticallyCollapsed, manuallyCollapsed, name }) { const file = store.state.diffs.diffFiles[index]; @@ -91,6 +93,7 @@ function createComponent({ file, first = false, last = false, options = {}, prop const diffs = diffsModule(); diffs.actions = { ...diffs.actions, + prefetchFileNeighbors: prefetchFileNeighborsMock, saveDiffDiscussion: saveDiffDiscussionMock, }; @@ -155,19 +158,44 @@ const triggerSaveDraftNote = (wrapper, note, parent, error) => findNoteForm(wrapper).vm.$emit('handleFormUpdateAddToReview', note, false, parent, error); describe('DiffFile', () => { + let readableFile; let wrapper; let store; let axiosMock; beforeEach(() => { + readableFile = getReadableFile(); axiosMock = new MockAdapter(axios); - ({ wrapper, store } = createComponent({ file: getReadableFile() })); + ({ wrapper, store } = createComponent({ file: readableFile })); }); afterEach(() => { axiosMock.restore(); }); + describe('mounted', () => { + beforeEach(() => { + jest.spyOn(window, 'requestIdleCallback').mockImplementation((fn) => fn()); + }); + + it.each` + description | fileByFile + ${'does not prefetch if not in file-by-file mode'} | ${false} + ${'prefetches when in file-by-file mode'} | ${true} + `('$description', ({ fileByFile }) => { + createComponent({ + props: { viewDiffsFileByFile: fileByFile }, + file: readableFile, + }); + + if (fileByFile) { + expect(prefetchFileNeighborsMock).toHaveBeenCalled(); + } else { + expect(prefetchFileNeighborsMock).not.toHaveBeenCalled(); + } + }); + }); + describe('bus events', () => { beforeEach(() => { jest.spyOn(eventHub, '$emit').mockImplementation(() => {}); diff --git a/spec/frontend/diffs/components/diff_code_quality_item_spec.js b/spec/frontend/diffs/components/diff_inline_findings_item_spec.js index 085eb096239..72d96d3435f 100644 --- a/spec/frontend/diffs/components/diff_code_quality_item_spec.js +++ b/spec/frontend/diffs/components/diff_inline_findings_item_spec.js @@ -1,8 +1,8 @@ import { GlIcon, GlLink } from '@gitlab/ui'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; -import DiffCodeQualityItem from '~/diffs/components/diff_code_quality_item.vue'; +import DiffInlineFindingsItem from '~/diffs/components/diff_inline_findings_item.vue'; import { SEVERITY_CLASSES, SEVERITY_ICONS } from '~/ci/reports/codequality_report/constants'; -import { multipleFindingsArrCodeQualityScale } from '../mock_data/diff_code_quality'; +import { multipleFindingsArrCodeQualityScale } from '../mock_data/inline_findings'; let wrapper; @@ -14,7 +14,7 @@ const findDescriptionLinkSection = () => wrapper.findByTestId('description-butto describe('DiffCodeQuality', () => { const createWrapper = ({ glFeatures = {}, link = true } = {}) => { - return shallowMountExtended(DiffCodeQualityItem, { + return shallowMountExtended(DiffInlineFindingsItem, { propsData: { finding: codeQualityFinding, link, @@ -30,7 +30,7 @@ describe('DiffCodeQuality', () => { expect(findIcon().exists()).toBe(true); expect(findIcon().attributes()).toMatchObject({ - class: `codequality-severity-icon ${SEVERITY_CLASSES[codeQualityFinding.severity]}`, + class: `inline-findings-severity-icon ${SEVERITY_CLASSES[codeQualityFinding.severity]}`, name: SEVERITY_ICONS[codeQualityFinding.severity], size: '12', }); diff --git a/spec/frontend/diffs/components/diff_inline_findings_spec.js b/spec/frontend/diffs/components/diff_inline_findings_spec.js index 9ccfb2a613d..65b2abe7dd5 100644 --- a/spec/frontend/diffs/components/diff_inline_findings_spec.js +++ b/spec/frontend/diffs/components/diff_inline_findings_spec.js @@ -1,12 +1,12 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import DiffInlineFindings from '~/diffs/components/diff_inline_findings.vue'; -import DiffCodeQualityItem from '~/diffs/components/diff_code_quality_item.vue'; +import DiffInlineFindingsItem from '~/diffs/components/diff_inline_findings_item.vue'; import { NEW_CODE_QUALITY_FINDINGS } from '~/diffs/i18n'; -import { multipleCodeQualityNoSast } from '../mock_data/diff_code_quality'; +import { multipleCodeQualityNoSast } from '../mock_data/inline_findings'; let wrapper; const heading = () => wrapper.findByTestId('diff-inline-findings-heading'); -const diffCodeQualityItems = () => wrapper.findAllComponents(DiffCodeQualityItem); +const diffInlineFindingsItems = () => wrapper.findAllComponents(DiffInlineFindingsItem); describe('DiffInlineFindings', () => { const createWrapper = () => { @@ -23,10 +23,10 @@ describe('DiffInlineFindings', () => { expect(heading().text()).toBe(NEW_CODE_QUALITY_FINDINGS); }); - it('renders the correct number of DiffCodeQualityItem components with correct props', () => { + it('renders the correct number of DiffInlineFindingsItem components with correct props', () => { wrapper = createWrapper(); - expect(diffCodeQualityItems()).toHaveLength(multipleCodeQualityNoSast.codeQuality.length); - expect(diffCodeQualityItems().wrappers[0].props('finding')).toEqual( + expect(diffInlineFindingsItems()).toHaveLength(multipleCodeQualityNoSast.codeQuality.length); + expect(diffInlineFindingsItems().wrappers[0].props('finding')).toEqual( wrapper.props('findings')[0], ); }); diff --git a/spec/frontend/diffs/components/diff_line_note_form_spec.js b/spec/frontend/diffs/components/diff_line_note_form_spec.js index 0ca48db2497..dfbf45e1d71 100644 --- a/spec/frontend/diffs/components/diff_line_note_form_spec.js +++ b/spec/frontend/diffs/components/diff_line_note_form_spec.js @@ -7,11 +7,13 @@ import DiffLineNoteForm from '~/diffs/components/diff_line_note_form.vue'; import store from '~/mr_notes/stores'; import NoteForm from '~/notes/components/note_form.vue'; import MultilineCommentForm from '~/notes/components/multiline_comment_form.vue'; +import { clearDraft } from '~/lib/utils/autosave'; import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal'; import { noteableDataMock } from 'jest/notes/mock_data'; import { SOMETHING_WENT_WRONG, SAVING_THE_COMMENT_FAILED } from '~/diffs/i18n'; import { getDiffFileMock } from '../mock_data/diff_file'; +jest.mock('~/lib/utils/autosave'); jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal'); jest.mock('~/mr_notes/stores', () => jest.requireActual('helpers/mocks/mr_notes/stores')); jest.mock('~/alert'); @@ -116,6 +118,17 @@ describe('DiffLineNoteForm', () => { fileHash: diffFile.file_hash, }); }); + + it('should clear the autosaved draft', async () => { + findNoteForm().vm.$emit('cancelForm', true, true); + await nextTick(); + expect(confirmAction).toHaveBeenCalled(); + await nextTick(); + + expect(clearDraft).toHaveBeenCalledWith( + `Note/Issue/${noteableDataMock.id}//DiffNote//${diffLines[1].line_code}`, + ); + }); }); describe('without confirmation', () => { diff --git a/spec/frontend/diffs/components/diff_line_spec.js b/spec/frontend/diffs/components/diff_line_spec.js index a552a9d3e7f..501bd0757c8 100644 --- a/spec/frontend/diffs/components/diff_line_spec.js +++ b/spec/frontend/diffs/components/diff_line_spec.js @@ -1,6 +1,6 @@ import { shallowMount } from '@vue/test-utils'; import DiffLine from '~/diffs/components/diff_line.vue'; -import DiffCodeQuality from '~/diffs/components/diff_code_quality.vue'; +import InlineFindings from '~/diffs/components/inline_findings.vue'; const EXAMPLE_LINE_NUMBER = 3; const EXAMPLE_DESCRIPTION = 'example description'; @@ -16,13 +16,6 @@ const left = { severity: EXAMPLE_SEVERITY, }, ], - sast: [ - { - line: EXAMPLE_LINE_NUMBER, - description: EXAMPLE_DESCRIPTION, - severity: EXAMPLE_SEVERITY, - }, - ], }, }, }; @@ -37,13 +30,6 @@ const right = { severity: EXAMPLE_SEVERITY, }, ], - sast: [ - { - line: EXAMPLE_LINE_NUMBER, - description: EXAMPLE_DESCRIPTION, - severity: EXAMPLE_SEVERITY, - }, - ], }, }, }; @@ -55,26 +41,19 @@ describe('DiffLine', () => { return shallowMount(DiffLine, { propsData }); }; - it('should emit event when hideCodeQualityFindings is called', () => { + it('should emit event when hideInlineFindings is called', () => { const wrapper = createWrapper(right); - wrapper.findComponent(DiffCodeQuality).vm.$emit('hideCodeQualityFindings'); + wrapper.findComponent(InlineFindings).vm.$emit('hideInlineFindings'); expect(wrapper.emitted()).toEqual({ - hideCodeQualityFindings: [[EXAMPLE_LINE_NUMBER]], + hideInlineFindings: [[EXAMPLE_LINE_NUMBER]], }); }); mockData.forEach((element) => { - it('should set correct props for DiffCodeQuality', () => { + it('should set correct props for InlineFindings', () => { const wrapper = createWrapper(element); - expect(wrapper.findComponent(DiffCodeQuality).props('codeQuality')).toEqual([ - { - line: EXAMPLE_LINE_NUMBER, - description: EXAMPLE_DESCRIPTION, - severity: EXAMPLE_SEVERITY, - }, - ]); - expect(wrapper.findComponent(DiffCodeQuality).props('sast')).toEqual([ + expect(wrapper.findComponent(InlineFindings).props('codeQuality')).toEqual([ { line: EXAMPLE_LINE_NUMBER, description: EXAMPLE_DESCRIPTION, diff --git a/spec/frontend/diffs/components/diff_row_spec.js b/spec/frontend/diffs/components/diff_row_spec.js index 119b8f9ad7f..8a67d7b152c 100644 --- a/spec/frontend/diffs/components/diff_row_spec.js +++ b/spec/frontend/diffs/components/diff_row_spec.js @@ -1,6 +1,7 @@ import { getByTestId, fireEvent } from '@testing-library/dom'; import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import DiffRow from '~/diffs/components/diff_row.vue'; import { mapParallel } from '~/diffs/components/diff_row_utils'; diff --git a/spec/frontend/diffs/components/diff_view_spec.js b/spec/frontend/diffs/components/diff_view_spec.js index 8778683c135..2c8f751804e 100644 --- a/spec/frontend/diffs/components/diff_view_spec.js +++ b/spec/frontend/diffs/components/diff_view_spec.js @@ -1,10 +1,11 @@ import { shallowMount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { throttle } from 'lodash'; import DiffView from '~/diffs/components/diff_view.vue'; import DiffLine from '~/diffs/components/diff_line.vue'; -import { diffCodeQuality } from '../mock_data/diff_code_quality'; +import { diffCodeQuality } from '../mock_data/inline_findings'; jest.mock('lodash/throttle', () => jest.fn((fn) => fn)); const lodash = jest.requireActual('lodash'); @@ -18,7 +19,7 @@ describe('DiffView', () => { const setSelectedCommentPosition = jest.fn(); const getDiffRow = (wrapper) => wrapper.findComponent(DiffRow).vm; - const createWrapper = (props) => { + const createWrapper = ({ props, flag = false } = {}) => { Vue.use(Vuex); const batchComments = { @@ -50,9 +51,21 @@ describe('DiffView', () => { diffFile: { file_hash: '123' }, diffLines: [], ...props, + provide: { + glFeatures: { + sastReportsInInlineDiff: flag, + }, + }, + }; + + const provide = { + glFeatures: { + sastReportsInInlineDiff: flag, + }, }; + const stubs = { DiffExpansionCell, DiffRow, DiffCommentCell, DraftNote }; - return shallowMount(DiffView, { propsData, store, stubs }); + return shallowMount(DiffView, { propsData, provide, store, stubs }); }; beforeEach(() => { @@ -69,12 +82,26 @@ describe('DiffView', () => { }); it('does render a diff-line component with the correct props when there is a finding', async () => { - const wrapper = createWrapper(diffCodeQuality); + const wrapper = createWrapper({ props: diffCodeQuality }); wrapper.findComponent(DiffRow).vm.$emit('toggleCodeQualityFindings', 2); await nextTick(); expect(wrapper.findComponent(DiffLine).props('line')).toBe(diffCodeQuality.diffLines[2]); }); + it('does not render a diff-line component when there is a finding and sastReportsInInlineDiff flag is true', async () => { + const wrapper = createWrapper({ props: diffCodeQuality, flag: true }); + wrapper.findComponent(DiffRow).vm.$emit('toggleCodeQualityFindings', 2); + await nextTick(); + expect(wrapper.findComponent(DiffLine).exists()).toBe(false); + }); + + it('does render a diff-line component when there is a finding and sastReportsInInlineDiff flag is false', async () => { + const wrapper = createWrapper({ props: diffCodeQuality }); + wrapper.findComponent(DiffRow).vm.$emit('toggleCodeQualityFindings', 2); + await nextTick(); + expect(wrapper.findComponent(DiffLine).exists()).toBe(true); + }); + it.each` type | side | container | sides | total ${'parallel'} | ${'left'} | ${'.old'} | ${{ left: { lineDrafts: [], renderDiscussion: true }, right: { lineDrafts: [], renderDiscussion: true } }} | ${2} @@ -86,8 +113,10 @@ describe('DiffView', () => { 'renders a $type comment row with comment cell on $side', ({ type, container, sides, total }) => { const wrapper = createWrapper({ - diffLines: [{ renderCommentRow: true, ...sides }], - inline: type === 'inline', + props: { + diffLines: [{ renderCommentRow: true, ...sides }], + inline: type === 'inline', + }, }); expect(wrapper.findAllComponents(DiffCommentCell).length).toBe(total); expect(wrapper.find(container).findComponent(DiffCommentCell).exists()).toBe(true); @@ -96,21 +125,20 @@ describe('DiffView', () => { it('renders a draft row', () => { const wrapper = createWrapper({ - diffLines: [{ renderCommentRow: true, left: { lineDrafts: [{ isDraft: true }] } }], + props: { diffLines: [{ renderCommentRow: true, left: { lineDrafts: [{ isDraft: true }] } }] }, }); expect(wrapper.findComponent(DraftNote).exists()).toBe(true); }); describe('drag operations', () => { it('sets `dragStart` onStartDragging', () => { - const wrapper = createWrapper({ diffLines: [{}] }); - + const wrapper = createWrapper({ props: { diffLines: [{}] } }); 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 wrapper = createWrapper({ props: { diffLines: [{}] } }); const diffRow = getDiffRow(wrapper); diffRow.$emit('startdragging', { line: { chunk: 0 } }); @@ -127,7 +155,7 @@ describe('DiffView', () => { `( 'calls `setSelectedCommentPosition` with correct `updatedLineRange`', ({ start, end, expectation }) => { - const wrapper = createWrapper({ diffLines: [{}] }); + const wrapper = createWrapper({ props: { diffLines: [{}] } }); const diffRow = getDiffRow(wrapper); diffRow.$emit('startdragging', { line: { chunk: 1, index: start } }); @@ -140,7 +168,7 @@ describe('DiffView', () => { ); it('sets `dragStart` to null onStopDragging', () => { - const wrapper = createWrapper({ diffLines: [{}] }); + const wrapper = createWrapper({ props: { diffLines: [{}] } }); const diffRow = getDiffRow(wrapper); diffRow.$emit('startdragging', { line: { test: true } }); @@ -152,7 +180,8 @@ describe('DiffView', () => { }); it('throttles multiple calls to enterdragging', () => { - const wrapper = createWrapper({ diffLines: [{}] }); + const wrapper = createWrapper({ props: { diffLines: [{}] } }); + const diffRow = getDiffRow(wrapper); diffRow.$emit('startdragging', { line: { chunk: 1, index: 1 } }); diff --git a/spec/frontend/diffs/components/diffs_file_tree_spec.js b/spec/frontend/diffs/components/diffs_file_tree_spec.js new file mode 100644 index 00000000000..a79023a07cb --- /dev/null +++ b/spec/frontend/diffs/components/diffs_file_tree_spec.js @@ -0,0 +1,116 @@ +import { nextTick } from 'vue'; +import { shallowMount } from '@vue/test-utils'; +import { Mousetrap } from '~/lib/mousetrap'; +import DiffsFileTree from '~/diffs/components/diffs_file_tree.vue'; +import TreeList from '~/diffs/components/tree_list.vue'; +import PanelResizer from '~/vue_shared/components/panel_resizer.vue'; +import { SET_SHOW_TREE_LIST } from '~/diffs/store/mutation_types'; +import createDiffsStore from '../create_diffs_store'; + +describe('DiffsFileTree', () => { + let wrapper; + let store; + + const createComponent = ({ renderDiffFiles = true, showTreeList = true } = {}) => { + store = createDiffsStore(); + store.commit(`diffs/${SET_SHOW_TREE_LIST}`, showTreeList); + wrapper = shallowMount(DiffsFileTree, { + store, + propsData: { + renderDiffFiles, + }, + }); + }; + + describe('visibility', () => { + describe('when renderDiffFiles and showTreeList are true', () => { + beforeEach(() => { + createComponent(); + }); + + it('tree list is visible', () => { + expect(wrapper.findComponent(TreeList).exists()).toBe(true); + }); + }); + + describe('when renderDiffFiles and showTreeList are false', () => { + beforeEach(() => { + createComponent({ renderDiffFiles: false, showTreeList: false }); + }); + + it('tree list is hidden', () => { + expect(wrapper.findComponent(TreeList).exists()).toBe(false); + }); + }); + }); + + it('emits toggled event', async () => { + createComponent(); + store.commit(`diffs/${SET_SHOW_TREE_LIST}`, false); + await nextTick(); + expect(wrapper.emitted('toggled')).toStrictEqual([[]]); + }); + + it('toggles when "f" hotkey is pressed', async () => { + createComponent(); + Mousetrap.trigger('f'); + await nextTick(); + expect(wrapper.findComponent(TreeList).exists()).toBe(false); + }); + + describe('size', () => { + const checkWidth = (width) => { + expect(wrapper.element.style.width).toEqual(`${width}px`); + expect(wrapper.findComponent(PanelResizer).props('startSize')).toEqual(width); + }; + + afterEach(() => { + localStorage.removeItem('mr_tree_list_width'); + }); + + describe('when no localStorage record is set', () => { + beforeEach(() => { + createComponent(); + }); + + it('sets initial width when no localStorage has been set', () => { + checkWidth(320); + }); + }); + + it('sets initial width to localStorage size', () => { + localStorage.setItem('mr_tree_list_width', '200'); + createComponent(); + checkWidth(200); + }); + + it('sets width of tree list', () => { + createComponent({}, ({ state }) => { + state.diffs.treeEntries = { 111: { type: 'blob', fileHash: '111', path: '111.js' } }; + }); + checkWidth(320); + }); + + it('updates width', async () => { + const WIDTH = 500; + createComponent(); + wrapper.findComponent(PanelResizer).vm.$emit('update:size', WIDTH); + await nextTick(); + checkWidth(WIDTH); + }); + + it('passes down hideFileStats as true when width is less than 260', async () => { + createComponent(); + wrapper.findComponent(PanelResizer).vm.$emit('update:size', 200); + await nextTick(); + expect(wrapper.findComponent(TreeList).props('hideFileStats')).toBe(true); + }); + + it('passes down hideFileStats as false when width is bigger than 260', async () => { + createComponent(); + wrapper.findComponent(PanelResizer).vm.$emit('update:size', 300); + await nextTick(); + expect(wrapper.findComponent(TreeList).props('hideFileStats')).toBe(false); + }); + }); +}); diff --git a/spec/frontend/diffs/components/inline_findings_spec.js b/spec/frontend/diffs/components/inline_findings_spec.js new file mode 100644 index 00000000000..71cc6ae49fd --- /dev/null +++ b/spec/frontend/diffs/components/inline_findings_spec.js @@ -0,0 +1,33 @@ +import { mountExtended } from 'helpers/vue_test_utils_helper'; +import InlineFindings from '~/diffs/components/inline_findings.vue'; +import DiffInlineFindings from '~/diffs/components/diff_inline_findings.vue'; +import { NEW_CODE_QUALITY_FINDINGS } from '~/diffs/i18n'; +import { threeCodeQualityFindingsRaw } from '../mock_data/inline_findings'; + +let wrapper; + +const diffInlineFindings = () => wrapper.findComponent(DiffInlineFindings); + +describe('InlineFindings', () => { + const createWrapper = () => { + return mountExtended(InlineFindings, { + propsData: { + codeQuality: threeCodeQualityFindingsRaw, + }, + }); + }; + + it('hides details and throws hideInlineFindings event on close click', async () => { + wrapper = createWrapper(); + expect(wrapper.findByTestId('inline-findings').exists()).toBe(true); + + await wrapper.findByTestId('inline-findings-close').trigger('click'); + expect(wrapper.emitted('hideInlineFindings')).toHaveLength(1); + }); + + it('renders diff inline findings component with correct props for codequality array', () => { + wrapper = createWrapper(); + expect(diffInlineFindings().props('title')).toBe(NEW_CODE_QUALITY_FINDINGS); + expect(diffInlineFindings().props('findings')).toBe(threeCodeQualityFindingsRaw); + }); +}); diff --git a/spec/frontend/diffs/components/shared/__snapshots__/findings_drawer_spec.js.snap b/spec/frontend/diffs/components/shared/__snapshots__/findings_drawer_spec.js.snap index e82687aa146..51bd8f380ee 100644 --- a/spec/frontend/diffs/components/shared/__snapshots__/findings_drawer_spec.js.snap +++ b/spec/frontend/diffs/components/shared/__snapshots__/findings_drawer_spec.js.snap @@ -30,7 +30,7 @@ exports[`FindingsDrawer matches the snapshot 1`] = ` </span> <gl-icon-stub - class="codequality-severity-icon gl-text-orange-300" + class="inline-findings-severity-icon gl-text-orange-300" data-testid="findings-drawer-severity-icon" name="severity-low" size="12" diff --git a/spec/frontend/diffs/components/tree_list_spec.js b/spec/frontend/diffs/components/tree_list_spec.js index f56dd28ce9c..a54cf9b8bff 100644 --- a/spec/frontend/diffs/components/tree_list_spec.js +++ b/spec/frontend/diffs/components/tree_list_spec.js @@ -1,4 +1,5 @@ import Vue, { nextTick } from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import TreeList from '~/diffs/components/tree_list.vue'; import createStore from '~/diffs/store/modules'; |