From 01debefab745b8d19bbbef3bb0c2df362fa38c7f Mon Sep 17 00:00:00 2001 From: George Lima Date: Wed, 20 Feb 2019 14:23:05 -0300 Subject: [PATCH 1/7] feat(scripts): add electron:clean-store hel --- package.json | 1 + utils/clean-electron-store.js | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 utils/clean-electron-store.js diff --git a/package.json b/package.json index 5174fc5..a70bac3 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "electron:prepare": "yarn icon:build && rm -rf dist && mkdir dist", "electron:pack": "yarn electron:prepare && electron-builder --dir", "electron:dist": "yarn electron:prepare && electron-builder", + "electron:clean-store": "electron -r @babel/register ./utils/clean-electron-store.js", "preelectron:prepare": "yarn build", "icon:build": "./node_modules/.bin/electron-icon-maker --input=build-assets/icon.png --output=./build", "docz:dev": "docz dev", diff --git a/utils/clean-electron-store.js b/utils/clean-electron-store.js new file mode 100644 index 0000000..21a72a2 --- /dev/null +++ b/utils/clean-electron-store.js @@ -0,0 +1,15 @@ +// @flow +/* eslint-disable */ +import path from 'path'; +import fs from 'fs'; +import { app } from 'electron'; + +fs.unlink(path.join(app.getPath('appData'), 'zec-react-wallet', 'config.json'), err => { + if (err) { + console.log("Couldn't remove config.json", err); + } else { + console.log('electron-store cleaned'); + } + + process.exit(0); +}); From c356ade1b3aa8c24101450c964fe630ec547b2cb Mon Sep 17 00:00:00 2001 From: George Lima Date: Wed, 20 Feb 2019 14:25:03 -0300 Subject: [PATCH 2/7] feat(transactions): save shielded txid in electron-store --- app/components/transaction-details.js | 8 +------- app/containers/dashboard.js | 4 ++-- app/containers/send.js | 1 + app/containers/transactions.js | 5 ++--- services/shielded-transactions.js | 3 +++ 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/app/components/transaction-details.js b/app/components/transaction-details.js index 6915e5e..f8b95bf 100644 --- a/app/components/transaction-details.js +++ b/app/components/transaction-details.js @@ -204,13 +204,7 @@ const Component = ({ diff --git a/app/containers/dashboard.js b/app/containers/dashboard.js index 27c8c9f..dbfd5c3 100644 --- a/app/containers/dashboard.js +++ b/app/containers/dashboard.js @@ -50,10 +50,10 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ const formattedTransactions: Array = flow([ arr => arr.map(transaction => ({ - transactionId: transaction.txid || 'N/A', + transactionId: transaction.txid, type: transaction.category, date: new Date(transaction.time * 1000).toISOString(), - address: transaction.address, + address: transaction.address || '(Shielded)', amount: Math.abs(transaction.amount), fees: transaction.fee ? new BigNumber(transaction.fee).abs().toFormat(4) : 'N/A', })), diff --git a/app/containers/send.js b/app/containers/send.js index c5d246c..a6e8f86 100644 --- a/app/containers/send.js +++ b/app/containers/send.js @@ -114,6 +114,7 @@ const mapDispatchToProps = (dispatch: Dispatch): MapDispatchToProps => ({ clearInterval(interval); if (from.startsWith('z')) { saveShieldedTransaction({ + txid: operationStatus.result.txid, category: 'send', time: Date.now() / 1000, address: '(Shielded)', diff --git a/app/containers/transactions.js b/app/containers/transactions.js index 5fefe14..12755b8 100644 --- a/app/containers/transactions.js +++ b/app/containers/transactions.js @@ -3,7 +3,6 @@ import eres from 'eres'; import { connect } from 'react-redux'; import { BigNumber } from 'bignumber.js'; -import uuidv4 from 'uuid/v4'; import { TransactionsView } from '../views/transactions'; import { @@ -65,10 +64,10 @@ const mapDispatchToProps = (dispatch: Dispatch): MapDispatchToProps => ({ ...transactions, ...listShieldedTransactions({ count, offset: shieldedTransactionsCount }), ].map(transaction => ({ - transactionId: transaction.txid ? transaction.txid : uuidv4(), + transactionId: transaction.txid, type: transaction.category, date: new Date(transaction.time * 1000).toISOString(), - address: transaction.address, + address: transaction.address || '(Shielded)', amount: new BigNumber(transaction.amount).absoluteValue().toNumber(), fees: transaction.fee ? new BigNumber(transaction.fee).abs().toFormat(4) : 'N/A', })), diff --git a/services/shielded-transactions.js b/services/shielded-transactions.js index f598b2e..1f57030 100644 --- a/services/shielded-transactions.js +++ b/services/shielded-transactions.js @@ -4,6 +4,7 @@ import electronStore from '../config/electron-store'; const STORE_KEY = 'SHIELDED_TRANSACTIONS'; type ShieldedTransaction = {| + txid: string, category: 'send' | 'receive', time: number, address: string, @@ -28,6 +29,7 @@ export const listShieldedTransactions = ( }; export const saveShieldedTransaction = ({ + txid, category, time, address, @@ -37,6 +39,7 @@ export const saveShieldedTransaction = ({ electronStore.set( STORE_KEY, listShieldedTransactions().concat({ + txid, category, time, address, From c9f39f4a2d000e374a984b3c2e3b749c7bf2de32 Mon Sep 17 00:00:00 2001 From: George Lima Date: Wed, 20 Feb 2019 14:56:35 -0300 Subject: [PATCH 3/7] test(zec-price): use got and add tests for zec-price service --- __tests__/services/zec-price.test.js | 15 +++++++++++++++ config/electron.js | 4 +--- services/zec-price.js | 21 ++++----------------- 3 files changed, 20 insertions(+), 20 deletions(-) create mode 100644 __tests__/services/zec-price.test.js diff --git a/__tests__/services/zec-price.test.js b/__tests__/services/zec-price.test.js new file mode 100644 index 0000000..3ce272f --- /dev/null +++ b/__tests__/services/zec-price.test.js @@ -0,0 +1,15 @@ +// @flow + +import getZECPrice from '../../services/zec-price'; + +describe('ZEC PRICE Services', () => { + test('should return the right value', async () => { + const response = await getZECPrice(['BRL', 'EUR', 'USD']); + + expect(response).toEqual({ + USD: expect.any(Number), + BRL: expect.any(Number), + EUR: expect.any(Number), + }); + }); +}); diff --git a/config/electron.js b/config/electron.js index 6dca7c2..550debe 100644 --- a/config/electron.js +++ b/config/electron.js @@ -65,9 +65,7 @@ const createWindow = () => { }, }); - getZecPrice().then((obj) => { - store.set('ZEC_DOLLAR_PRICE', String(obj.USD)); - }); + getZecPrice().then(({ USD }) => store.set('ZEC_DOLLAR_PRICE', String(USD))); mainWindow.setVisibleOnAllWorkspaces(true); registerDebugShortcut(app, mainWindow); diff --git a/services/zec-price.js b/services/zec-price.js index 13815da..18983b1 100644 --- a/services/zec-price.js +++ b/services/zec-price.js @@ -1,8 +1,6 @@ // @flow -/* eslint-disable import/no-extraneous-dependencies */ -// $FlowFixMe -import { net } from 'electron'; +import got from 'got'; type Payload = { [currency: string]: number, @@ -18,18 +16,7 @@ export default (currencies: string[] = ['USD']): Promise => new Promise ',', )}&api_key=${String(process.env.ZEC_PRICE_API_KEY)}`; - const request = net.request(ENDPOINT); - request.on('response', (response) => { - let data = ''; - /* eslint-disable-next-line no-return-assign */ - response.on('data', chunk => (data += chunk)); - response.on('end', () => { - try { - resolve(JSON.parse(data)); - } catch (err) { - reject(err); - } - }); - }); - request.end(); + got(ENDPOINT) + .then(response => resolve(JSON.parse(response.body))) + .catch(reject); }); From d137f8724a6003490fc54c055e38ba2f1593af26 Mon Sep 17 00:00:00 2001 From: George Lima Date: Wed, 20 Feb 2019 16:35:23 -0300 Subject: [PATCH 4/7] feat(status-pill): move status-pill to redux --- app/components/header.js | 8 +-- app/components/status-pill.js | 117 +++++++++++++++------------------ app/containers/app.js | 13 +++- app/containers/status-pill.js | 57 ++++++++++++++++ app/redux/modules/app.js | 33 ++++++++-- public/flow-coverage-badge.svg | 2 +- services/sync-status.js | 63 ------------------ 7 files changed, 154 insertions(+), 139 deletions(-) create mode 100644 app/containers/status-pill.js delete mode 100644 services/sync-status.js diff --git a/app/components/header.js b/app/components/header.js index 97b23ed..bfaa431 100644 --- a/app/components/header.js +++ b/app/components/header.js @@ -7,9 +7,7 @@ import { ZcashLogo } from './zcash-logo'; import { TextComponent } from './text'; import { Divider } from './divider'; import { RowComponent } from './row'; -import { StatusPill } from './status-pill'; - -import { withSyncStatus } from '../../services/sync-status'; +import { StatusPillContainer } from '../containers/status-pill'; const Wrapper = styled.div` height: ${props => props.theme.headerHeight}; @@ -62,8 +60,6 @@ type Props = { title: string, }; -const Status = withSyncStatus(StatusPill); - export const HeaderComponent = ({ title }: Props) => ( @@ -72,7 +68,7 @@ export const HeaderComponent = ({ title }: Props) => ( - <Status type='syncing' progress={0} /> + <StatusPillContainer /> </TitleRow> <Divider opacity={0.2} /> </TitleWrapper> diff --git a/app/components/status-pill.js b/app/components/status-pill.js index 33842cc..25c2d8d 100644 --- a/app/components/status-pill.js +++ b/app/components/status-pill.js @@ -2,11 +2,9 @@ import React, { PureComponent } from 'react'; import styled, { keyframes, withTheme } from 'styled-components'; -import eres from 'eres'; import { TextComponent } from './text'; -import rpc from '../../services/api'; import { DARK } from '../constants/themes'; import readyIconDark from '../assets/images/green_check_dark.png'; @@ -16,6 +14,8 @@ import syncIconLight from '../assets/images/sync_icon_light.png'; import errorIconDark from '../assets/images/error_icon_dark.png'; import errorIconLight from '../assets/images/error_icon_light.png'; +import type { MapDispatchToProps, MapStateToProps } from '../containers/status-pill'; + const rotate = keyframes` from { transform: rotate(0deg); @@ -55,94 +55,85 @@ const StatusPillLabel = styled(TextComponent)` type Props = { theme: AppTheme, -}; +} & MapStateToProps & + MapDispatchToProps; -type State = { - type: string, - icon: string, - progress: number, - isSyncing: boolean, -}; +const MINUTE_IN_MILI = 60000; -class Component extends PureComponent<Props, State> { +class Component extends PureComponent<Props> { timer: ?IntervalID = null; - constructor(props: Props) { - super(props); + componentDidMount() { + const { getBlockchainStatus } = this.props; - const { theme } = props; - - const syncIcon = theme.mode === DARK - ? syncIconDark - : syncIconLight; - - this.state = { - type: 'syncing', - icon: syncIcon, - progress: 0, - isSyncing: true, - }; + this.timer = setInterval(() => getBlockchainStatus(), 2000); } - componentDidMount() { - this.timer = setInterval(() => { - this.getBlockchainStatus(); - }, 2000); + componentDidUpdate(prevProps: Props) { + const { getBlockchainStatus, nodeSyncType } = this.props; + if (prevProps.nodeSyncType === 'syncing' && nodeSyncType === 'ready') { + // if the status is "ready", we can increase the interval to avoid useless rpc calls + this.cleanUpdateInterval(); + this.timer = setInterval(() => getBlockchainStatus(), MINUTE_IN_MILI); + } } componentWillUnmount() { + this.cleanUpdateInterval(); + } + + cleanUpdateInterval = () => { if (this.timer) { clearInterval(this.timer); this.timer = null; } - } + }; - getBlockchainStatus = async () => { + isSyncing = () => { + const { nodeSyncType } = this.props; + return nodeSyncType === 'syncing'; + }; + + getReadyIcon = () => { const { theme } = this.props; + return theme.mode === DARK ? readyIconDark : readyIconLight; + }; - const readyIcon = theme.mode === DARK - ? readyIconDark - : readyIconLight; - const errorIcon = theme.mode === DARK - ? errorIconDark - : errorIconLight; + getErrorIcon = () => { + const { theme } = this.props; + return theme.mode === DARK ? errorIconDark : errorIconLight; + }; - const [blockchainErr, blockchaininfo] = await eres(rpc.getblockchaininfo()); + getSyncingIcon = () => { + const { theme } = this.props; + return theme.mode === DARK ? syncIconDark : syncIconLight; + }; - if (blockchainErr || !blockchaininfo) return; + getIcon = () => { + const { nodeSyncType } = this.props; - const newProgress = blockchaininfo.verificationprogress * 100; - - this.setState({ - progress: newProgress, - ...(newProgress > 99.99 - ? { - type: 'ready', - icon: readyIcon, - isSyncing: false, - } - : {}), - }); - - if (blockchainErr) { - this.setState(() => ({ - type: 'error', - icon: errorIcon, - })); + switch (nodeSyncType) { + case 'syncing': + return this.getSyncingIcon(); + case 'ready': + return this.getReadyIcon(); + case 'error': + return this.getErrorIcon(); + default: + return null; } }; render() { - const { - type, icon, progress, isSyncing, - } = this.state; - const showPercent = isSyncing ? `(${progress.toFixed(2)}%)` : ''; - const typeText = type === 'ready' ? 'Synced' : type; + const icon = this.getIcon(); + const { nodeSyncType, nodeSyncProgress } = this.props; + const percent = nodeSyncType === 'syncing' ? `(${nodeSyncProgress.toFixed(2)}%)` : ''; + const typeText = nodeSyncType === 'ready' ? 'Synced' : nodeSyncType; return ( <Wrapper id='status-pill'> - <Icon src={icon} animated={isSyncing} /> - <StatusPillLabel value={`${typeText} ${showPercent}`} /> + {icon && <Icon src={icon} animated={this.isSyncing()} />} + <StatusPillLabel value={`${typeText} ${percent}`} /> </Wrapper> ); } diff --git a/app/containers/app.js b/app/containers/app.js index dd6f147..28381d2 100644 --- a/app/containers/app.js +++ b/app/containers/app.js @@ -8,12 +8,21 @@ import { LayoutComponent } from '../components/layout'; import type { Dispatch } from '../types/redux'; import type { AppState } from '../types/app-state'; -const mapStateToProps = ({ app }: AppState) => ({ +export type MapStateToProps = {| + isErrorModalVisible: boolean, + error: string | null, +|}; + +const mapStateToProps = ({ app }: AppState): MapStateToProps => ({ isErrorModalVisible: app.isErrorModalVisible, error: app.error, }); -const mapDispatchToProps = (dispatch: Dispatch) => ({ +export type MapDispatchToProps = {| + closeErrorModal: () => void, +|}; + +const mapDispatchToProps = (dispatch: Dispatch): MapDispatchToProps => ({ closeErrorModal: () => dispatch(closeErrorModal()), }); diff --git a/app/containers/status-pill.js b/app/containers/status-pill.js new file mode 100644 index 0000000..e98d50c --- /dev/null +++ b/app/containers/status-pill.js @@ -0,0 +1,57 @@ +// @flow + +import { connect } from 'react-redux'; +import eres from 'eres'; +import { BigNumber } from 'bignumber.js'; +import { updateNodeSyncStatus } from '../redux/modules/app'; + +import { StatusPill } from '../components/status-pill'; + +import rpc from '../../services/api'; + +import type { Dispatch } from '../types/redux'; +import type { AppState } from '../types/app-state'; + +export type MapStateToProps = {| + nodeSyncProgress: number, + nodeSyncType: 'ready' | 'syncing' | 'error', +|}; + +const mapStateToProps = ({ app }: AppState): MapStateToProps => ({ + nodeSyncProgress: app.nodeSyncProgress, + nodeSyncType: app.nodeSyncType, +}); + +export type MapDispatchToProps = {| + getBlockchainStatus: () => Promise<void>, +|}; + +const mapDispatchToProps = (dispatch: Dispatch): MapDispatchToProps => ({ + getBlockchainStatus: async () => { + const [blockchainErr, blockchaininfo] = await eres(rpc.getblockchaininfo()); + + if (blockchainErr || !blockchaininfo) { + return dispatch( + updateNodeSyncStatus({ + nodeSyncProgress: 0, + nodeSyncType: 'error', + }), + ); + } + + const newProgress = blockchaininfo.verificationprogress * 100; + + dispatch( + updateNodeSyncStatus({ + nodeSyncProgress: newProgress, + nodeSyncType: new BigNumber(newProgress).gt(99.99) ? 'ready' : 'syncing', + }), + ); + }, +}); + +// $FlowFixMe +export const StatusPillContainer = connect( + mapStateToProps, + mapDispatchToProps, +)(StatusPill); diff --git a/app/redux/modules/app.js b/app/redux/modules/app.js index f8d8495..f704ef1 100644 --- a/app/redux/modules/app.js +++ b/app/redux/modules/app.js @@ -2,9 +2,17 @@ import type { Action } from '../../types/redux'; +export type State = {| + isErrorModalVisible: boolean, + error: string | null, + nodeSyncProgress: number, + nodeSyncType: 'ready' | 'syncing' | 'error', +|}; + // Actions export const SHOW_ERROR_MODAL = 'SHOW_ERROR_MODAL'; export const HIDE_ERROR_MODAL = 'HIDE_ERROR_MODAL'; +export const UPDATE_NODE_SYNC_STATUS = 'UPDATE_NODE_SYNC_STATUS'; export const showErrorModal = ({ error }: { error: string }) => ({ type: SHOW_ERROR_MODAL, @@ -18,14 +26,25 @@ export const closeErrorModal = () => ({ payload: {}, }); -export type State = { - isErrorModalVisible: boolean, - error: string | null, -}; +export const updateNodeSyncStatus = ({ + nodeSyncProgress, + nodeSyncType, +}: { + nodeSyncProgress: number, + nodeSyncType: $PropertyType<State, 'nodeSyncType'>, +}) => ({ + type: UPDATE_NODE_SYNC_STATUS, + payload: { + nodeSyncProgress, + nodeSyncType, + }, +}); const initialState: State = { isErrorModalVisible: false, error: null, + nodeSyncProgress: 0, + nodeSyncType: 'syncing', }; // eslint-disable-next-line @@ -35,6 +54,12 @@ export default (state: State = initialState, action: Action) => { return { isErrorModalVisible: true, error: action.payload.error }; case HIDE_ERROR_MODAL: return { isErrorModalVisible: false, error: null }; + case UPDATE_NODE_SYNC_STATUS: + return { + ...state, + nodeSyncProgress: action.payload.nodeSyncProgress, + nodeSyncType: action.payload.nodeSyncType, + }; default: return state; } diff --git a/public/flow-coverage-badge.svg b/public/flow-coverage-badge.svg index f5dabfe..b36be62 100644 --- a/public/flow-coverage-badge.svg +++ b/public/flow-coverage-badge.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="125" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><mask id="a"><rect width="125" height="20" rx="3" fill="#fff"/></mask><g mask="url(#a)"><path fill="#555" d="M0 0h91v20H0z"/><path fill="#4C1" d="M91 0h34v20H91z"/><path fill="url(#b)" d="M0 0h125v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,DejaVu Sans,Geneva,sans-serif" font-size="11"><text x="45.5" y="15" fill="#010101" fill-opacity=".3">flow-coverage</text><text x="45.5" y="14">flow-coverage</text><text x="107" y="15" fill="#010101" fill-opacity=".3">89%</text><text x="107" y="14">89%</text></g></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" width="125" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><mask id="a"><rect width="125" height="20" rx="3" fill="#fff"/></mask><g mask="url(#a)"><path fill="#555" d="M0 0h91v20H0z"/><path fill="#4C1" d="M91 0h34v20H91z"/><path fill="url(#b)" d="M0 0h125v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,DejaVu Sans,Geneva,sans-serif" font-size="11"><text x="45.5" y="15" fill="#010101" fill-opacity=".3">flow-coverage</text><text x="45.5" y="14">flow-coverage</text><text x="107" y="15" fill="#010101" fill-opacity=".3">88%</text><text x="107" y="14">88%</text></g></svg> \ No newline at end of file diff --git a/services/sync-status.js b/services/sync-status.js deleted file mode 100644 index 435830f..0000000 --- a/services/sync-status.js +++ /dev/null @@ -1,63 +0,0 @@ -// @flow - -import React, { type ComponentType, Component } from 'react'; -import eres from 'eres'; - -import rpc from './api'; - -type Props = {}; - -type State = { - type?: 'syncing' | 'ready' | 'error', - progress: number, -}; - -/* eslint-disable max-len */ -export const withSyncStatus = <PassedProps: {}>( - WrappedComponent: ComponentType<PassedProps>, -): ComponentType<$Diff<PassedProps, Props>> => class extends Component<PassedProps, State> { - timer: ?IntervalID = null; - - state = { - type: 'syncing', - progress: 0, - }; - - componentDidMount() { - this.timer = setInterval(() => { - this.getBlockchainStatus(); - }, 2000); - } - - componentWillUnmount() { - if (this.timer) { - clearInterval(this.timer); - this.timer = null; - } - } - - getBlockchainStatus = async () => { - const [blockchainErr, blockchaininfo] = await eres( - rpc.getblockchaininfo(), - ); - - const newProgress = blockchaininfo.verificationprogress * 100; - - this.setState({ - progress: newProgress, - ...(newProgress > 99.99 ? { - type: 'ready', - } : {}), - }); - - if (blockchainErr) { - this.setState(() => ({ type: 'error' })); - } - } - - render() { - const { type, progress } = this.state; - - return <WrappedComponent {...this.props} {...this.state} type={type} progress={progress} />; - } - }; From 140da1da29e3c0cb73ac1703e09d2ba3d2b4a52e Mon Sep 17 00:00:00 2001 From: George Lima <georgelima11@hotmail.com> Date: Wed, 20 Feb 2019 16:36:39 -0300 Subject: [PATCH 5/7] test: fix tests --- __mocks__/electron-is-dev.js | 5 + .../transaction-item.test.js.snap | 61 ++++++++ .../transactions-daily.test.js.snap | 130 ++++++++++++++++++ __tests__/components/status-pill.test.js | 28 ++-- __tests__/components/transaction-item.test.js | 2 +- .../components/transactions-daily.test.js | 6 +- __tests__/components/wallet-address.test.js | 8 +- 7 files changed, 218 insertions(+), 22 deletions(-) create mode 100644 __mocks__/electron-is-dev.js create mode 100644 __tests__/components/__snapshots__/transaction-item.test.js.snap create mode 100644 __tests__/components/__snapshots__/transactions-daily.test.js.snap diff --git a/__mocks__/electron-is-dev.js b/__mocks__/electron-is-dev.js new file mode 100644 index 0000000..35d4a32 --- /dev/null +++ b/__mocks__/electron-is-dev.js @@ -0,0 +1,5 @@ +module.exports = { + app: { + isPackaged: false, + }, +}; diff --git a/__tests__/components/__snapshots__/transaction-item.test.js.snap b/__tests__/components/__snapshots__/transaction-item.test.js.snap new file mode 100644 index 0000000..b6618f3 --- /dev/null +++ b/__tests__/components/__snapshots__/transaction-item.test.js.snap @@ -0,0 +1,61 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`<TransactionItem /> should render a transaction item correctly 1`] = ` +<div> + <div + class="sc-jzJRlG bgSReS sc-bdVaJa bWRfen" + id="transaction-item-a0s9dujo23j0" + > + <div + class="sc-bdVaJa eFCRqo" + > + <div + class="sc-bdVaJa eFCRqo" + > + <img + alt="Transaction Type Icon" + class="sc-cSHVUG fQARKX" + src="[object Object]" + /> + <div + class="sc-kGXeez iHFhdz sc-bwzfXH iiePXZ" + width="" + > + <p + class="sc-kAzzGY gABhMI sc-htpNat ccIOzB" + > + send + </p> + <p + class="sc-kgoBCf bfmmtg sc-htpNat pRhzD" + > + 16:31 PM + </p> + </div> + </div> + <p + class="sc-chPdSV bQobpM sc-htpNat pRhzD" + > + 12345678912345678912...9123456789 + </p> + </div> + <div + class="sc-bwzfXH jExuEg" + width="" + > + <p + class="sc-htpNat jAbxuE" + color="#FF6C6C" + > + -ZEC 0.865 + </p> + <p + class="sc-htpNat dhSLjI" + color="#5d5d65" + > + -USD $2.544 + </p> + </div> + </div> +</div> +`; diff --git a/__tests__/components/__snapshots__/transactions-daily.test.js.snap b/__tests__/components/__snapshots__/transactions-daily.test.js.snap new file mode 100644 index 0000000..017aff2 --- /dev/null +++ b/__tests__/components/__snapshots__/transactions-daily.test.js.snap @@ -0,0 +1,130 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`<TransactionDailyComponent /> render() should render user daily transactions 1`] = ` +<div> + <div + class="sc-kpOJdX inMzwo" + data-testid="TransactionsDaily" + > + <p + class="sc-ckVGcZ kFpbuU sc-htpNat pRhzD" + > + 2019-02-20T19:31:57.117Z + </p> + <div + class="sc-dxgOiQ dHRuWE" + > + <div + class="sc-jzJRlG bgSReS sc-bdVaJa bWRfen" + id="transaction-item-s0a8das098fgh2348a" + > + <div + class="sc-bdVaJa eFCRqo" + > + <div + class="sc-bdVaJa eFCRqo" + > + <img + alt="Transaction Type Icon" + class="sc-cSHVUG fQARKX" + src="[object Object]" + /> + <div + class="sc-kGXeez iHFhdz sc-bwzfXH iiePXZ" + width="" + > + <p + class="sc-kAzzGY edxhBx sc-htpNat ccIOzB" + > + receive + </p> + <p + class="sc-kgoBCf bfmmtg sc-htpNat pRhzD" + > + 16:31 PM + </p> + </div> + </div> + <p + class="sc-chPdSV bQobpM sc-htpNat pRhzD" + > + 12345678912345678912...9123456789 + </p> + </div> + <div + class="sc-bwzfXH jExuEg" + width="" + > + <p + class="sc-htpNat dztgbW" + color="#6AEAC0" + > + +ZEC 1.789 + </p> + <p + class="sc-htpNat dhSLjI" + color="#5d5d65" + > + +USD $2.406 + </p> + </div> + </div> + <div + class="sc-jzJRlG bgSReS sc-bdVaJa bWRfen" + id="transaction-item-0asd908fgj90f01" + > + <div + class="sc-bdVaJa eFCRqo" + > + <div + class="sc-bdVaJa eFCRqo" + > + <img + alt="Transaction Type Icon" + class="sc-cSHVUG fQARKX" + src="[object Object]" + /> + <div + class="sc-kGXeez iHFhdz sc-bwzfXH iiePXZ" + width="" + > + <p + class="sc-kAzzGY gABhMI sc-htpNat ccIOzB" + > + send + </p> + <p + class="sc-kgoBCf bfmmtg sc-htpNat pRhzD" + > + 16:31 PM + </p> + </div> + </div> + <p + class="sc-chPdSV bQobpM sc-htpNat pRhzD" + > + 12345678912345678912...9123456789 + </p> + </div> + <div + class="sc-bwzfXH jExuEg" + width="" + > + <p + class="sc-htpNat jAbxuE" + color="#FF6C6C" + > + -ZEC 0.846 + </p> + <p + class="sc-htpNat dhSLjI" + color="#5d5d65" + > + -USD $1.138 + </p> + </div> + </div> + </div> + </div> +</div> +`; diff --git a/__tests__/components/status-pill.test.js b/__tests__/components/status-pill.test.js index 83250ea..ea690e7 100644 --- a/__tests__/components/status-pill.test.js +++ b/__tests__/components/status-pill.test.js @@ -11,20 +11,14 @@ import { appTheme } from '../../app/theme'; afterEach(cleanup); describe('<StatusPill />', () => { - test('should render status pill correctly', () => { - const { queryByTestId } = render( - <ThemeProvider theme={appTheme}> - <StatusPill progress={83.0} type='syncing' /> - </ThemeProvider>, - ); - - expect(queryByTestId('StatusPill')).toBeInTheDocument(); - }); - test('should show percentage on status pill syncing', () => { const { container } = render( <ThemeProvider theme={appTheme}> - <StatusPill progress={56.0} type='syncing' /> + <StatusPill + getBlockchainStatus={() => Promise.resolve()} + nodeSyncProgress={56.0} + nodeSyncType='syncing' + /> </ThemeProvider>, ); @@ -34,7 +28,11 @@ describe('<StatusPill />', () => { test('should hide percentage on status pill', () => { const { container } = render( <ThemeProvider theme={appTheme}> - <StatusPill progress={100.0} type='ready' /> + <StatusPill + getBlockchainStatus={() => Promise.resolve()} + nodeSyncProgress={100.0} + nodeSyncType='ready' + /> </ThemeProvider>, ); @@ -44,7 +42,11 @@ describe('<StatusPill />', () => { test('should show error string and hide percentage on status pill', () => { const { container } = render( <ThemeProvider theme={appTheme}> - <StatusPill progress={0.0} type='error' /> + <StatusPill + getBlockchainStatus={() => Promise.resolve()} + nodeSyncProgress={0.0} + nodeSyncType='error' + /> </ThemeProvider>, ); diff --git a/__tests__/components/transaction-item.test.js b/__tests__/components/transaction-item.test.js index 44ff1ed..4f23fe4 100644 --- a/__tests__/components/transaction-item.test.js +++ b/__tests__/components/transaction-item.test.js @@ -19,7 +19,7 @@ describe('<TransactionItem />', () => { address='123456789123456789123456789123456789' transactionId='a0s9dujo23j0' amount={0.8652} - date={new Date().toISOString()} + date='2019-02-20T19:31:57.117Z' zecPrice={2.94} fees={0.0001} /> diff --git a/__tests__/components/transactions-daily.test.js b/__tests__/components/transactions-daily.test.js index 44f768f..3a5fc8d 100644 --- a/__tests__/components/transactions-daily.test.js +++ b/__tests__/components/transactions-daily.test.js @@ -16,7 +16,7 @@ describe('<TransactionDailyComponent />', () => { const { container } = render( <ThemeProvider theme={appTheme}> <TransactionDailyComponent - transactionsDate={new Date().toISOString()} + transactionsDate='2019-02-20T19:31:57.117Z' zecPrice={1.345} transactions={[ { @@ -25,7 +25,7 @@ describe('<TransactionDailyComponent />', () => { address: '123456789123456789123456789123456789', amount: 1.7891, zecPrice: 1.345, - date: new Date().toISOString(), + date: '2019-02-20T19:31:57.117Z', theme: appTheme, fees: 0.001, }, @@ -35,7 +35,7 @@ describe('<TransactionDailyComponent />', () => { address: '123456789123456789123456789123456789', amount: 0.8458, zecPrice: 1.344, - date: new Date().toISOString(), + date: '2019-02-20T19:31:57.117Z', theme: appTheme, fees: 0.001, }, diff --git a/__tests__/components/wallet-address.test.js b/__tests__/components/wallet-address.test.js index 9940fe9..c79003a 100644 --- a/__tests__/components/wallet-address.test.js +++ b/__tests__/components/wallet-address.test.js @@ -12,16 +12,14 @@ afterEach(cleanup); describe('<WalletAddress />', () => { test('should render wallet address component correctly', () => { - const { queryByTestId } = render( + const { getByText } = render( <ThemeProvider theme={appTheme}> <div style={{ width: '700px' }}> - <WalletAddress - address='t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1' - /> + <WalletAddress address='t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1' /> </div> </ThemeProvider>, ); - expect(queryByTestId('Address')).toBeInTheDocument(); + expect(getByText('t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1')).toBeInTheDocument(); }); }); From 77954da81a994a9ab24e815fbf7a8b7a7849b7de Mon Sep 17 00:00:00 2001 From: George Lima <georgelima11@hotmail.com> Date: Wed, 20 Feb 2019 16:40:58 -0300 Subject: [PATCH 6/7] ci(config): run unit tests --- .circleci/config.yml | 3 +++ package.json | 1 + 2 files changed, 4 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7a04354..9308fdb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,6 +13,9 @@ jobs: - run: apt-get -y install libusb-1.0-0-dev graphicsmagick libudev-dev - run: apt-get -y install tmux xvfb libxtst6 libxss1 libgtk2.0-0 libnss3 libasound2 libgconf-2-4 ffmpeg frei0r-plugins - run: yarn install + - run: + name: Run Unit Tests + command: yarn test:unit - run: name: Run Webpack command: yarn dev diff --git a/package.json b/package.json index a70bac3..89d9284 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "docz:deploy": "yarn docz:build && cd ./.docz/dist && now && now alias zec-docz.now.sh", "test": "jest --runInBand", "test:watch": "jest --watch", + "test:unit": "jest --testPathIgnorePatterns=e2e --testPathIgnorePatterns=setup", "e2e:serve": "node -r @babel/register ./__tests__/setup/mockAPI.js", "e2e:run": "yarn test e2e" }, From 29486d02b5bb339efef7a5163c149ce774c3b031 Mon Sep 17 00:00:00 2001 From: George Lima <georgelima11@hotmail.com> Date: Wed, 20 Feb 2019 16:50:18 -0300 Subject: [PATCH 7/7] fix(sidebar): icon prop typo --- app/components/sidebar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/sidebar.js b/app/components/sidebar.js index c756926..6b3d1a6 100644 --- a/app/components/sidebar.js +++ b/app/components/sidebar.js @@ -99,7 +99,7 @@ export const Component = ({ <Icon isActive={isActive} src={item.icon(isActive, theme.mode)} - Alt={`${item.route}`} + alt={`${item.route}`} /> {item.label} </StyledLink>