Skip to content

Commit

Permalink
Merge pull request #1297 from LiskHQ/1293-move-api-calls-from-compone…
Browse files Browse the repository at this point in the history
…nt-level

Move newsFeed API call to actions - Closes #1293
  • Loading branch information
michaeltomasik authored Oct 25, 2018
2 parents b5d70db + 950fe97 commit 5329e5b
Show file tree
Hide file tree
Showing 16 changed files with 173 additions and 100 deletions.
1 change: 1 addition & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ module.exports = function (config) {
'src/store/reducers/liskService.js',
'src/actions/transactions.js',
'src/components/errorBoundary/index.js',
'src/components/request/specifyRequest.test.js',
'src/components/feedbackForm/**/*.js',
],
overrides: {
Expand Down
34 changes: 34 additions & 0 deletions src/actions/liskService.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ export const clearDataOfCurrencyGraph = () => ({
type: actionTypes.clearDataOfCurrencyGraph,
});

export const addNewsFeed = data => ({
type: actionTypes.getNewsFeed,
data,
});

export const showEmptyNewsFeedState = data => ({
type: actionTypes.showEmptyNewsFeed,
data,
});

export const addPriceTicker = data => ({
type: actionTypes.addPriceTicker,
data,
});

export const getCurrencyGraphData = step => (dispatch) => {
dispatch(clearDataOfCurrencyGraph());
liskServiceApi.getCurrencyGraphData(step).then((response) => {
Expand All @@ -23,3 +38,22 @@ export const getCurrencyGraphData = step => (dispatch) => {
dispatch(addErrorToCurrencyGraph(error));
});
};

export const getNewsFeed = () => (dispatch) => {
liskServiceApi.getNewsFeed().then((newsFeed) => {
dispatch(addNewsFeed(newsFeed));
}).catch((error) => {
dispatch(addNewsFeed(error));
}).finally(() => {
// To prevent dispalying empty View before fetching data
dispatch(showEmptyNewsFeedState({ showNewsFeedEmptyState: true }));
});
};

export const getPriceTicker = () => (dispatch) => {
liskServiceApi.getPriceTicker().then((response) => {
dispatch(addPriceTicker({ ...response }));
}).catch((error) => {
dispatch(addPriceTicker({ error }));
});
};
15 changes: 3 additions & 12 deletions src/components/converter/converter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import liskServiceApi from '../../utils/api/liskService';
import Input from '../toolbox/inputs/input';
import { fromRawLsk } from '../../utils/lsk';

Expand All @@ -19,19 +18,11 @@ class Converter extends React.Component {
};
this.fee = fees.send;

this.updateData();
}

updateData() {
liskServiceApi.getPriceTicker().then((response) => {
this.setState({ ...response });
}).catch((error) => {
this.setState({ error });
});
this.props.getPriceTicker();
}

render() {
const { LSK } = this.state;
const { LSK } = this.props.priceTicker;
const currency = this.props.settings.currency || 'USD';

let price = !!this.props.error && Number.isNaN(this.props.value) ?
Expand All @@ -46,7 +37,7 @@ class Converter extends React.Component {
theme={styles}
onChange={this.props.onChange} >
<div className={styles.convertorWrapper}>
{this.props.value !== '' && this.state.LSK[currency] ?
{this.props.value !== '' && this.props.priceTicker.LSK[currency] ?
<div className={this.props.error ? `${styles.convertorErr} convertorErr` : `${styles.convertor} convertor`}>
<div className={`${styles.convertElem}`}>
{this.props.t('ca.')}
Expand Down
49 changes: 11 additions & 38 deletions src/components/converter/converter.test.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,31 @@
import { expect } from 'chai';
import sinon from 'sinon';
import React from 'react';
import configureStore from 'redux-mock-store';
import configureMockStore from 'redux-mock-store';

import thunk from 'redux-thunk';

import { mountWithContext } from '../../../test/utils/mountHelpers';
import liskServiceApi from '../../utils/api/liskService';
import Converter from './index';

describe('Converter', () => {
let explorereApiMock;
let wrapper;
const fakeStore = configureStore();
const store = fakeStore({
settings: {},
settingsUpdated: () => {},
});

beforeEach(() => {
explorereApiMock = sinon.stub(liskServiceApi, 'getPriceTicker').returnsPromise();
});

afterEach(() => {
explorereApiMock.restore();
const store = configureMockStore([thunk])({
settings: { currency: 'USD' },
settingsUpdated: () => {},
getPriceTicker: () => {},
liskService: {},
});

it('shold render Converter component', () => {
const props = {
t: key => key,
settings: { currency: 'EUR' },
priceTicker: { LSK: { USD: 123, EUR: 12 } },
};

wrapper = mountWithContext(<Converter {...props} store={store}/>, { storeState: store });
expect(wrapper.find('Converter')).to.have.present();
});

it('should convert price to EUR from localStorage', () => {
const storeWithCurrency = fakeStore({
settings: { currency: 'USD' },
settingsUpdated: () => {},
});

const props = {
t: key => key,
value: 2,
error: false,
currency: 'USD',
};

wrapper = mountWithContext(
<Converter {...props} store={storeWithCurrency}/>,
{ storeState: storeWithCurrency },
);

explorereApiMock.resolves({ LSK: { USD: 123, EUR: 12 } });
wrapper.update();
expect(wrapper.find('.converted-price').at(0)).to.have.text('246.00 USD');
});
});

10 changes: 10 additions & 0 deletions src/components/converter/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import { connect } from 'react-redux';

import { settingsUpdated } from '../../actions/settings';
import { getPriceTicker } from '../../actions/liskService';
import Converter from './converter';

const mapStateToProps = state => ({
settings: state.settings,
priceTicker: (state.liskService && state.liskService.priceTicker) ?
state.liskService.priceTicker :
{
LSK: {
USD: '0',
EUR: '0',
},
},
});

const mapDispatchToProps = dispatch => ({
settingsUpdated: data => dispatch(settingsUpdated(data)),
getPriceTicker: () => dispatch(getPriceTicker()),
});

export default connect(
Expand Down
5 changes: 4 additions & 1 deletion src/components/converter/index.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import thunk from 'redux-thunk';
import { expect } from 'chai';
import { spy } from 'sinon';
import configureMockStore from 'redux-mock-store';
Expand All @@ -15,12 +16,14 @@ describe('ConverterHOC', () => {
const account = {};
const transactions = { pending: [] };
beforeEach(() => {
const store = configureMockStore([])({
const store = configureMockStore([thunk])({
peers,
account,
transactions,
settings: { currency: 'USD' },
settingsUpdated: () => {},
getPriceTicker: () => {},
liskService: {},
});
const props = {
t: () => {},
Expand Down
6 changes: 5 additions & 1 deletion src/components/newsFeed/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { connect } from 'react-redux';
import { translate } from 'react-i18next';
import { settingsUpdated } from '../../actions/settings';
import { getNewsFeed } from '../../actions/liskService';
import { channels } from '../../store/reducers/settings';
import NewsFeed from './newsFeed';


const mapDispatchToProps = dispatch => ({
settingsUpdated: data => dispatch(settingsUpdated(data)),
getNewsFeed: () => dispatch(getNewsFeed()),
});

const mapStateToProps = state => ({
channels: state.settings.channels || channels,
channels: (state.settings && state.settings.channels) ? state.settings.channels : channels,
newsFeed: (state.liskService && state.liskService.newsFeed) ? state.liskService.newsFeed : [],
showNewsFeedEmptyState: (state.liskService && state.liskService.showNewsFeedEmptyState) || false,
});

export default connect(
Expand Down
15 changes: 12 additions & 3 deletions src/components/newsFeed/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,24 @@ import { Provider } from 'react-redux';
import { BrowserRouter as Router } from 'react-router-dom';
import { I18nextProvider } from 'react-i18next';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

import i18n from '../../i18n';
import NewsFeed from './index';
import * as settingsActions from '../../actions/settings';

describe('NewsFeedHOC', () => {
let wrapper;
const settings = {};
const store = configureMockStore([])({
settings,
const store = configureMockStore([thunk])({
settings: {
channels: {},
},
liskService: {
newsFeed: [],
showNewsFeedEmptyState: false,
},
getNewsFeed: sinon.spy(),
settingsUpdated: sinon.spy(),
});

beforeEach(() => {
Expand Down
23 changes: 5 additions & 18 deletions src/components/newsFeed/newsFeed.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,16 @@ import News from './news';
import Box from '../box';
import { FontIcon } from '../fontIcon';
import SettingsNewsFeed from './settingsNewsFeed';
import liskServiceApi from '../../utils/api/liskService';
import logo from '../../assets/images/Lisk-Logo.svg';

class NewsFeed extends React.Component {
constructor() {
super();
constructor(props) {
super(props);
this.state = {
showSettings: false,
newsFeed: [],
showEmptyState: false, // To prevent dispalying empty View before fetching data
};
this.updateData();
}


updateData() {
liskServiceApi.getNewsFeed().then((newsFeed) => {
this.setState({ newsFeed });
}).catch((error) => {
this.setState({ error });
}).finally(() => {
this.setState({ showEmptyState: true });
});
props.getNewsFeed();
}

openSettings() {
Expand All @@ -51,7 +38,7 @@ class NewsFeed extends React.Component {
</div>);

const filteredNewsFeed =
this.state.newsFeed.filter(feed => this.props.channels[feed.source]) || [];
this.props.newsFeed.filter(feed => this.props.channels[feed.source]) || [];

return (
<Box className={`newsFeed-box ${styles.newsFeedBox}`}>
Expand All @@ -77,7 +64,7 @@ class NewsFeed extends React.Component {
{...news} />
</div>
)) : null}
{this.state.showEmptyState && filteredNewsFeed.length === 0 ?
{this.props.showNewsFeedEmptyState && filteredNewsFeed.length === 0 ?
<div className={styles.emptyNews}>
{this.props.t('No newsfeed chosen – click on edit in the top right corner to add a feed.')}
<img className={styles.liskLogo} src={logo} />
Expand Down
7 changes: 7 additions & 0 deletions src/components/newsFeed/newsFeed.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ describe('NewsFeed', () => {
const props = {
channels: { test: true },
t,
getNewsFeed: () => {},
newsFeed: [{
source: 'test',
content: '',
timestamp: '',
url: '',
}],
};
const timestampNow = 1483228800000;
const newsFeed = [
Expand Down
30 changes: 21 additions & 9 deletions src/components/request/specifyRequest.test.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
import React from 'react';
import { expect } from 'chai';
import thunk from 'redux-thunk';
import { mount } from 'enzyme';
import { spy } from 'sinon';
import { mountWithContext } from './../../../test/utils/mountHelpers';
import { Provider } from 'react-redux';
import { BrowserRouter as Router } from 'react-router-dom';
import configureMockStore from 'redux-mock-store';

import SpecifyRequest from './specifyRequest';

describe('Specify Request', () => {
let wrapper;
let props;
let storeState;

beforeEach(() => {
storeState = {
settings: {},
settingsUpdated: () => {},
const priceTicker = {
success: true,
LSK: {
USD: 1,
},
};

const context = {
storeState,
};
const store = configureMockStore([thunk])({
settings: {},
settingsUpdated: () => {},
liskService: { priceTicker },
});

props = {
t: key => key,
Expand All @@ -27,7 +35,11 @@ describe('Specify Request', () => {
prevStep: spy(),
};

wrapper = mountWithContext(<SpecifyRequest {...props} />, context);
wrapper = mount(<Provider store={store}>
<Router>
<SpecifyRequest {...props}/>
</Router>
</Provider>);
});

it('accepts valid amount', () => {
Expand Down
Loading

0 comments on commit 5329e5b

Please sign in to comment.