Commit 0e8d7147 authored by Phil Hughes's avatar Phil Hughes

Merge branch 'fe-ide-clean-up-discard-duplication' into 'master'

Clean up discard duplication in IDE

See merge request gitlab-org/gitlab!22572
parents e0e12ea1 3717c57f
...@@ -16,21 +16,7 @@ export const redirectToUrl = (self, url) => visitUrl(url); ...@@ -16,21 +16,7 @@ export const redirectToUrl = (self, url) => visitUrl(url);
export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DATA, data); export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DATA, data);
export const discardAllChanges = ({ state, commit, dispatch }) => { export const discardAllChanges = ({ state, commit, dispatch }) => {
state.changedFiles.forEach(file => { state.changedFiles.forEach(file => dispatch('restoreOriginalFile', file.path));
if (file.tempFile || file.prevPath) dispatch('closeFile', file);
if (file.tempFile) {
dispatch('deleteEntry', file.path);
} else if (file.prevPath) {
dispatch('renameEntry', {
path: file.path,
name: file.prevName,
parentPath: file.prevParentPath,
});
} else {
commit(types.DISCARD_FILE_CHANGES, file.path);
}
});
commit(types.REMOVE_ALL_CHANGES_FILES); commit(types.REMOVE_ALL_CHANGES_FILES);
}; };
......
...@@ -191,38 +191,47 @@ export const setFileViewMode = ({ commit }, { file, viewMode }) => { ...@@ -191,38 +191,47 @@ export const setFileViewMode = ({ commit }, { file, viewMode }) => {
commit(types.SET_FILE_VIEWMODE, { file, viewMode }); commit(types.SET_FILE_VIEWMODE, { file, viewMode });
}; };
export const discardFileChanges = ({ dispatch, state, commit, getters }, path) => { export const restoreOriginalFile = ({ dispatch, state, commit }, path) => {
const file = state.entries[path]; const file = state.entries[path];
const isDestructiveDiscard = file.tempFile || file.prevPath;
if (file.deleted && file.parentPath) { if (file.deleted && file.parentPath) {
dispatch('restoreTree', file.parentPath); dispatch('restoreTree', file.parentPath);
} }
if (file.tempFile || file.prevPath) { if (isDestructiveDiscard) {
dispatch('closeFile', file); dispatch('closeFile', file);
}
if (file.tempFile) { if (file.tempFile) {
dispatch('deleteEntry', file.path); dispatch('deleteEntry', file.path);
} else {
commit(types.DISCARD_FILE_CHANGES, file.path);
dispatch('renameEntry', {
path: file.path,
name: file.prevName,
parentPath: file.prevParentPath,
});
}
} else { } else {
commit(types.DISCARD_FILE_CHANGES, path); commit(types.DISCARD_FILE_CHANGES, file.path);
}
if (getters.activeFile && file.path === getters.activeFile.path) {
dispatch('updateDelayViewerUpdated', true) if (file.prevPath) {
.then(() => { dispatch('renameEntry', {
router.push(`/project${file.url}`); path: file.path,
}) name: file.prevName,
.catch(e => { parentPath: file.prevParentPath,
throw e; });
}); }
} };
export const discardFileChanges = ({ dispatch, state, commit, getters }, path) => {
const file = state.entries[path];
const isDestructiveDiscard = file.tempFile || file.prevPath;
dispatch('restoreOriginalFile', path);
if (!isDestructiveDiscard && file.path === getters.activeFile?.path) {
dispatch('updateDelayViewerUpdated', true)
.then(() => {
router.push(`/project${file.url}`);
})
.catch(e => {
throw e;
});
} }
commit(types.REMOVE_FILE_FROM_CHANGED, path); commit(types.REMOVE_FILE_FROM_CHANGED, path);
......
---
title: Fix discard all to behave like discard single file in Web IDE
merge_request: 22572
author:
type: fixed
...@@ -619,107 +619,113 @@ describe('IDE store file actions', () => { ...@@ -619,107 +619,113 @@ describe('IDE store file actions', () => {
}); });
}); });
describe('discardFileChanges', () => { describe('with changed file', () => {
let tmpFile; let tmpFile;
beforeEach(() => { beforeEach(() => {
jest.spyOn(eventHub, '$on').mockImplementation(() => {});
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
tmpFile = file('tempFile'); tmpFile = file('tempFile');
tmpFile.content = 'testing'; tmpFile.content = 'testing';
tmpFile.raw = ORIGINAL_CONTENT; tmpFile.raw = ORIGINAL_CONTENT;
store.state.changedFiles.push(tmpFile); store.state.changedFiles.push(tmpFile);
store.state.entries[tmpFile.path] = tmpFile; store.state.entries[tmpFile.path] = tmpFile;
jest.spyOn(store, 'dispatch');
}); });
it('resets file content', done => { describe('restoreOriginalFile', () => {
store it('resets file content', () =>
.dispatch('discardFileChanges', tmpFile.path) store.dispatch('restoreOriginalFile', tmpFile.path).then(() => {
.then(() => {
expect(tmpFile.content).toBe(ORIGINAL_CONTENT); expect(tmpFile.content).toBe(ORIGINAL_CONTENT);
}));
done(); it('closes temp file and deletes it', () => {
}) tmpFile.tempFile = true;
.catch(done.fail); tmpFile.opened = true;
}); tmpFile.parentPath = 'parentFile';
store.state.entries.parentFile = file('parentFile');
it('removes file from changedFiles array', done => { actions.restoreOriginalFile(store, tmpFile.path);
store
.dispatch('discardFileChanges', tmpFile.path)
.then(() => {
expect(store.state.changedFiles.length).toBe(0);
done(); expect(store.dispatch).toHaveBeenCalledWith('closeFile', tmpFile);
}) expect(store.dispatch).toHaveBeenCalledWith('deleteEntry', tmpFile.path);
.catch(done.fail); });
});
it('closes temp file and deletes it', () => { describe('with renamed file', () => {
tmpFile.tempFile = true; beforeEach(() => {
tmpFile.opened = true; Object.assign(tmpFile, {
tmpFile.parentPath = 'parentFile'; prevPath: 'parentPath/old_name',
store.state.entries.parentFile = file('parentFile'); prevName: 'old_name',
prevParentPath: 'parentPath',
});
actions.discardFileChanges(store, tmpFile.path); store.state.entries.parentPath = file('parentPath');
expect(store.dispatch).toHaveBeenCalledWith('closeFile', tmpFile); actions.restoreOriginalFile(store, tmpFile.path);
expect(store.dispatch).toHaveBeenCalledWith('deleteEntry', tmpFile.path); });
});
describe('with renamed file', () => { it('renames the file to its original name and closes it if it was open', () => {
beforeEach(() => { expect(store.dispatch).toHaveBeenCalledWith('closeFile', tmpFile);
Object.assign(tmpFile, { expect(store.dispatch).toHaveBeenCalledWith('renameEntry', {
prevPath: 'parentPath/old_name', path: 'tempFile',
prevName: 'old_name', name: 'old_name',
prevParentPath: 'parentPath', parentPath: 'parentPath',
});
}); });
store.state.entries.parentPath = file('parentPath'); it('resets file content', () => {
expect(tmpFile.content).toBe(ORIGINAL_CONTENT);
});
});
});
actions.discardFileChanges(store, tmpFile.path); describe('discardFileChanges', () => {
beforeEach(() => {
jest.spyOn(eventHub, '$on').mockImplementation(() => {});
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
}); });
it('renames the file to its original name and closes it if it was open', () => { describe('with regular file', () => {
expect(store.dispatch).toHaveBeenCalledWith('closeFile', tmpFile); beforeEach(() => {
expect(store.dispatch).toHaveBeenCalledWith('renameEntry', { actions.discardFileChanges(store, tmpFile.path);
path: 'tempFile',
name: 'old_name',
parentPath: 'parentPath',
}); });
});
it('resets file content', () => { it('restores original file', () => {
expect(tmpFile.content).toBe(ORIGINAL_CONTENT); expect(store.dispatch).toHaveBeenCalledWith('restoreOriginalFile', tmpFile.path);
}); });
});
it('pushes route for active file', done => { it('removes file from changedFiles array', () => {
tmpFile.active = true; expect(store.state.changedFiles.length).toBe(0);
store.state.openFiles.push(tmpFile); });
store it('does not push a new route', () => {
.dispatch('discardFileChanges', tmpFile.path) expect(router.push).not.toHaveBeenCalled();
.then(() => { });
expect(router.push).toHaveBeenCalledWith(`/project${tmpFile.url}`);
done(); it('emits eventHub event to dispose cached model', () => {
}) actions.discardFileChanges(store, tmpFile.path);
.catch(done.fail);
}); expect(eventHub.$emit).toHaveBeenCalledWith(
`editor.update.model.new.content.${tmpFile.key}`,
ORIGINAL_CONTENT,
);
expect(eventHub.$emit).toHaveBeenCalledWith(
`editor.update.model.dispose.unstaged-${tmpFile.key}`,
ORIGINAL_CONTENT,
);
});
});
it('emits eventHub event to dispose cached model', done => { describe('with active file', () => {
store beforeEach(() => {
.dispatch('discardFileChanges', tmpFile.path) tmpFile.active = true;
.then(() => { store.state.openFiles.push(tmpFile);
expect(eventHub.$emit).toHaveBeenCalled();
done(); actions.discardFileChanges(store, tmpFile.path);
}) });
.catch(done.fail);
it('pushes route for active file', () => {
expect(router.push).toHaveBeenCalledWith(`/project${tmpFile.url}`);
});
});
}); });
}); });
......
...@@ -61,24 +61,25 @@ describe('Multi-file store actions', () => { ...@@ -61,24 +61,25 @@ describe('Multi-file store actions', () => {
}); });
describe('discardAllChanges', () => { describe('discardAllChanges', () => {
let f; const paths = ['to_discard', 'another_one_to_discard'];
beforeEach(() => { beforeEach(() => {
f = file('discardAll'); paths.forEach(path => {
f.changed = true; const f = file(path);
f.changed = true;
store.state.openFiles.push(f); store.state.openFiles.push(f);
store.state.changedFiles.push(f); store.state.changedFiles.push(f);
store.state.entries[f.path] = f; store.state.entries[f.path] = f;
});
}); });
it('discards changes in file', done => { it('discards all changes in file', () => {
store const expectedCalls = paths.map(path => ['restoreOriginalFile', path]);
.dispatch('discardAllChanges')
.then(() => { discardAllChanges(store);
expect(store.state.openFiles.changed).toBeFalsy();
}) expect(store.dispatch.calls.allArgs()).toEqual(jasmine.arrayContaining(expectedCalls));
.then(done)
.catch(done.fail);
}); });
it('removes all files from changedFiles state', done => { it('removes all files from changedFiles state', done => {
...@@ -86,64 +87,11 @@ describe('Multi-file store actions', () => { ...@@ -86,64 +87,11 @@ describe('Multi-file store actions', () => {
.dispatch('discardAllChanges') .dispatch('discardAllChanges')
.then(() => { .then(() => {
expect(store.state.changedFiles.length).toBe(0); expect(store.state.changedFiles.length).toBe(0);
expect(store.state.openFiles.length).toBe(1); expect(store.state.openFiles.length).toBe(2);
}) })
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
}); });
it('closes the temp file and deletes it if it was open', done => {
f.tempFile = true;
testAction(
discardAllChanges,
undefined,
store.state,
[{ type: types.REMOVE_ALL_CHANGES_FILES }],
[
{ type: 'closeFile', payload: jasmine.objectContaining({ path: 'discardAll' }) },
{ type: 'deleteEntry', payload: 'discardAll' },
],
done,
);
});
it('renames the file to its original name and closes it if it was open', done => {
Object.assign(f, {
prevPath: 'parent/path/old_name',
prevName: 'old_name',
prevParentPath: 'parent/path',
});
testAction(
discardAllChanges,
undefined,
store.state,
[{ type: types.REMOVE_ALL_CHANGES_FILES }],
[
{ type: 'closeFile', payload: jasmine.objectContaining({ path: 'discardAll' }) },
{
type: 'renameEntry',
payload: { path: 'discardAll', name: 'old_name', parentPath: 'parent/path' },
},
],
done,
);
});
it('discards file changes on all other files', done => {
testAction(
discardAllChanges,
undefined,
store.state,
[
{ type: types.DISCARD_FILE_CHANGES, payload: 'discardAll' },
{ type: types.REMOVE_ALL_CHANGES_FILES },
],
[],
done,
);
});
}); });
describe('closeAllFiles', () => { describe('closeAllFiles', () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment