summaryrefslogtreecommitdiff
path: root/spec/frontend/ide/components
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-07-20 12:26:25 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-07-20 12:26:25 +0000
commita09983ae35713f5a2bbb100981116d31ce99826e (patch)
tree2ee2af7bd104d57086db360a7e6d8c9d5d43667a /spec/frontend/ide/components
parent18c5ab32b738c0b6ecb4d0df3994000482f34bd8 (diff)
downloadgitlab-ce-a09983ae35713f5a2bbb100981116d31ce99826e.tar.gz
Add latest changes from gitlab-org/gitlab@13-2-stable-ee
Diffstat (limited to 'spec/frontend/ide/components')
-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
3 files changed, 95 insertions, 28 deletions
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' },