From 85dc423f7090da0a52c73eb66faf22ddb20efff9 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Sat, 19 Sep 2020 01:45:44 +0000 Subject: Add latest changes from gitlab-org/gitlab@13-4-stable-ee --- spec/frontend/ide/components/branches/item_spec.js | 6 +- .../ide/components/commit_sidebar/form_spec.js | 53 +++++++-- spec/frontend/ide/components/error_message_spec.js | 2 +- .../frontend/ide/components/file_row_extra_spec.js | 4 +- .../ide/components/ide_status_list_spec.js | 3 +- .../jobs/__snapshots__/stage_spec.js.snap | 2 +- .../ide/components/jobs/detail/description_spec.js | 12 +- .../components/jobs/detail/scroll_button_spec.js | 4 +- spec/frontend/ide/components/jobs/detail_spec.js | 8 +- spec/frontend/ide/components/jobs/item_spec.js | 2 +- spec/frontend/ide/components/jobs/list_spec.js | 6 +- .../ide/components/merge_requests/item_spec.js | 2 +- .../ide/components/merge_requests/list_spec.js | 36 ++---- .../ide/components/nav_dropdown_button_spec.js | 2 +- spec/frontend/ide/components/nav_dropdown_spec.js | 2 +- .../ide/components/new_dropdown/button_spec.js | 2 +- .../ide/components/new_dropdown/upload_spec.js | 2 - .../frontend/ide/components/pipelines/list_spec.js | 63 +++++----- .../ide/components/preview/clientside_spec.js | 22 ++-- spec/frontend/ide/components/repo_editor_spec.js | 13 +- spec/frontend/ide/components/repo_tab_spec.js | 132 +++++++++------------ spec/frontend/ide/components/repo_tabs_spec.js | 43 ++++--- .../ide/components/terminal/session_spec.js | 2 +- .../components/terminal/terminal_controls_spec.js | 8 +- .../terminal_sync/terminal_sync_status_spec.js | 9 +- 25 files changed, 227 insertions(+), 213 deletions(-) (limited to 'spec/frontend/ide/components') diff --git a/spec/frontend/ide/components/branches/item_spec.js b/spec/frontend/ide/components/branches/item_spec.js index d8175025755..f1aa9187a8d 100644 --- a/spec/frontend/ide/components/branches/item_spec.js +++ b/spec/frontend/ide/components/branches/item_spec.js @@ -1,8 +1,8 @@ import { shallowMount } from '@vue/test-utils'; +import { GlIcon } from '@gitlab/ui'; import { createStore } from '~/ide/stores'; import { createRouter } from '~/ide/ide_router'; import Item from '~/ide/components/branches/item.vue'; -import Icon from '~/vue_shared/components/icon.vue'; import Timeago from '~/vue_shared/components/time_ago_tooltip.vue'; import { projectData } from '../../mock_data'; @@ -45,7 +45,7 @@ describe('IDE branch item', () => { it('renders branch name and timeago', () => { expect(wrapper.text()).toContain(TEST_BRANCH.name); expect(wrapper.find(Timeago).props('time')).toBe(TEST_BRANCH.committedDate); - expect(wrapper.find(Icon).exists()).toBe(false); + expect(wrapper.find(GlIcon).exists()).toBe(false); }); it('renders link to branch', () => { @@ -60,6 +60,6 @@ describe('IDE branch item', () => { it('renders icon if is not active', () => { createComponent({ isActive: true }); - expect(wrapper.find(Icon).exists()).toBe(true); + expect(wrapper.find(GlIcon).exists()).toBe(true); }); }); diff --git a/spec/frontend/ide/components/commit_sidebar/form_spec.js b/spec/frontend/ide/components/commit_sidebar/form_spec.js index 9245cefc183..56667d6b03d 100644 --- a/spec/frontend/ide/components/commit_sidebar/form_spec.js +++ b/spec/frontend/ide/components/commit_sidebar/form_spec.js @@ -1,10 +1,13 @@ import Vue from 'vue'; +import { getByText } from '@testing-library/dom'; import { createComponentWithStore } from 'helpers/vue_mount_component_helper'; import { projectData } from 'jest/ide/mock_data'; import waitForPromises from 'helpers/wait_for_promises'; import { createStore } from '~/ide/stores'; +import consts from '~/ide/stores/modules/commit/constants'; import CommitForm from '~/ide/components/commit_sidebar/form.vue'; import { leftSidebarViews } from '~/ide/constants'; +import { createCodeownersCommitError, createUnexpectedCommitError } from '~/ide/lib/errors'; describe('IDE commit form', () => { const Component = Vue.extend(CommitForm); @@ -259,21 +262,47 @@ describe('IDE commit form', () => { }); }); - it('opens new branch modal if commitChanges throws an error', () => { - vm.commitChanges.mockRejectedValue({ success: false }); + it.each` + createError | props + ${() => createCodeownersCommitError('test message')} | ${{ actionPrimary: { text: 'Create new branch' } }} + ${createUnexpectedCommitError} | ${{ actionPrimary: null }} + `('opens error modal if commitError with $error', async ({ createError, props }) => { + jest.spyOn(vm.$refs.commitErrorModal, 'show'); - jest.spyOn(vm.$refs.createBranchModal, 'show').mockImplementation(); + const error = createError(); + store.state.commit.commitError = error; - return vm - .$nextTick() - .then(() => { - vm.$el.querySelector('.btn-success').click(); + await vm.$nextTick(); - return vm.$nextTick(); - }) - .then(() => { - expect(vm.$refs.createBranchModal.show).toHaveBeenCalled(); - }); + expect(vm.$refs.commitErrorModal.show).toHaveBeenCalled(); + expect(vm.$refs.commitErrorModal).toMatchObject({ + actionCancel: { text: 'Cancel' }, + ...props, + }); + // Because of the legacy 'mountComponent' approach here, the only way to + // test the text of the modal is by viewing the content of the modal added to the document. + expect(document.body).toHaveText(error.messageHTML); + }); + }); + + describe('with error modal with primary', () => { + beforeEach(() => { + jest.spyOn(vm.$store, 'dispatch').mockReturnValue(Promise.resolve()); + }); + + it('updates commit action and commits', async () => { + store.state.commit.commitError = createCodeownersCommitError('test message'); + + await vm.$nextTick(); + + getByText(document.body, 'Create new branch').click(); + + await waitForPromises(); + + expect(vm.$store.dispatch.mock.calls).toEqual([ + ['commit/updateCommitAction', consts.COMMIT_TO_NEW_BRANCH], + ['commit/commitChanges', undefined], + ]); }); }); }); diff --git a/spec/frontend/ide/components/error_message_spec.js b/spec/frontend/ide/components/error_message_spec.js index 3a4dcc5873d..8b7e7da3b51 100644 --- a/spec/frontend/ide/components/error_message_spec.js +++ b/spec/frontend/ide/components/error_message_spec.js @@ -51,7 +51,7 @@ describe('IDE error message component', () => { createComponent(); findDismissButton().trigger('click'); - expect(setErrorMessageMock).toHaveBeenCalledWith(expect.any(Object), null, undefined); + expect(setErrorMessageMock).toHaveBeenCalledWith(expect.any(Object), null); }); describe('with action', () => { diff --git a/spec/frontend/ide/components/file_row_extra_spec.js b/spec/frontend/ide/components/file_row_extra_spec.js index 4bd27d23f76..2a106ad37c0 100644 --- a/spec/frontend/ide/components/file_row_extra_spec.js +++ b/spec/frontend/ide/components/file_row_extra_spec.js @@ -153,14 +153,14 @@ describe('IDE extra file row component', () => { describe('merge request icon', () => { it('hides when not a merge request change', () => { - expect(vm.$el.querySelector('.ic-git-merge')).toBe(null); + expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).toBe(null); }); it('shows when a merge request change', done => { vm.file.mrChange = true; vm.$nextTick(() => { - expect(vm.$el.querySelector('.ic-git-merge')).not.toBe(null); + expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).not.toBe(null); done(); }); diff --git a/spec/frontend/ide/components/ide_status_list_spec.js b/spec/frontend/ide/components/ide_status_list_spec.js index fed61233e55..bb8165d1a52 100644 --- a/spec/frontend/ide/components/ide_status_list_spec.js +++ b/spec/frontend/ide/components/ide_status_list_spec.js @@ -75,7 +75,8 @@ describe('ide/components/ide_status_list', () => { describe('with binary file', () => { beforeEach(() => { - activeFile.binary = true; + activeFile.name = 'abc.dat'; + activeFile.content = '🐱'; // non-ascii binary content createComponent(); }); diff --git a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap index dbfacb98813..a65d9e6f78b 100644 --- a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap +++ b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap @@ -34,7 +34,7 @@ exports[`IDE pipeline stage renders stage details & icon 1`] = ` - { }); it('renders CI icon', () => { - expect(vm.$el.querySelector('.ci-status-icon .ic-status_success_borderless')).not.toBe(null); + expect( + vm.$el.querySelector('.ci-status-icon [data-testid="status_success_borderless-icon"]'), + ).not.toBe(null); + }); + + it('renders bridge job details without the job link', () => { + vm = mountComponent(Component, { + job: { ...jobs[0], path: undefined }, + }); + + expect(vm.$el.querySelector('[data-testid="description-detail-link"]')).toBe(null); }); }); diff --git a/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js b/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js index b8dbca97ade..42526590ebb 100644 --- a/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js +++ b/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js @@ -1,5 +1,5 @@ import { shallowMount } from '@vue/test-utils'; -import Icon from '~/vue_shared/components/icon.vue'; +import { GlIcon } from '@gitlab/ui'; import ScrollButton from '~/ide/components/jobs/detail/scroll_button.vue'; describe('IDE job log scroll button', () => { @@ -27,7 +27,7 @@ describe('IDE job log scroll button', () => { beforeEach(() => createComponent({ direction })); it('returns proper icon name', () => { - expect(wrapper.find(Icon).props('name')).toBe(icon); + expect(wrapper.find(GlIcon).props('name')).toBe(icon); }); it('returns proper title', () => { diff --git a/spec/frontend/ide/components/jobs/detail_spec.js b/spec/frontend/ide/components/jobs/detail_spec.js index acd30dee718..496d8284fdd 100644 --- a/spec/frontend/ide/components/jobs/detail_spec.js +++ b/spec/frontend/ide/components/jobs/detail_spec.js @@ -24,7 +24,7 @@ describe('IDE jobs detail view', () => { beforeEach(() => { vm = createComponent(); - jest.spyOn(vm, 'fetchJobTrace').mockResolvedValue(); + jest.spyOn(vm, 'fetchJobLogs').mockResolvedValue(); }); afterEach(() => { @@ -36,8 +36,8 @@ describe('IDE jobs detail view', () => { vm = vm.$mount(); }); - it('calls fetchJobTrace', () => { - expect(vm.fetchJobTrace).toHaveBeenCalled(); + it('calls fetchJobLogs', () => { + expect(vm.fetchJobLogs).toHaveBeenCalled(); }); it('scrolls to bottom', () => { @@ -96,7 +96,7 @@ describe('IDE jobs detail view', () => { describe('scroll buttons', () => { beforeEach(() => { vm = createComponent(); - jest.spyOn(vm, 'fetchJobTrace').mockResolvedValue(); + jest.spyOn(vm, 'fetchJobLogs').mockResolvedValue(); }); afterEach(() => { diff --git a/spec/frontend/ide/components/jobs/item_spec.js b/spec/frontend/ide/components/jobs/item_spec.js index 2f97d39e98e..93c01640b54 100644 --- a/spec/frontend/ide/components/jobs/item_spec.js +++ b/spec/frontend/ide/components/jobs/item_spec.js @@ -24,7 +24,7 @@ describe('IDE jobs item', () => { }); it('renders CI icon', () => { - expect(vm.$el.querySelector('.ic-status_success_borderless')).not.toBe(null); + expect(vm.$el.querySelector('[data-testid="status_success_borderless-icon"]')).not.toBe(null); }); it('does not render view logs button if not started', done => { diff --git a/spec/frontend/ide/components/jobs/list_spec.js b/spec/frontend/ide/components/jobs/list_spec.js index d8880fa7cb7..e821a585e18 100644 --- a/spec/frontend/ide/components/jobs/list_spec.js +++ b/spec/frontend/ide/components/jobs/list_spec.js @@ -99,11 +99,7 @@ describe('IDE stages list', () => { it('calls toggleStageCollapsed when clicking stage header', () => { findCardHeader().trigger('click'); - expect(storeActions.toggleStageCollapsed).toHaveBeenCalledWith( - expect.any(Object), - 0, - undefined, - ); + expect(storeActions.toggleStageCollapsed).toHaveBeenCalledWith(expect.any(Object), 0); }); it('calls fetchJobs when stage is mounted', () => { diff --git a/spec/frontend/ide/components/merge_requests/item_spec.js b/spec/frontend/ide/components/merge_requests/item_spec.js index b1da89d7a9b..20adaa7abbc 100644 --- a/spec/frontend/ide/components/merge_requests/item_spec.js +++ b/spec/frontend/ide/components/merge_requests/item_spec.js @@ -33,7 +33,7 @@ describe('IDE merge request item', () => { store, }); }; - const findIcon = () => wrapper.find('.ic-mobile-issue-close'); + const findIcon = () => wrapper.find('[data-testid="mobile-issue-close-icon"]'); beforeEach(() => { store = createStore(); diff --git a/spec/frontend/ide/components/merge_requests/list_spec.js b/spec/frontend/ide/components/merge_requests/list_spec.js index e2c6ac49e07..80dcd861451 100644 --- a/spec/frontend/ide/components/merge_requests/list_spec.js +++ b/spec/frontend/ide/components/merge_requests/list_spec.js @@ -56,14 +56,10 @@ describe('IDE merge requests list', () => { it('calls fetch on mounted', () => { createComponent(); - expect(fetchMergeRequestsMock).toHaveBeenCalledWith( - expect.any(Object), - { - search: '', - type: '', - }, - undefined, - ); + expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), { + search: '', + type: '', + }); }); it('renders loading icon when merge request is loading', () => { @@ -95,14 +91,10 @@ describe('IDE merge requests list', () => { const searchType = wrapper.vm.$options.searchTypes[0]; expect(findTokenedInput().props('tokens')).toEqual([searchType]); - expect(fetchMergeRequestsMock).toHaveBeenCalledWith( - expect.any(Object), - { - type: searchType.type, - search: '', - }, - undefined, - ); + expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), { + type: searchType.type, + search: '', + }); }); }); @@ -136,14 +128,10 @@ describe('IDE merge requests list', () => { input.vm.$emit('input', 'something'); return wrapper.vm.$nextTick().then(() => { - expect(fetchMergeRequestsMock).toHaveBeenCalledWith( - expect.any(Object), - { - search: 'something', - type: '', - }, - undefined, - ); + expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), { + search: 'something', + type: '', + }); }); }); }); diff --git a/spec/frontend/ide/components/nav_dropdown_button_spec.js b/spec/frontend/ide/components/nav_dropdown_button_spec.js index 2aa3992a6d8..c98aa313f40 100644 --- a/spec/frontend/ide/components/nav_dropdown_button_spec.js +++ b/spec/frontend/ide/components/nav_dropdown_button_spec.js @@ -23,7 +23,7 @@ describe('NavDropdown', () => { vm.$mount(); }; - const findIcon = name => vm.$el.querySelector(`.ic-${name}`); + const findIcon = name => vm.$el.querySelector(`[data-testid="${name}-icon"]`); const findMRIcon = () => findIcon('merge-request'); const findBranchIcon = () => findIcon('branch'); diff --git a/spec/frontend/ide/components/nav_dropdown_spec.js b/spec/frontend/ide/components/nav_dropdown_spec.js index ce123d925c8..2f91ab7af0a 100644 --- a/spec/frontend/ide/components/nav_dropdown_spec.js +++ b/spec/frontend/ide/components/nav_dropdown_spec.js @@ -39,7 +39,7 @@ describe('IDE NavDropdown', () => { }); }; - const findIcon = name => wrapper.find(`.ic-${name}`); + const findIcon = name => wrapper.find(`[data-testid="${name}-icon"]`); const findMRIcon = () => findIcon('merge-request'); const findNavForm = () => wrapper.find('.ide-nav-form'); const showDropdown = () => { diff --git a/spec/frontend/ide/components/new_dropdown/button_spec.js b/spec/frontend/ide/components/new_dropdown/button_spec.js index 3c611b7de8f..66317296ee9 100644 --- a/spec/frontend/ide/components/new_dropdown/button_spec.js +++ b/spec/frontend/ide/components/new_dropdown/button_spec.js @@ -28,7 +28,7 @@ describe('IDE new entry dropdown button component', () => { }); it('renders icon', () => { - expect(vm.$el.querySelector('.ic-doc-new')).not.toBe(null); + expect(vm.$el.querySelector('[data-testid="doc-new-icon"]')).not.toBe(null); }); it('emits click event', () => { diff --git a/spec/frontend/ide/components/new_dropdown/upload_spec.js b/spec/frontend/ide/components/new_dropdown/upload_spec.js index ad27954cd10..ae497106f73 100644 --- a/spec/frontend/ide/components/new_dropdown/upload_spec.js +++ b/spec/frontend/ide/components/new_dropdown/upload_spec.js @@ -85,7 +85,6 @@ describe('new dropdown upload', () => { name: textFile.name, type: 'blob', content: 'plain text', - binary: false, rawPath: '', }); }) @@ -102,7 +101,6 @@ describe('new dropdown upload', () => { name: binaryFile.name, type: 'blob', content: binaryTarget.result.split('base64,')[1], - binary: true, rawPath: binaryTarget.result, }); }); diff --git a/spec/frontend/ide/components/pipelines/list_spec.js b/spec/frontend/ide/components/pipelines/list_spec.js index 86cdbafaff9..7f083fa7c25 100644 --- a/spec/frontend/ide/components/pipelines/list_spec.js +++ b/spec/frontend/ide/components/pipelines/list_spec.js @@ -22,11 +22,11 @@ describe('IDE pipelines list', () => { const defaultState = { links: { ciHelpPagePath: TEST_HOST }, pipelinesEmptyStateSvgPath: TEST_HOST, - pipelines: { - stages: [], - failedStages: [], - isLoadingJobs: false, - }, + }; + const defaultPipelinesState = { + stages: [], + failedStages: [], + isLoadingJobs: false, }; const fetchLatestPipelineMock = jest.fn(); @@ -34,23 +34,20 @@ describe('IDE pipelines list', () => { const failedStagesGetterMock = jest.fn().mockReturnValue([]); const fakeProjectPath = 'alpha/beta'; - const createComponent = (state = {}) => { - const { pipelines: pipelinesState, ...restOfState } = state; - const { defaultPipelines, ...defaultRestOfState } = defaultState; - - const fakeStore = new Vuex.Store({ + const createStore = (rootState, pipelinesState) => { + return new Vuex.Store({ getters: { currentProject: () => ({ web_url: 'some/url ', path_with_namespace: fakeProjectPath }), }, state: { - ...defaultRestOfState, - ...restOfState, + ...defaultState, + ...rootState, }, modules: { pipelines: { namespaced: true, state: { - ...defaultPipelines, + ...defaultPipelinesState, ...pipelinesState, }, actions: { @@ -69,10 +66,12 @@ describe('IDE pipelines list', () => { }, }, }); + }; + const createComponent = (state = {}, pipelinesState = {}) => { wrapper = shallowMount(List, { localVue, - store: fakeStore, + store: createStore(state, pipelinesState), }); }; @@ -94,31 +93,33 @@ describe('IDE pipelines list', () => { describe('when loading', () => { let defaultPipelinesLoadingState; + beforeAll(() => { defaultPipelinesLoadingState = { - ...defaultState.pipelines, isLoadingPipeline: true, }; }); it('does not render when pipeline has loaded before', () => { - createComponent({ - pipelines: { + createComponent( + {}, + { ...defaultPipelinesLoadingState, hasLoadedPipeline: true, }, - }); + ); expect(wrapper.find(GlLoadingIcon).exists()).toBe(false); }); it('renders loading state', () => { - createComponent({ - pipelines: { + createComponent( + {}, + { ...defaultPipelinesLoadingState, hasLoadedPipeline: false, }, - }); + ); expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); }); @@ -126,21 +127,22 @@ describe('IDE pipelines list', () => { describe('when loaded', () => { let defaultPipelinesLoadedState; + beforeAll(() => { defaultPipelinesLoadedState = { - ...defaultState.pipelines, isLoadingPipeline: false, hasLoadedPipeline: true, }; }); it('renders empty state when no latestPipeline', () => { - createComponent({ pipelines: { ...defaultPipelinesLoadedState, latestPipeline: null } }); + createComponent({}, { ...defaultPipelinesLoadedState, latestPipeline: null }); expect(wrapper.element).toMatchSnapshot(); }); describe('with latest pipeline loaded', () => { let withLatestPipelineState; + beforeAll(() => { withLatestPipelineState = { ...defaultPipelinesLoadedState, @@ -149,12 +151,12 @@ describe('IDE pipelines list', () => { }); it('renders ci icon', () => { - createComponent({ pipelines: withLatestPipelineState }); + createComponent({}, withLatestPipelineState); expect(wrapper.find(CiIcon).exists()).toBe(true); }); it('renders pipeline data', () => { - createComponent({ pipelines: withLatestPipelineState }); + createComponent({}, withLatestPipelineState); expect(wrapper.text()).toContain('#1'); }); @@ -162,7 +164,7 @@ describe('IDE pipelines list', () => { it('renders list of jobs', () => { const stages = []; const isLoadingJobs = true; - createComponent({ pipelines: { ...withLatestPipelineState, stages, isLoadingJobs } }); + createComponent({}, { ...withLatestPipelineState, stages, isLoadingJobs }); const jobProps = wrapper .findAll(Tab) @@ -177,7 +179,7 @@ describe('IDE pipelines list', () => { const failedStages = []; failedStagesGetterMock.mockReset().mockReturnValue(failedStages); const isLoadingJobs = true; - createComponent({ pipelines: { ...withLatestPipelineState, isLoadingJobs } }); + createComponent({}, { ...withLatestPipelineState, isLoadingJobs }); const jobProps = wrapper .findAll(Tab) @@ -191,12 +193,13 @@ describe('IDE pipelines list', () => { describe('with YAML error', () => { it('renders YAML error', () => { const yamlError = 'test yaml error'; - createComponent({ - pipelines: { + createComponent( + {}, + { ...defaultPipelinesLoadedState, latestPipeline: { ...pipelines[0], yamlError }, }, - }); + ); expect(wrapper.text()).toContain('Found errors in your .gitlab-ci.yml:'); expect(wrapper.text()).toContain(yamlError); diff --git a/spec/frontend/ide/components/preview/clientside_spec.js b/spec/frontend/ide/components/preview/clientside_spec.js index 7b2025f5e9f..7b22f75cee4 100644 --- a/spec/frontend/ide/components/preview/clientside_spec.js +++ b/spec/frontend/ide/components/preview/clientside_spec.js @@ -279,24 +279,16 @@ describe('IDE clientside preview', () => { }); it('calls getFileData', () => { - expect(storeActions.getFileData).toHaveBeenCalledWith( - expect.any(Object), - { - path: 'package.json', - makeFileActive: false, - }, - undefined, // vuex callback - ); + expect(storeActions.getFileData).toHaveBeenCalledWith(expect.any(Object), { + path: 'package.json', + makeFileActive: false, + }); }); it('calls getRawFileData', () => { - expect(storeActions.getRawFileData).toHaveBeenCalledWith( - expect.any(Object), - { - path: 'package.json', - }, - undefined, // vuex callback - ); + expect(storeActions.getRawFileData).toHaveBeenCalledWith(expect.any(Object), { + path: 'package.json', + }); }); }); diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js index f0ae2ba732b..9f4c9c1622a 100644 --- a/spec/frontend/ide/components/repo_editor_spec.js +++ b/spec/frontend/ide/components/repo_editor_spec.js @@ -45,7 +45,7 @@ describe('RepoEditor', () => { const createOpenFile = path => { const origFile = store.state.openFiles[0]; - const newFile = { ...origFile, path, key: path }; + const newFile = { ...origFile, path, key: path, name: 'myfile.txt', content: 'hello world' }; store.state.entries[path] = newFile; @@ -54,8 +54,9 @@ describe('RepoEditor', () => { beforeEach(() => { const f = { - ...file(), + ...file('file.txt'), viewMode: FILE_VIEW_MODE_EDITOR, + content: 'hello world', }; const storeOptions = createStoreOptions(); @@ -142,6 +143,7 @@ describe('RepoEditor', () => { ...vm.file, projectId: 'namespace/project', path: 'sample.md', + name: 'sample.md', content: 'testing 123', }); @@ -200,7 +202,8 @@ describe('RepoEditor', () => { describe('when open file is binary and not raw', () => { beforeEach(done => { - vm.file.binary = true; + vm.file.name = 'file.dat'; + vm.file.content = '🐱'; // non-ascii binary content vm.$nextTick(done); }); @@ -407,6 +410,9 @@ describe('RepoEditor', () => { beforeEach(done => { jest.spyOn(vm.editor, 'updateDimensions').mockImplementation(); vm.file.viewMode = FILE_VIEW_MODE_PREVIEW; + vm.file.name = 'myfile.md'; + vm.file.content = 'hello world'; + vm.$nextTick(done); }); @@ -650,7 +656,6 @@ describe('RepoEditor', () => { path: 'foo/foo.png', type: 'blob', content: 'Zm9v', - binary: true, rawPath: 'data:image/png;base64,Zm9v', }); }); diff --git a/spec/frontend/ide/components/repo_tab_spec.js b/spec/frontend/ide/components/repo_tab_spec.js index 5a591d3dcd0..f35726de27c 100644 --- a/spec/frontend/ide/components/repo_tab_spec.js +++ b/spec/frontend/ide/components/repo_tab_spec.js @@ -1,21 +1,24 @@ -import Vue from 'vue'; +import { mount, createLocalVue } from '@vue/test-utils'; +import Vuex from 'vuex'; import { createStore } from '~/ide/stores'; -import repoTab from '~/ide/components/repo_tab.vue'; +import RepoTab from '~/ide/components/repo_tab.vue'; import { createRouter } from '~/ide/ide_router'; import { file } from '../helpers'; +const localVue = createLocalVue(); +localVue.use(Vuex); + describe('RepoTab', () => { - let vm; + let wrapper; let store; let router; function createComponent(propsData) { - const RepoTab = Vue.extend(repoTab); - - return new RepoTab({ + wrapper = mount(RepoTab, { + localVue, store, propsData, - }).$mount(); + }); } beforeEach(() => { @@ -25,23 +28,24 @@ describe('RepoTab', () => { }); afterEach(() => { - vm.$destroy(); + wrapper.destroy(); + wrapper = null; }); it('renders a close link and a name link', () => { - vm = createComponent({ + createComponent({ tab: file(), }); - vm.$store.state.openFiles.push(vm.tab); - const close = vm.$el.querySelector('.multi-file-tab-close'); - const name = vm.$el.querySelector(`[title="${vm.tab.url}"]`); + wrapper.vm.$store.state.openFiles.push(wrapper.vm.tab); + const close = wrapper.find('.multi-file-tab-close'); + const name = wrapper.find(`[title]`); - expect(close.innerHTML).toContain('#close'); - expect(name.textContent.trim()).toEqual(vm.tab.name); + expect(close.html()).toContain('#close'); + expect(name.text().trim()).toEqual(wrapper.vm.tab.name); }); - it('does not call openPendingTab when tab is active', done => { - vm = createComponent({ + it('does not call openPendingTab when tab is active', async () => { + createComponent({ tab: { ...file(), pending: true, @@ -49,63 +53,51 @@ describe('RepoTab', () => { }, }); - jest.spyOn(vm, 'openPendingTab').mockImplementation(() => {}); + jest.spyOn(wrapper.vm, 'openPendingTab').mockImplementation(() => {}); - vm.$el.click(); + await wrapper.trigger('click'); - vm.$nextTick(() => { - expect(vm.openPendingTab).not.toHaveBeenCalled(); - - done(); - }); + expect(wrapper.vm.openPendingTab).not.toHaveBeenCalled(); }); it('fires clickFile when the link is clicked', () => { - vm = createComponent({ + createComponent({ tab: file(), }); - jest.spyOn(vm, 'clickFile').mockImplementation(() => {}); + jest.spyOn(wrapper.vm, 'clickFile').mockImplementation(() => {}); - vm.$el.click(); + wrapper.trigger('click'); - expect(vm.clickFile).toHaveBeenCalledWith(vm.tab); + expect(wrapper.vm.clickFile).toHaveBeenCalledWith(wrapper.vm.tab); }); it('calls closeFile when clicking close button', () => { - vm = createComponent({ + createComponent({ tab: file(), }); - jest.spyOn(vm, 'closeFile').mockImplementation(() => {}); + jest.spyOn(wrapper.vm, 'closeFile').mockImplementation(() => {}); - vm.$el.querySelector('.multi-file-tab-close').click(); + wrapper.find('.multi-file-tab-close').trigger('click'); - expect(vm.closeFile).toHaveBeenCalledWith(vm.tab); + expect(wrapper.vm.closeFile).toHaveBeenCalledWith(wrapper.vm.tab); }); - it('changes icon on hover', done => { + it('changes icon on hover', async () => { const tab = file(); tab.changed = true; - vm = createComponent({ + createComponent({ tab, }); - vm.$el.dispatchEvent(new Event('mouseover')); + await wrapper.trigger('mouseover'); - Vue.nextTick() - .then(() => { - expect(vm.$el.querySelector('.file-modified')).toBeNull(); + expect(wrapper.find('.file-modified').exists()).toBe(false); - vm.$el.dispatchEvent(new Event('mouseout')); - }) - .then(Vue.nextTick) - .then(() => { - expect(vm.$el.querySelector('.file-modified')).not.toBeNull(); + await wrapper.trigger('mouseout'); - done(); - }) - .catch(done.fail); + expect(wrapper.find('.file-modified').exists()).toBe(true); }); describe('locked file', () => { @@ -120,21 +112,17 @@ describe('RepoTab', () => { }, }; - vm = createComponent({ + createComponent({ tab: f, }); }); - afterEach(() => { - vm.$destroy(); - }); - it('renders lock icon', () => { - expect(vm.$el.querySelector('.file-status-icon')).not.toBeNull(); + expect(wrapper.find('.file-status-icon')).not.toBeNull(); }); it('renders a tooltip', () => { - expect(vm.$el.querySelector('span:nth-child(2)').dataset.originalTitle).toContain( + expect(wrapper.find('span:nth-child(2)').attributes('data-original-title')).toContain( 'Locked by testuser', ); }); @@ -142,45 +130,37 @@ describe('RepoTab', () => { describe('methods', () => { describe('closeTab', () => { - it('closes tab if file has changed', done => { + it('closes tab if file has changed', async () => { const tab = file(); tab.changed = true; tab.opened = true; - vm = createComponent({ + createComponent({ tab, }); - vm.$store.state.openFiles.push(tab); - vm.$store.state.changedFiles.push(tab); - vm.$store.state.entries[tab.path] = tab; - vm.$store.dispatch('setFileActive', tab.path); - - vm.$el.querySelector('.multi-file-tab-close').click(); + wrapper.vm.$store.state.openFiles.push(tab); + wrapper.vm.$store.state.changedFiles.push(tab); + wrapper.vm.$store.state.entries[tab.path] = tab; + wrapper.vm.$store.dispatch('setFileActive', tab.path); - vm.$nextTick(() => { - expect(tab.opened).toBeFalsy(); - expect(vm.$store.state.changedFiles.length).toBe(1); + await wrapper.find('.multi-file-tab-close').trigger('click'); - done(); - }); + expect(tab.opened).toBeFalsy(); + expect(wrapper.vm.$store.state.changedFiles).toHaveLength(1); }); - it('closes tab when clicking close btn', done => { + it('closes tab when clicking close btn', async () => { const tab = file('lose'); tab.opened = true; - vm = createComponent({ + createComponent({ tab, }); - vm.$store.state.openFiles.push(tab); - vm.$store.state.entries[tab.path] = tab; - vm.$store.dispatch('setFileActive', tab.path); + wrapper.vm.$store.state.openFiles.push(tab); + wrapper.vm.$store.state.entries[tab.path] = tab; + wrapper.vm.$store.dispatch('setFileActive', tab.path); - vm.$el.querySelector('.multi-file-tab-close').click(); + await wrapper.find('.multi-file-tab-close').trigger('click'); - vm.$nextTick(() => { - expect(tab.opened).toBeFalsy(); - - done(); - }); + expect(tab.opened).toBeFalsy(); }); }); }); diff --git a/spec/frontend/ide/components/repo_tabs_spec.js b/spec/frontend/ide/components/repo_tabs_spec.js index df5b01770f5..b251f207853 100644 --- a/spec/frontend/ide/components/repo_tabs_spec.js +++ b/spec/frontend/ide/components/repo_tabs_spec.js @@ -1,27 +1,40 @@ -import Vue from 'vue'; -import repoTabs from '~/ide/components/repo_tabs.vue'; -import createComponent from '../../helpers/vue_mount_component_helper'; +import Vuex from 'vuex'; +import { mount, createLocalVue } from '@vue/test-utils'; +import { createStore } from '~/ide/stores'; +import RepoTabs from '~/ide/components/repo_tabs.vue'; import { file } from '../helpers'; +const localVue = createLocalVue(); +localVue.use(Vuex); + describe('RepoTabs', () => { - const openedFiles = [file('open1'), file('open2')]; - const RepoTabs = Vue.extend(repoTabs); - let vm; + let wrapper; + let store; + + beforeEach(() => { + store = createStore(); + store.state.openFiles = [file('open1'), file('open2')]; + + wrapper = mount(RepoTabs, { + propsData: { + files: store.state.openFiles, + viewer: 'editor', + activeFile: file('activeFile'), + }, + store, + localVue, + }); + }); afterEach(() => { - vm.$destroy(); + wrapper.destroy(); }); it('renders a list of tabs', done => { - vm = createComponent(RepoTabs, { - files: openedFiles, - viewer: 'editor', - activeFile: file('activeFile'), - }); - openedFiles[0].active = true; + store.state.openFiles[0].active = true; - vm.$nextTick(() => { - const tabs = [...vm.$el.querySelectorAll('.multi-file-tab')]; + wrapper.vm.$nextTick(() => { + const tabs = [...wrapper.vm.$el.querySelectorAll('.multi-file-tab')]; expect(tabs.length).toEqual(2); expect(tabs[0].parentNode.classList.contains('active')).toEqual(true); diff --git a/spec/frontend/ide/components/terminal/session_spec.js b/spec/frontend/ide/components/terminal/session_spec.js index 2399446ed15..ce61a31691a 100644 --- a/spec/frontend/ide/components/terminal/session_spec.js +++ b/spec/frontend/ide/components/terminal/session_spec.js @@ -52,7 +52,7 @@ describe('IDE TerminalSession', () => { state.session = null; factory(); - expect(wrapper.isEmpty()).toBe(true); + expect(wrapper.html()).toBe(''); }); it('shows terminal', () => { diff --git a/spec/frontend/ide/components/terminal/terminal_controls_spec.js b/spec/frontend/ide/components/terminal/terminal_controls_spec.js index 6c2871abb46..c22063e1d72 100644 --- a/spec/frontend/ide/components/terminal/terminal_controls_spec.js +++ b/spec/frontend/ide/components/terminal/terminal_controls_spec.js @@ -42,24 +42,24 @@ describe('IDE TerminalControls', () => { it('emits "scroll-up" when click up button', () => { factory({ propsData: { canScrollUp: true } }); - expect(wrapper.emittedByOrder()).toEqual([]); + expect(wrapper.emitted()).toEqual({}); buttons.at(0).vm.$emit('click'); return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emittedByOrder()).toEqual([{ name: 'scroll-up', args: [] }]); + expect(wrapper.emitted('scroll-up')).toEqual([[]]); }); }); it('emits "scroll-down" when click down button', () => { factory({ propsData: { canScrollDown: true } }); - expect(wrapper.emittedByOrder()).toEqual([]); + expect(wrapper.emitted()).toEqual({}); buttons.at(1).vm.$emit('click'); return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emittedByOrder()).toEqual([{ name: 'scroll-down', args: [] }]); + expect(wrapper.emitted('scroll-down')).toEqual([[]]); }); }); }); diff --git a/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js b/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js index 16a76fae1dd..9adf5848f9d 100644 --- a/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js +++ b/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js @@ -1,13 +1,12 @@ import Vuex from 'vuex'; import { createLocalVue, shallowMount } from '@vue/test-utils'; -import { GlLoadingIcon } from '@gitlab/ui'; +import { GlLoadingIcon, GlIcon } from '@gitlab/ui'; import TerminalSyncStatus from '~/ide/components/terminal_sync/terminal_sync_status.vue'; import { MSG_TERMINAL_SYNC_CONNECTING, MSG_TERMINAL_SYNC_UPLOADING, MSG_TERMINAL_SYNC_RUNNING, } from '~/ide/stores/modules/terminal_sync/messages'; -import Icon from '~/vue_shared/components/icon.vue'; const TEST_MESSAGE = 'lorem ipsum dolar sit'; const START_LOADING = 'START_LOADING'; @@ -58,7 +57,7 @@ describe('ide/components/terminal_sync/terminal_sync_status', () => { it('shows nothing', () => { createComponent(); - expect(wrapper.isEmpty()).toBe(true); + expect(wrapper.html()).toBe(''); }); }); @@ -80,7 +79,7 @@ describe('ide/components/terminal_sync/terminal_sync_status', () => { if (!icon) { it('does not render icon', () => { - expect(wrapper.find(Icon).exists()).toBe(false); + expect(wrapper.find(GlIcon).exists()).toBe(false); }); it('renders loading icon', () => { @@ -88,7 +87,7 @@ describe('ide/components/terminal_sync/terminal_sync_status', () => { }); } else { it('renders icon', () => { - expect(wrapper.find(Icon).props('name')).toEqual(icon); + expect(wrapper.find(GlIcon).props('name')).toEqual(icon); }); it('does not render loading icon', () => { -- cgit v1.2.1