diff --git a/scm-ui/src/config/modules/config.js b/scm-ui/src/config/modules/config.js new file mode 100644 index 0000000000..b951d33ed3 --- /dev/null +++ b/scm-ui/src/config/modules/config.js @@ -0,0 +1,71 @@ +// @flow +import { apiClient } from "../../apiclient"; +import * as types from "../../modules/types"; +import type { Action } from "../../types/Action"; + +export const FETCH_CONFIG = "scm/groups/FETCH_CONFIG"; +export const FETCH_CONFIG_PENDING = `${FETCH_CONFIG}_${types.PENDING_SUFFIX}`; +export const FETCH_CONFIG_SUCCESS = `${FETCH_CONFIG}_${types.SUCCESS_SUFFIX}`; +export const FETCH_CONFIG_FAILURE = `${FETCH_CONFIG}_${types.FAILURE_SUFFIX}`; + +const CONFIG_URL = "config"; + +//fetch config +export function fetchConfig() { + return function(dispatch: any) { + dispatch(fetchConfigPending()); + return apiClient + .get(CONFIG_URL) + .then(response => { + return response.json(); + }) + .then(data => { + dispatch(fetchConfigSuccess(data)); + }) + .catch(cause => { + const error = new Error(`could not fetch config: ${cause.message}`); + dispatch(fetchConfigFailure(error)); + }); + }; +} + +export function fetchConfigPending(): Action { + return { + type: FETCH_CONFIG_PENDING + }; +} + +export function fetchConfigSuccess(config: any): Action { + return { + type: FETCH_CONFIG_SUCCESS, + payload: config + }; +} + +export function fetchConfigFailure(error: Error): Action { + return { + type: FETCH_CONFIG_FAILURE, + payload: { + error + } + }; +} + +//reducer + +function reducer(state: any = {}, action: any = {}) { + switch (action.type) { + case FETCH_CONFIG_SUCCESS: + return { + ...state, + config: { + entries: action.payload, + configUpdatePermission: action.payload._links.update ? true : false + } + }; + default: + return state; + } +} + +export default reducer; diff --git a/scm-ui/src/config/modules/config.test.js b/scm-ui/src/config/modules/config.test.js new file mode 100644 index 0000000000..f81df3d522 --- /dev/null +++ b/scm-ui/src/config/modules/config.test.js @@ -0,0 +1,116 @@ +//@flow +import configureMockStore from "redux-mock-store"; +import thunk from "redux-thunk"; +import fetchMock from "fetch-mock"; + +import reducer, { + FETCH_CONFIG_PENDING, + FETCH_CONFIG_SUCCESS, + FETCH_CONFIG_FAILURE, + fetchConfig, + fetchConfigSuccess +} from "./config"; + +const CONFIG_URL = "/scm/api/rest/v2/config"; + +const error = new Error("You have an error!"); + +const config = { + proxyPassword: null, + proxyPort: 8080, + proxyServer: "proxy.mydomain.com", + proxyUser: null, + enableProxy: false, + realmDescription: "SONIA :: SCM Manager", + enableRepositoryArchive: false, + disableGroupingGrid: false, + dateFormat: "YYYY-MM-DD HH:mm:ss", + anonymousAccessEnabled: false, + adminGroups: [], + adminUsers: [], + baseUrl: "http://localhost:8081/scm", + forceBaseUrl: false, + loginAttemptLimit: -1, + proxyExcludes: [], + skipFailedAuthenticators: false, + pluginUrl: + "http://plugins.scm-manager.org/scm-plugin-backend/api/{version}/plugins?os={os}&arch={arch}&snapshot=false", + loginAttemptLimitTimeout: 300, + enabledXsrfProtection: true, + defaultNamespaceStrategy: "sonia.scm.repository.DefaultNamespaceStrategy", + _links: { + self: { href: "http://localhost:8081/scm/api/rest/v2/config" }, + update: { href: "http://localhost:8081/scm/api/rest/v2/config" } + } +}; + +const responseBody = { + entries: config +}; + +const response = { + headers: { "content-type": "application/json" }, + responseBody +}; + +describe("config fetch()", () => { + const mockStore = configureMockStore([thunk]); + afterEach(() => { + fetchMock.reset(); + fetchMock.restore(); + }); + + it("should successfully fetch config", () => { + fetchMock.getOnce(CONFIG_URL, response); + + const expectedActions = [ + { type: FETCH_CONFIG_PENDING }, + { + type: FETCH_CONFIG_SUCCESS, + payload: response + } + ]; + + const store = mockStore({}); + + return store.dispatch(fetchConfig()).then(() => { + expect(store.getActions()).toEqual(expectedActions); + }); + }); + + it("should fail getting config on HTTP 500", () => { + fetchMock.getOnce(CONFIG_URL, { + status: 500 + }); + + const store = mockStore({}); + return store.dispatch(fetchConfig()).then(() => { + const actions = store.getActions(); + expect(actions[0].type).toEqual(FETCH_CONFIG_PENDING); + expect(actions[1].type).toEqual(FETCH_CONFIG_FAILURE); + expect(actions[1].payload).toBeDefined(); + }); + }); +}); + +describe("config reducer", () => { + it("should update state correctly according to FETCH_CONFIG_SUCCESS action", () => { + const newState = reducer({}, fetchConfigSuccess(config)); + + expect(newState.config).toEqual({ + entries: config, + configUpdatePermission: true + }); + }); + + it("should set configUpdatePermission to true if update link is present", () => { + const newState = reducer({}, fetchConfigSuccess(config)); + + expect(newState.config.configUpdatePermission).toBeTruthy(); + }); + + it("should update state according to FETCH_GROUP_SUCCESS action", () => { + const newState = reducer({}, fetchConfigSuccess(config)); + expect(newState.config.entries).toBe(config); + }); +});