Skip to content
Snippets Groups Projects
Verified Commit 3764ad1a authored by Paul Slaughter's avatar Paul Slaughter :two:
Browse files

Integrate approval rules settings FE with BE

- Adds endpoints to API
- Removes service stub
parent 0c594493
No related branches found
No related tags found
No related merge requests found
import CEApi from '~/api';
import axios from '~/lib/utils/axios_utils';
export default {
...CEApi,
projectApprovalRulesPath: '/api/:version/projects/:id/approval_rules',
projectApprovalRulePath: '/api/:version/projects/:id/approval_rules/:ruleid',
getProjectApprovalRules(projectId) {
const url = this.buildUrl(this.projectApprovalRulesPath).replace(
':id',
encodeURIComponent(projectId),
);
return axios.get(url);
},
postProjectApprovalRule(projectId, rule) {
const url = this.buildUrl(this.projectApprovalRulesPath).replace(
':id',
encodeURIComponent(projectId),
);
return axios.post(url, rule);
},
putProjectApprovalRule(projectId, ruleId, rule) {
const url = this.buildUrl(this.projectApprovalRulePath)
.replace(':id', encodeURIComponent(projectId))
.replace(':ruleid', encodeURIComponent(ruleId));
return axios.put(url, rule);
},
deleteProjectApprovalRule(projectId, ruleId) {
const url = this.buildUrl(this.projectApprovalRulePath)
.replace(':id', encodeURIComponent(projectId))
.replace(':ruleid', encodeURIComponent(ruleId));
return axios.delete(url);
},
};
/**
* This provides a stubbed API for approval rule requests.
*
* **PLEASE NOTE:**
* - This class will be removed when the BE is merged for https://gitlab.com/gitlab-org/gitlab-ee/issues/1979
*/
export function createApprovalsServiceStub() {
const projectApprovalRules = [];
return {
getProjectApprovalRules() {
return Promise.resolve({
data: { rules: projectApprovalRules },
});
},
};
}
export default createApprovalsServiceStub();
import createFlash from '~/flash';
import { __ } from '~/locale';
import Api from 'ee/api';
import * as types from './mutation_types';
import service from '../services/approvals_service_stub';
import { mapApprovalRuleRequest, mapApprovalRulesResponse } from '../mappers';
export const setSettings = ({ commit }, settings) => {
......@@ -26,10 +26,11 @@ export const fetchRules = ({ state, dispatch }) => {
return Promise.resolve();
}
const { projectId } = state.settings;
dispatch('requestRules');
return service
.getProjectApprovalRules()
return Api.getProjectApprovalRules(projectId)
.then(response => dispatch('receiveRulesSuccess', mapApprovalRulesResponse(response.data)))
.catch(() => dispatch('receiveRulesError'));
};
......@@ -43,17 +44,21 @@ export const postRuleError = () => {
createFlash(__('An error occurred while updating approvers'));
};
export const postRule = ({ dispatch }, rule) =>
service
.postProjectApprovalRule(mapApprovalRuleRequest(rule))
export const postRule = ({ state, dispatch }, rule) => {
const { projectId } = state.settings;
return Api.postProjectApprovalRule(projectId, mapApprovalRuleRequest(rule))
.then(() => dispatch('postRuleSuccess'))
.catch(() => dispatch('postRuleError'));
};
export const putRule = ({ state, dispatch }, { id, ...newRule }) => {
const { projectId } = state.settings;
export const putRule = ({ dispatch }, { id, ...newRule }) =>
service
.putProjectApprovalRule(id, mapApprovalRuleRequest(newRule))
return Api.putProjectApprovalRule(projectId, id, mapApprovalRuleRequest(newRule))
.then(() => dispatch('postRuleSuccess'))
.catch(() => dispatch('postRuleError'));
};
export const deleteRuleSuccess = ({ dispatch }) => {
dispatch('deleteModal/close');
......@@ -64,8 +69,10 @@ export const deleteRuleError = () => {
createFlash(__('An error occurred while deleting the approvers group'));
};
export const deleteRule = ({ dispatch }, id) =>
service
.deleteProjectApprovalRule(id)
export const deleteRule = ({ state, dispatch }, id) => {
const { projectId } = state.settings;
return Api.deleteProjectApprovalRule(projectId, id)
.then(() => dispatch('deleteRuleSuccess'))
.catch(() => dispatch('deleteRuleError'));
};
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import Api from 'ee/api';
import { TEST_HOST } from 'spec/test_constants';
const TEST_API_VERSION = 'v3000';
const TEST_PROJECT_ID = 17;
const TEST_RULE_ID = 22;
describe('EE Api', () => {
let originalGon;
let mock;
beforeEach(() => {
mock = new MockAdapter(axios);
originalGon = window.gon;
window.gon = {
api_version: TEST_API_VERSION,
relative_url_root: TEST_HOST,
};
});
afterEach(() => {
mock.restore();
window.gon = originalGon;
});
describe('getProjectApprovalRules', () => {
it('gets with projectApprovalRulesPath', done => {
const expectedData = { rules: [] };
const expectedUrl = `${TEST_HOST}${Api.projectApprovalRulesPath}`
.replace(':version', TEST_API_VERSION)
.replace(':id', TEST_PROJECT_ID);
mock.onGet(expectedUrl).reply(200, expectedData);
Api.getProjectApprovalRules(TEST_PROJECT_ID)
.then(response => {
expect(response.data).toEqual(expectedData);
})
.then(done)
.catch(done.fail);
});
});
describe('postProjectApprovalRule', () => {
it('posts with projectApprovalRulesPath', done => {
const expectedUrl = `${TEST_HOST}${Api.projectApprovalRulesPath}`
.replace(':version', TEST_API_VERSION)
.replace(':id', TEST_PROJECT_ID);
mock.onPost(expectedUrl).reply(200);
Api.postProjectApprovalRule(TEST_PROJECT_ID)
.then(done)
.catch(done.fail);
});
});
describe('putProjectApprovalRule', () => {
it('puts with projectApprovalRulePath', done => {
const rule = { name: 'Lorem' };
const expectedUrl = `${TEST_HOST}${Api.projectApprovalRulePath}`
.replace(':version', TEST_API_VERSION)
.replace(':id', TEST_PROJECT_ID)
.replace(':ruleid', TEST_RULE_ID);
mock.onPut(expectedUrl).reply(200);
Api.putProjectApprovalRule(TEST_PROJECT_ID, TEST_RULE_ID, rule)
.then(() => {
expect(mock.history.put.length).toBe(1);
expect(mock.history.put[0].data).toBe(JSON.stringify(rule));
})
.then(done)
.catch(done.fail);
});
});
describe('deleteProjectApprovalRule', () => {
it('deletes with projectApprovalRulePath', done => {
const expectedUrl = `${TEST_HOST}${Api.projectApprovalRulePath}`
.replace(':version', TEST_API_VERSION)
.replace(':id', TEST_PROJECT_ID)
.replace(':ruleid', TEST_RULE_ID);
mock.onDelete(expectedUrl).reply(200);
Api.deleteProjectApprovalRule(TEST_PROJECT_ID, TEST_RULE_ID)
.then(done)
.catch(done.fail);
});
});
});
import Api from 'ee/api';
import testAction from 'spec/helpers/vuex_action_helper';
import * as types from 'ee/approvals/stores/mutation_types';
import actionsModule, * as actions from 'ee/approvals/stores/actions';
import service from 'ee/approvals/services/approvals_service_stub';
import { mapApprovalRuleRequest, mapApprovalRulesResponse } from 'ee/approvals/mappers';
const TEST_PROJECT_ID = 9;
const TEST_RULE_ID = 7;
const TEST_RULE_REQUEST = {
name: 'Lorem',
......@@ -21,14 +22,18 @@ const TEST_RULE_RESPONSE = {
};
describe('EE approvals store actions', () => {
let state;
let flashSpy;
beforeEach(() => {
state = {
settings: { projectId: TEST_PROJECT_ID },
};
flashSpy = spyOnDependency(actionsModule, 'createFlash');
spyOn(service, 'getProjectApprovalRules');
spyOn(service, 'postProjectApprovalRule');
spyOn(service, 'putProjectApprovalRule');
spyOn(service, 'deleteProjectApprovalRule');
spyOn(Api, 'getProjectApprovalRules');
spyOn(Api, 'postProjectApprovalRule');
spyOn(Api, 'putProjectApprovalRule');
spyOn(Api, 'deleteProjectApprovalRule');
});
describe('setSettings', () => {
......@@ -94,28 +99,32 @@ describe('EE approvals store actions', () => {
const response = {
data: { rules: [TEST_RULE_RESPONSE] },
};
service.getProjectApprovalRules.and.returnValue(Promise.resolve(response));
Api.getProjectApprovalRules.and.returnValue(Promise.resolve(response));
testAction(
actions.fetchRules,
null,
{},
state,
[],
[
{ type: 'requestRules' },
{ type: 'receiveRulesSuccess', payload: mapApprovalRulesResponse(response.data) },
],
done,
() => {
expect(Api.getProjectApprovalRules).toHaveBeenCalledWith(TEST_PROJECT_ID);
done();
},
);
});
it('dispatches request/receive on error', done => {
service.getProjectApprovalRules.and.returnValue(Promise.reject());
Api.getProjectApprovalRules.and.returnValue(Promise.reject());
testAction(
actions.fetchRules,
null,
{},
state,
[],
[{ type: 'requestRules' }, { type: 'receiveRulesError' }],
done,
......@@ -148,53 +157,73 @@ describe('EE approvals store actions', () => {
describe('postRule', () => {
it('dispatches success on success', done => {
service.postProjectApprovalRule.and.callFake(data => {
expect(data).toEqual(mapApprovalRuleRequest(TEST_RULE_REQUEST));
return Promise.resolve();
});
Api.postProjectApprovalRule.and.returnValue(Promise.resolve());
testAction(actions.postRule, TEST_RULE_REQUEST, {}, [], [{ type: 'postRuleSuccess' }], done);
testAction(
actions.postRule,
TEST_RULE_REQUEST,
state,
[],
[{ type: 'postRuleSuccess' }],
() => {
expect(Api.postProjectApprovalRule).toHaveBeenCalledWith(
TEST_PROJECT_ID,
mapApprovalRuleRequest(TEST_RULE_REQUEST),
);
done();
},
);
});
it('dispatches error on error', done => {
service.postProjectApprovalRule.and.callFake(data => {
expect(data).toEqual(mapApprovalRuleRequest(TEST_RULE_REQUEST));
return Promise.reject();
});
Api.postProjectApprovalRule.and.returnValue(Promise.reject());
testAction(actions.postRule, TEST_RULE_REQUEST, {}, [], [{ type: 'postRuleError' }], done);
testAction(
actions.postRule,
TEST_RULE_REQUEST,
state,
[],
[{ type: 'postRuleError' }],
() => {
expect(Api.postProjectApprovalRule).toHaveBeenCalledWith(
TEST_PROJECT_ID,
mapApprovalRuleRequest(TEST_RULE_REQUEST),
);
done();
},
);
});
});
describe('putRule', () => {
it('dispatches success on success', done => {
service.putProjectApprovalRule.and.callFake((id, data) => {
expect(id).toBe(TEST_RULE_ID);
expect(data).toEqual(mapApprovalRuleRequest(TEST_RULE_REQUEST));
return Promise.resolve();
});
Api.putProjectApprovalRule.and.returnValue(Promise.resolve());
testAction(
actions.putRule,
{ id: TEST_RULE_ID, ...TEST_RULE_REQUEST },
{},
state,
[],
[{ type: 'postRuleSuccess' }],
done,
() => {
expect(Api.putProjectApprovalRule).toHaveBeenCalledWith(
TEST_PROJECT_ID,
TEST_RULE_ID,
mapApprovalRuleRequest(TEST_RULE_REQUEST),
);
done();
},
);
});
it('dispatches error on error', done => {
service.putProjectApprovalRule.and.callFake((id, data) => {
expect(id).toBe(TEST_RULE_ID);
expect(data).toEqual(mapApprovalRuleRequest(TEST_RULE_REQUEST));
return Promise.reject();
});
Api.putProjectApprovalRule.and.returnValue(Promise.reject());
testAction(
actions.putRule,
{ id: TEST_RULE_ID, ...TEST_RULE_REQUEST },
{},
state,
[],
[{ type: 'postRuleError' }],
done,
......@@ -227,21 +256,26 @@ describe('EE approvals store actions', () => {
describe('deleteRule', () => {
it('dispatches success on success', done => {
service.deleteProjectApprovalRule.and.callFake(id => {
expect(id).toBe(TEST_RULE_ID);
return Promise.resolve();
});
Api.deleteProjectApprovalRule.and.returnValue(Promise.resolve());
testAction(actions.deleteRule, TEST_RULE_ID, {}, [], [{ type: 'deleteRuleSuccess' }], done);
testAction(
actions.deleteRule,
TEST_RULE_ID,
state,
[],
[{ type: 'deleteRuleSuccess' }],
() => {
expect(Api.deleteProjectApprovalRule).toHaveBeenCalledWith(TEST_PROJECT_ID, TEST_RULE_ID);
done();
},
);
});
it('dispatches error on error', done => {
service.deleteProjectApprovalRule.and.callFake(id => {
expect(id).toBe(TEST_RULE_ID);
return Promise.reject();
});
Api.deleteProjectApprovalRule.and.returnValue(Promise.reject());
testAction(actions.deleteRule, TEST_RULE_ID, {}, [], [{ type: 'deleteRuleError' }], done);
testAction(actions.deleteRule, TEST_RULE_ID, state, [], [{ type: 'deleteRuleError' }], done);
});
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment