Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-09-19 04:45:44 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-19 04:45:44 +0300
commit85dc423f7090da0a52c73eb66faf22ddb20efff9 (patch)
tree9160f299afd8c80c038f08e1545be119f5e3f1e1 /spec/frontend/ide
parent15c2c8c66dbe422588e5411eee7e68f1fa440bb8 (diff)
Add latest changes from gitlab-org/gitlab@13-4-stable-ee
Diffstat (limited to 'spec/frontend/ide')
-rw-r--r--spec/frontend/ide/commit_icon_spec.js1
-rw-r--r--spec/frontend/ide/components/branches/item_spec.js6
-rw-r--r--spec/frontend/ide/components/commit_sidebar/form_spec.js53
-rw-r--r--spec/frontend/ide/components/error_message_spec.js2
-rw-r--r--spec/frontend/ide/components/file_row_extra_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_status_list_spec.js3
-rw-r--r--spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap2
-rw-r--r--spec/frontend/ide/components/jobs/detail/description_spec.js12
-rw-r--r--spec/frontend/ide/components/jobs/detail/scroll_button_spec.js4
-rw-r--r--spec/frontend/ide/components/jobs/detail_spec.js8
-rw-r--r--spec/frontend/ide/components/jobs/item_spec.js2
-rw-r--r--spec/frontend/ide/components/jobs/list_spec.js6
-rw-r--r--spec/frontend/ide/components/merge_requests/item_spec.js2
-rw-r--r--spec/frontend/ide/components/merge_requests/list_spec.js36
-rw-r--r--spec/frontend/ide/components/nav_dropdown_button_spec.js2
-rw-r--r--spec/frontend/ide/components/nav_dropdown_spec.js2
-rw-r--r--spec/frontend/ide/components/new_dropdown/button_spec.js2
-rw-r--r--spec/frontend/ide/components/new_dropdown/upload_spec.js2
-rw-r--r--spec/frontend/ide/components/pipelines/list_spec.js63
-rw-r--r--spec/frontend/ide/components/preview/clientside_spec.js22
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js13
-rw-r--r--spec/frontend/ide/components/repo_tab_spec.js132
-rw-r--r--spec/frontend/ide/components/repo_tabs_spec.js43
-rw-r--r--spec/frontend/ide/components/terminal/session_spec.js2
-rw-r--r--spec/frontend/ide/components/terminal/terminal_controls_spec.js8
-rw-r--r--spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js9
-rw-r--r--spec/frontend/ide/helpers.js1
-rw-r--r--spec/frontend/ide/lib/editor_spec.js22
-rw-r--r--spec/frontend/ide/lib/errors_spec.js70
-rw-r--r--spec/frontend/ide/lib/files_spec.js19
-rw-r--r--spec/frontend/ide/mock_data.js3
-rw-r--r--spec/frontend/ide/services/index_spec.js6
-rw-r--r--spec/frontend/ide/stores/actions/file_spec.js26
-rw-r--r--spec/frontend/ide/stores/actions/merge_request_spec.js2
-rw-r--r--spec/frontend/ide/stores/actions_spec.js15
-rw-r--r--spec/frontend/ide/stores/getters_spec.js45
-rw-r--r--spec/frontend/ide/stores/integration_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/commit/actions_spec.js22
-rw-r--r--spec/frontend/ide/stores/modules/commit/mutations_spec.js21
-rw-r--r--spec/frontend/ide/stores/modules/pipelines/actions_spec.js40
-rw-r--r--spec/frontend/ide/stores/modules/pipelines/mutations_spec.js12
-rw-r--r--spec/frontend/ide/stores/mutations/file_spec.js2
-rw-r--r--spec/frontend/ide/stores/mutations_spec.js18
-rw-r--r--spec/frontend/ide/sync_router_and_store_spec.js8
-rw-r--r--spec/frontend/ide/utils_spec.js162
45 files changed, 523 insertions, 414 deletions
diff --git a/spec/frontend/ide/commit_icon_spec.js b/spec/frontend/ide/commit_icon_spec.js
index e4a7394b089..0dfcae00298 100644
--- a/spec/frontend/ide/commit_icon_spec.js
+++ b/spec/frontend/ide/commit_icon_spec.js
@@ -7,7 +7,6 @@ const createFile = (name = 'name', id = name, type = '', parent = null) =>
id,
type,
icon: 'icon',
- url: 'url',
name,
path: parent ? `${parent.path}/${name}` : name,
parentPath: parent ? parent.path : '',
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`] = `
</span>
</div>
- <icon-stub
+ <gl-icon-stub
class="ide-stage-collapse-icon"
name="angle-down"
size="16"
diff --git a/spec/frontend/ide/components/jobs/detail/description_spec.js b/spec/frontend/ide/components/jobs/detail/description_spec.js
index babae00d2f7..5554738336a 100644
--- a/spec/frontend/ide/components/jobs/detail/description_spec.js
+++ b/spec/frontend/ide/components/jobs/detail/description_spec.js
@@ -23,6 +23,16 @@ describe('IDE job description', () => {
});
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', () => {
diff --git a/spec/frontend/ide/helpers.js b/spec/frontend/ide/helpers.js
index 8caa9c2b437..0e85b523cbd 100644
--- a/spec/frontend/ide/helpers.js
+++ b/spec/frontend/ide/helpers.js
@@ -6,7 +6,6 @@ export const file = (name = 'name', id = name, type = '', parent = null) =>
id,
type,
icon: 'icon',
- url: 'url',
name,
path: parent ? `${parent.path}/${name}` : name,
parentPath: parent ? parent.path : '',
diff --git a/spec/frontend/ide/lib/editor_spec.js b/spec/frontend/ide/lib/editor_spec.js
index 529f80e6f6f..01c2eab33a5 100644
--- a/spec/frontend/ide/lib/editor_spec.js
+++ b/spec/frontend/ide/lib/editor_spec.js
@@ -202,28 +202,6 @@ describe('Multi-file editor library', () => {
});
});
- describe('schemas', () => {
- let originalGon;
-
- beforeEach(() => {
- originalGon = window.gon;
- window.gon = { features: { schemaLinting: true } };
-
- delete Editor.editorInstance;
- instance = Editor.create();
- });
-
- afterEach(() => {
- window.gon = originalGon;
- });
-
- it('registers custom schemas defined with Monaco', () => {
- expect(monacoLanguages.yaml.yamlDefaults.diagnosticsOptions).toMatchObject({
- schemas: [{ fileMatch: ['*.gitlab-ci.yml'] }],
- });
- });
- });
-
describe('replaceSelectedText', () => {
let model;
let editor;
diff --git a/spec/frontend/ide/lib/errors_spec.js b/spec/frontend/ide/lib/errors_spec.js
new file mode 100644
index 00000000000..8c3fb378302
--- /dev/null
+++ b/spec/frontend/ide/lib/errors_spec.js
@@ -0,0 +1,70 @@
+import {
+ createUnexpectedCommitError,
+ createCodeownersCommitError,
+ createBranchChangedCommitError,
+ parseCommitError,
+} from '~/ide/lib/errors';
+
+const TEST_SPECIAL = '&special<';
+const TEST_SPECIAL_ESCAPED = '&amp;special&lt;';
+const TEST_MESSAGE = 'Test message.';
+const CODEOWNERS_MESSAGE =
+ 'Push to protected branches that contain changes to files matching CODEOWNERS is not allowed';
+const CHANGED_MESSAGE = 'Things changed since you started editing';
+
+describe('~/ide/lib/errors', () => {
+ const createResponseError = message => ({
+ response: {
+ data: {
+ message,
+ },
+ },
+ });
+
+ describe('createCodeownersCommitError', () => {
+ it('uses given message', () => {
+ expect(createCodeownersCommitError(TEST_MESSAGE)).toEqual({
+ title: 'CODEOWNERS rule violation',
+ messageHTML: TEST_MESSAGE,
+ canCreateBranch: true,
+ });
+ });
+
+ it('escapes special chars', () => {
+ expect(createCodeownersCommitError(TEST_SPECIAL)).toEqual({
+ title: 'CODEOWNERS rule violation',
+ messageHTML: TEST_SPECIAL_ESCAPED,
+ canCreateBranch: true,
+ });
+ });
+ });
+
+ describe('createBranchChangedCommitError', () => {
+ it.each`
+ message | expectedMessage
+ ${TEST_MESSAGE} | ${`${TEST_MESSAGE}<br/><br/>Would you like to create a new branch?`}
+ ${TEST_SPECIAL} | ${`${TEST_SPECIAL_ESCAPED}<br/><br/>Would you like to create a new branch?`}
+ `('uses given message="$message"', ({ message, expectedMessage }) => {
+ expect(createBranchChangedCommitError(message)).toEqual({
+ title: 'Branch changed',
+ messageHTML: expectedMessage,
+ canCreateBranch: true,
+ });
+ });
+ });
+
+ describe('parseCommitError', () => {
+ it.each`
+ message | expectation
+ ${null} | ${createUnexpectedCommitError()}
+ ${{}} | ${createUnexpectedCommitError()}
+ ${{ response: {} }} | ${createUnexpectedCommitError()}
+ ${{ response: { data: {} } }} | ${createUnexpectedCommitError()}
+ ${createResponseError('test')} | ${createUnexpectedCommitError()}
+ ${createResponseError(CODEOWNERS_MESSAGE)} | ${createCodeownersCommitError(CODEOWNERS_MESSAGE)}
+ ${createResponseError(CHANGED_MESSAGE)} | ${createBranchChangedCommitError(CHANGED_MESSAGE)}
+ `('parses message into error object with "$message"', ({ message, expectation }) => {
+ expect(parseCommitError(message)).toEqual(expectation);
+ });
+ });
+});
diff --git a/spec/frontend/ide/lib/files_spec.js b/spec/frontend/ide/lib/files_spec.js
index 6974cdc4074..8ca6f01d9a6 100644
--- a/spec/frontend/ide/lib/files_spec.js
+++ b/spec/frontend/ide/lib/files_spec.js
@@ -1,29 +1,16 @@
-import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
import { decorateFiles, splitParent } from '~/ide/lib/files';
import { decorateData } from '~/ide/stores/utils';
-const TEST_BRANCH_ID = 'lorem-ipsum';
-const TEST_PROJECT_ID = 10;
-
const createEntries = paths => {
const createEntry = (acc, { path, type, children }) => {
- // Sometimes we need to end the url with a '/'
- const createUrl = base => (type === 'tree' ? `${base}/` : base);
-
const { name, parent } = splitParent(path);
- const previewMode = viewerInformationForPath(name);
acc[path] = {
...decorateData({
- projectId: TEST_PROJECT_ID,
- branchId: TEST_BRANCH_ID,
id: path,
name,
path,
- url: createUrl(`/${TEST_PROJECT_ID}/${type}/${TEST_BRANCH_ID}/-/${path}`),
type,
- previewMode,
- binary: (previewMode && previewMode.binary) || false,
parentPath: parent,
}),
tree: children.map(childName => expect.objectContaining({ name: childName })),
@@ -56,11 +43,7 @@ describe('IDE lib decorate files', () => {
{ path: 'README.md', type: 'blob', children: [] },
]);
- const { entries, treeList } = decorateFiles({
- data,
- branchId: TEST_BRANCH_ID,
- projectId: TEST_PROJECT_ID,
- });
+ const { entries, treeList } = decorateFiles({ data });
// Here we test the keys and then each key/value individually because `expect(entries).toEqual(expectedEntries)`
// was taking a very long time for some reason. Probably due to large objects and nested `expect.objectContaining`.
diff --git a/spec/frontend/ide/mock_data.js b/spec/frontend/ide/mock_data.js
index 472516b6a2c..c8925e6745d 100644
--- a/spec/frontend/ide/mock_data.js
+++ b/spec/frontend/ide/mock_data.js
@@ -112,7 +112,8 @@ export const jobs = [
{
id: 4,
name: 'test 4',
- path: 'testing4',
+ // bridge jobs don't have details page and so there is no path attribute
+ // see https://gitlab.com/gitlab-org/gitlab/-/issues/216480
status: {
icon: 'status_failed',
text: 'failed',
diff --git a/spec/frontend/ide/services/index_spec.js b/spec/frontend/ide/services/index_spec.js
index bc3f86702cf..d2c32a81811 100644
--- a/spec/frontend/ide/services/index_spec.js
+++ b/spec/frontend/ide/services/index_spec.js
@@ -146,7 +146,7 @@ describe('IDE services', () => {
it('gives back file.baseRaw for files with that property present', () => {
file.baseRaw = TEST_FILE_CONTENTS;
- return services.getBaseRawFileData(file, TEST_COMMIT_SHA).then(content => {
+ return services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then(content => {
expect(content).toEqual(TEST_FILE_CONTENTS);
});
});
@@ -155,7 +155,7 @@ describe('IDE services', () => {
file.tempFile = true;
file.baseRaw = TEST_FILE_CONTENTS;
- return services.getBaseRawFileData(file, TEST_COMMIT_SHA).then(content => {
+ return services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then(content => {
expect(content).toEqual(TEST_FILE_CONTENTS);
});
});
@@ -192,7 +192,7 @@ describe('IDE services', () => {
});
it('fetches file content', () =>
- services.getBaseRawFileData(file, TEST_COMMIT_SHA).then(content => {
+ services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then(content => {
expect(content).toEqual(TEST_FILE_CONTENTS);
}));
},
diff --git a/spec/frontend/ide/stores/actions/file_spec.js b/spec/frontend/ide/stores/actions/file_spec.js
index 88e7a9fff36..974c0715c06 100644
--- a/spec/frontend/ide/stores/actions/file_spec.js
+++ b/spec/frontend/ide/stores/actions/file_spec.js
@@ -27,6 +27,10 @@ describe('IDE store file actions', () => {
};
store = createStore();
+
+ store.state.currentProjectId = 'test/test';
+ store.state.currentBranchId = 'master';
+
router = createRouter(store);
jest.spyOn(store, 'commit');
@@ -72,10 +76,7 @@ describe('IDE store file actions', () => {
});
it('closes file & opens next available file', () => {
- const f = {
- ...file('newOpenFile'),
- url: '/newOpenFile',
- };
+ const f = file('newOpenFile');
store.state.openFiles.push(f);
store.state.entries[f.path] = f;
@@ -84,7 +85,7 @@ describe('IDE store file actions', () => {
.dispatch('closeFile', localFile)
.then(Vue.nextTick)
.then(() => {
- expect(router.push).toHaveBeenCalledWith(`/project${f.url}`);
+ expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/master/-/newOpenFile/');
});
});
@@ -240,7 +241,6 @@ describe('IDE store file actions', () => {
200,
{
raw_path: 'raw_path',
- binary: false,
},
{
'page-title': 'testing getFileData',
@@ -296,7 +296,6 @@ describe('IDE store file actions', () => {
describe('Re-named success', () => {
beforeEach(() => {
localFile = file(`newCreate-${Math.random()}`);
- localFile.url = `project/getFileDataURL`;
localFile.prevPath = 'old-dull-file';
localFile.path = 'new-shiny-file';
store.state.entries[localFile.path] = localFile;
@@ -305,7 +304,6 @@ describe('IDE store file actions', () => {
200,
{
raw_path: 'raw_path',
- binary: false,
},
{
'page-title': 'testing old-dull-file',
@@ -393,7 +391,11 @@ describe('IDE store file actions', () => {
tmpFile.mrChange = { new_file: false };
return store.dispatch('getRawFileData', { path: tmpFile.path }).then(() => {
- expect(service.getBaseRawFileData).toHaveBeenCalledWith(tmpFile, 'SHA');
+ expect(service.getBaseRawFileData).toHaveBeenCalledWith(
+ tmpFile,
+ 'gitlab-org/gitlab-ce',
+ 'SHA',
+ );
expect(tmpFile.baseRaw).toBe('baseraw');
});
});
@@ -660,7 +662,7 @@ describe('IDE store file actions', () => {
});
it('pushes route for active file', () => {
- expect(router.push).toHaveBeenCalledWith(`/project${tmpFile.url}`);
+ expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/master/-/tempFile/');
});
});
});
@@ -735,10 +737,8 @@ describe('IDE store file actions', () => {
});
it('pushes router URL when added', () => {
- store.state.currentBranchId = 'master';
-
return store.dispatch('openPendingTab', { file: f, keyPrefix: 'pending' }).then(() => {
- expect(router.push).toHaveBeenCalledWith('/project/123/tree/master/');
+ expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/master/');
});
});
});
diff --git a/spec/frontend/ide/stores/actions/merge_request_spec.js b/spec/frontend/ide/stores/actions/merge_request_spec.js
index 62971b9cad6..b1cceda9d85 100644
--- a/spec/frontend/ide/stores/actions/merge_request_spec.js
+++ b/spec/frontend/ide/stores/actions/merge_request_spec.js
@@ -453,11 +453,9 @@ describe('IDE store merge request actions', () => {
it('updates activity bar view and gets file data, if changes are found', done => {
store.state.entries.foo = {
- url: 'test',
type: 'blob',
};
store.state.entries.bar = {
- url: 'test',
type: 'blob',
};
diff --git a/spec/frontend/ide/stores/actions_spec.js b/spec/frontend/ide/stores/actions_spec.js
index f77dbd80025..ebf39df2f6f 100644
--- a/spec/frontend/ide/stores/actions_spec.js
+++ b/spec/frontend/ide/stores/actions_spec.js
@@ -123,7 +123,6 @@ describe('Multi-file store actions', () => {
it('creates temp tree', done => {
store
.dispatch('createTempEntry', {
- branchId: store.state.currentBranchId,
name: 'test',
type: 'tree',
})
@@ -150,7 +149,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
- branchId: store.state.currentBranchId,
name: 'testing/test',
type: 'tree',
})
@@ -176,7 +174,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
- branchId: store.state.currentBranchId,
name: 'testing',
type: 'tree',
})
@@ -197,7 +194,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
name,
- branchId: 'mybranch',
type: 'blob',
})
.then(() => {
@@ -217,7 +213,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
name,
- branchId: 'mybranch',
type: 'blob',
})
.then(() => {
@@ -237,7 +232,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
name,
- branchId: 'mybranch',
type: 'blob',
})
.then(() => {
@@ -249,7 +243,7 @@ describe('Multi-file store actions', () => {
});
it('sets tmp file as active', () => {
- createTempEntry(store, { name: 'test', branchId: 'mybranch', type: 'blob' });
+ createTempEntry(store, { name: 'test', type: 'blob' });
expect(store.dispatch).toHaveBeenCalledWith('setFileActive', 'test');
});
@@ -262,7 +256,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
name: 'test',
- branchId: 'mybranch',
type: 'blob',
})
.then(() => {
@@ -780,9 +773,11 @@ describe('Multi-file store actions', () => {
});
it('routes to the renamed file if the original file has been opened', done => {
+ store.state.currentProjectId = 'test/test';
+ store.state.currentBranchId = 'master';
+
Object.assign(store.state.entries.orig, {
opened: true,
- url: '/foo-bar.md',
});
store
@@ -792,7 +787,7 @@ describe('Multi-file store actions', () => {
})
.then(() => {
expect(router.push.mock.calls).toHaveLength(1);
- expect(router.push).toHaveBeenCalledWith(`/project/foo-bar.md`);
+ expect(router.push).toHaveBeenCalledWith(`/project/test/test/tree/master/-/renamed/`);
})
.then(done)
.catch(done.fail);
diff --git a/spec/frontend/ide/stores/getters_spec.js b/spec/frontend/ide/stores/getters_spec.js
index dcf05329ce0..e24f08fa802 100644
--- a/spec/frontend/ide/stores/getters_spec.js
+++ b/spec/frontend/ide/stores/getters_spec.js
@@ -1,3 +1,4 @@
+import { TEST_HOST } from 'helpers/test_constants';
import * as getters from '~/ide/stores/getters';
import { createStore } from '~/ide/stores';
import { file } from '../helpers';
@@ -482,4 +483,48 @@ describe('IDE store getters', () => {
expect(localStore.getters.getAvailableFileName('foo-bar1.jpg')).toBe('foo-bar1.jpg');
});
});
+
+ describe('getUrlForPath', () => {
+ it('returns a route url for the given path', () => {
+ localState.currentProjectId = 'test/test';
+ localState.currentBranchId = 'master';
+
+ expect(localStore.getters.getUrlForPath('path/to/foo/bar-1.jpg')).toBe(
+ `/project/test/test/tree/master/-/path/to/foo/bar-1.jpg/`,
+ );
+ });
+ });
+
+ describe('getJsonSchemaForPath', () => {
+ beforeEach(() => {
+ localState.currentProjectId = 'path/to/some/project';
+ localState.currentBranchId = 'master';
+ });
+
+ it('returns a json schema uri and match config for a json/yaml file that can be loaded by monaco', () => {
+ expect(localStore.getters.getJsonSchemaForPath('.gitlab-ci.yml')).toEqual({
+ fileMatch: ['*.gitlab-ci.yml'],
+ uri: `${TEST_HOST}/path/to/some/project/-/schema/master/.gitlab-ci.yml`,
+ });
+ });
+
+ it('returns a path containing sha if branch details are present in state', () => {
+ localState.projects['path/to/some/project'] = {
+ name: 'project',
+ branches: {
+ master: {
+ name: 'master',
+ commit: {
+ id: 'abcdef123456',
+ },
+ },
+ },
+ };
+
+ expect(localStore.getters.getJsonSchemaForPath('.gitlab-ci.yml')).toEqual({
+ fileMatch: ['*.gitlab-ci.yml'],
+ uri: `${TEST_HOST}/path/to/some/project/-/schema/abcdef123456/.gitlab-ci.yml`,
+ });
+ });
+ });
});
diff --git a/spec/frontend/ide/stores/integration_spec.js b/spec/frontend/ide/stores/integration_spec.js
index f95f036f572..b6a7c7fd02d 100644
--- a/spec/frontend/ide/stores/integration_spec.js
+++ b/spec/frontend/ide/stores/integration_spec.js
@@ -36,8 +36,6 @@ describe('IDE store integration', () => {
beforeEach(() => {
const { entries, treeList } = decorateFiles({
data: [`${TEST_PATH_DIR}/`, TEST_PATH, 'README.md'],
- projectId: TEST_PROJECT_ID,
- branchId: TEST_BRANCH,
});
Object.assign(entries[TEST_PATH], {
diff --git a/spec/frontend/ide/stores/modules/commit/actions_spec.js b/spec/frontend/ide/stores/modules/commit/actions_spec.js
index a14879112fd..babc50e54f1 100644
--- a/spec/frontend/ide/stores/modules/commit/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/actions_spec.js
@@ -9,6 +9,7 @@ import eventHub from '~/ide/eventhub';
import consts from '~/ide/stores/modules/commit/constants';
import * as mutationTypes from '~/ide/stores/modules/commit/mutation_types';
import * as actions from '~/ide/stores/modules/commit/actions';
+import { createUnexpectedCommitError } from '~/ide/lib/errors';
import { commitActionTypes, PERMISSION_CREATE_MR } from '~/ide/constants';
import testAction from '../../../../helpers/vuex_action_helper';
@@ -510,7 +511,7 @@ describe('IDE commit module actions', () => {
});
});
- describe('failed', () => {
+ describe('success response with failed message', () => {
beforeEach(() => {
jest.spyOn(service, 'commit').mockResolvedValue({
data: {
@@ -533,6 +534,25 @@ describe('IDE commit module actions', () => {
});
});
+ describe('failed response', () => {
+ beforeEach(() => {
+ jest.spyOn(service, 'commit').mockRejectedValue({});
+ });
+
+ it('commits error updates', async () => {
+ jest.spyOn(store, 'commit');
+
+ await store.dispatch('commit/commitChanges').catch(() => {});
+
+ expect(store.commit.mock.calls).toEqual([
+ ['commit/CLEAR_ERROR', undefined, undefined],
+ ['commit/UPDATE_LOADING', true, undefined],
+ ['commit/UPDATE_LOADING', false, undefined],
+ ['commit/SET_ERROR', createUnexpectedCommitError(), undefined],
+ ]);
+ });
+ });
+
describe('first commit of a branch', () => {
const COMMIT_RESPONSE = {
id: '123456',
diff --git a/spec/frontend/ide/stores/modules/commit/mutations_spec.js b/spec/frontend/ide/stores/modules/commit/mutations_spec.js
index 45ac1a86ab3..6393a70eac6 100644
--- a/spec/frontend/ide/stores/modules/commit/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/mutations_spec.js
@@ -1,5 +1,6 @@
import commitState from '~/ide/stores/modules/commit/state';
import mutations from '~/ide/stores/modules/commit/mutations';
+import * as types from '~/ide/stores/modules/commit/mutation_types';
describe('IDE commit module mutations', () => {
let state;
@@ -62,4 +63,24 @@ describe('IDE commit module mutations', () => {
expect(state.shouldCreateMR).toBe(false);
});
});
+
+ describe(types.CLEAR_ERROR, () => {
+ it('should clear commitError', () => {
+ state.commitError = {};
+
+ mutations[types.CLEAR_ERROR](state);
+
+ expect(state.commitError).toBeNull();
+ });
+ });
+
+ describe(types.SET_ERROR, () => {
+ it('should set commitError', () => {
+ const error = { title: 'foo' };
+
+ mutations[types.SET_ERROR](state, error);
+
+ expect(state.commitError).toBe(error);
+ });
+ });
});
diff --git a/spec/frontend/ide/stores/modules/pipelines/actions_spec.js b/spec/frontend/ide/stores/modules/pipelines/actions_spec.js
index 71918e7e2c2..8511843cc92 100644
--- a/spec/frontend/ide/stores/modules/pipelines/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/pipelines/actions_spec.js
@@ -15,10 +15,10 @@ import {
fetchJobs,
toggleStageCollapsed,
setDetailJob,
- requestJobTrace,
- receiveJobTraceError,
- receiveJobTraceSuccess,
- fetchJobTrace,
+ requestJobLogs,
+ receiveJobLogsError,
+ receiveJobLogsSuccess,
+ fetchJobLogs,
resetLatestPipeline,
} from '~/ide/stores/modules/pipelines/actions';
import state from '~/ide/stores/modules/pipelines/state';
@@ -324,24 +324,24 @@ describe('IDE pipelines actions', () => {
});
});
- describe('requestJobTrace', () => {
+ describe('requestJobLogs', () => {
it('commits request', done => {
- testAction(requestJobTrace, null, mockedState, [{ type: types.REQUEST_JOB_TRACE }], [], done);
+ testAction(requestJobLogs, null, mockedState, [{ type: types.REQUEST_JOB_LOGS }], [], done);
});
});
- describe('receiveJobTraceError', () => {
+ describe('receiveJobLogsError', () => {
it('commits error', done => {
testAction(
- receiveJobTraceError,
+ receiveJobLogsError,
null,
mockedState,
- [{ type: types.RECEIVE_JOB_TRACE_ERROR }],
+ [{ type: types.RECEIVE_JOB_LOGS_ERROR }],
[
{
type: 'setErrorMessage',
payload: {
- text: 'An error occurred while fetching the job trace.',
+ text: 'An error occurred while fetching the job logs.',
action: expect.any(Function),
actionText: 'Please try again',
actionPayload: null,
@@ -353,20 +353,20 @@ describe('IDE pipelines actions', () => {
});
});
- describe('receiveJobTraceSuccess', () => {
+ describe('receiveJobLogsSuccess', () => {
it('commits data', done => {
testAction(
- receiveJobTraceSuccess,
+ receiveJobLogsSuccess,
'data',
mockedState,
- [{ type: types.RECEIVE_JOB_TRACE_SUCCESS, payload: 'data' }],
+ [{ type: types.RECEIVE_JOB_LOGS_SUCCESS, payload: 'data' }],
[],
done,
);
});
});
- describe('fetchJobTrace', () => {
+ describe('fetchJobLogs', () => {
beforeEach(() => {
mockedState.detailJob = { path: `${TEST_HOST}/project/builds` };
});
@@ -379,20 +379,20 @@ describe('IDE pipelines actions', () => {
it('dispatches request', done => {
testAction(
- fetchJobTrace,
+ fetchJobLogs,
null,
mockedState,
[],
[
- { type: 'requestJobTrace' },
- { type: 'receiveJobTraceSuccess', payload: { html: 'html' } },
+ { type: 'requestJobLogs' },
+ { type: 'receiveJobLogsSuccess', payload: { html: 'html' } },
],
done,
);
});
it('sends get request to correct URL', () => {
- fetchJobTrace({
+ fetchJobLogs({
state: mockedState,
dispatch() {},
@@ -410,11 +410,11 @@ describe('IDE pipelines actions', () => {
it('dispatches error', done => {
testAction(
- fetchJobTrace,
+ fetchJobLogs,
null,
mockedState,
[],
- [{ type: 'requestJobTrace' }, { type: 'receiveJobTraceError' }],
+ [{ type: 'requestJobLogs' }, { type: 'receiveJobLogsError' }],
done,
);
});
diff --git a/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js b/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js
index 3b7f92cfa74..7d2f5d5d710 100644
--- a/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js
@@ -175,37 +175,37 @@ describe('IDE pipelines mutations', () => {
});
});
- describe('REQUEST_JOB_TRACE', () => {
+ describe('REQUEST_JOB_LOGS', () => {
beforeEach(() => {
mockedState.detailJob = { ...jobs[0] };
});
it('sets loading on detail job', () => {
- mutations[types.REQUEST_JOB_TRACE](mockedState);
+ mutations[types.REQUEST_JOB_LOGS](mockedState);
expect(mockedState.detailJob.isLoading).toBe(true);
});
});
- describe('RECEIVE_JOB_TRACE_ERROR', () => {
+ describe('RECEIVE_JOB_LOGS_ERROR', () => {
beforeEach(() => {
mockedState.detailJob = { ...jobs[0], isLoading: true };
});
it('sets loading to false on detail job', () => {
- mutations[types.RECEIVE_JOB_TRACE_ERROR](mockedState);
+ mutations[types.RECEIVE_JOB_LOGS_ERROR](mockedState);
expect(mockedState.detailJob.isLoading).toBe(false);
});
});
- describe('RECEIVE_JOB_TRACE_SUCCESS', () => {
+ describe('RECEIVE_JOB_LOGS_SUCCESS', () => {
beforeEach(() => {
mockedState.detailJob = { ...jobs[0], isLoading: true };
});
it('sets output on detail job', () => {
- mutations[types.RECEIVE_JOB_TRACE_SUCCESS](mockedState, { html: 'html' });
+ mutations[types.RECEIVE_JOB_LOGS_SUCCESS](mockedState, { html: 'html' });
expect(mockedState.detailJob.output).toBe('html');
expect(mockedState.detailJob.isLoading).toBe(false);
});
diff --git a/spec/frontend/ide/stores/mutations/file_spec.js b/spec/frontend/ide/stores/mutations/file_spec.js
index ff904bbc9cd..b53e40be980 100644
--- a/spec/frontend/ide/stores/mutations/file_spec.js
+++ b/spec/frontend/ide/stores/mutations/file_spec.js
@@ -61,13 +61,11 @@ describe('IDE store file mutations', () => {
mutations.SET_FILE_DATA(localState, {
data: {
raw_path: 'raw',
- binary: true,
},
file: localFile,
});
expect(localFile.rawPath).toBe('raw');
- expect(localFile.binary).toBeTruthy();
expect(localFile.raw).toBeNull();
expect(localFile.baseRaw).toBeNull();
});
diff --git a/spec/frontend/ide/stores/mutations_spec.js b/spec/frontend/ide/stores/mutations_spec.js
index 1b29648fb8b..09e9481e5d4 100644
--- a/spec/frontend/ide/stores/mutations_spec.js
+++ b/spec/frontend/ide/stores/mutations_spec.js
@@ -113,8 +113,6 @@ describe('Multi-file store mutations', () => {
},
treeList: [tmpFile],
},
- projectId: 'gitlab-ce',
- branchId: 'master',
});
expect(localState.trees['gitlab-ce/master'].tree.length).toEqual(1);
@@ -272,7 +270,6 @@ describe('Multi-file store mutations', () => {
prevId: undefined,
prevPath: undefined,
prevName: undefined,
- prevUrl: undefined,
prevKey: undefined,
}),
);
@@ -337,7 +334,6 @@ describe('Multi-file store mutations', () => {
};
Object.assign(localState.entries['root-folder/oldPath'], {
parentPath: 'root-folder',
- url: 'root-folder/oldPath-blob-root-folder/oldPath',
});
mutations.RENAME_ENTRY(localState, {
@@ -366,9 +362,6 @@ describe('Multi-file store mutations', () => {
});
it('renames entry, preserving old parameters', () => {
- Object.assign(localState.entries.oldPath, {
- url: `project/-/oldPath`,
- });
const oldPathData = localState.entries.oldPath;
mutations.RENAME_ENTRY(localState, {
@@ -382,12 +375,10 @@ describe('Multi-file store mutations', () => {
id: 'newPath',
path: 'newPath',
name: 'newPath',
- url: `project/-/newPath`,
key: expect.stringMatching('newPath'),
prevId: 'oldPath',
prevName: 'oldPath',
prevPath: 'oldPath',
- prevUrl: `project/-/oldPath`,
prevKey: oldPathData.key,
prevParentPath: oldPathData.parentPath,
});
@@ -409,7 +400,6 @@ describe('Multi-file store mutations', () => {
prevId: expect.anything(),
prevName: expect.anything(),
prevPath: expect.anything(),
- prevUrl: expect.anything(),
prevKey: expect.anything(),
prevParentPath: expect.anything(),
}),
@@ -419,7 +409,7 @@ describe('Multi-file store mutations', () => {
it('properly handles files with spaces in name', () => {
const path = 'my fancy path';
const newPath = 'new path';
- const oldEntry = { ...file(path, path, 'blob'), url: `project/-/${path}` };
+ const oldEntry = file(path, path, 'blob');
localState.entries[path] = oldEntry;
@@ -435,12 +425,10 @@ describe('Multi-file store mutations', () => {
id: newPath,
path: newPath,
name: newPath,
- url: `project/-/new path`,
key: expect.stringMatching(newPath),
prevId: path,
prevName: path,
prevPath: path,
- prevUrl: `project/-/my fancy path`,
prevKey: oldEntry.key,
prevParentPath: oldEntry.parentPath,
});
@@ -549,7 +537,7 @@ describe('Multi-file store mutations', () => {
it('correctly saves original values if an entry is renamed multiple times', () => {
const original = { ...localState.entries.oldPath };
- const paramsToCheck = ['prevId', 'prevPath', 'prevName', 'prevUrl'];
+ const paramsToCheck = ['prevId', 'prevPath', 'prevName'];
const expectedObj = paramsToCheck.reduce(
(o, param) => ({ ...o, [param]: original[param.replace('prev', '').toLowerCase()] }),
{},
@@ -577,7 +565,6 @@ describe('Multi-file store mutations', () => {
prevId: 'lorem/orig',
prevPath: 'lorem/orig',
prevName: 'orig',
- prevUrl: 'project/-/loren/orig',
prevKey: 'lorem/orig',
prevParentPath: 'lorem',
};
@@ -602,7 +589,6 @@ describe('Multi-file store mutations', () => {
prevId: undefined,
prevPath: undefined,
prevName: undefined,
- prevUrl: undefined,
prevKey: undefined,
prevParentPath: undefined,
}),
diff --git a/spec/frontend/ide/sync_router_and_store_spec.js b/spec/frontend/ide/sync_router_and_store_spec.js
index ccf6e200806..20fd77c4dfb 100644
--- a/spec/frontend/ide/sync_router_and_store_spec.js
+++ b/spec/frontend/ide/sync_router_and_store_spec.js
@@ -17,9 +17,13 @@ describe('~/ide/sync_router_and_store', () => {
const getRouterCurrentPath = () => router.currentRoute.fullPath;
const getStoreCurrentPath = () => store.state.router.fullPath;
- const updateRouter = path => {
+ const updateRouter = async path => {
+ if (getRouterCurrentPath() === path) {
+ return;
+ }
+
router.push(path);
- return waitForPromises();
+ await waitForPromises();
};
const updateStore = path => {
store.dispatch('router/push', path);
diff --git a/spec/frontend/ide/utils_spec.js b/spec/frontend/ide/utils_spec.js
index e7ef0de45a0..97dc8217ecc 100644
--- a/spec/frontend/ide/utils_spec.js
+++ b/spec/frontend/ide/utils_spec.js
@@ -2,7 +2,7 @@ import { languages } from 'monaco-editor';
import {
isTextFile,
registerLanguages,
- registerSchemas,
+ registerSchema,
trimPathComponents,
insertFinalNewline,
trimTrailingWhitespace,
@@ -13,60 +13,78 @@ import {
describe('WebIDE utils', () => {
describe('isTextFile', () => {
- it('returns false for known binary types', () => {
- expect(isTextFile('file content', 'image/png', 'my.png')).toBeFalsy();
- // mime types are case insensitive
- expect(isTextFile('file content', 'IMAGE/PNG', 'my.png')).toBeFalsy();
+ it.each`
+ mimeType | name | type | result
+ ${'image/png'} | ${'my.png'} | ${'binary'} | ${false}
+ ${'IMAGE/PNG'} | ${'my.png'} | ${'binary'} | ${false}
+ ${'text/plain'} | ${'my.txt'} | ${'text'} | ${true}
+ ${'TEXT/PLAIN'} | ${'my.txt'} | ${'text'} | ${true}
+ `('returns $result for known $type types', ({ mimeType, name, result }) => {
+ expect(isTextFile({ content: 'file content', mimeType, name })).toBe(result);
});
- it('returns true for known text types', () => {
- expect(isTextFile('file content', 'text/plain', 'my.txt')).toBeTruthy();
- // mime types are case insensitive
- expect(isTextFile('file content', 'TEXT/PLAIN', 'my.txt')).toBeTruthy();
- });
+ it.each`
+ content | mimeType | name
+ ${'{"éêė":"value"}'} | ${'application/json'} | ${'my.json'}
+ ${'{"éêė":"value"}'} | ${'application/json'} | ${'.tsconfig'}
+ ${'SELECT "éêė" from tablename'} | ${'application/sql'} | ${'my.sql'}
+ ${'{"éêė":"value"}'} | ${'application/json'} | ${'MY.JSON'}
+ ${'SELECT "éêė" from tablename'} | ${'application/sql'} | ${'MY.SQL'}
+ ${'var code = "something"'} | ${'application/javascript'} | ${'Gruntfile'}
+ ${'MAINTAINER Александр "a21283@me.com"'} | ${'application/octet-stream'} | ${'dockerfile'}
+ `(
+ 'returns true for file extensions that Monaco supports syntax highlighting for',
+ ({ content, mimeType, name }) => {
+ expect(isTextFile({ content, mimeType, name })).toBe(true);
+ },
+ );
- it('returns true for file extensions that Monaco supports syntax highlighting for', () => {
- // test based on both MIME and extension
- expect(isTextFile('{"éêė":"value"}', 'application/json', 'my.json')).toBeTruthy();
- expect(isTextFile('{"éêė":"value"}', 'application/json', '.tsconfig')).toBeTruthy();
- expect(isTextFile('SELECT "éêė" from tablename', 'application/sql', 'my.sql')).toBeTruthy();
+ it('returns false if filename is same as the expected extension', () => {
+ expect(
+ isTextFile({
+ name: 'sql',
+ content: 'SELECT "éêė" from tablename',
+ mimeType: 'application/sql',
+ }),
+ ).toBeFalsy();
});
- it('returns true even irrespective of whether the mimes, extensions or file names are lowercase or upper case', () => {
- expect(isTextFile('{"éêė":"value"}', 'application/json', 'MY.JSON')).toBeTruthy();
- expect(isTextFile('SELECT "éêė" from tablename', 'application/sql', 'MY.SQL')).toBeTruthy();
- expect(
- isTextFile('var code = "something"', 'application/javascript', 'Gruntfile'),
- ).toBeTruthy();
+ it('returns true for ASCII only content for unknown types', () => {
expect(
- isTextFile(
- 'MAINTAINER Александр "alexander11354322283@me.com"',
- 'application/octet-stream',
- 'dockerfile',
- ),
+ isTextFile({
+ name: 'hello.mytype',
+ content: 'plain text',
+ mimeType: 'application/x-new-type',
+ }),
).toBeTruthy();
});
- it('returns false if filename is same as the expected extension', () => {
- expect(isTextFile('SELECT "éêė" from tablename', 'application/sql', 'sql')).toBeFalsy();
- });
-
- it('returns true for ASCII only content for unknown types', () => {
- expect(isTextFile('plain text', 'application/x-new-type', 'hello.mytype')).toBeTruthy();
+ it('returns false for non-ASCII content for unknown types', () => {
+ expect(
+ isTextFile({
+ name: 'my.random',
+ content: '{"éêė":"value"}',
+ mimeType: 'application/octet-stream',
+ }),
+ ).toBeFalsy();
});
- it('returns true for relevant filenames', () => {
- expect(
- isTextFile(
- 'MAINTAINER Александр "alexander11354322283@me.com"',
- 'application/octet-stream',
- 'Dockerfile',
- ),
- ).toBeTruthy();
+ it.each`
+ name | result
+ ${'myfile.txt'} | ${true}
+ ${'Dockerfile'} | ${true}
+ ${'img.png'} | ${false}
+ ${'abc.js'} | ${true}
+ ${'abc.random'} | ${false}
+ ${'image.jpeg'} | ${false}
+ `('returns $result for $filename when no content or mimeType is passed', ({ name, result }) => {
+ expect(isTextFile({ name })).toBe(result);
});
- it('returns false for non-ASCII content for unknown types', () => {
- expect(isTextFile('{"éêė":"value"}', 'application/octet-stream', 'my.random')).toBeFalsy();
+ it('returns true if content is empty string but false if content is not passed', () => {
+ expect(isTextFile({ name: 'abc.dat' })).toBe(false);
+ expect(isTextFile({ name: 'abc.dat', content: '' })).toBe(true);
+ expect(isTextFile({ name: 'abc.dat', content: ' ' })).toBe(true);
});
});
@@ -159,55 +177,37 @@ describe('WebIDE utils', () => {
});
});
- describe('registerSchemas', () => {
- let options;
+ describe('registerSchema', () => {
+ let schema;
beforeEach(() => {
- options = {
- validate: true,
- enableSchemaRequest: true,
- hover: true,
- completion: true,
- schemas: [
- {
- uri: 'http://myserver/foo-schema.json',
- fileMatch: ['*'],
- schema: {
- id: 'http://myserver/foo-schema.json',
- type: 'object',
- properties: {
- p1: { enum: ['v1', 'v2'] },
- p2: { $ref: 'http://myserver/bar-schema.json' },
- },
- },
- },
- {
- uri: 'http://myserver/bar-schema.json',
- schema: {
- id: 'http://myserver/bar-schema.json',
- type: 'object',
- properties: { q1: { enum: ['x1', 'x2'] } },
- },
+ schema = {
+ uri: 'http://myserver/foo-schema.json',
+ fileMatch: ['*'],
+ schema: {
+ id: 'http://myserver/foo-schema.json',
+ type: 'object',
+ properties: {
+ p1: { enum: ['v1', 'v2'] },
+ p2: { $ref: 'http://myserver/bar-schema.json' },
},
- ],
+ },
};
jest.spyOn(languages.json.jsonDefaults, 'setDiagnosticsOptions');
jest.spyOn(languages.yaml.yamlDefaults, 'setDiagnosticsOptions');
});
- it.each`
- language | defaultsObj
- ${'json'} | ${languages.json.jsonDefaults}
- ${'yaml'} | ${languages.yaml.yamlDefaults}
- `(
- 'registers the given schemas with monaco for lang: $language',
- ({ language, defaultsObj }) => {
- registerSchemas({ language, options });
+ it('registers the given schemas with monaco for both json and yaml languages', () => {
+ registerSchema(schema);
- expect(defaultsObj.setDiagnosticsOptions).toHaveBeenCalledWith(options);
- },
- );
+ expect(languages.json.jsonDefaults.setDiagnosticsOptions).toHaveBeenCalledWith(
+ expect.objectContaining({ schemas: [schema] }),
+ );
+ expect(languages.yaml.yamlDefaults.setDiagnosticsOptions).toHaveBeenCalledWith(
+ expect.objectContaining({ schemas: [schema] }),
+ );
+ });
});
describe('trimTrailingWhitespace', () => {