From a33aed3461d31e4d22a202fe1b652f52364a967d Mon Sep 17 00:00:00 2001 From: ivaosthu Date: Fri, 24 Nov 2017 08:41:36 +0100 Subject: [PATCH 1/5] Add version details to the footer. --- .../api/show-api-details-component.jsx | 30 +++++++++++++++++++ .../api/show-api-details-container.jsx | 13 ++++++++ frontend/src/component/app.jsx | 12 ++------ frontend/src/data/api.js | 13 ++++++++ frontend/src/store/api/actions.js | 24 +++++++++++++++ frontend/src/store/api/index.js | 14 +++++++++ frontend/src/store/index.js | 2 ++ 7 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 frontend/src/component/api/show-api-details-component.jsx create mode 100644 frontend/src/component/api/show-api-details-container.jsx create mode 100644 frontend/src/data/api.js create mode 100644 frontend/src/store/api/actions.js create mode 100644 frontend/src/store/api/index.js diff --git a/frontend/src/component/api/show-api-details-component.jsx b/frontend/src/component/api/show-api-details-component.jsx new file mode 100644 index 0000000000..d9c639ee8b --- /dev/null +++ b/frontend/src/component/api/show-api-details-component.jsx @@ -0,0 +1,30 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { FooterSection, FooterLinkList } from 'react-mdl'; + +export default class ShowApiDetailsComponent extends React.Component { + static propTypes = { + apiDetails: PropTypes.object.isRequired, + fetchAll: PropTypes.func.isRequired, + }; + + componentDidMount() { + this.props.fetchAll(); + } + + render() { + const version = this.props.apiDetails.version || ''; + return ( + + + + GitHub + + + A product by FINN.no + + + + ); + } +} diff --git a/frontend/src/component/api/show-api-details-container.jsx b/frontend/src/component/api/show-api-details-container.jsx new file mode 100644 index 0000000000..fccb7319ef --- /dev/null +++ b/frontend/src/component/api/show-api-details-container.jsx @@ -0,0 +1,13 @@ +import { connect } from 'react-redux'; +import ShowApiDetailsComponent from './show-api-details-component'; +import { fetchAll } from '../../store/api/actions'; + +const mapDispatchToProps = { + fetchAll, +}; + +const mapStateToProps = state => ({ + apiDetails: state.api.toJS(), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(ShowApiDetailsComponent); diff --git a/frontend/src/component/app.jsx b/frontend/src/component/app.jsx index f252587ff8..a573d253d2 100644 --- a/frontend/src/component/app.jsx +++ b/frontend/src/component/app.jsx @@ -20,6 +20,7 @@ import ErrorContainer from './error/error-container'; import UserContainer from './user/user-container'; import ShowUserContainer from './user/show-user-container'; +import ShowApiDetailsContainer from './api/show-api-details-container'; import { ScrollContainer } from 'react-router-scroll'; function replace(input, params) { @@ -193,16 +194,7 @@ export default class App extends Component { - - - - GitHub - - - A product by FINN.no - - - + diff --git a/frontend/src/data/api.js b/frontend/src/data/api.js new file mode 100644 index 0000000000..e584f14407 --- /dev/null +++ b/frontend/src/data/api.js @@ -0,0 +1,13 @@ +import { throwIfNotSuccess, headers } from './helper'; + +const URI = 'api'; + +function fetchAll() { + return fetch(URI, { headers, credentials: 'include' }) + .then(throwIfNotSuccess) + .then(response => response.json()); +} + +export default { + fetchAll, +}; diff --git a/frontend/src/store/api/actions.js b/frontend/src/store/api/actions.js new file mode 100644 index 0000000000..a8ef51b855 --- /dev/null +++ b/frontend/src/store/api/actions.js @@ -0,0 +1,24 @@ +import api from '../../data/api'; + +export const RECIEVE_API_DETAILS = 'RECIEVE_API_DETAILS'; +export const ERROR_RECIEVE_API_DETAILS = 'ERROR_RECIEVE_API_DETAILS'; + +export const RECEIVE_APPLICATION = 'RECEIVE_APPLICATION'; + +const recieveApiDetails = json => ({ + type: RECIEVE_API_DETAILS, + value: json, +}); + +const errorRecieveApiDetails = (statusCode, type = ERROR_RECIEVE_API_DETAILS) => ({ + type, + statusCode, +}); + +export function fetchAll() { + return dispatch => + api + .fetchAll() + .then(json => dispatch(recieveApiDetails(json))) + .catch(error => dispatch(errorRecieveApiDetails(error))); +} diff --git a/frontend/src/store/api/index.js b/frontend/src/store/api/index.js new file mode 100644 index 0000000000..756b8b4688 --- /dev/null +++ b/frontend/src/store/api/index.js @@ -0,0 +1,14 @@ +import { Map } from 'immutable'; +import { RECIEVE_API_DETAILS } from './actions'; + +const store = (state = new Map(), action) => { + switch (action.type) { + case RECIEVE_API_DETAILS: + state = new Map(action.value); + return state; + default: + return state; + } +}; + +export default store; diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index 0ca4a4b88f..278cea3ab9 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -9,6 +9,7 @@ import error from './error-store'; import clientInstances from './client-instance-store'; import settings from './settings'; import user from './user'; +import api from './api'; import applications from './application'; const unleashStore = combineReducers({ @@ -23,6 +24,7 @@ const unleashStore = combineReducers({ settings, user, applications, + api, }); export default unleashStore; From ff8b11af4d7aaab519c97644be814b30e8efe12c Mon Sep 17 00:00:00 2001 From: ivaosthu Date: Wed, 29 Nov 2017 09:25:32 +0100 Subject: [PATCH 2/5] Add a few snapshot tests --- frontend/src/__mocks__/react-mdl.js | 38 +++++++------- .../src/component/api/__tests__/.eslintrc | 5 ++ .../show-api-details-component-test.jsx.snap | 51 +++++++++++++++++++ .../show-api-details-component-test.jsx | 18 +++++++ .../api/show-api-details-component.jsx | 6 ++- 5 files changed, 98 insertions(+), 20 deletions(-) create mode 100644 frontend/src/component/api/__tests__/.eslintrc create mode 100644 frontend/src/component/api/__tests__/__snapshots__/show-api-details-component-test.jsx.snap create mode 100644 frontend/src/component/api/__tests__/show-api-details-component-test.jsx diff --git a/frontend/src/__mocks__/react-mdl.js b/frontend/src/__mocks__/react-mdl.js index 2deaebe0e0..9563ea7159 100644 --- a/frontend/src/__mocks__/react-mdl.js +++ b/frontend/src/__mocks__/react-mdl.js @@ -1,20 +1,22 @@ module.exports = { - Card: 'react-mdl-Card', - CardTitle: 'react-mdl-CardTitle', - CardText: 'react-mdl-CardText', - CardMenu: 'react-mdl-CardMenu', - DataTable: 'react-mdl-DataTable', - Cell: 'react-mdl-Cell', - Grid: 'react-mdl-Grid', - Icon: 'react-mdl-Icon', - IconButton: 'react-mdl-IconButton', - List: 'react-mdl-List', - ListItem: 'react-mdl-ListItem', - ListItemContent: 'react-mdl-ListItemContent', - ProgressBar: 'react-mdl-ProgressBar', - Switch: 'react-mdl-Switch', - Tab: 'react-mdl-Tab', - Tabs: 'react-mdl-Tabs', - TableHeader: 'react-mdl-TableHeader', - Textfield: 'react-mdl-Textfield', + Card: "react-mdl-Card", + CardTitle: "react-mdl-CardTitle", + CardText: "react-mdl-CardText", + CardMenu: "react-mdl-CardMenu", + DataTable: "react-mdl-DataTable", + Cell: "react-mdl-Cell", + Grid: "react-mdl-Grid", + Icon: "react-mdl-Icon", + IconButton: "react-mdl-IconButton", + List: "react-mdl-List", + ListItem: "react-mdl-ListItem", + ListItemContent: "react-mdl-ListItemContent", + ProgressBar: "react-mdl-ProgressBar", + Switch: "react-mdl-Switch", + Tab: "react-mdl-Tab", + Tabs: "react-mdl-Tabs", + TableHeader: "react-mdl-TableHeader", + Textfield: "react-mdl-Textfield", + FooterSection: "react-mdl-FooterSection", + FooterLinkList: "react-mdl-FooterLinkList" }; diff --git a/frontend/src/component/api/__tests__/.eslintrc b/frontend/src/component/api/__tests__/.eslintrc new file mode 100644 index 0000000000..eba2077219 --- /dev/null +++ b/frontend/src/component/api/__tests__/.eslintrc @@ -0,0 +1,5 @@ +{ + "env": { + "jest": true + } +} diff --git a/frontend/src/component/api/__tests__/__snapshots__/show-api-details-component-test.jsx.snap b/frontend/src/component/api/__tests__/__snapshots__/show-api-details-component-test.jsx.snap new file mode 100644 index 0000000000..3bfed09ff5 --- /dev/null +++ b/frontend/src/component/api/__tests__/__snapshots__/show-api-details-component-test.jsx.snap @@ -0,0 +1,51 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly with details 1`] = ` + + + + GitHub + + + + A product by + + FINN.no + + + +`; + +exports[`renders correctly with empty api details 1`] = ` + + + + GitHub + + + + A product by + + FINN.no + + + +`; diff --git a/frontend/src/component/api/__tests__/show-api-details-component-test.jsx b/frontend/src/component/api/__tests__/show-api-details-component-test.jsx new file mode 100644 index 0000000000..c712fff910 --- /dev/null +++ b/frontend/src/component/api/__tests__/show-api-details-component-test.jsx @@ -0,0 +1,18 @@ +import React from 'react'; + +import ShowApiDetailsComponent from '../show-api-details-component'; +import renderer from 'react-test-renderer'; + +jest.mock('react-mdl'); + +test('renders correctly with empty api details', () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); +}); + +test('renders correctly with details', () => { + const tree = renderer + .create() + .toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/frontend/src/component/api/show-api-details-component.jsx b/frontend/src/component/api/show-api-details-component.jsx index d9c639ee8b..c0c83a42ec 100644 --- a/frontend/src/component/api/show-api-details-component.jsx +++ b/frontend/src/component/api/show-api-details-component.jsx @@ -1,8 +1,8 @@ -import React from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { FooterSection, FooterLinkList } from 'react-mdl'; -export default class ShowApiDetailsComponent extends React.Component { +class ShowApiDetailsComponent extends Component { static propTypes = { apiDetails: PropTypes.object.isRequired, fetchAll: PropTypes.func.isRequired, @@ -28,3 +28,5 @@ export default class ShowApiDetailsComponent extends React.Component { ); } } + +export default ShowApiDetailsComponent; From 61f7db603dc7210c742a761f2d5a1a15c457fc87 Mon Sep 17 00:00:00 2001 From: ivaosthu Date: Wed, 29 Nov 2017 09:26:42 +0100 Subject: [PATCH 3/5] fix tests --- frontend/src/component/common/__tests__/util-test.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/component/common/__tests__/util-test.jsx b/frontend/src/component/common/__tests__/util-test.jsx index 94eab6c84b..83ad202f4f 100644 --- a/frontend/src/component/common/__tests__/util-test.jsx +++ b/frontend/src/component/common/__tests__/util-test.jsx @@ -1,7 +1,7 @@ import { formatFullDateTime } from '../util'; test('formats dates correctly', () => { - expect(formatFullDateTime(1487861809466)).toEqual('02/23/2017, 2:56:49 PM'); - expect(formatFullDateTime(1487232809466)).toEqual('02/16/2017, 8:13:29 AM'); - expect(formatFullDateTime(1477232809466)).toEqual('10/23/2016, 2:26:49 PM'); + expect(formatFullDateTime(1487861809466)).toEqual('2017-02-23 14:56:49'); + expect(formatFullDateTime(1487232809466)).toEqual('2017-02-16 08:13:29'); + expect(formatFullDateTime(1477232809466)).toEqual('2016-10-23 14:26:49'); }); From 5a15396ce4755748d4dca998c48e95a84d200c7b Mon Sep 17 00:00:00 2001 From: ivaosthu Date: Wed, 29 Nov 2017 10:01:12 +0100 Subject: [PATCH 4/5] Add reducer test --- frontend/src/__mocks__/react-mdl.js | 40 +++++++++---------- frontend/src/store/api/__tests__/.eslintrc | 5 +++ .../store/api/__tests__/api-store-tests.js | 18 +++++++++ 3 files changed, 43 insertions(+), 20 deletions(-) create mode 100644 frontend/src/store/api/__tests__/.eslintrc create mode 100644 frontend/src/store/api/__tests__/api-store-tests.js diff --git a/frontend/src/__mocks__/react-mdl.js b/frontend/src/__mocks__/react-mdl.js index 9563ea7159..04e07f153d 100644 --- a/frontend/src/__mocks__/react-mdl.js +++ b/frontend/src/__mocks__/react-mdl.js @@ -1,22 +1,22 @@ module.exports = { - Card: "react-mdl-Card", - CardTitle: "react-mdl-CardTitle", - CardText: "react-mdl-CardText", - CardMenu: "react-mdl-CardMenu", - DataTable: "react-mdl-DataTable", - Cell: "react-mdl-Cell", - Grid: "react-mdl-Grid", - Icon: "react-mdl-Icon", - IconButton: "react-mdl-IconButton", - List: "react-mdl-List", - ListItem: "react-mdl-ListItem", - ListItemContent: "react-mdl-ListItemContent", - ProgressBar: "react-mdl-ProgressBar", - Switch: "react-mdl-Switch", - Tab: "react-mdl-Tab", - Tabs: "react-mdl-Tabs", - TableHeader: "react-mdl-TableHeader", - Textfield: "react-mdl-Textfield", - FooterSection: "react-mdl-FooterSection", - FooterLinkList: "react-mdl-FooterLinkList" + Card: 'react-mdl-Card', + CardTitle: 'react-mdl-CardTitle', + CardText: 'react-mdl-CardText', + CardMenu: 'react-mdl-CardMenu', + DataTable: 'react-mdl-DataTable', + Cell: 'react-mdl-Cell', + Grid: 'react-mdl-Grid', + Icon: 'react-mdl-Icon', + IconButton: 'react-mdl-IconButton', + List: 'react-mdl-List', + ListItem: 'react-mdl-ListItem', + ListItemContent: 'react-mdl-ListItemContent', + ProgressBar: 'react-mdl-ProgressBar', + Switch: 'react-mdl-Switch', + Tab: 'react-mdl-Tab', + Tabs: 'react-mdl-Tabs', + TableHeader: 'react-mdl-TableHeader', + Textfield: 'react-mdl-Textfield', + FooterSection: 'react-mdl-FooterSection', + FooterLinkList: 'react-mdl-FooterLinkList', }; diff --git a/frontend/src/store/api/__tests__/.eslintrc b/frontend/src/store/api/__tests__/.eslintrc new file mode 100644 index 0000000000..eba2077219 --- /dev/null +++ b/frontend/src/store/api/__tests__/.eslintrc @@ -0,0 +1,5 @@ +{ + "env": { + "jest": true + } +} diff --git a/frontend/src/store/api/__tests__/api-store-tests.js b/frontend/src/store/api/__tests__/api-store-tests.js new file mode 100644 index 0000000000..93140f8d2d --- /dev/null +++ b/frontend/src/store/api/__tests__/api-store-tests.js @@ -0,0 +1,18 @@ +import apiReducer from '../index'; +import { RECIEVE_API_DETAILS } from '../actions'; + +test('should have inital state', () => { + const store = apiReducer(undefined, {}); + expect(store.toJS()).toEqual({}); +}); + +test('should have new state', () => { + const store = apiReducer(undefined, { type: RECIEVE_API_DETAILS, value: { version: '1.1.1' } }); + expect(store.toJS()).toEqual({ version: '1.1.1' }); +}); + +test('should have updated state', () => { + const inital = apiReducer(undefined, { type: RECIEVE_API_DETAILS, value: { version: '1.1.1' } }); + const store = apiReducer(inital, { type: RECIEVE_API_DETAILS, value: { version: '1.2.1' } }); + expect(store.toJS()).toEqual({ version: '1.2.1' }); +}); From 5d6d1c5e3151fcd71edecb762d1776447475bb85 Mon Sep 17 00:00:00 2001 From: ivaosthu Date: Wed, 29 Nov 2017 10:24:59 +0100 Subject: [PATCH 5/5] revert common test update --- frontend/src/component/common/__tests__/util-test.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/component/common/__tests__/util-test.jsx b/frontend/src/component/common/__tests__/util-test.jsx index 83ad202f4f..94eab6c84b 100644 --- a/frontend/src/component/common/__tests__/util-test.jsx +++ b/frontend/src/component/common/__tests__/util-test.jsx @@ -1,7 +1,7 @@ import { formatFullDateTime } from '../util'; test('formats dates correctly', () => { - expect(formatFullDateTime(1487861809466)).toEqual('2017-02-23 14:56:49'); - expect(formatFullDateTime(1487232809466)).toEqual('2017-02-16 08:13:29'); - expect(formatFullDateTime(1477232809466)).toEqual('2016-10-23 14:26:49'); + expect(formatFullDateTime(1487861809466)).toEqual('02/23/2017, 2:56:49 PM'); + expect(formatFullDateTime(1487232809466)).toEqual('02/16/2017, 8:13:29 AM'); + expect(formatFullDateTime(1477232809466)).toEqual('10/23/2016, 2:26:49 PM'); });