diff --git a/scm-ui-components/packages/ui-types/src/IndexResources.js b/scm-ui-components/packages/ui-types/src/IndexResources.js new file mode 100644 index 0000000000..59cd4005da --- /dev/null +++ b/scm-ui-components/packages/ui-types/src/IndexResources.js @@ -0,0 +1,7 @@ +//@flow +import type { Links } from "./hal"; + +export type IndexResources = { + version: String, + _links: Links +}; diff --git a/scm-ui-components/packages/ui-types/src/index.js b/scm-ui-components/packages/ui-types/src/index.js index 109fb9bb6a..89f6a40ea4 100644 --- a/scm-ui-components/packages/ui-types/src/index.js +++ b/scm-ui-components/packages/ui-types/src/index.js @@ -10,3 +10,5 @@ export type { Repository, RepositoryCollection, RepositoryGroup } from "./Reposi export type { RepositoryType, RepositoryTypeCollection } from "./RepositoryTypes"; export type { Config } from "./Config"; + +export type {IndexResources} from "./IndexResources"; diff --git a/scm-ui/src/modules/indexResource.js b/scm-ui/src/modules/indexResource.js new file mode 100644 index 0000000000..0e4b4e3cd0 --- /dev/null +++ b/scm-ui/src/modules/indexResource.js @@ -0,0 +1,55 @@ +// @flow +import * as types from "./types"; + +import { apiClient } from "@scm-manager/ui-components"; +import type { Action, IndexResources } from "@scm-manager/ui-types"; + +// Action + +export const FETCH_INDEXRESOURCES = "scm/indexResource"; +export const FETCH_INDEXRESOURCES_PENDING = `${FETCH_INDEXRESOURCES}_${ + types.PENDING_SUFFIX +}`; +export const FETCH_INDEXRESOURCES_SUCCESS = `${FETCH_INDEXRESOURCES}_${ + types.SUCCESS_SUFFIX +}`; +export const FETCH_INDEXRESOURCES_FAILURE = `${FETCH_INDEXRESOURCES}_${ + types.FAILURE_SUFFIX +}`; + +const INDEX_RESOURCES_LINK = "/"; + +export function fetchIndexResources() { + return function(dispatch: any) { + dispatch(fetchIndexResourcesPending()); + return apiClient + .get(INDEX_RESOURCES_LINK) + .then(response => response.json()) + .then(resources => { + dispatch(fetchIndexResourcesSuccess(resources)); + }) + .catch(err => { + dispatch(fetchIndexResourcesFailure(err)); + }); + }; +} + +export function fetchIndexResourcesPending(): Action { + return { + type: FETCH_INDEXRESOURCES_PENDING + }; +} + +export function fetchIndexResourcesSuccess(resources: IndexResources): Action { + return { + type: FETCH_INDEXRESOURCES_SUCCESS, + payload: resources + }; +} + +export function fetchIndexResourcesFailure(err: Error): Action { + return { + type: FETCH_INDEXRESOURCES_FAILURE, + payload: err + }; +} diff --git a/scm-ui/src/modules/indexResource.test.js b/scm-ui/src/modules/indexResource.test.js new file mode 100644 index 0000000000..8cc0137481 --- /dev/null +++ b/scm-ui/src/modules/indexResource.test.js @@ -0,0 +1,121 @@ +import configureMockStore from "redux-mock-store"; +import thunk from "redux-thunk"; +import fetchMock from "fetch-mock"; +import { + FETCH_INDEXRESOURCES_PENDING, + FETCH_INDEXRESOURCES_SUCCESS, + FETCH_INDEXRESOURCES_FAILURE, + fetchIndexResources +} from "./indexResource"; + +const indexResourcesUnauthenticated = { + version: "2.0.0-SNAPSHOT", + _links: { + self: { + href: "http://localhost:8081/scm/api/v2/" + }, + uiPlugins: { + href: "http://localhost:8081/scm/api/v2/ui/plugins" + }, + login: { + href: "http://localhost:8081/scm/api/v2/auth/access_token" + } + } +}; + +const indexResourcesAuthenticated = { + version: "2.0.0-SNAPSHOT", + _links: { + self: { + href: "http://localhost:8081/scm/api/v2/" + }, + uiPlugins: { + href: "http://localhost:8081/scm/api/v2/ui/plugins" + }, + me: { + href: "http://localhost:8081/scm/api/v2/me/" + }, + logout: { + href: "http://localhost:8081/scm/api/v2/auth/access_token" + }, + users: { + href: "http://localhost:8081/scm/api/v2/users/" + }, + groups: { + href: "http://localhost:8081/scm/api/v2/groups/" + }, + config: { + href: "http://localhost:8081/scm/api/v2/config" + }, + repositories: { + href: "http://localhost:8081/scm/api/v2/repositories/" + }, + hgConfig: { + href: "http://localhost:8081/scm/api/v2/config/hg" + }, + gitConfig: { + href: "http://localhost:8081/scm/api/v2/config/git" + }, + svnConfig: { + href: "http://localhost:8081/scm/api/v2/config/svn" + } + } +}; + +describe("fetch index resource", () => { + const index_url = "/api/v2/"; + const mockStore = configureMockStore([thunk]); + + afterEach(() => { + fetchMock.reset(); + fetchMock.restore(); + }); + + it("should successfully fetch index resources when unauthenticated", () => { + fetchMock.getOnce(index_url, indexResourcesUnauthenticated); + + const expectedActions = [ + { type: FETCH_INDEXRESOURCES_PENDING }, + { + type: FETCH_INDEXRESOURCES_SUCCESS, + payload: indexResourcesUnauthenticated + } + ]; + + const store = mockStore({}); + return store.dispatch(fetchIndexResources()).then(() => { + expect(store.getActions()).toEqual(expectedActions); + }); + }); + + it("should successfully fetch index resources when authenticated", () => { + fetchMock.getOnce(index_url, indexResourcesAuthenticated); + + const expectedActions = [ + { type: FETCH_INDEXRESOURCES_PENDING }, + { + type: FETCH_INDEXRESOURCES_SUCCESS, + payload: indexResourcesAuthenticated + } + ]; + + const store = mockStore({}); + return store.dispatch(fetchIndexResources()).then(() => { + expect(store.getActions()).toEqual(expectedActions); + }); + }); + + it("should dispatch FETCH_INDEX_RESOURCES_FAILURE if request fails", () => { + fetchMock.getOnce(index_url, { + status: 500 + }); + + const store = mockStore({}); + return store.dispatch(fetchIndexResources()).then(() => { + const actions = store.getActions(); + expect(actions[0].type).toEqual(FETCH_INDEXRESOURCES_PENDING); + expect(actions[1].type).toEqual(FETCH_INDEXRESOURCES_FAILURE); + expect(actions[1].payload).toBeDefined(); + }); + }); +});