Commit b7f8ba97 authored by Paul Slaughter's avatar Paul Slaughter

Fix ide action to handle empty repo with tree

**How?**
Previously the openBranch action (which is called
 on a route change) would recreate the tree
 whenever there was an empty repo. Now we
 only do this if the current file tree does not exist.
parent 8a6b537d
......@@ -83,10 +83,14 @@ export const showBranchNotFoundError = ({ dispatch }, branchId) => {
});
};
export const showEmptyState = ({ commit, state, dispatch }, { projectId, branchId }) => {
export const loadEmptyBranch = ({ commit, state }, { projectId, branchId }) => {
const treePath = `${projectId}/${branchId}`;
const currentTree = state.trees[`${projectId}/${branchId}`];
dispatch('setCurrentBranchId', branchId);
// If we already have a tree, let's not recreate an empty one
if (currentTree) {
return;
}
commit(types.CREATE_TREE, { treePath });
commit(types.TOGGLE_LOADING, {
......@@ -114,8 +118,16 @@ export const loadFile = ({ dispatch, state }, { basePath }) => {
}
};
export const loadBranch = ({ dispatch, getters }, { projectId, branchId }) =>
dispatch('getBranchData', {
export const loadBranch = ({ dispatch, getters, state }, { projectId, branchId }) => {
const currentProject = state.projects[projectId];
if (currentProject?.branches?.[branchId]) {
return Promise.resolve();
} else if (getters.emptyRepo) {
return dispatch('loadEmptyBranch', { projectId, branchId });
}
return dispatch('getBranchData', {
projectId,
branchId,
})
......@@ -137,29 +149,23 @@ export const loadBranch = ({ dispatch, getters }, { projectId, branchId }) =>
dispatch('showBranchNotFoundError', branchId);
throw err;
});
};
export const openBranch = ({ dispatch, state, getters }, { projectId, branchId, basePath }) => {
const currentProject = state.projects[projectId];
if (getters.emptyRepo) {
return dispatch('showEmptyState', { projectId, branchId });
}
if (!currentProject || !currentProject.branches[branchId]) {
dispatch('setCurrentBranchId', branchId);
return dispatch('loadBranch', { projectId, branchId })
.then(() => dispatch('loadFile', { basePath }))
.catch(
() =>
new Error(
sprintf(
__('An error occurred while getting files for - %{branchId}'),
{
branchId: `<strong>${esc(projectId)}/${esc(branchId)}</strong>`,
},
false,
),
export const openBranch = ({ dispatch }, { projectId, branchId, basePath }) => {
dispatch('setCurrentBranchId', branchId);
return dispatch('loadBranch', { projectId, branchId })
.then(() => dispatch('loadFile', { basePath }))
.catch(
() =>
new Error(
sprintf(
__('An error occurred while getting files for - %{branchId}'),
{
branchId: `<strong>${esc(projectId)}/${esc(branchId)}</strong>`,
},
false,
),
);
}
return Promise.resolve(dispatch('loadFile', { basePath }));
),
);
};
---
title: Fix some Web IDE bugs with empty projects
merge_request: 25463
author:
type: fixed
......@@ -4,7 +4,7 @@ import {
refreshLastCommitData,
showBranchNotFoundError,
createNewBranchFromDefault,
showEmptyState,
loadEmptyBranch,
openBranch,
loadFile,
loadBranch,
......@@ -16,6 +16,8 @@ import router from '~/ide/ide_router';
import { resetStore } from '../../helpers';
import testAction from '../../../helpers/vuex_action_helper';
const TEST_PROJECT_ID = 'abc/def';
describe('IDE store project actions', () => {
let mock;
let store;
......@@ -24,7 +26,7 @@ describe('IDE store project actions', () => {
store = createStore();
mock = new MockAdapter(axios);
store.state.projects['abc/def'] = {
store.state.projects[TEST_PROJECT_ID] = {
branches: {},
};
});
......@@ -83,7 +85,7 @@ describe('IDE store project actions', () => {
{
type: 'SET_BRANCH_COMMIT',
payload: {
projectId: 'abc/def',
projectId: TEST_PROJECT_ID,
branchId: 'master',
commit: { id: '123' },
},
......@@ -200,17 +202,17 @@ describe('IDE store project actions', () => {
});
});
describe('showEmptyState', () => {
describe('loadEmptyBranch', () => {
it('creates a blank tree and sets loading state to false', done => {
testAction(
showEmptyState,
{ projectId: 'abc/def', branchId: 'master' },
loadEmptyBranch,
{ projectId: TEST_PROJECT_ID, branchId: 'master' },
store.state,
[
{ type: 'CREATE_TREE', payload: { treePath: 'abc/def/master' } },
{ type: 'CREATE_TREE', payload: { treePath: `${TEST_PROJECT_ID}/master` } },
{
type: 'TOGGLE_LOADING',
payload: { entry: store.state.trees['abc/def/master'], forceValue: false },
payload: { entry: store.state.trees[`${TEST_PROJECT_ID}/master`], forceValue: false },
},
],
jasmine.any(Object),
......@@ -218,13 +220,15 @@ describe('IDE store project actions', () => {
);
});
it('sets the currentBranchId to the branchId that was passed', done => {
it('does nothing, if tree already exists', done => {
const trees = { [`${TEST_PROJECT_ID}/master`]: [] };
testAction(
showEmptyState,
{ projectId: 'abc/def', branchId: 'master' },
store.state,
jasmine.any(Object),
[{ type: 'setCurrentBranchId', payload: 'master' }],
loadEmptyBranch,
{ projectId: TEST_PROJECT_ID, branchId: 'master' },
{ trees },
[],
[],
done,
);
});
......@@ -278,10 +282,29 @@ describe('IDE store project actions', () => {
});
describe('loadBranch', () => {
const projectId = 'abc/def';
const projectId = TEST_PROJECT_ID;
const branchId = '123-lorem';
const ref = 'abcd2322';
it('when empty repo, loads empty branch', done => {
const mockGetters = { emptyRepo: true };
testAction(
loadBranch,
{ projectId, branchId },
{ ...store.state, ...mockGetters },
[],
[{ type: 'loadEmptyBranch', payload: { projectId, branchId } }],
done,
);
});
it('when branch already exists, does nothing', done => {
store.state.projects[projectId].branches[branchId] = {};
testAction(loadBranch, { projectId, branchId }, store.state, [], [], done);
});
it('fetches branch data', done => {
const mockGetters = { findBranch: () => ({ commit: { id: ref } }) };
spyOn(store, 'dispatch').and.returnValue(Promise.resolve());
......@@ -317,7 +340,7 @@ describe('IDE store project actions', () => {
});
describe('openBranch', () => {
const projectId = 'abc/def';
const projectId = TEST_PROJECT_ID;
const branchId = '123-lorem';
const branch = {
......@@ -335,55 +358,6 @@ describe('IDE store project actions', () => {
});
});
it('loads file right away if the branch has already been fetched', done => {
spyOn(store, 'dispatch');
Object.assign(store.state, {
projects: {
[projectId]: {
branches: {
[branchId]: { foo: 'bar' },
},
},
},
});
openBranch(store, branch)
.then(() => {
expect(store.dispatch.calls.allArgs()).toEqual([['loadFile', { basePath: undefined }]]);
})
.then(done)
.catch(done.fail);
});
describe('empty repo', () => {
beforeEach(() => {
spyOn(store, 'dispatch').and.returnValue(Promise.resolve());
Object.assign(store.state, {
currentProjectId: 'abc/def',
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([['showEmptyState', branch]]);
done();
})
.catch(done.fail);
});
});
describe('existing branch', () => {
beforeEach(() => {
spyOn(store, 'dispatch').and.returnValue(Promise.resolve());
......@@ -410,11 +384,17 @@ describe('IDE store project actions', () => {
it('dispatches correct branch actions', done => {
openBranch(store, branch)
.then(() => {
.then(val => {
expect(store.dispatch.calls.allArgs()).toEqual([
['setCurrentBranchId', branchId],
['loadBranch', { projectId, branchId }],
]);
expect(val).toEqual(
new Error(
`An error occurred while getting files for - <strong>${projectId}/${branchId}</strong>`,
),
);
})
.then(done)
.catch(done.fail);
......
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