summaryrefslogtreecommitdiff
path: root/spec/javascripts
diff options
context:
space:
mode:
authorDenys Mishunov <dmishunov@gitlab.com>2019-05-29 12:13:27 +0000
committerFatih Acet <acetfatih@gmail.com>2019-05-29 12:13:27 +0000
commit0d7afb9561eae91b86f9fcc3a2a6d54ac527b177 (patch)
tree86aadaf779ee1f32798c823c16a7bb9a4e401793 /spec/javascripts
parent4ca791e6977d5717c22a3911ece00f69a5d9a93e (diff)
downloadgitlab-ce-0d7afb9561eae91b86f9fcc3a2a6d54ac527b177.tar.gz
Updated heading for default state in Web IDE
Resolves https://gitlab.com/gitlab-org/gitlab-ce/issues/60107
Diffstat (limited to 'spec/javascripts')
-rw-r--r--spec/javascripts/ide/components/ide_spec.js92
-rw-r--r--spec/javascripts/ide/components/ide_tree_list_spec.js59
-rw-r--r--spec/javascripts/ide/stores/actions/project_spec.js203
-rw-r--r--spec/javascripts/ide/stores/actions/tree_spec.js32
-rw-r--r--spec/javascripts/ide/stores/actions_spec.js64
-rw-r--r--spec/javascripts/ide/stores/modules/commit/actions_spec.js59
6 files changed, 358 insertions, 151 deletions
diff --git a/spec/javascripts/ide/components/ide_spec.js b/spec/javascripts/ide/components/ide_spec.js
index dc5790f6562..de4becec1cd 100644
--- a/spec/javascripts/ide/components/ide_spec.js
+++ b/spec/javascripts/ide/components/ide_spec.js
@@ -5,21 +5,53 @@ import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helpe
import { file, resetStore } from '../helpers';
import { projectData } from '../mock_data';
-describe('ide component', () => {
+function bootstrap(projData) {
+ const Component = Vue.extend(ide);
+
+ store.state.currentProjectId = 'abcproject';
+ store.state.currentBranchId = 'master';
+ store.state.projects.abcproject = Object.assign({}, projData);
+ Vue.set(store.state.trees, 'abcproject/master', {
+ tree: [],
+ loading: false,
+ });
+
+ return createComponentWithStore(Component, store, {
+ emptyStateSvgPath: 'svg',
+ noChangesStateSvgPath: 'svg',
+ committedStateSvgPath: 'svg',
+ });
+}
+
+describe('ide component, empty repo', () => {
let vm;
beforeEach(() => {
- const Component = Vue.extend(ide);
+ const emptyProjData = Object.assign({}, projectData, { empty_repo: true, branches: {} });
+ vm = bootstrap(emptyProjData);
+ vm.$mount();
+ });
- store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
- store.state.projects.abcproject = Object.assign({}, projectData);
+ afterEach(() => {
+ vm.$destroy();
+
+ resetStore(vm.$store);
+ });
- vm = createComponentWithStore(Component, store, {
- emptyStateSvgPath: 'svg',
- noChangesStateSvgPath: 'svg',
- committedStateSvgPath: 'svg',
- }).$mount();
+ it('renders "New file" button in empty repo', done => {
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.ide-empty-state button[title="New file"]')).not.toBeNull();
+ done();
+ });
+ });
+});
+
+describe('ide component, non-empty repo', () => {
+ let vm;
+
+ beforeEach(() => {
+ vm = bootstrap(projectData);
+ vm.$mount();
});
afterEach(() => {
@@ -28,17 +60,15 @@ describe('ide component', () => {
resetStore(vm.$store);
});
- it('does not render right when no files open', () => {
- expect(vm.$el.querySelector('.panel-right')).toBeNull();
- });
+ it('shows error message when set', done => {
+ expect(vm.$el.querySelector('.flash-container')).toBe(null);
- it('renders right panel when files are open', done => {
- vm.$store.state.trees['abcproject/mybranch'] = {
- tree: [file()],
+ vm.$store.state.errorMessage = {
+ text: 'error',
};
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.panel-right')).toBeNull();
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.flash-container')).not.toBe(null);
done();
});
@@ -71,17 +101,25 @@ describe('ide component', () => {
});
});
- it('shows error message when set', done => {
- expect(vm.$el.querySelector('.flash-container')).toBe(null);
-
- vm.$store.state.errorMessage = {
- text: 'error',
- };
+ describe('non-existent branch', () => {
+ it('does not render "New file" button for non-existent branch when repo is not empty', done => {
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.ide-empty-state button[title="New file"]')).toBeNull();
+ done();
+ });
+ });
+ });
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.flash-container')).not.toBe(null);
+ describe('branch with files', () => {
+ beforeEach(() => {
+ store.state.trees['abcproject/master'].tree = [file()];
+ });
- done();
+ it('does not render "New file" button', done => {
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.ide-empty-state button[title="New file"]')).toBeNull();
+ done();
+ });
});
});
});
diff --git a/spec/javascripts/ide/components/ide_tree_list_spec.js b/spec/javascripts/ide/components/ide_tree_list_spec.js
index 4ecbdb8a55e..f63007c7dd2 100644
--- a/spec/javascripts/ide/components/ide_tree_list_spec.js
+++ b/spec/javascripts/ide/components/ide_tree_list_spec.js
@@ -7,25 +7,23 @@ import { projectData } from '../mock_data';
describe('IDE tree list', () => {
const Component = Vue.extend(IdeTreeList);
+ const normalBranchTree = [file('fileName')];
+ const emptyBranchTree = [];
let vm;
- beforeEach(() => {
+ const bootstrapWithTree = (tree = normalBranchTree) => {
store.state.currentProjectId = 'abcproject';
store.state.currentBranchId = 'master';
store.state.projects.abcproject = Object.assign({}, projectData);
Vue.set(store.state.trees, 'abcproject/master', {
- tree: [file('fileName')],
+ tree,
loading: false,
});
vm = createComponentWithStore(Component, store, {
viewerType: 'edit',
});
-
- spyOn(vm, 'updateViewer').and.callThrough();
-
- vm.$mount();
- });
+ };
afterEach(() => {
vm.$destroy();
@@ -33,22 +31,47 @@ describe('IDE tree list', () => {
resetStore(vm.$store);
});
- it('updates viewer on mount', () => {
- expect(vm.updateViewer).toHaveBeenCalledWith('edit');
- });
+ describe('normal branch', () => {
+ beforeEach(() => {
+ bootstrapWithTree();
+
+ spyOn(vm, 'updateViewer').and.callThrough();
+
+ vm.$mount();
+ });
+
+ it('updates viewer on mount', () => {
+ expect(vm.updateViewer).toHaveBeenCalledWith('edit');
+ });
+
+ it('renders loading indicator', done => {
+ store.state.trees['abcproject/master'].loading = true;
- it('renders loading indicator', done => {
- store.state.trees['abcproject/master'].loading = true;
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.multi-file-loading-container')).not.toBeNull();
+ expect(vm.$el.querySelectorAll('.multi-file-loading-container').length).toBe(3);
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.multi-file-loading-container')).not.toBeNull();
- expect(vm.$el.querySelectorAll('.multi-file-loading-container').length).toBe(3);
+ done();
+ });
+ });
- done();
+ it('renders list of files', () => {
+ expect(vm.$el.textContent).toContain('fileName');
});
});
- it('renders list of files', () => {
- expect(vm.$el.textContent).toContain('fileName');
+ describe('empty-branch state', () => {
+ beforeEach(() => {
+ bootstrapWithTree(emptyBranchTree);
+
+ spyOn(vm, 'updateViewer').and.callThrough();
+
+ vm.$mount();
+ });
+
+ it('does not load files if the branch is empty', () => {
+ expect(vm.$el.textContent).not.toContain('fileName');
+ expect(vm.$el.textContent).toContain('No files');
+ });
});
});
diff --git a/spec/javascripts/ide/stores/actions/project_spec.js b/spec/javascripts/ide/stores/actions/project_spec.js
index cd519eaed7c..8ecb6129c63 100644
--- a/spec/javascripts/ide/stores/actions/project_spec.js
+++ b/spec/javascripts/ide/stores/actions/project_spec.js
@@ -4,7 +4,7 @@ import {
refreshLastCommitData,
showBranchNotFoundError,
createNewBranchFromDefault,
- getBranchData,
+ showEmptyState,
openBranch,
} from '~/ide/stores/actions';
import store from '~/ide/stores';
@@ -196,39 +196,44 @@ describe('IDE store project actions', () => {
});
});
- describe('getBranchData', () => {
- describe('error', () => {
- it('dispatches branch not found action when response is 404', done => {
- const dispatch = jasmine.createSpy('dispatchSpy');
-
- mock.onGet(/(.*)/).replyOnce(404);
-
- getBranchData(
+ describe('showEmptyState', () => {
+ it('commits proper mutations when supplied error is 404', done => {
+ testAction(
+ showEmptyState,
+ {
+ err: {
+ response: {
+ status: 404,
+ },
+ },
+ projectId: 'abc/def',
+ branchId: 'master',
+ },
+ store.state,
+ [
{
- commit() {},
- dispatch,
- state: store.state,
+ type: 'CREATE_TREE',
+ payload: {
+ treePath: 'abc/def/master',
+ },
},
{
- projectId: 'abc/def',
- branchId: 'master-testing',
+ type: 'TOGGLE_LOADING',
+ payload: {
+ entry: store.state.trees['abc/def/master'],
+ forceValue: false,
+ },
},
- )
- .then(done.fail)
- .catch(() => {
- expect(dispatch.calls.argsFor(0)).toEqual([
- 'showBranchNotFoundError',
- 'master-testing',
- ]);
- done();
- });
- });
+ ],
+ [],
+ done,
+ );
});
});
describe('openBranch', () => {
const branch = {
- projectId: 'feature/lorem-ipsum',
+ projectId: 'abc/def',
branchId: '123-lorem',
};
@@ -238,63 +243,113 @@ describe('IDE store project actions', () => {
'foo/bar-pending': { pending: true },
'foo/bar': { pending: false },
};
-
- spyOn(store, 'dispatch').and.returnValue(Promise.resolve());
});
- it('dispatches branch actions', done => {
- openBranch(store, branch)
- .then(() => {
- expect(store.dispatch.calls.allArgs()).toEqual([
- ['setCurrentBranchId', branch.branchId],
- ['getBranchData', branch],
- ['getFiles', branch],
- ['getMergeRequestsForBranch', branch],
- ]);
- })
- .then(done)
- .catch(done.fail);
- });
+ describe('empty repo', () => {
+ beforeEach(() => {
+ spyOn(store, 'dispatch').and.returnValue(Promise.resolve());
- it('handles tree entry action, if basePath is given', done => {
- openBranch(store, { ...branch, basePath: 'foo/bar/' })
- .then(() => {
- expect(store.dispatch).toHaveBeenCalledWith(
- 'handleTreeEntryAction',
- store.state.entries['foo/bar'],
- );
- })
- .then(done)
- .catch(done.fail);
+ store.state.currentProjectId = 'abc/def';
+ store.state.projects['abc/def'] = {
+ empty_repo: true,
+ };
+ });
+
+ afterEach(() => {
+ resetStore(store);
+ });
+
+ it('dispatches showEmptyState action right away', done => {
+ openBranch(store, branch)
+ .then(() => {
+ expect(store.dispatch.calls.allArgs()).toEqual([
+ ['setCurrentBranchId', branch.branchId],
+ ['showEmptyState', branch],
+ ]);
+ done();
+ })
+ .catch(done.fail);
+ });
});
- it('does not handle tree entry action, if entry is pending', done => {
- openBranch(store, { ...branch, basePath: 'foo/bar-pending' })
- .then(() => {
- expect(store.dispatch).not.toHaveBeenCalledWith(
- 'handleTreeEntryAction',
- jasmine.anything(),
- );
- })
- .then(done)
- .catch(done.fail);
+ describe('existing branch', () => {
+ beforeEach(() => {
+ spyOn(store, 'dispatch').and.returnValue(Promise.resolve());
+ });
+
+ it('dispatches branch actions', done => {
+ openBranch(store, branch)
+ .then(() => {
+ expect(store.dispatch.calls.allArgs()).toEqual([
+ ['setCurrentBranchId', branch.branchId],
+ ['getBranchData', branch],
+ ['getMergeRequestsForBranch', branch],
+ ['getFiles', branch],
+ ]);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('handles tree entry action, if basePath is given', done => {
+ openBranch(store, { ...branch, basePath: 'foo/bar/' })
+ .then(() => {
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'handleTreeEntryAction',
+ store.state.entries['foo/bar'],
+ );
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('does not handle tree entry action, if entry is pending', done => {
+ openBranch(store, { ...branch, basePath: 'foo/bar-pending' })
+ .then(() => {
+ expect(store.dispatch).not.toHaveBeenCalledWith(
+ 'handleTreeEntryAction',
+ jasmine.anything(),
+ );
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('creates a new file supplied via URL if the file does not exist yet', done => {
+ openBranch(store, { ...branch, basePath: 'not-existent.md' })
+ .then(() => {
+ expect(store.dispatch).not.toHaveBeenCalledWith(
+ 'handleTreeEntryAction',
+ jasmine.anything(),
+ );
+
+ expect(store.dispatch).toHaveBeenCalledWith('createTempEntry', {
+ name: 'not-existent.md',
+ type: 'blob',
+ });
+ })
+ .then(done)
+ .catch(done.fail);
+ });
});
- it('creates a new file supplied via URL if the file does not exist yet', done => {
- openBranch(store, { ...branch, basePath: 'not-existent.md' })
- .then(() => {
- expect(store.dispatch).not.toHaveBeenCalledWith(
- 'handleTreeEntryAction',
- jasmine.anything(),
- );
+ describe('non-existent branch', () => {
+ beforeEach(() => {
+ spyOn(store, 'dispatch').and.returnValue(Promise.reject());
+ });
- expect(store.dispatch).toHaveBeenCalledWith('createTempEntry', {
- name: 'not-existent.md',
- type: 'blob',
- });
- })
- .then(done)
- .catch(done.fail);
+ it('dispatches correct branch actions', done => {
+ openBranch(store, branch)
+ .then(() => {
+ expect(store.dispatch.calls.allArgs()).toEqual([
+ ['setCurrentBranchId', branch.branchId],
+ ['getBranchData', branch],
+ ['showBranchNotFoundError', branch.branchId],
+ ]);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
});
});
});
diff --git a/spec/javascripts/ide/stores/actions/tree_spec.js b/spec/javascripts/ide/stores/actions/tree_spec.js
index 5ed9b9003a7..674ecdc6764 100644
--- a/spec/javascripts/ide/stores/actions/tree_spec.js
+++ b/spec/javascripts/ide/stores/actions/tree_spec.js
@@ -93,38 +93,6 @@ describe('Multi-file store tree actions', () => {
});
describe('error', () => {
- it('dispatches branch not found actions when response is 404', done => {
- const dispatch = jasmine.createSpy('dispatchSpy');
-
- store.state.projects = {
- 'abc/def': {
- web_url: `${gl.TEST_HOST}/files`,
- },
- };
-
- mock.onGet(/(.*)/).replyOnce(404);
-
- getFiles(
- {
- commit() {},
- dispatch,
- state: store.state,
- },
- {
- projectId: 'abc/def',
- branchId: 'master-testing',
- },
- )
- .then(done.fail)
- .catch(() => {
- expect(dispatch.calls.argsFor(0)).toEqual([
- 'showBranchNotFoundError',
- 'master-testing',
- ]);
- done();
- });
- });
-
it('dispatches error action', done => {
const dispatch = jasmine.createSpy('dispatchSpy');
diff --git a/spec/javascripts/ide/stores/actions_spec.js b/spec/javascripts/ide/stores/actions_spec.js
index 0b5587d02ae..04e236fb042 100644
--- a/spec/javascripts/ide/stores/actions_spec.js
+++ b/spec/javascripts/ide/stores/actions_spec.js
@@ -9,12 +9,15 @@ import actions, {
setErrorMessage,
deleteEntry,
renameEntry,
+ getBranchData,
} from '~/ide/stores/actions';
+import axios from '~/lib/utils/axios_utils';
import store from '~/ide/stores';
import * as types from '~/ide/stores/mutation_types';
import router from '~/ide/ide_router';
import { resetStore, file } from '../helpers';
import testAction from '../../helpers/vuex_action_helper';
+import MockAdapter from 'axios-mock-adapter';
describe('Multi-file store actions', () => {
beforeEach(() => {
@@ -560,4 +563,65 @@ describe('Multi-file store actions', () => {
);
});
});
+
+ describe('getBranchData', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('error', () => {
+ let dispatch;
+ const callParams = [
+ {
+ commit() {},
+ state: store.state,
+ },
+ {
+ projectId: 'abc/def',
+ branchId: 'master-testing',
+ },
+ ];
+
+ beforeEach(() => {
+ dispatch = jasmine.createSpy('dispatchSpy');
+ document.body.innerHTML += '<div class="flash-container"></div>';
+ });
+
+ afterEach(() => {
+ document.querySelector('.flash-container').remove();
+ });
+
+ it('passes the error further unchanged without dispatching any action when response is 404', done => {
+ mock.onGet(/(.*)/).replyOnce(404);
+
+ getBranchData(...callParams)
+ .then(done.fail)
+ .catch(e => {
+ expect(dispatch.calls.count()).toEqual(0);
+ expect(e.response.status).toEqual(404);
+ expect(document.querySelector('.flash-alert')).toBeNull();
+ done();
+ });
+ });
+
+ it('does not pass the error further and flashes an alert if error is not 404', done => {
+ mock.onGet(/(.*)/).replyOnce(418);
+
+ getBranchData(...callParams)
+ .then(done.fail)
+ .catch(e => {
+ expect(dispatch.calls.count()).toEqual(0);
+ expect(e.response).toBeUndefined();
+ expect(document.querySelector('.flash-alert')).not.toBeNull();
+ done();
+ });
+ });
+ });
+ });
});
diff --git a/spec/javascripts/ide/stores/modules/commit/actions_spec.js b/spec/javascripts/ide/stores/modules/commit/actions_spec.js
index cdeb9b4b896..4413a12fac4 100644
--- a/spec/javascripts/ide/stores/modules/commit/actions_spec.js
+++ b/spec/javascripts/ide/stores/modules/commit/actions_spec.js
@@ -272,6 +272,7 @@ describe('IDE commit module actions', () => {
short_id: '123',
message: 'test message',
committed_date: 'date',
+ parent_ids: '321',
stats: {
additions: '1',
deletions: '2',
@@ -463,5 +464,63 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
});
+
+ describe('first commit of a branch', () => {
+ const COMMIT_RESPONSE = {
+ id: '123456',
+ short_id: '123',
+ message: 'test message',
+ committed_date: 'date',
+ parent_ids: [],
+ stats: {
+ additions: '1',
+ deletions: '2',
+ },
+ };
+
+ it('commits TOGGLE_EMPTY_STATE mutation on empty repo', done => {
+ spyOn(service, 'commit').and.returnValue(
+ Promise.resolve({
+ data: COMMIT_RESPONSE,
+ }),
+ );
+
+ spyOn(store, 'commit').and.callThrough();
+
+ store
+ .dispatch('commit/commitChanges')
+ .then(() => {
+ expect(store.commit.calls.allArgs()).toEqual(
+ jasmine.arrayContaining([
+ ['TOGGLE_EMPTY_STATE', jasmine.any(Object), jasmine.any(Object)],
+ ]),
+ );
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('does not commmit TOGGLE_EMPTY_STATE mutation on existing project', done => {
+ COMMIT_RESPONSE.parent_ids.push('1234');
+ spyOn(service, 'commit').and.returnValue(
+ Promise.resolve({
+ data: COMMIT_RESPONSE,
+ }),
+ );
+ spyOn(store, 'commit').and.callThrough();
+
+ store
+ .dispatch('commit/commitChanges')
+ .then(() => {
+ expect(store.commit.calls.allArgs()).not.toEqual(
+ jasmine.arrayContaining([
+ ['TOGGLE_EMPTY_STATE', jasmine.any(Object), jasmine.any(Object)],
+ ]),
+ );
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
});
});