diff options
Diffstat (limited to 'spec/frontend')
19 files changed, 757 insertions, 164 deletions
diff --git a/spec/frontend/boards/services/board_service_spec.js b/spec/frontend/boards/services/board_service_spec.js index e106c2bf1f1..86f49f63f4e 100644 --- a/spec/frontend/boards/services/board_service_spec.js +++ b/spec/frontend/boards/services/board_service_spec.js @@ -97,8 +97,9 @@ describe('BoardService', () => { describe('updateList', () => { const id = 'David Webb'; const position = 'unknown'; + const collapsed = false; const expectedRequest = expect.objectContaining({ - data: JSON.stringify({ list: { position } }), + data: JSON.stringify({ list: { position, collapsed } }), }); let requestSpy; @@ -112,7 +113,7 @@ describe('BoardService', () => { requestSpy.mockReturnValue([200, dummyResponse]); const expectedResponse = expect.objectContaining({ data: dummyResponse }); - return expect(service.updateList(id, position)) + return expect(service.updateList(id, position, collapsed)) .resolves.toEqual(expectedResponse) .then(() => { expect(requestSpy).toHaveBeenCalledWith(expectedRequest); @@ -122,7 +123,7 @@ describe('BoardService', () => { it('fails for error response', () => { requestSpy.mockReturnValue([500]); - return expect(service.updateList(id, position)) + return expect(service.updateList(id, position, collapsed)) .rejects.toThrow() .then(() => { expect(requestSpy).toHaveBeenCalledWith(expectedRequest); diff --git a/spec/frontend/clusters/clusters_bundle_spec.js b/spec/frontend/clusters/clusters_bundle_spec.js index 80816faa5fc..517d8781600 100644 --- a/spec/frontend/clusters/clusters_bundle_spec.js +++ b/spec/frontend/clusters/clusters_bundle_spec.js @@ -11,6 +11,8 @@ import { loadHTMLFixture } from 'helpers/fixtures'; import { setTestTimeout } from 'helpers/timeout'; import $ from 'jquery'; +jest.mock('~/lib/utils/poll'); + const { INSTALLING, INSTALLABLE, INSTALLED, UNINSTALLING } = APPLICATION_STATUS; describe('Clusters', () => { @@ -44,6 +46,17 @@ describe('Clusters', () => { mock.restore(); }); + describe('class constructor', () => { + beforeEach(() => { + jest.spyOn(Clusters.prototype, 'initPolling'); + cluster = new Clusters(); + }); + + it('should call initPolling on construct', () => { + expect(cluster.initPolling).toHaveBeenCalled(); + }); + }); + describe('toggle', () => { it('should update the button and the input field on click', done => { const toggleButton = document.querySelector( @@ -327,14 +340,31 @@ describe('Clusters', () => { }); }); - describe('handleSuccess', () => { + describe('fetch cluster environments success', () => { + beforeEach(() => { + jest.spyOn(cluster.store, 'toggleFetchEnvironments').mockReturnThis(); + jest.spyOn(cluster.store, 'updateEnvironments').mockReturnThis(); + + cluster.handleClusterEnvironmentsSuccess({ data: {} }); + }); + + it('toggles the cluster environments loading icon', () => { + expect(cluster.store.toggleFetchEnvironments).toHaveBeenCalled(); + }); + + it('updates the store when cluster environments is retrieved', () => { + expect(cluster.store.updateEnvironments).toHaveBeenCalled(); + }); + }); + + describe('handleClusterStatusSuccess', () => { beforeEach(() => { jest.spyOn(cluster.store, 'updateStateFromServer').mockReturnThis(); jest.spyOn(cluster, 'toggleIngressDomainHelpText').mockReturnThis(); jest.spyOn(cluster, 'checkForNewInstalls').mockReturnThis(); jest.spyOn(cluster, 'updateContainer').mockReturnThis(); - cluster.handleSuccess({ data: {} }); + cluster.handleClusterStatusSuccess({ data: {} }); }); it('updates clusters store', () => { diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js new file mode 100644 index 00000000000..b0dd25f746b --- /dev/null +++ b/spec/frontend/diffs/components/diff_content_spec.js @@ -0,0 +1,200 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import Vuex from 'vuex'; +import { GlLoadingIcon } from '@gitlab/ui'; +import DiffContentComponent from '~/diffs/components/diff_content.vue'; +import InlineDiffView from '~/diffs/components/inline_diff_view.vue'; +import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_diffable.vue'; +import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_preview.vue'; +import ParallelDiffView from '~/diffs/components/parallel_diff_view.vue'; +import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue'; +import NoteForm from '~/notes/components/note_form.vue'; +import DiffDiscussions from '~/diffs/components/diff_discussions.vue'; +import { IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants'; +import diffFileMockData from '../../../javascripts/diffs/mock_data/diff_file'; +import { diffViewerModes } from '~/ide/constants'; + +const localVue = createLocalVue(); +localVue.use(Vuex); + +describe('DiffContent', () => { + let wrapper; + + const saveDiffDiscussionMock = jest.fn(); + const closeDiffFileCommentFormMock = jest.fn(); + + const noteableTypeGetterMock = jest.fn(); + const getUserDataGetterMock = jest.fn(); + + const isInlineViewGetterMock = jest.fn(); + const isParallelViewGetterMock = jest.fn(); + const getCommentFormForDiffFileGetterMock = jest.fn(); + + const defaultProps = { + diffFile: JSON.parse(JSON.stringify(diffFileMockData)), + }; + + const createComponent = ({ props, state } = {}) => { + const fakeStore = new Vuex.Store({ + getters: { + getNoteableData() { + return { + current_user: { + can_create_note: true, + }, + }; + }, + noteableType: noteableTypeGetterMock, + getUserData: getUserDataGetterMock, + }, + modules: { + /* + we need extra batchComments since vue-test-utils does not + stub async components properly + */ + batchComments: { + namespaced: true, + getters: { + draftsForFile: () => () => true, + }, + }, + diffs: { + namespaced: true, + state: { + projectPath: 'project/path', + endpoint: 'endpoint', + ...state, + }, + getters: { + isInlineView: isInlineViewGetterMock, + isParallelView: isParallelViewGetterMock, + getCommentFormForDiffFile: getCommentFormForDiffFileGetterMock, + }, + actions: { + saveDiffDiscussion: saveDiffDiscussionMock, + closeDiffFileCommentForm: closeDiffFileCommentFormMock, + }, + }, + }, + }); + + wrapper = shallowMount(DiffContentComponent, { + propsData: { + ...defaultProps, + ...props, + }, + localVue, + store: fakeStore, + sync: false, + }); + }; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + describe('with text based files', () => { + afterEach(() => { + [isParallelViewGetterMock, isInlineViewGetterMock].forEach(m => m.mockRestore()); + }); + + 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('renders rendering more lines loading icon', () => { + createComponent({ props: { diffFile: { ...textDiffFile, renderingLines: true } } }); + + expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); + }); + }); + + describe('with empty files', () => { + const emptyDiffFile = { + ...defaultProps.diffFile, + viewer: { name: diffViewerModes.text }, + highlighted_diff_lines: [], + parallel_diff_lines: [], + }; + + it('should render a no preview view if viewer set to no preview', () => { + createComponent({ + props: { diffFile: { ...emptyDiffFile, viewer: { name: diffViewerModes.no_preview } } }, + }); + + expect(wrapper.find(NoPreviewViewer).exists()).toBe(true); + }); + + it('should render not diffable view if viewer set to non_diffable', () => { + createComponent({ + props: { diffFile: { ...emptyDiffFile, viewer: { name: diffViewerModes.not_diffable } } }, + }); + + expect(wrapper.find(NotDiffableViewer).exists()).toBe(true); + }); + }); + + describe('with image files', () => { + const imageDiffFile = { ...defaultProps.diffFile, viewer: { name: diffViewerModes.image } }; + + it('should have image diff view in place', () => { + getCommentFormForDiffFileGetterMock.mockReturnValue(() => true); + createComponent({ props: { diffFile: imageDiffFile } }); + + expect(wrapper.find(InlineDiffView).exists()).toBe(false); + expect(wrapper.find(ImageDiffOverlay).exists()).toBe(true); + }); + + it('renders diff file discussions', () => { + getCommentFormForDiffFileGetterMock.mockReturnValue(() => true); + createComponent({ + props: { + diffFile: { ...imageDiffFile, discussions: [{ name: 'discussion-stub ' }] }, + }, + }); + + expect(wrapper.find(DiffDiscussions).exists()).toBe(true); + }); + + it('emits saveDiffDiscussion when note-form emits `handleFormUpdate`', () => { + const noteStub = {}; + getCommentFormForDiffFileGetterMock.mockReturnValue(() => true); + const currentDiffFile = { ...imageDiffFile, discussions: [{ name: 'discussion-stub ' }] }; + createComponent({ + props: { + diffFile: currentDiffFile, + }, + }); + + wrapper.find(NoteForm).vm.$emit('handleFormUpdate', noteStub); + expect(saveDiffDiscussionMock).toHaveBeenCalledWith( + expect.any(Object), + { + note: noteStub, + formData: { + noteableData: expect.any(Object), + diffFile: currentDiffFile, + positionType: IMAGE_DIFF_POSITION_TYPE, + x: undefined, + y: undefined, + width: undefined, + height: undefined, + noteableType: undefined, + }, + }, + undefined, + ); + }); + }); +}); diff --git a/spec/frontend/fixtures/static/projects.json b/spec/frontend/fixtures/static/projects.json index 68a150f602a..d92d3acdea0 100644 --- a/spec/frontend/fixtures/static/projects.json +++ b/spec/frontend/fixtures/static/projects.json @@ -352,8 +352,8 @@ "archived": false, "visibility_level": 10, "ssh_url_to_repo": "phil@localhost:gitlab-org/gitlab-ce.git", - "http_url_to_repo": "http://localhost:3000/gitlab-org/gitlab-ce.git", - "web_url": "http://localhost:3000/gitlab-org/gitlab-ce", + "http_url_to_repo": "http://localhost:3000/gitlab-org/gitlab-foss.git", + "web_url": "http://localhost:3000/gitlab-org/gitlab-foss", "name": "Gitlab Ce", "name_with_namespace": "Gitlab Org / Gitlab Ce", "path": "gitlab-ce", diff --git a/spec/frontend/jobs/components/log/duration_badge_spec.js b/spec/frontend/jobs/components/log/duration_badge_spec.js new file mode 100644 index 00000000000..2ac34e78909 --- /dev/null +++ b/spec/frontend/jobs/components/log/duration_badge_spec.js @@ -0,0 +1,31 @@ +import { shallowMount } from '@vue/test-utils'; +import DurationBadge from '~/jobs/components/log/duration_badge.vue'; + +describe('Job Log Duration Badge', () => { + let wrapper; + + const data = { + duration: '00:30:01', + }; + + const createComponent = (props = {}) => { + wrapper = shallowMount(DurationBadge, { + sync: false, + propsData: { + ...props, + }, + }); + }; + + beforeEach(() => { + createComponent(data); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('renders provided duration', () => { + expect(wrapper.text()).toBe(data.duration); + }); +}); diff --git a/spec/frontend/jobs/components/log/line_header_spec.js b/spec/frontend/jobs/components/log/line_header_spec.js new file mode 100644 index 00000000000..2d2f92fad9d --- /dev/null +++ b/spec/frontend/jobs/components/log/line_header_spec.js @@ -0,0 +1,95 @@ +import { mount } from '@vue/test-utils'; +import LineHeader from '~/jobs/components/log/line_header.vue'; +import LineNumber from '~/jobs/components/log/line_number.vue'; +import DurationBadge from '~/jobs/components/log/duration_badge.vue'; + +describe('Job Log Header Line', () => { + let wrapper; + + const data = { + line: { + content: [ + { + text: 'Running with gitlab-runner 12.1.0 (de7731dd)', + style: 'term-fg-l-green', + }, + ], + lineNumber: 0, + }, + isClosed: true, + path: '/jashkenas/underscore/-/jobs/335', + }; + + const createComponent = (props = {}) => { + wrapper = mount(LineHeader, { + sync: false, + propsData: { + ...props, + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + describe('line', () => { + beforeEach(() => { + createComponent(data); + }); + + it('renders the line number component', () => { + expect(wrapper.contains(LineNumber)).toBe(true); + }); + + it('renders a span the provided text', () => { + expect(wrapper.find('span').text()).toBe(data.line.content[0].text); + }); + + it('renders the provided style as a class attribute', () => { + expect(wrapper.find('span').classes()).toContain(data.line.content[0].style); + }); + }); + + describe('when isCloses is true', () => { + beforeEach(() => { + createComponent({ ...data, isClosed: true }); + }); + + it('sets icon name to be angle-right', () => { + expect(wrapper.vm.iconName).toEqual('angle-right'); + }); + }); + + describe('when isCloses is false', () => { + beforeEach(() => { + createComponent({ ...data, isClosed: false }); + }); + + it('sets icon name to be angle-down', () => { + expect(wrapper.vm.iconName).toEqual('angle-down'); + }); + }); + + describe('on click', () => { + beforeEach(() => { + createComponent(data); + }); + + it('emits toggleLine event', () => { + wrapper.trigger('click'); + + expect(wrapper.emitted().toggleLine.length).toBe(1); + }); + }); + + describe('with duration', () => { + beforeEach(() => { + createComponent(Object.assign({}, data, { duration: '00:10' })); + }); + + it('renders the duration badge', () => { + expect(wrapper.contains(DurationBadge)).toBe(true); + }); + }); +}); diff --git a/spec/frontend/jobs/components/log/line_number_spec.js b/spec/frontend/jobs/components/log/line_number_spec.js new file mode 100644 index 00000000000..fcf2edf9159 --- /dev/null +++ b/spec/frontend/jobs/components/log/line_number_spec.js @@ -0,0 +1,40 @@ +import { shallowMount } from '@vue/test-utils'; +import LineNumber from '~/jobs/components/log/line_number.vue'; + +describe('Job Log Line Number', () => { + let wrapper; + + const data = { + lineNumber: 0, + path: '/jashkenas/underscore/-/jobs/335', + }; + + const createComponent = (props = {}) => { + wrapper = shallowMount(LineNumber, { + sync: false, + propsData: { + ...props, + }, + }); + }; + + beforeEach(() => { + createComponent(data); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('renders incremented lineNunber by 1', () => { + expect(wrapper.text()).toBe('1'); + }); + + it('renders link with lineNumber as an ID', () => { + expect(wrapper.attributes().id).toBe('L1'); + }); + + it('links to the provided path with line number as anchor', () => { + expect(wrapper.attributes().href).toBe(`${data.path}#L1`); + }); +}); diff --git a/spec/frontend/jobs/components/log/line_spec.js b/spec/frontend/jobs/components/log/line_spec.js new file mode 100644 index 00000000000..ea593e3c39a --- /dev/null +++ b/spec/frontend/jobs/components/log/line_spec.js @@ -0,0 +1,49 @@ +import { shallowMount } from '@vue/test-utils'; +import Line from '~/jobs/components/log/line.vue'; +import LineNumber from '~/jobs/components/log/line_number.vue'; + +describe('Job Log Line', () => { + let wrapper; + + const data = { + line: { + content: [ + { + text: 'Running with gitlab-runner 12.1.0 (de7731dd)', + style: 'term-fg-l-green', + }, + ], + lineNumber: 0, + }, + path: '/jashkenas/underscore/-/jobs/335', + }; + + const createComponent = (props = {}) => { + wrapper = shallowMount(Line, { + sync: false, + propsData: { + ...props, + }, + }); + }; + + beforeEach(() => { + createComponent(data); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('renders the line number component', () => { + expect(wrapper.contains(LineNumber)).toBe(true); + }); + + it('renders a span the provided text', () => { + expect(wrapper.find('span').text()).toBe(data.line.content[0].text); + }); + + it('renders the provided style as a class attribute', () => { + expect(wrapper.find('span').classes()).toContain(data.line.content[0].style); + }); +}); diff --git a/spec/frontend/jobs/components/log/log_spec.js b/spec/frontend/jobs/components/log/log_spec.js new file mode 100644 index 00000000000..cc334009982 --- /dev/null +++ b/spec/frontend/jobs/components/log/log_spec.js @@ -0,0 +1,77 @@ +import { mount, createLocalVue } from '@vue/test-utils'; +import Vuex from 'vuex'; +import { logLinesParser } from '~/jobs/store/utils'; +import Log from '~/jobs/components/log/log.vue'; +import { jobLog } from './mock_data'; + +describe('Job Log', () => { + let wrapper; + let actions; + let state; + let store; + + const localVue = createLocalVue(); + localVue.use(Vuex); + + const createComponent = () => { + wrapper = mount(Log, { + sync: false, + localVue, + store, + }); + }; + + beforeEach(() => { + actions = { + toggleCollapsibleLine: () => {}, + }; + + state = { + trace: logLinesParser(jobLog), + traceEndpoint: 'jobs/id', + }; + + store = new Vuex.Store({ + actions, + state, + }); + + createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + describe('line numbers', () => { + it('renders a line number for each open line', () => { + expect(wrapper.find('#L1').text()).toBe('1'); + expect(wrapper.find('#L2').text()).toBe('2'); + expect(wrapper.find('#L3').text()).toBe('3'); + }); + + it('links to the provided path and correct line number', () => { + expect(wrapper.find('#L1').attributes('href')).toBe(`${state.traceEndpoint}#L1`); + }); + }); + + describe('collapsible sections', () => { + it('renders a clickable header section', () => { + expect(wrapper.find('.collapsible-line').attributes('role')).toBe('button'); + }); + + it('renders an icon with the closed state', () => { + expect(wrapper.find('.collapsible-line svg').classes()).toContain('ic-angle-right'); + }); + + describe('on click header section', () => { + it('calls toggleCollapsibleLine', () => { + jest.spyOn(wrapper.vm, 'toggleCollapsibleLine'); + + wrapper.find('.collapsible-line').trigger('click'); + + expect(wrapper.vm.toggleCollapsibleLine).toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/spec/frontend/jobs/components/log/mock_data.js b/spec/frontend/jobs/components/log/mock_data.js new file mode 100644 index 00000000000..db42644de77 --- /dev/null +++ b/spec/frontend/jobs/components/log/mock_data.js @@ -0,0 +1,152 @@ +export const jobLog = [ + { + offset: 1000, + content: [{ text: 'Running with gitlab-runner 12.1.0 (de7731dd)' }], + }, + { + offset: 1001, + content: [{ text: ' on docker-auto-scale-com 8a6210b8' }], + }, + { + offset: 1002, + content: [ + { + text: 'Using Docker executor with image dev.gitlab.org3', + }, + ], + sections: ['prepare-executor'], + section_header: true, + }, + { + offset: 1003, + content: [{ text: 'Starting service postgres:9.6.14 ...', style: 'text-green' }], + sections: ['prepare-executor'], + }, +]; + +export const utilsMockData = [ + { + offset: 1001, + content: [{ text: ' on docker-auto-scale-com 8a6210b8' }], + }, + { + offset: 1002, + content: [ + { + text: + 'Using Docker executor with image dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.22-chrome-73.0-node-12.x-yarn-1.16-postgresql-9.6-graphicsmagick-1.3.33', + }, + ], + sections: ['prepare-executor'], + section_header: true, + }, + { + offset: 1003, + content: [{ text: 'Starting service postgres:9.6.14 ...' }], + sections: ['prepare-executor'], + }, + { + offset: 1004, + content: [{ text: 'Pulling docker image postgres:9.6.14 ...', style: 'term-fg-l-green' }], + sections: ['prepare-executor'], + }, + { + offset: 1005, + content: [], + sections: ['prepare-executor'], + section_duration: '10:00', + }, +]; + +export const originalTrace = [ + { + offset: 1, + content: [ + { + text: 'Downloading', + }, + ], + }, +]; + +export const regularIncremental = [ + { + offset: 2, + content: [ + { + text: 'log line', + }, + ], + }, +]; + +export const regularIncrementalRepeated = [ + { + offset: 1, + content: [ + { + text: 'log line', + }, + ], + }, +]; + +export const headerTrace = [ + { + offset: 1, + section_header: true, + content: [ + { + text: 'log line', + }, + ], + sections: ['section'], + }, +]; + +export const headerTraceIncremental = [ + { + offset: 1, + section_header: true, + content: [ + { + text: 'updated log line', + }, + ], + sections: ['section'], + }, +]; + +export const collapsibleTrace = [ + { + offset: 1, + section_header: true, + content: [ + { + text: 'log line', + }, + ], + sections: ['section'], + }, + { + offset: 2, + content: [ + { + text: 'log line', + }, + ], + sections: ['section'], + }, +]; + +export const collapsibleTraceIncremental = [ + { + offset: 2, + content: [ + { + text: 'updated log line', + }, + ], + sections: ['section'], + }, +]; diff --git a/spec/frontend/jobs/store/utils_spec.js b/spec/frontend/jobs/store/utils_spec.js index 7b484ccfa07..780d42fd6a1 100644 --- a/spec/frontend/jobs/store/utils_spec.js +++ b/spec/frontend/jobs/store/utils_spec.js @@ -1,45 +1,21 @@ import { logLinesParser, updateIncrementalTrace } from '~/jobs/store/utils'; +import { + utilsMockData, + originalTrace, + regularIncremental, + regularIncrementalRepeated, + headerTrace, + headerTraceIncremental, + collapsibleTrace, + collapsibleTraceIncremental, +} from '../components/log/mock_data'; describe('Jobs Store Utils', () => { describe('logLinesParser', () => { - const mockData = [ - { - offset: 1001, - content: [{ text: ' on docker-auto-scale-com 8a6210b8' }], - }, - { - offset: 1002, - content: [ - { - text: - 'Using Docker executor with image dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.22-chrome-73.0-node-12.x-yarn-1.16-postgresql-9.6-graphicsmagick-1.3.33', - }, - ], - sections: ['prepare-executor'], - section_header: true, - }, - { - offset: 1003, - content: [{ text: 'Starting service postgres:9.6.14 ...' }], - sections: ['prepare-executor'], - }, - { - offset: 1004, - content: [{ text: 'Pulling docker image postgres:9.6.14 ...', style: 'term-fg-l-green' }], - sections: ['prepare-executor'], - }, - { - offset: 1005, - content: [], - sections: ['prepare-executor'], - section_duration: '10:00', - }, - ]; - let result; beforeEach(() => { - result = logLinesParser(mockData); + result = logLinesParser(utilsMockData); }); describe('regular line', () => { @@ -60,48 +36,27 @@ describe('Jobs Store Utils', () => { it('creates a lines array property with the content of the collpasible section', () => { expect(result[1].lines.length).toEqual(2); - expect(result[1].lines[0].content).toEqual(mockData[2].content); - expect(result[1].lines[1].content).toEqual(mockData[3].content); + expect(result[1].lines[0].content).toEqual(utilsMockData[2].content); + expect(result[1].lines[1].content).toEqual(utilsMockData[3].content); }); }); describe('section duration', () => { it('adds the section information to the header section', () => { - expect(result[1].section_duration).toEqual(mockData[4].section_duration); + expect(result[1].section_duration).toEqual(utilsMockData[4].section_duration); }); it('does not add section duration as a line', () => { - expect(result[1].lines.includes(mockData[4])).toEqual(false); + expect(result[1].lines.includes(utilsMockData[4])).toEqual(false); }); }); }); describe('updateIncrementalTrace', () => { - const originalTrace = [ - { - offset: 1, - content: [ - { - text: 'Downloading', - }, - ], - }, - ]; - describe('without repeated section', () => { it('concats and parses both arrays', () => { const oldLog = logLinesParser(originalTrace); - const newLog = [ - { - offset: 2, - content: [ - { - text: 'log line', - }, - ], - }, - ]; - const result = updateIncrementalTrace(originalTrace, oldLog, newLog); + const result = updateIncrementalTrace(originalTrace, oldLog, regularIncremental); expect(result).toEqual([ { @@ -129,17 +84,7 @@ describe('Jobs Store Utils', () => { describe('with regular line repeated offset', () => { it('updates the last line and formats with the incremental part', () => { const oldLog = logLinesParser(originalTrace); - const newLog = [ - { - offset: 1, - content: [ - { - text: 'log line', - }, - ], - }, - ]; - const result = updateIncrementalTrace(originalTrace, oldLog, newLog); + const result = updateIncrementalTrace(originalTrace, oldLog, regularIncrementalRepeated); expect(result).toEqual([ { @@ -157,32 +102,8 @@ describe('Jobs Store Utils', () => { describe('with header line repeated', () => { it('updates the header line and formats with the incremental part', () => { - const headerTrace = [ - { - offset: 1, - section_header: true, - content: [ - { - text: 'log line', - }, - ], - sections: ['section'], - }, - ]; const oldLog = logLinesParser(headerTrace); - const newLog = [ - { - offset: 1, - section_header: true, - content: [ - { - text: 'updated log line', - }, - ], - sections: ['section'], - }, - ]; - const result = updateIncrementalTrace(headerTrace, oldLog, newLog); + const result = updateIncrementalTrace(headerTrace, oldLog, headerTraceIncremental); expect(result).toEqual([ { @@ -207,40 +128,12 @@ describe('Jobs Store Utils', () => { describe('with collapsible line repeated', () => { it('updates the collapsible line and formats with the incremental part', () => { - const collapsibleTrace = [ - { - offset: 1, - section_header: true, - content: [ - { - text: 'log line', - }, - ], - sections: ['section'], - }, - { - offset: 2, - content: [ - { - text: 'log line', - }, - ], - sections: ['section'], - }, - ]; const oldLog = logLinesParser(collapsibleTrace); - const newLog = [ - { - offset: 2, - content: [ - { - text: 'updated log line', - }, - ], - sections: ['section'], - }, - ]; - const result = updateIncrementalTrace(collapsibleTrace, oldLog, newLog); + const result = updateIncrementalTrace( + collapsibleTrace, + oldLog, + collapsibleTraceIncremental, + ); expect(result).toEqual([ { diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js index 751fb5e1b94..9f1700bb243 100644 --- a/spec/frontend/lib/utils/datetime_utility_spec.js +++ b/spec/frontend/lib/utils/datetime_utility_spec.js @@ -248,7 +248,7 @@ describe('datefix', () => { }); describe('parsePikadayDate', () => { - // removed because of https://gitlab.com/gitlab-org/gitlab-ce/issues/39834 + // removed because of https://gitlab.com/gitlab-org/gitlab-foss/issues/39834 }); describe('pikadayToString', () => { diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js index b0bdd924921..41df93c9a48 100644 --- a/spec/frontend/lib/utils/url_utility_spec.js +++ b/spec/frontend/lib/utils/url_utility_spec.js @@ -15,8 +15,8 @@ describe('URL utility', () => { describe('without relative_url_root', () => { it('returns IDE path with route', () => { - expect(urlUtils.webIDEUrl('/gitlab-org/gitlab-ce/merge_requests/1')).toBe( - '/-/ide/project/gitlab-org/gitlab-ce/merge_requests/1', + expect(urlUtils.webIDEUrl('/gitlab-org/gitlab-foss/merge_requests/1')).toBe( + '/-/ide/project/gitlab-org/gitlab-foss/merge_requests/1', ); }); }); @@ -27,8 +27,8 @@ describe('URL utility', () => { }); it('returns IDE path with route', () => { - expect(urlUtils.webIDEUrl('/gitlab/gitlab-org/gitlab-ce/merge_requests/1')).toBe( - '/gitlab/-/ide/project/gitlab-org/gitlab-ce/merge_requests/1', + expect(urlUtils.webIDEUrl('/gitlab/gitlab-org/gitlab-foss/merge_requests/1')).toBe( + '/gitlab/-/ide/project/gitlab-org/gitlab-foss/merge_requests/1', ); }); }); diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js index f582729d773..d3c8cf72376 100644 --- a/spec/frontend/notes/components/discussion_actions_spec.js +++ b/spec/frontend/notes/components/discussion_actions_spec.js @@ -7,6 +7,18 @@ import ResolveDiscussionButton from '~/notes/components/discussion_resolve_butto import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue'; import JumpToNextDiscussionButton from '~/notes/components/discussion_jump_to_next_button.vue'; +// NOTE: clone mock_data so that it is not accidentally mutated +const createDiscussionMock = (props = {}) => + Object.assign(JSON.parse(JSON.stringify(discussionMock)), props); +const createNoteMock = (props = {}) => + Object.assign(JSON.parse(JSON.stringify(discussionMock.notes[0])), props); +const createResolvableNote = () => + createNoteMock({ resolvable: true, current_user: { can_resolve: true } }); +const createUnresolvableNote = () => + createNoteMock({ resolvable: false, current_user: { can_resolve: false } }); +const createUnallowedNote = () => + createNoteMock({ resolvable: true, current_user: { can_resolve: false } }); + describe('DiscussionActions', () => { let wrapper; const createComponentFactory = (shallow = true) => props => { @@ -66,13 +78,23 @@ describe('DiscussionActions', () => { expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false); }); - it('does not renders discussion button for non-member', () => { - const discussion = JSON.parse(JSON.stringify(discussionMock)); - discussion.notes[1].current_user.can_resolve = false; - createComponent({ discussion }); - - expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(false); - expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false); + describe.each` + desc | notes | shouldRender + ${'with no notes'} | ${[]} | ${true} + ${'with resolvable notes'} | ${[createResolvableNote(), createResolvableNote()]} | ${true} + ${'with unresolvable notes'} | ${[createResolvableNote(), createUnresolvableNote()]} | ${true} + ${'with unallowed note'} | ${[createResolvableNote(), createUnallowedNote()]} | ${false} + `('$desc', ({ notes, shouldRender }) => { + beforeEach(() => { + createComponent({ + discussion: createDiscussionMock({ notes }), + }); + }); + + it(shouldRender ? 'renders resolve buttons' : 'does not render resolve buttons', () => { + expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(shouldRender); + expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(shouldRender); + }); }); }); diff --git a/spec/frontend/notes/components/note_app_spec.js b/spec/frontend/notes/components/note_app_spec.js index d2c17310e9c..a8ec47fd44f 100644 --- a/spec/frontend/notes/components/note_app_spec.js +++ b/spec/frontend/notes/components/note_app_spec.js @@ -8,7 +8,7 @@ import service from '~/notes/services/notes_service'; import createStore from '~/notes/stores'; import '~/behaviors/markdown/render_gfm'; import { setTestTimeout } from 'helpers/timeout'; -// TODO: use generated fixture (https://gitlab.com/gitlab-org/gitlab-ce/issues/62491) +// TODO: use generated fixture (https://gitlab.com/gitlab-org/gitlab-foss/issues/62491) import * as mockData from '../../../javascripts/notes/mock_data'; setTestTimeout(1000); @@ -108,7 +108,7 @@ describe('note_app', () => { it('should render list of notes', () => { const note = mockData.INDIVIDUAL_NOTE_RESPONSE_MAP.GET[ - '/gitlab-org/gitlab-ce/issues/26/discussions.json' + '/gitlab-org/gitlab-foss/issues/26/discussions.json' ][0].notes[0]; expect( diff --git a/spec/frontend/repository/log_tree_spec.js b/spec/frontend/repository/log_tree_spec.js index a9499f7c61b..a3a766eca41 100644 --- a/spec/frontend/repository/log_tree_spec.js +++ b/spec/frontend/repository/log_tree_spec.js @@ -61,7 +61,7 @@ describe('fetchLogsTree', () => { client = { readQuery: () => ({ - projectPath: 'gitlab-org/gitlab-ce', + projectPath: 'gitlab-org/gitlab-foss', ref: 'master', commits: [], }), @@ -81,7 +81,7 @@ describe('fetchLogsTree', () => { it('calls axios get', () => fetchLogsTree(client, '', '0', resolver).then(() => { expect(axios.get).toHaveBeenCalledWith( - 'https://test.com/gitlab-org/gitlab-ce/refs/master/logs_tree', + 'https://test.com/gitlab-org/gitlab-foss/refs/master/logs_tree', { params: { format: 'json', offset: '0' } }, ); })); diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js index d52aeb1fe6b..6e1f1038dcd 100644 --- a/spec/frontend/test_setup.js +++ b/spec/frontend/test_setup.js @@ -4,13 +4,13 @@ import $ from 'jquery'; import Translate from '~/vue_shared/translate'; import { config as testUtilsConfig } from '@vue/test-utils'; import { initializeTestTimeout } from './helpers/timeout'; -import { loadHTMLFixture, setHTMLFixture } from './helpers/fixtures'; +import { getJSONFixture, loadHTMLFixture, setHTMLFixture } from './helpers/fixtures'; import { setupManualMocks } from './mocks/mocks_helper'; import customMatchers from './matchers'; // Expose jQuery so specs using jQuery plugins can be imported nicely. // Here is an issue to explore better alternatives: -// https://gitlab.com/gitlab-org/gitlab-ee/issues/12448 +// https://gitlab.com/gitlab-org/gitlab/issues/12448 window.jQuery = $; process.on('unhandledRejection', global.promiseRejectionHandler); @@ -43,6 +43,7 @@ Object.defineProperty(global.Element.prototype, 'innerText', { // convenience wrapper for migration from Karma Object.assign(global, { + getJSONFixture, loadFixtures: loadHTMLFixture, setFixtures: setHTMLFixture, diff --git a/spec/frontend/tracking_spec.js b/spec/frontend/tracking_spec.js index 7c98a1a66c9..dfc068ab6ea 100644 --- a/spec/frontend/tracking_spec.js +++ b/spec/frontend/tracking_spec.js @@ -29,24 +29,26 @@ describe('Tracking', () => { forceSecureTracker: true, eventMethod: 'post', contexts: { webPage: true }, - activityTrackingEnabled: false, - pageTrackingEnabled: false, + formTracking: false, + linkClickTracking: false, }); }); it('should activate features based on what has been enabled', () => { initUserTracking(); - expect(snowplowSpy).not.toHaveBeenCalledWith('enableActivityTracking', 30, 30); - expect(snowplowSpy).not.toHaveBeenCalledWith('trackPageView'); + expect(snowplowSpy).toHaveBeenCalledWith('enableActivityTracking', 30, 30); + expect(snowplowSpy).toHaveBeenCalledWith('trackPageView'); + expect(snowplowSpy).not.toHaveBeenCalledWith('enableFormTracking'); + expect(snowplowSpy).not.toHaveBeenCalledWith('enableLinkClickTracking'); window.snowplowOptions = Object.assign({}, window.snowplowOptions, { - activityTrackingEnabled: true, - pageTrackingEnabled: true, + formTracking: true, + linkClickTracking: true, }); initUserTracking(); - expect(snowplowSpy).toHaveBeenCalledWith('enableActivityTracking', 30, 30); - expect(snowplowSpy).toHaveBeenCalledWith('trackPageView'); + expect(snowplowSpy).toHaveBeenCalledWith('enableFormTracking'); + expect(snowplowSpy).toHaveBeenCalledWith('enableLinkClickTracking'); }); }); diff --git a/spec/frontend/vue_shared/components/notes/system_note_spec.js b/spec/frontend/vue_shared/components/notes/system_note_spec.js index dc66150ab8d..a65e3eb294a 100644 --- a/spec/frontend/vue_shared/components/notes/system_note_spec.js +++ b/spec/frontend/vue_shared/components/notes/system_note_spec.js @@ -55,7 +55,7 @@ describe('system note component', () => { // Redcarpet Markdown renderer wraps text in `<p>` tags // we need to strip them because they break layout of commit lists in system notes: - // https://gitlab.com/gitlab-org/gitlab-ce/uploads/b07a10670919254f0220d3ff5c1aa110/jqzI.png + // https://gitlab.com/gitlab-org/gitlab-foss/uploads/b07a10670919254f0220d3ff5c1aa110/jqzI.png it('removes wrapping paragraph from note HTML', () => { expect(vm.$el.querySelector('.system-note-message').innerHTML).toEqual('<span>closed</span>'); }); |