debian-mirror-gitlab/spec/frontend/ide/stores/actions/merge_request_spec.js
2020-11-24 15:15:51 +05:30

505 lines
15 KiB
JavaScript

import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import { createStore } from '~/ide/stores';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import {
getMergeRequestData,
getMergeRequestChanges,
getMergeRequestVersions,
openMergeRequest,
} from '~/ide/stores/actions/merge_request';
import service from '~/ide/services';
import { leftSidebarViews, PERMISSION_READ_MR } from '~/ide/constants';
const TEST_PROJECT = 'abcproject';
const TEST_PROJECT_ID = 17;
jest.mock('~/flash');
describe('IDE store merge request actions', () => {
let store;
let mock;
beforeEach(() => {
store = createStore();
mock = new MockAdapter(axios);
store.state.projects[TEST_PROJECT] = {
id: TEST_PROJECT_ID,
mergeRequests: {},
userPermissions: {
[PERMISSION_READ_MR]: true,
},
};
});
afterEach(() => {
mock.restore();
});
describe('getMergeRequestsForBranch', () => {
describe('success', () => {
const mrData = { iid: 2, source_branch: 'bar' };
const mockData = [mrData];
describe('base case', () => {
beforeEach(() => {
jest.spyOn(service, 'getProjectMergeRequests');
mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests/).reply(200, mockData);
});
it('calls getProjectMergeRequests service method', done => {
store
.dispatch('getMergeRequestsForBranch', { projectId: TEST_PROJECT, branchId: 'bar' })
.then(() => {
expect(service.getProjectMergeRequests).toHaveBeenCalledWith(TEST_PROJECT, {
source_branch: 'bar',
source_project_id: TEST_PROJECT_ID,
state: 'opened',
order_by: 'created_at',
per_page: 1,
});
done();
})
.catch(done.fail);
});
it('sets the "Merge Request" Object', done => {
store
.dispatch('getMergeRequestsForBranch', { projectId: TEST_PROJECT, branchId: 'bar' })
.then(() => {
expect(store.state.projects.abcproject.mergeRequests).toEqual({
'2': expect.objectContaining(mrData),
});
done();
})
.catch(done.fail);
});
it('sets "Current Merge Request" object to the most recent MR', done => {
store
.dispatch('getMergeRequestsForBranch', { projectId: TEST_PROJECT, branchId: 'bar' })
.then(() => {
expect(store.state.currentMergeRequestId).toEqual('2');
done();
})
.catch(done.fail);
});
it('does nothing if user cannot read MRs', done => {
store.state.projects[TEST_PROJECT].userPermissions[PERMISSION_READ_MR] = false;
store
.dispatch('getMergeRequestsForBranch', { projectId: TEST_PROJECT, branchId: 'bar' })
.then(() => {
expect(service.getProjectMergeRequests).not.toHaveBeenCalled();
expect(store.state.currentMergeRequestId).toBe('');
})
.then(done)
.catch(done.fail);
});
});
describe('no merge requests for branch available case', () => {
beforeEach(() => {
jest.spyOn(service, 'getProjectMergeRequests');
mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests/).reply(200, []);
});
it('does not fail if there are no merge requests for current branch', done => {
store
.dispatch('getMergeRequestsForBranch', { projectId: TEST_PROJECT, branchId: 'foo' })
.then(() => {
expect(store.state.projects[TEST_PROJECT].mergeRequests).toEqual({});
expect(store.state.currentMergeRequestId).toEqual('');
done();
})
.catch(done.fail);
});
});
});
describe('error', () => {
beforeEach(() => {
mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests/).networkError();
});
it('flashes message, if error', done => {
store
.dispatch('getMergeRequestsForBranch', { projectId: TEST_PROJECT, branchId: 'bar' })
.catch(() => {
expect(createFlash).toHaveBeenCalled();
expect(createFlash.mock.calls[0][0]).toBe('Error fetching merge requests for bar');
})
.then(done)
.catch(done.fail);
});
});
});
describe('getMergeRequestData', () => {
describe('success', () => {
beforeEach(() => {
jest.spyOn(service, 'getProjectMergeRequestData');
mock
.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests\/1/)
.reply(200, { title: 'mergerequest' });
});
it('calls getProjectMergeRequestData service method', done => {
store
.dispatch('getMergeRequestData', { projectId: TEST_PROJECT, mergeRequestId: 1 })
.then(() => {
expect(service.getProjectMergeRequestData).toHaveBeenCalledWith(TEST_PROJECT, 1);
done();
})
.catch(done.fail);
});
it('sets the Merge Request Object', done => {
store
.dispatch('getMergeRequestData', { projectId: TEST_PROJECT, mergeRequestId: 1 })
.then(() => {
expect(store.state.currentMergeRequestId).toBe(1);
expect(store.state.projects[TEST_PROJECT].mergeRequests['1'].title).toBe(
'mergerequest',
);
done();
})
.catch(done.fail);
});
});
describe('error', () => {
beforeEach(() => {
mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests\/1/).networkError();
});
it('dispatches error action', done => {
const dispatch = jest.fn();
getMergeRequestData(
{
commit() {},
dispatch,
state: store.state,
},
{ projectId: TEST_PROJECT, mergeRequestId: 1 },
)
.then(done.fail)
.catch(() => {
expect(dispatch).toHaveBeenCalledWith('setErrorMessage', {
text: 'An error occurred while loading the merge request.',
action: expect.any(Function),
actionText: 'Please try again',
actionPayload: {
projectId: TEST_PROJECT,
mergeRequestId: 1,
force: false,
},
});
done();
});
});
});
});
describe('getMergeRequestChanges', () => {
beforeEach(() => {
store.state.projects[TEST_PROJECT].mergeRequests['1'] = { changes: [] };
});
describe('success', () => {
beforeEach(() => {
jest.spyOn(service, 'getProjectMergeRequestChanges');
mock
.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests\/1\/changes/)
.reply(200, { title: 'mergerequest' });
});
it('calls getProjectMergeRequestChanges service method', done => {
store
.dispatch('getMergeRequestChanges', { projectId: TEST_PROJECT, mergeRequestId: 1 })
.then(() => {
expect(service.getProjectMergeRequestChanges).toHaveBeenCalledWith(TEST_PROJECT, 1);
done();
})
.catch(done.fail);
});
it('sets the Merge Request Changes Object', done => {
store
.dispatch('getMergeRequestChanges', { projectId: TEST_PROJECT, mergeRequestId: 1 })
.then(() => {
expect(store.state.projects[TEST_PROJECT].mergeRequests['1'].changes.title).toBe(
'mergerequest',
);
done();
})
.catch(done.fail);
});
});
describe('error', () => {
beforeEach(() => {
mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests\/1\/changes/).networkError();
});
it('dispatches error action', done => {
const dispatch = jest.fn();
getMergeRequestChanges(
{
commit() {},
dispatch,
state: store.state,
},
{ projectId: TEST_PROJECT, mergeRequestId: 1 },
)
.then(done.fail)
.catch(() => {
expect(dispatch).toHaveBeenCalledWith('setErrorMessage', {
text: 'An error occurred while loading the merge request changes.',
action: expect.any(Function),
actionText: 'Please try again',
actionPayload: {
projectId: TEST_PROJECT,
mergeRequestId: 1,
force: false,
},
});
done();
});
});
});
});
describe('getMergeRequestVersions', () => {
beforeEach(() => {
store.state.projects[TEST_PROJECT].mergeRequests['1'] = { versions: [] };
});
describe('success', () => {
beforeEach(() => {
mock
.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests\/1\/versions/)
.reply(200, [{ id: 789 }]);
jest.spyOn(service, 'getProjectMergeRequestVersions');
});
it('calls getProjectMergeRequestVersions service method', done => {
store
.dispatch('getMergeRequestVersions', { projectId: TEST_PROJECT, mergeRequestId: 1 })
.then(() => {
expect(service.getProjectMergeRequestVersions).toHaveBeenCalledWith(TEST_PROJECT, 1);
done();
})
.catch(done.fail);
});
it('sets the Merge Request Versions Object', done => {
store
.dispatch('getMergeRequestVersions', { projectId: TEST_PROJECT, mergeRequestId: 1 })
.then(() => {
expect(store.state.projects[TEST_PROJECT].mergeRequests['1'].versions.length).toBe(1);
done();
})
.catch(done.fail);
});
});
describe('error', () => {
beforeEach(() => {
mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests\/1\/versions/).networkError();
});
it('dispatches error action', done => {
const dispatch = jest.fn();
getMergeRequestVersions(
{
commit() {},
dispatch,
state: store.state,
},
{ projectId: TEST_PROJECT, mergeRequestId: 1 },
)
.then(done.fail)
.catch(() => {
expect(dispatch).toHaveBeenCalledWith('setErrorMessage', {
text: 'An error occurred while loading the merge request version data.',
action: expect.any(Function),
actionText: 'Please try again',
actionPayload: {
projectId: TEST_PROJECT,
mergeRequestId: 1,
force: false,
},
});
done();
});
});
});
});
describe('openMergeRequest', () => {
const mr = {
projectId: TEST_PROJECT,
targetProjectId: 'defproject',
mergeRequestId: 2,
};
let testMergeRequest;
let testMergeRequestChanges;
const mockGetters = { findBranch: () => ({ commit: { id: 'abcd2322' } }) };
beforeEach(() => {
testMergeRequest = {
source_branch: 'abcbranch',
};
testMergeRequestChanges = {
changes: [],
};
store.state.entries = {
foo: {
type: 'blob',
},
bar: {
type: 'blob',
},
};
store.state.currentProjectId = 'test/test';
store.state.currentBranchId = 'master';
store.state.projects['test/test'] = {
branches: {
master: {
commit: {
id: '7297abc',
},
},
abcbranch: {
commit: {
id: '29020fc',
},
},
},
};
const originalDispatch = store.dispatch;
jest.spyOn(store, 'dispatch').mockImplementation((type, payload) => {
switch (type) {
case 'getMergeRequestData':
return Promise.resolve(testMergeRequest);
case 'getMergeRequestChanges':
return Promise.resolve(testMergeRequestChanges);
case 'getFiles':
case 'getMergeRequestVersions':
case 'getBranchData':
case 'setFileMrChange':
return Promise.resolve();
default:
return originalDispatch(type, payload);
}
});
jest.spyOn(service, 'getFileData').mockImplementation(() =>
Promise.resolve({
headers: {},
}),
);
});
it('dispatches actions for merge request data', done => {
openMergeRequest({ state: store.state, dispatch: store.dispatch, getters: mockGetters }, mr)
.then(() => {
expect(store.dispatch.mock.calls).toEqual([
['getMergeRequestData', mr],
['setCurrentBranchId', testMergeRequest.source_branch],
[
'getBranchData',
{
projectId: mr.projectId,
branchId: testMergeRequest.source_branch,
},
],
[
'getFiles',
{
projectId: mr.projectId,
branchId: testMergeRequest.source_branch,
ref: 'abcd2322',
},
],
['getMergeRequestVersions', mr],
['getMergeRequestChanges', mr],
]);
})
.then(done)
.catch(done.fail);
});
it('updates activity bar view and gets file data, if changes are found', done => {
store.state.entries.foo = {
type: 'blob',
};
store.state.entries.bar = {
type: 'blob',
};
testMergeRequestChanges.changes = [
{ new_path: 'foo', path: 'foo' },
{ new_path: 'bar', path: 'bar' },
];
openMergeRequest({ state: store.state, dispatch: store.dispatch, getters: mockGetters }, mr)
.then(() => {
expect(store.dispatch).toHaveBeenCalledWith(
'updateActivityBarView',
leftSidebarViews.review.name,
);
testMergeRequestChanges.changes.forEach((change, i) => {
expect(store.dispatch).toHaveBeenCalledWith('setFileMrChange', {
file: store.state.entries[change.new_path],
mrChange: change,
});
expect(store.dispatch).toHaveBeenCalledWith('getFileData', {
path: change.new_path,
makeFileActive: i === 0,
openFile: true,
});
});
expect(store.state.openFiles.length).toBe(testMergeRequestChanges.changes.length);
})
.then(done)
.catch(done.fail);
});
it('flashes message, if error', done => {
store.dispatch.mockRejectedValue();
openMergeRequest(store, mr)
.catch(() => {
expect(createFlash).toHaveBeenCalledWith(expect.any(String));
})
.then(done)
.catch(done.fail);
});
});
});