diff options
author | Denys Mishunov <dmishunov@gitlab.com> | 2019-05-29 12:13:27 +0000 |
---|---|---|
committer | Fatih Acet <acetfatih@gmail.com> | 2019-05-29 12:13:27 +0000 |
commit | 0d7afb9561eae91b86f9fcc3a2a6d54ac527b177 (patch) | |
tree | 86aadaf779ee1f32798c823c16a7bb9a4e401793 /spec/javascripts | |
parent | 4ca791e6977d5717c22a3911ece00f69a5d9a93e (diff) | |
download | gitlab-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.js | 92 | ||||
-rw-r--r-- | spec/javascripts/ide/components/ide_tree_list_spec.js | 59 | ||||
-rw-r--r-- | spec/javascripts/ide/stores/actions/project_spec.js | 203 | ||||
-rw-r--r-- | spec/javascripts/ide/stores/actions/tree_spec.js | 32 | ||||
-rw-r--r-- | spec/javascripts/ide/stores/actions_spec.js | 64 | ||||
-rw-r--r-- | spec/javascripts/ide/stores/modules/commit/actions_spec.js | 59 |
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); + }); + }); }); }); |