diff --git a/app/assets/javascripts/ide/stores/mutations/file.js b/app/assets/javascripts/ide/stores/mutations/file.js index 0d878d6c6e53dd05e939ed4476ad31d9a2d9a554..25faac7c828f10402b7a9f222715793246ba4092 100644 --- a/app/assets/javascripts/ide/stores/mutations/file.js +++ b/app/assets/javascripts/ide/stores/mutations/file.js @@ -114,24 +114,30 @@ export default { }), }); } else { - Object.assign(state, { - entries: Object.assign(state.entries, { - [file.path]: Object.assign(state.entries[file.path], { - opened: false, - }), - }), - openFiles: state.openFiles.map(f => { + const openFile = state.openFiles.find(f => f.path === file.path); + const openFiles = state.openFiles + .concat(openFile ? null : file) + .filter(f => f) + .reduce((acc, f) => { if (f.path === file.path) { - return { + return acc.concat({ ...f, active: true, pending: true, key: `pending-${f.key}`, - }; + }); } - return f; + return acc.concat(f); + }, []); + + Object.assign(state, { + entries: Object.assign(state.entries, { + [file.path]: Object.assign(state.entries[file.path], { + opened: false, + }), }), + openFiles, }); } }, diff --git a/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js b/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js index 3ab461511b3f1563b65fc6f3a5cbd348481400e8..f007d89f437189b1dec9d3d45469057037d319a4 100644 --- a/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js +++ b/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js @@ -14,6 +14,8 @@ describe('Multi-file editor commit sidebar list item', () => { f = file('test-file'); + store.state.entries[f.path] = f; + vm = createComponentWithStore(Component, store, { file: f, }).$mount(); @@ -24,9 +26,7 @@ describe('Multi-file editor commit sidebar list item', () => { }); it('renders file path', () => { - expect( - vm.$el.querySelector('.multi-file-commit-list-path').textContent.trim(), - ).toBe(f.path); + expect(vm.$el.querySelector('.multi-file-commit-list-path').textContent.trim()).toBe(f.path); }); it('calls discardFileChanges when clicking discard button', () => { @@ -39,7 +39,6 @@ describe('Multi-file editor commit sidebar list item', () => { it('opens a closed file in the editor when clicking the file path', done => { spyOn(vm, 'openFileInEditor').and.callThrough(); - spyOn(vm, 'updateViewer').and.callThrough(); spyOn(router, 'push'); vm.$el.querySelector('.multi-file-commit-list-path').click(); @@ -52,14 +51,18 @@ describe('Multi-file editor commit sidebar list item', () => { }); }); - it('calls updateViewer with diff when clicking file', () => { + it('calls updateViewer with diff when clicking file', done => { spyOn(vm, 'openFileInEditor').and.callThrough(); spyOn(vm, 'updateViewer').and.callThrough(); spyOn(router, 'push'); vm.$el.querySelector('.multi-file-commit-list-path').click(); - expect(vm.updateViewer).toHaveBeenCalledWith('diff'); + setTimeout(() => { + expect(vm.updateViewer).toHaveBeenCalledWith('diff'); + + done(); + }); }); describe('computed', () => { diff --git a/spec/javascripts/ide/stores/actions/file_spec.js b/spec/javascripts/ide/stores/actions/file_spec.js index be1a17e6830080424bdbd24d34aabe16ce96ccac..eb8933b2b3f9db6e4ea336a95f2d137a10f2c423 100644 --- a/spec/javascripts/ide/stores/actions/file_spec.js +++ b/spec/javascripts/ide/stores/actions/file_spec.js @@ -74,6 +74,22 @@ describe('Multi-file store file actions', () => { }) .catch(done.fail); }); + + it('removes file if it pending', done => { + store.state.openFiles.push({ + ...localFile, + pending: true, + }); + + store + .dispatch('closeFile', localFile) + .then(() => { + expect(store.state.openFiles.length).toBe(0); + + done(); + }) + .catch(done.fail); + }); }); describe('setFileActive', () => { @@ -418,4 +434,113 @@ describe('Multi-file store file actions', () => { .catch(done.fail); }); }); + + describe('openPendingTab', () => { + let f; + + beforeEach(() => { + f = { + ...file(), + projectId: '123', + }; + + store.state.entries[f.path] = f; + }); + + it('makes file pending in openFiles', done => { + store + .dispatch('openPendingTab', f) + .then(() => { + expect(store.state.openFiles[0].pending).toBe(true); + }) + .then(done) + .catch(done.fail); + }); + + it('returns true when opened', done => { + store + .dispatch('openPendingTab', f) + .then(added => { + expect(added).toBe(true); + }) + .then(done) + .catch(done.fail); + }); + + it('pushes router URL when added', done => { + store.state.currentBranchId = 'master'; + + store + .dispatch('openPendingTab', f) + .then(() => { + expect(router.push).toHaveBeenCalledWith('/project/123/tree/master/'); + }) + .then(done) + .catch(done.fail); + }); + + it('calls scrollToTab', done => { + const scrollToTabSpy = jasmine.createSpy('scrollToTab'); + const oldScrollToTab = store._actions.scrollToTab; // eslint-disable-line + store._actions.scrollToTab = [scrollToTabSpy]; // eslint-disable-line + + store + .dispatch('openPendingTab', f) + .then(() => { + expect(scrollToTabSpy).toHaveBeenCalled(); + store._actions.scrollToTab = oldScrollToTab; // eslint-disable-line + }) + .then(done) + .catch(done.fail); + }); + + it('returns false when passed in file is active & viewer is diff', done => { + f.active = true; + store.state.openFiles.push(f); + store.state.viewer = 'diff'; + + store + .dispatch('openPendingTab', f) + .then(added => { + expect(added).toBe(false); + }) + .then(done) + .catch(done.fail); + }); + }); + + describe('removePendingTab', () => { + let f; + + beforeEach(() => { + spyOn(eventHub, '$emit'); + + f = { + ...file('pendingFile'), + pending: true, + }; + }); + + it('removes pending file from open files', done => { + store.state.openFiles.push(f); + + store + .dispatch('removePendingTab', f) + .then(() => { + expect(store.state.openFiles.length).toBe(0); + }) + .then(done) + .catch(done.fail); + }); + + 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); + }); + }); }); diff --git a/spec/javascripts/ide/stores/mutations/file_spec.js b/spec/javascripts/ide/stores/mutations/file_spec.js index 131380248e8538ca73a1328ded2cd191d38ac5cd..9978f22f44a0a202949b767b60a8d5c53f83d413 100644 --- a/spec/javascripts/ide/stores/mutations/file_spec.js +++ b/spec/javascripts/ide/stores/mutations/file_spec.js @@ -22,6 +22,20 @@ describe('Multi-file store file mutations', () => { expect(localFile.active).toBeTruthy(); }); + + it('sets pending tab as not active', () => { + localState.openFiles.push({ + ...localFile, + pending: true, + }); + + mutations.SET_FILE_ACTIVE(localState, { + path: localFile.path, + active: true, + }); + + expect(localState.openFiles[0].active).toBe(false); + }); }); describe('TOGGLE_FILE_OPEN', () => { @@ -154,4 +168,69 @@ describe('Multi-file store file mutations', () => { expect(localFile.changed).toBeTruthy(); }); }); + + describe('ADD_PENDING_TAB', () => { + beforeEach(() => { + const f = { + ...file('openFile'), + path: 'openFile', + active: true, + opened: true, + }; + + localState.entries[f.path] = f; + localState.openFiles.push(f); + }); + + it('adds file into openFiles as pending', () => { + mutations.ADD_PENDING_TAB(localState, localFile); + + expect(localState.openFiles.length).toBe(2); + expect(localState.openFiles[1].pending).toBe(true); + expect(localState.openFiles[1].key).toBe(`pending-${localFile.key}`); + }); + + it('updates open file to pending', () => { + mutations.ADD_PENDING_TAB(localState, localState.openFiles[0]); + + expect(localState.openFiles.length).toBe(1); + }); + + it('updates pending open file to active', () => { + localState.openFiles.push({ + ...localFile, + pending: true, + }); + + mutations.ADD_PENDING_TAB(localState, localFile); + + expect(localState.openFiles[1].pending).toBe(true); + expect(localState.openFiles[1].active).toBe(true); + }); + + it('sets all openFiles to not active', () => { + mutations.ADD_PENDING_TAB(localState, localFile); + + expect(localState.openFiles.length).toBe(2); + + localState.openFiles.forEach(f => { + if (f.pending) { + expect(f.active).toBe(true); + } else { + expect(f.active).toBe(false); + } + }); + }); + }); + + describe('REMOVE_PENDING_TAB', () => { + it('removes pending tab from openFiles', () => { + localFile.key = 'testing'; + localState.openFiles.push(localFile); + + mutations.REMOVE_PENDING_TAB(localState, localFile); + + expect(localState.openFiles.length).toBe(0); + }); + }); });