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:
Diffstat (limited to 'spec/frontend/ide')
-rw-r--r--spec/frontend/ide/commit_icon_spec.js1
-rw-r--r--spec/frontend/ide/components/ide_status_list_spec.js8
-rw-r--r--spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap2
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js113
-rw-r--r--spec/frontend/ide/helpers.js1
-rw-r--r--spec/frontend/ide/lib/editor_spec.js22
-rw-r--r--spec/frontend/ide/services/index_spec.js6
-rw-r--r--spec/frontend/ide/stores/actions/file_spec.js361
-rw-r--r--spec/frontend/ide/stores/actions/merge_request_spec.js1
-rw-r--r--spec/frontend/ide/stores/actions/tree_spec.js3
-rw-r--r--spec/frontend/ide/utils_spec.js52
11 files changed, 335 insertions, 235 deletions
diff --git a/spec/frontend/ide/commit_icon_spec.js b/spec/frontend/ide/commit_icon_spec.js
index 90b8e34497c..e4a7394b089 100644
--- a/spec/frontend/ide/commit_icon_spec.js
+++ b/spec/frontend/ide/commit_icon_spec.js
@@ -11,7 +11,6 @@ const createFile = (name = 'name', id = name, type = '', parent = null) =>
name,
path: parent ? `${parent.path}/${name}` : name,
parentPath: parent ? parent.path : '',
- lastCommit: {},
});
describe('getCommitIconMap', () => {
diff --git a/spec/frontend/ide/components/ide_status_list_spec.js b/spec/frontend/ide/components/ide_status_list_spec.js
index 847464ed806..fed61233e55 100644
--- a/spec/frontend/ide/components/ide_status_list_spec.js
+++ b/spec/frontend/ide/components/ide_status_list_spec.js
@@ -1,5 +1,6 @@
import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlLink } from '@gitlab/ui';
import IdeStatusList from '~/ide/components/ide_status_list.vue';
import TerminalSyncStatusSafe from '~/ide/components/terminal_sync/terminal_sync_status_safe.vue';
@@ -9,6 +10,7 @@ const TEST_FILE = {
editorColumn: 23,
fileLanguage: 'markdown',
content: 'abc\nndef',
+ permalink: '/lorem.md',
};
const localVue = createLocalVue();
@@ -19,6 +21,7 @@ describe('ide/components/ide_status_list', () => {
let store;
let wrapper;
+ const findLink = () => wrapper.find(GlLink);
const createComponent = (options = {}) => {
store = new Vuex.Store({
getters: {
@@ -51,8 +54,9 @@ describe('ide/components/ide_status_list', () => {
createComponent();
});
- it('shows file name', () => {
- expect(wrapper.text()).toContain(TEST_FILE.name);
+ it('shows a link to the file that contains the file name', () => {
+ expect(findLink().attributes('href')).toBe(TEST_FILE.permalink);
+ expect(findLink().text()).toBe(TEST_FILE.name);
});
it('shows file eol', () => {
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 bdd3d439fd4..dbfacb98813 100644
--- a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap
+++ b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap
@@ -2,7 +2,7 @@
exports[`IDE pipeline stage renders stage details & icon 1`] = `
<div
- class="ide-stage card prepend-top-default"
+ class="ide-stage card gl-mt-3"
>
<div
class="card-header"
diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js
index 4967434dfd7..a4336b8f2eb 100644
--- a/spec/frontend/ide/components/repo_editor_spec.js
+++ b/spec/frontend/ide/components/repo_editor_spec.js
@@ -4,19 +4,25 @@ import MockAdapter from 'axios-mock-adapter';
import '~/behaviors/markdown/render_gfm';
import { Range } from 'monaco-editor';
import axios from '~/lib/utils/axios_utils';
+import service from '~/ide/services';
import { createStoreOptions } from '~/ide/stores';
import RepoEditor from '~/ide/components/repo_editor.vue';
import Editor from '~/ide/lib/editor';
-import { leftSidebarViews, FILE_VIEW_MODE_EDITOR, FILE_VIEW_MODE_PREVIEW } from '~/ide/constants';
+import {
+ leftSidebarViews,
+ FILE_VIEW_MODE_EDITOR,
+ FILE_VIEW_MODE_PREVIEW,
+ viewerTypes,
+} from '~/ide/constants';
import { createComponentWithStore } from '../../helpers/vue_mount_component_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { file } from '../helpers';
import { exampleConfigs, exampleFiles } from '../lib/editorconfig/mock_data';
+import waitUsingRealTimer from 'helpers/wait_using_real_timer';
describe('RepoEditor', () => {
let vm;
let store;
- let mockActions;
const waitForEditorSetup = () =>
new Promise(resolve => {
@@ -30,6 +36,10 @@ describe('RepoEditor', () => {
vm = createComponentWithStore(Vue.extend(RepoEditor), store, {
file: store.state.openFiles[0],
});
+
+ jest.spyOn(vm, 'getFileData').mockResolvedValue();
+ jest.spyOn(vm, 'getRawFileData').mockResolvedValue();
+
vm.$mount();
};
@@ -43,21 +53,12 @@ describe('RepoEditor', () => {
};
beforeEach(() => {
- mockActions = {
- getFileData: jest.fn().mockResolvedValue(),
- getRawFileData: jest.fn().mockResolvedValue(),
- };
-
const f = {
...file(),
viewMode: FILE_VIEW_MODE_EDITOR,
};
const storeOptions = createStoreOptions();
- storeOptions.actions = {
- ...storeOptions.actions,
- ...mockActions,
- };
store = new Vuex.Store(storeOptions);
f.active = true;
@@ -438,7 +439,7 @@ describe('RepoEditor', () => {
vm.initEditor();
vm.$nextTick()
.then(() => {
- expect(mockActions.getFileData).not.toHaveBeenCalled();
+ expect(vm.getFileData).not.toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
@@ -449,10 +450,11 @@ describe('RepoEditor', () => {
vm.file.raw = '';
vm.initEditor();
+
vm.$nextTick()
.then(() => {
- expect(mockActions.getFileData).toHaveBeenCalled();
- expect(mockActions.getRawFileData).toHaveBeenCalled();
+ expect(vm.getFileData).toHaveBeenCalled();
+ expect(vm.getRawFileData).toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
@@ -464,8 +466,8 @@ describe('RepoEditor', () => {
vm.initEditor();
vm.$nextTick()
.then(() => {
- expect(mockActions.getFileData).not.toHaveBeenCalled();
- expect(mockActions.getRawFileData).not.toHaveBeenCalled();
+ expect(vm.getFileData).not.toHaveBeenCalled();
+ expect(vm.getRawFileData).not.toHaveBeenCalled();
expect(vm.editor.createInstance).not.toHaveBeenCalled();
})
.then(done)
@@ -526,6 +528,63 @@ describe('RepoEditor', () => {
});
});
+ describe('populates editor with the fetched content', () => {
+ beforeEach(() => {
+ vm.getRawFileData.mockRestore();
+ });
+
+ const createRemoteFile = name => ({
+ ...file(name),
+ tmpFile: false,
+ });
+
+ it('after switching viewer from edit to diff', async () => {
+ jest.spyOn(service, 'getRawFileData').mockImplementation(async () => {
+ expect(vm.file.loading).toBe(true);
+
+ // switching from edit to diff mode usually triggers editor initialization
+ store.state.viewer = viewerTypes.diff;
+
+ // we delay returning the file to make sure editor doesn't initialize before we fetch file content
+ await waitUsingRealTimer(30);
+ return 'rawFileData123\n';
+ });
+
+ const f = createRemoteFile('newFile');
+ Vue.set(store.state.entries, f.path, f);
+
+ vm.file = f;
+
+ await waitForEditorSetup();
+ expect(vm.model.getModel().getValue()).toBe('rawFileData123\n');
+ });
+
+ it('after opening multiple files at the same time', async () => {
+ const fileA = createRemoteFile('fileA');
+ const fileB = createRemoteFile('fileB');
+ Vue.set(store.state.entries, fileA.path, fileA);
+ Vue.set(store.state.entries, fileB.path, fileB);
+
+ jest
+ .spyOn(service, 'getRawFileData')
+ .mockImplementationOnce(async () => {
+ // opening fileB while the content of fileA is still being fetched
+ vm.file = fileB;
+ return 'fileA-rawContent\n';
+ })
+ .mockImplementationOnce(async () => {
+ // we delay returning fileB content to make sure the editor doesn't initialize prematurely
+ await waitUsingRealTimer(30);
+ return 'fileB-rawContent\n';
+ });
+
+ vm.file = fileA;
+
+ await waitForEditorSetup();
+ expect(vm.model.getModel().getValue()).toBe('fileB-rawContent\n');
+ });
+ });
+
describe('onPaste', () => {
const setFileName = name => {
Vue.set(vm, 'file', {
@@ -557,6 +616,11 @@ describe('RepoEditor', () => {
});
});
+ // Pasting an image does a lot of things like using the FileReader API,
+ // so, waitForPromises isn't very reliable (and causes a flaky spec)
+ // Read more about state.watch: https://vuex.vuejs.org/api/#watch
+ const waitForFileContentChange = () => watchState(s => s.entries['foo/bar.md'].content);
+
beforeEach(() => {
setFileName('bar.md');
@@ -573,13 +637,15 @@ describe('RepoEditor', () => {
// set cursor to line 2, column 1
vm.editor.instance.setSelection(new Range(2, 1, 2, 1));
vm.editor.instance.focus();
+
+ jest.spyOn(vm.editor.instance, 'hasTextFocus').mockReturnValue(true);
});
});
it('adds an image entry to the same folder for a pasted image in a markdown file', () => {
pasteImage();
- return waitForPromises().then(() => {
+ return waitForFileContentChange().then(() => {
expect(vm.$store.state.entries['foo/foo.png']).toMatchObject({
path: 'foo/foo.png',
type: 'blob',
@@ -593,10 +659,7 @@ describe('RepoEditor', () => {
it("adds a markdown image tag to the file's contents", () => {
pasteImage();
- // Pasting an image does a lot of things like using the FileReader API,
- // so, waitForPromises isn't very reliable (and causes a flaky spec)
- // Read more about state.watch: https://vuex.vuejs.org/api/#watch
- return watchState(s => s.entries['foo/bar.md'].content).then(() => {
+ return waitForFileContentChange().then(() => {
expect(vm.file.content).toBe('hello world\n![foo.png](./foo.png)');
});
});
@@ -629,8 +692,8 @@ describe('RepoEditor', () => {
return waitForEditorSetup().then(() => {
expect(vm.rules).toEqual(monacoRules);
expect(vm.model.options).toMatchObject(monacoRules);
- expect(mockActions.getFileData).not.toHaveBeenCalled();
- expect(mockActions.getRawFileData).not.toHaveBeenCalled();
+ expect(vm.getFileData).not.toHaveBeenCalled();
+ expect(vm.getRawFileData).not.toHaveBeenCalled();
});
},
);
@@ -646,13 +709,13 @@ describe('RepoEditor', () => {
createComponent();
return waitForEditorSetup().then(() => {
- expect(mockActions.getFileData.mock.calls.map(([, args]) => args)).toEqual([
+ expect(vm.getFileData.mock.calls.map(([args]) => args)).toEqual([
{ makeFileActive: false, path: 'foo/bar/baz/.editorconfig' },
{ makeFileActive: false, path: 'foo/bar/.editorconfig' },
{ makeFileActive: false, path: 'foo/.editorconfig' },
{ makeFileActive: false, path: '.editorconfig' },
]);
- expect(mockActions.getRawFileData.mock.calls.map(([, args]) => args)).toEqual([
+ expect(vm.getRawFileData.mock.calls.map(([args]) => args)).toEqual([
{ path: 'foo/bar/baz/.editorconfig' },
{ path: 'foo/bar/.editorconfig' },
{ path: 'foo/.editorconfig' },
diff --git a/spec/frontend/ide/helpers.js b/spec/frontend/ide/helpers.js
index de839fa99ca..a9620d26313 100644
--- a/spec/frontend/ide/helpers.js
+++ b/spec/frontend/ide/helpers.js
@@ -30,7 +30,6 @@ export const file = (name = 'name', id = name, type = '', parent = null) =>
name,
path: parent ? `${parent.path}/${name}` : name,
parentPath: parent ? parent.path : '',
- lastCommit: {},
});
export const createEntriesFromPaths = paths =>
diff --git a/spec/frontend/ide/lib/editor_spec.js b/spec/frontend/ide/lib/editor_spec.js
index f5815771cdf..5f28309422d 100644
--- a/spec/frontend/ide/lib/editor_spec.js
+++ b/spec/frontend/ide/lib/editor_spec.js
@@ -199,6 +199,28 @@ 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/services/index_spec.js b/spec/frontend/ide/services/index_spec.js
index 3cb6e064aa2..bc3f86702cf 100644
--- a/spec/frontend/ide/services/index_spec.js
+++ b/spec/frontend/ide/services/index_spec.js
@@ -2,7 +2,7 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import services from '~/ide/services';
import Api from '~/api';
-import gqClient from '~/ide/services/gql';
+import { query } from '~/ide/services/gql';
import { escapeFileUrl } from '~/lib/utils/url_utility';
import getUserPermissions from '~/ide/queries/getUserPermissions.query.graphql';
import { projectData } from '../mock_data';
@@ -207,12 +207,12 @@ describe('IDE services', () => {
},
};
Api.project.mockReturnValue(Promise.resolve({ data: { ...projectData } }));
- gqClient.query.mockReturnValue(Promise.resolve({ data: { project: gqlProjectData } }));
+ query.mockReturnValue(Promise.resolve({ data: { project: gqlProjectData } }));
return services.getProjectData(TEST_NAMESPACE, TEST_PROJECT).then(response => {
expect(response).toEqual({ data: { ...projectData, ...gqlProjectData } });
expect(Api.project).toHaveBeenCalledWith(TEST_PROJECT_ID);
- expect(gqClient.query).toHaveBeenCalledWith({
+ expect(query).toHaveBeenCalledWith({
query: getUserPermissions,
variables: {
projectPath: TEST_PROJECT_ID,
diff --git a/spec/frontend/ide/stores/actions/file_spec.js b/spec/frontend/ide/stores/actions/file_spec.js
index e2dc7626c67..88e7a9fff36 100644
--- a/spec/frontend/ide/stores/actions/file_spec.js
+++ b/spec/frontend/ide/stores/actions/file_spec.js
@@ -51,35 +51,27 @@ describe('IDE store file actions', () => {
store.state.entries[localFile.path] = localFile;
});
- it('closes open files', done => {
- store
- .dispatch('closeFile', localFile)
- .then(() => {
- expect(localFile.opened).toBeFalsy();
- expect(localFile.active).toBeFalsy();
- expect(store.state.openFiles.length).toBe(0);
-
- done();
- })
- .catch(done.fail);
+ it('closes open files', () => {
+ return store.dispatch('closeFile', localFile).then(() => {
+ expect(localFile.opened).toBeFalsy();
+ expect(localFile.active).toBeFalsy();
+ expect(store.state.openFiles.length).toBe(0);
+ });
});
- it('closes file even if file has changes', done => {
+ it('closes file even if file has changes', () => {
store.state.changedFiles.push(localFile);
- store
+ return store
.dispatch('closeFile', localFile)
.then(Vue.nextTick)
.then(() => {
expect(store.state.openFiles.length).toBe(0);
expect(store.state.changedFiles.length).toBe(1);
-
- done();
- })
- .catch(done.fail);
+ });
});
- it('closes file & opens next available file', done => {
+ it('closes file & opens next available file', () => {
const f = {
...file('newOpenFile'),
url: '/newOpenFile',
@@ -88,31 +80,23 @@ describe('IDE store file actions', () => {
store.state.openFiles.push(f);
store.state.entries[f.path] = f;
- store
+ return store
.dispatch('closeFile', localFile)
.then(Vue.nextTick)
.then(() => {
expect(router.push).toHaveBeenCalledWith(`/project${f.url}`);
-
- done();
- })
- .catch(done.fail);
+ });
});
- it('removes file if it pending', done => {
+ it('removes file if it pending', () => {
store.state.openFiles.push({
...localFile,
pending: true,
});
- store
- .dispatch('closeFile', localFile)
- .then(() => {
- expect(store.state.openFiles.length).toBe(0);
-
- done();
- })
- .catch(done.fail);
+ return store.dispatch('closeFile', localFile).then(() => {
+ expect(store.state.openFiles.length).toBe(0);
+ });
});
});
@@ -264,61 +248,48 @@ describe('IDE store file actions', () => {
);
});
- it('calls the service', done => {
- store
- .dispatch('getFileData', { path: localFile.path })
- .then(() => {
- expect(service.getFileData).toHaveBeenCalledWith(
- `${RELATIVE_URL_ROOT}/test/test/-/7297abc/${localFile.path}`,
- );
-
- done();
- })
- .catch(done.fail);
+ it('calls the service', () => {
+ return store.dispatch('getFileData', { path: localFile.path }).then(() => {
+ expect(service.getFileData).toHaveBeenCalledWith(
+ `${RELATIVE_URL_ROOT}/test/test/-/7297abc/${localFile.path}`,
+ );
+ });
});
- it('sets document title with the branchId', done => {
- store
- .dispatch('getFileData', { path: localFile.path })
- .then(() => {
- expect(document.title).toBe(`${localFile.path} · master · test/test · GitLab`);
- done();
- })
- .catch(done.fail);
+ it('sets document title with the branchId', () => {
+ return store.dispatch('getFileData', { path: localFile.path }).then(() => {
+ expect(document.title).toBe(`${localFile.path} · master · test/test · GitLab`);
+ });
});
- it('sets the file as active', done => {
- store
- .dispatch('getFileData', { path: localFile.path })
- .then(() => {
- expect(localFile.active).toBeTruthy();
-
- done();
- })
- .catch(done.fail);
+ it('sets the file as active', () => {
+ return store.dispatch('getFileData', { path: localFile.path }).then(() => {
+ expect(localFile.active).toBeTruthy();
+ });
});
- it('sets the file not as active if we pass makeFileActive false', done => {
- store
+ it('sets the file not as active if we pass makeFileActive false', () => {
+ return store
.dispatch('getFileData', { path: localFile.path, makeFileActive: false })
.then(() => {
expect(localFile.active).toBeFalsy();
-
- done();
- })
- .catch(done.fail);
+ });
});
- it('adds the file to open files', done => {
- store
- .dispatch('getFileData', { path: localFile.path })
+ it('does not update the page title with the path of the file if makeFileActive is false', () => {
+ document.title = 'dummy title';
+ return store
+ .dispatch('getFileData', { path: localFile.path, makeFileActive: false })
.then(() => {
- expect(store.state.openFiles.length).toBe(1);
- expect(store.state.openFiles[0].name).toBe(localFile.name);
+ expect(document.title).toBe(`dummy title`);
+ });
+ });
- done();
- })
- .catch(done.fail);
+ it('adds the file to open files', () => {
+ return store.dispatch('getFileData', { path: localFile.path }).then(() => {
+ expect(store.state.openFiles.length).toBe(1);
+ expect(store.state.openFiles[0].name).toBe(localFile.name);
+ });
});
});
@@ -342,15 +313,10 @@ describe('IDE store file actions', () => {
);
});
- it('sets document title considering `prevPath` on a file', done => {
- store
- .dispatch('getFileData', { path: localFile.path })
- .then(() => {
- expect(document.title).toBe(`new-shiny-file · master · test/test · GitLab`);
-
- done();
- })
- .catch(done.fail);
+ it('sets document title considering `prevPath` on a file', () => {
+ return store.dispatch('getFileData', { path: localFile.path }).then(() => {
+ expect(document.title).toBe(`new-shiny-file · master · test/test · GitLab`);
+ });
});
});
@@ -397,29 +363,19 @@ describe('IDE store file actions', () => {
mock.onGet(/(.*)/).replyOnce(200, 'raw');
});
- it('calls getRawFileData service method', done => {
- store
- .dispatch('getRawFileData', { path: tmpFile.path })
- .then(() => {
- expect(service.getRawFileData).toHaveBeenCalledWith(tmpFile);
-
- done();
- })
- .catch(done.fail);
+ it('calls getRawFileData service method', () => {
+ return store.dispatch('getRawFileData', { path: tmpFile.path }).then(() => {
+ expect(service.getRawFileData).toHaveBeenCalledWith(tmpFile);
+ });
});
- it('updates file raw data', done => {
- store
- .dispatch('getRawFileData', { path: tmpFile.path })
- .then(() => {
- expect(tmpFile.raw).toBe('raw');
-
- done();
- })
- .catch(done.fail);
+ it('updates file raw data', () => {
+ return store.dispatch('getRawFileData', { path: tmpFile.path }).then(() => {
+ expect(tmpFile.raw).toBe('raw');
+ });
});
- it('calls also getBaseRawFileData service method', done => {
+ it('calls also getBaseRawFileData service method', () => {
jest.spyOn(service, 'getBaseRawFileData').mockReturnValue(Promise.resolve('baseraw'));
store.state.currentProjectId = 'gitlab-org/gitlab-ce';
@@ -436,15 +392,58 @@ describe('IDE store file actions', () => {
tmpFile.mrChange = { new_file: false };
- store
- .dispatch('getRawFileData', { path: tmpFile.path })
- .then(() => {
- expect(service.getBaseRawFileData).toHaveBeenCalledWith(tmpFile, 'SHA');
- expect(tmpFile.baseRaw).toBe('baseraw');
+ return store.dispatch('getRawFileData', { path: tmpFile.path }).then(() => {
+ expect(service.getBaseRawFileData).toHaveBeenCalledWith(tmpFile, 'SHA');
+ expect(tmpFile.baseRaw).toBe('baseraw');
+ });
+ });
+
+ describe('sets file loading to true', () => {
+ let loadingWhenGettingRawData;
+ let loadingWhenGettingBaseRawData;
+
+ beforeEach(() => {
+ loadingWhenGettingRawData = undefined;
+ loadingWhenGettingBaseRawData = undefined;
+
+ jest.spyOn(service, 'getRawFileData').mockImplementation(f => {
+ loadingWhenGettingRawData = f.loading;
+ return Promise.resolve('raw');
+ });
+ jest.spyOn(service, 'getBaseRawFileData').mockImplementation(f => {
+ loadingWhenGettingBaseRawData = f.loading;
+ return Promise.resolve('rawBase');
+ });
+ });
- done();
- })
- .catch(done.fail);
+ it('when getting raw file data', async () => {
+ expect(tmpFile.loading).toBe(false);
+
+ await store.dispatch('getRawFileData', { path: tmpFile.path });
+
+ expect(loadingWhenGettingRawData).toBe(true);
+ expect(tmpFile.loading).toBe(false);
+ });
+
+ it('when getting base raw file data', async () => {
+ tmpFile.mrChange = { new_file: false };
+
+ expect(tmpFile.loading).toBe(false);
+
+ await store.dispatch('getRawFileData', { path: tmpFile.path });
+
+ expect(loadingWhenGettingBaseRawData).toBe(true);
+ expect(tmpFile.loading).toBe(false);
+ });
+
+ it('when file was already loading', async () => {
+ tmpFile.loading = true;
+
+ await store.dispatch('getRawFileData', { path: tmpFile.path });
+
+ expect(loadingWhenGettingRawData).toBe(true);
+ expect(tmpFile.loading).toBe(false);
+ });
});
});
@@ -453,15 +452,10 @@ describe('IDE store file actions', () => {
mock.onGet(/(.*)/).replyOnce(200, JSON.stringify({ test: '123' }));
});
- it('does not parse returned JSON', done => {
- store
- .dispatch('getRawFileData', { path: tmpFile.path })
- .then(() => {
- expect(tmpFile.raw).toEqual('{"test":"123"}');
-
- done();
- })
- .catch(done.fail);
+ it('does not parse returned JSON', () => {
+ return store.dispatch('getRawFileData', { path: tmpFile.path }).then(() => {
+ expect(tmpFile.raw).toEqual('{"test":"123"}');
+ });
});
});
@@ -489,6 +483,12 @@ describe('IDE store file actions', () => {
});
});
});
+
+ it('toggles loading off after error', async () => {
+ await expect(store.dispatch('getRawFileData', { path: tmpFile.path })).rejects.toThrow();
+
+ expect(tmpFile.loading).toBe(false);
+ });
});
});
@@ -504,32 +504,25 @@ describe('IDE store file actions', () => {
store.state.entries[tmpFile.path] = tmpFile;
});
- it('updates file content', done => {
- callAction()
- .then(() => {
- expect(tmpFile.content).toBe('content\n');
-
- done();
- })
- .catch(done.fail);
+ it('updates file content', () => {
+ return callAction().then(() => {
+ expect(tmpFile.content).toBe('content\n');
+ });
});
- it('adds file into stagedFiles array', done => {
- store
+ it('adds file into stagedFiles array', () => {
+ return store
.dispatch('changeFileContent', {
path: tmpFile.path,
content: 'content',
})
.then(() => {
expect(store.state.stagedFiles.length).toBe(1);
-
- done();
- })
- .catch(done.fail);
+ });
});
- it('adds file not more than once into stagedFiles array', done => {
- store
+ it('adds file not more than once into stagedFiles array', () => {
+ return store
.dispatch('changeFileContent', {
path: tmpFile.path,
content: 'content',
@@ -542,14 +535,11 @@ describe('IDE store file actions', () => {
)
.then(() => {
expect(store.state.stagedFiles.length).toBe(1);
-
- done();
- })
- .catch(done.fail);
+ });
});
- it('removes file from changedFiles array if not changed', done => {
- store
+ it('removes file from changedFiles array if not changed', () => {
+ return store
.dispatch('changeFileContent', {
path: tmpFile.path,
content: 'content\n',
@@ -562,10 +552,7 @@ describe('IDE store file actions', () => {
)
.then(() => {
expect(store.state.changedFiles.length).toBe(0);
-
- done();
- })
- .catch(done.fail);
+ });
});
});
@@ -723,52 +710,36 @@ describe('IDE store file actions', () => {
store.state.entries[f.path] = f;
});
- it('makes file pending in openFiles', done => {
- store
- .dispatch('openPendingTab', { file: f, keyPrefix: 'pending' })
- .then(() => {
- expect(store.state.openFiles[0].pending).toBe(true);
- })
- .then(done)
- .catch(done.fail);
+ it('makes file pending in openFiles', () => {
+ return store.dispatch('openPendingTab', { file: f, keyPrefix: 'pending' }).then(() => {
+ expect(store.state.openFiles[0].pending).toBe(true);
+ });
});
- it('returns true when opened', done => {
- store
- .dispatch('openPendingTab', { file: f, keyPrefix: 'pending' })
- .then(added => {
- expect(added).toBe(true);
- })
- .then(done)
- .catch(done.fail);
+ it('returns true when opened', () => {
+ return store.dispatch('openPendingTab', { file: f, keyPrefix: 'pending' }).then(added => {
+ expect(added).toBe(true);
+ });
});
- it('returns false when already opened', done => {
+ it('returns false when already opened', () => {
store.state.openFiles.push({
...f,
active: true,
key: `pending-${f.key}`,
});
- store
- .dispatch('openPendingTab', { file: f, keyPrefix: 'pending' })
- .then(added => {
- expect(added).toBe(false);
- })
- .then(done)
- .catch(done.fail);
+ return store.dispatch('openPendingTab', { file: f, keyPrefix: 'pending' }).then(added => {
+ expect(added).toBe(false);
+ });
});
- it('pushes router URL when added', done => {
+ it('pushes router URL when added', () => {
store.state.currentBranchId = 'master';
- store
- .dispatch('openPendingTab', { file: f, keyPrefix: 'pending' })
- .then(() => {
- expect(router.push).toHaveBeenCalledWith('/project/123/tree/master/');
- })
- .then(done)
- .catch(done.fail);
+ return store.dispatch('openPendingTab', { file: f, keyPrefix: 'pending' }).then(() => {
+ expect(router.push).toHaveBeenCalledWith('/project/123/tree/master/');
+ });
});
});
@@ -784,26 +755,18 @@ describe('IDE store file actions', () => {
};
});
- it('removes pending file from open files', done => {
+ it('removes pending file from open files', () => {
store.state.openFiles.push(f);
- store
- .dispatch('removePendingTab', f)
- .then(() => {
- expect(store.state.openFiles.length).toBe(0);
- })
- .then(done)
- .catch(done.fail);
+ return store.dispatch('removePendingTab', f).then(() => {
+ expect(store.state.openFiles.length).toBe(0);
+ });
});
- it('emits event to dispose model', done => {
- store
- .dispatch('removePendingTab', f)
- .then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith(`editor.update.model.dispose.${f.key}`);
- })
- .then(done)
- .catch(done.fail);
+ it('emits event to dispose model', () => {
+ return store.dispatch('removePendingTab', f).then(() => {
+ expect(eventHub.$emit).toHaveBeenCalledWith(`editor.update.model.dispose.${f.key}`);
+ });
});
});
@@ -812,14 +775,10 @@ describe('IDE store file actions', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
});
- it('emits event that files have changed', done => {
- store
- .dispatch('triggerFilesChange')
- .then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('ide.files.change');
- })
- .then(done)
- .catch(done.fail);
+ it('emits event that files have changed', () => {
+ return store.dispatch('triggerFilesChange').then(() => {
+ expect(eventHub.$emit).toHaveBeenCalledWith('ide.files.change');
+ });
});
});
});
diff --git a/spec/frontend/ide/stores/actions/merge_request_spec.js b/spec/frontend/ide/stores/actions/merge_request_spec.js
index cb4eebd97d9..e5c4f346459 100644
--- a/spec/frontend/ide/stores/actions/merge_request_spec.js
+++ b/spec/frontend/ide/stores/actions/merge_request_spec.js
@@ -55,6 +55,7 @@ describe('IDE store merge request actions', () => {
expect(service.getProjectMergeRequests).toHaveBeenCalledWith(TEST_PROJECT, {
source_branch: 'bar',
source_project_id: TEST_PROJECT_ID,
+ state: 'opened',
order_by: 'created_at',
per_page: 1,
});
diff --git a/spec/frontend/ide/stores/actions/tree_spec.js b/spec/frontend/ide/stores/actions/tree_spec.js
index 44e2fcab436..c20941843c4 100644
--- a/spec/frontend/ide/stores/actions/tree_spec.js
+++ b/spec/frontend/ide/stores/actions/tree_spec.js
@@ -7,6 +7,7 @@ import { createStore } from '~/ide/stores';
import service from '~/ide/services';
import { createRouter } from '~/ide/ide_router';
import { file, createEntriesFromPaths } from '../../helpers';
+import { TEST_HOST } from 'jest/helpers/test_constants';
describe('Multi-file store tree actions', () => {
let projectTree;
@@ -97,7 +98,7 @@ describe('Multi-file store tree actions', () => {
store.state.projects = {
'abc/def': {
- web_url: `${gl.TEST_HOST}/files`,
+ web_url: `${TEST_HOST}/files`,
branches: {
'master-testing': {
commit: {
diff --git a/spec/frontend/ide/utils_spec.js b/spec/frontend/ide/utils_spec.js
index 15baeca7f36..b6de576a0a4 100644
--- a/spec/frontend/ide/utils_spec.js
+++ b/spec/frontend/ide/utils_spec.js
@@ -1,6 +1,7 @@
import {
isTextFile,
registerLanguages,
+ registerSchemas,
trimPathComponents,
insertFinalNewline,
trimTrailingWhitespace,
@@ -158,6 +159,57 @@ describe('WebIDE utils', () => {
});
});
+ describe('registerSchemas', () => {
+ let options;
+
+ 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'] } },
+ },
+ },
+ ],
+ };
+
+ 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 });
+
+ expect(defaultsObj.setDiagnosticsOptions).toHaveBeenCalledWith(options);
+ },
+ );
+ });
+
describe('trimTrailingWhitespace', () => {
it.each`
input | output