mirror of
https://github.com/kremalicious/blowfish.git
synced 2024-11-22 09:47:00 +01:00
provider splitup and refactor
This commit is contained in:
parent
c3edae6280
commit
2efee0ec73
16
package.json
16
package.json
@ -30,11 +30,13 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@coingecko/cryptoformat": "^0.3.4",
|
"@coingecko/cryptoformat": "^0.3.4",
|
||||||
|
"axios": "^0.19.2",
|
||||||
"electron-is-dev": "^1.1.0",
|
"electron-is-dev": "^1.1.0",
|
||||||
"electron-next": "^3.1.5",
|
"electron-next": "^3.1.5",
|
||||||
"electron-store": "^5.1.0",
|
"electron-store": "^5.1.1",
|
||||||
"ethereum-address": "^0.0.4",
|
"ethereum-address": "^0.0.4",
|
||||||
"ethereum-blockies": "github:MyEtherWallet/blockies",
|
"ethereum-blockies": "github:MyEtherWallet/blockies",
|
||||||
|
"ethjs-unit": "^0.1.6",
|
||||||
"ms": "^2.1.2",
|
"ms": "^2.1.2",
|
||||||
"shortid": "^2.2.15"
|
"shortid": "^2.2.15"
|
||||||
},
|
},
|
||||||
@ -43,15 +45,15 @@
|
|||||||
"@babel/preset-env": "^7.8.4",
|
"@babel/preset-env": "^7.8.4",
|
||||||
"@jest-runner/electron": "^2.0.3",
|
"@jest-runner/electron": "^2.0.3",
|
||||||
"@react-mock/state": "^0.1.8",
|
"@react-mock/state": "^0.1.8",
|
||||||
"@svgr/webpack": "^5.1.0",
|
"@svgr/webpack": "^5.2.0",
|
||||||
"@testing-library/jest-dom": "^5.1.1",
|
"@testing-library/jest-dom": "^5.1.1",
|
||||||
"@testing-library/react": "^9.4.0",
|
"@testing-library/react": "^9.4.1",
|
||||||
"auto-changelog": "^1.16.2",
|
"auto-changelog": "^1.16.2",
|
||||||
"babel-eslint": "^10.0.3",
|
"babel-eslint": "^10.0.3",
|
||||||
"babel-jest": "^25.1.0",
|
"babel-jest": "^25.1.0",
|
||||||
"copy": "^0.3.2",
|
"copy": "^0.3.2",
|
||||||
"cross-env": "^7.0.0",
|
"cross-env": "^7.0.0",
|
||||||
"electron": "^8.0.0",
|
"electron": "^8.0.1",
|
||||||
"electron-builder": "^22.3.2",
|
"electron-builder": "^22.3.2",
|
||||||
"electron-devtools-installer": "^2.2.4",
|
"electron-devtools-installer": "^2.2.4",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^6.8.0",
|
||||||
@ -59,14 +61,14 @@
|
|||||||
"eslint-plugin-react": "^7.18.3",
|
"eslint-plugin-react": "^7.18.3",
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "^25.1.0",
|
"jest": "^25.1.0",
|
||||||
"next": "^9.2.1",
|
"next": "^9.2.2",
|
||||||
"prettier": "^1.19.1",
|
"prettier": "^1.19.1",
|
||||||
"prettier-stylelint": "^0.4.2",
|
"prettier-stylelint": "^0.4.2",
|
||||||
"react": "^16.12.0",
|
"react": "^16.12.0",
|
||||||
"react-dom": "^16.12.0",
|
"react-dom": "^16.12.0",
|
||||||
"react-pose": "^4.0.10",
|
"react-pose": "^4.0.10",
|
||||||
"release-it": "^12.4.3",
|
"release-it": "^12.6.1",
|
||||||
"stylelint": "^13.1.0",
|
"stylelint": "^13.2.0",
|
||||||
"stylelint-config-css-modules": "^2.2.0",
|
"stylelint-config-css-modules": "^2.2.0",
|
||||||
"stylelint-config-standard": "^20.0.0"
|
"stylelint-config-standard": "^20.0.0"
|
||||||
},
|
},
|
||||||
|
@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
|
|||||||
import posed, { PoseGroup } from 'react-pose'
|
import posed, { PoseGroup } from 'react-pose'
|
||||||
import shortid from 'shortid'
|
import shortid from 'shortid'
|
||||||
import AppProvider from './store/AppProvider'
|
import AppProvider from './store/AppProvider'
|
||||||
|
import PriceProvider from './store/PriceProvider'
|
||||||
import { defaultAnimation } from './components/Animations'
|
import { defaultAnimation } from './components/Animations'
|
||||||
import Titlebar from './components/Titlebar'
|
import Titlebar from './components/Titlebar'
|
||||||
import styles from './Layout.module.css'
|
import styles from './Layout.module.css'
|
||||||
@ -11,14 +12,16 @@ const Animation = posed.div(defaultAnimation)
|
|||||||
|
|
||||||
export default function Layout({ children }) {
|
export default function Layout({ children }) {
|
||||||
return (
|
return (
|
||||||
<AppProvider>
|
<PriceProvider>
|
||||||
{process.platform === 'darwin' && <Titlebar />}
|
<AppProvider>
|
||||||
<div className={styles.app}>
|
{process.platform === 'darwin' && <Titlebar />}
|
||||||
<PoseGroup animateOnMount>
|
<div className={styles.app}>
|
||||||
<Animation key={shortid.generate()}>{children}</Animation>
|
<PoseGroup animateOnMount>
|
||||||
</PoseGroup>
|
<Animation key={shortid.generate()}>{children}</Animation>
|
||||||
</div>
|
</PoseGroup>
|
||||||
</AppProvider>
|
</div>
|
||||||
|
</AppProvider>
|
||||||
|
</PriceProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useContext } from 'react'
|
import React, { useContext } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import posed, { PoseGroup } from 'react-pose'
|
import posed, { PoseGroup } from 'react-pose'
|
||||||
import { AppContext } from '../../store/createContext'
|
import { AppContext, PriceContext } from '../../store/createContext'
|
||||||
import { cryptoFormatter } from '../../../utils'
|
import { cryptoFormatter } from '../../../utils'
|
||||||
import stylesIndex from '../../pages/index.module.css'
|
import stylesIndex from '../../pages/index.module.css'
|
||||||
import styles from './Ticker.module.css'
|
import styles from './Ticker.module.css'
|
||||||
@ -10,7 +10,7 @@ import { fadeIn } from '../Animations'
|
|||||||
const Item = posed.div(fadeIn)
|
const Item = posed.div(fadeIn)
|
||||||
|
|
||||||
const Change = ({ currency }) => {
|
const Change = ({ currency }) => {
|
||||||
const { priceChanges } = useContext(AppContext)
|
const { priceChanges } = useContext(PriceContext)
|
||||||
const isNegative = JSON.stringify(priceChanges[currency]).startsWith('-')
|
const isNegative = JSON.stringify(priceChanges[currency]).startsWith('-')
|
||||||
let classes = isNegative ? styles.negative : styles.positive
|
let classes = isNegative ? styles.negative : styles.positive
|
||||||
|
|
||||||
@ -27,13 +27,10 @@ Change.propTypes = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Items = () => {
|
const Items = () => {
|
||||||
const {
|
const { prices } = useContext(PriceContext)
|
||||||
prices,
|
const { needsConfig, currency, toggleCurrencies, accentColor } = useContext(
|
||||||
needsConfig,
|
AppContext
|
||||||
currency,
|
)
|
||||||
toggleCurrencies,
|
|
||||||
accentColor
|
|
||||||
} = useContext(AppContext)
|
|
||||||
|
|
||||||
const activeStyle = {
|
const activeStyle = {
|
||||||
backgroundColor: accentColor,
|
backgroundColor: accentColor,
|
||||||
|
@ -2,9 +2,9 @@ import React, { useEffect } from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import Router from 'next/router'
|
import Router from 'next/router'
|
||||||
// import { ipcRenderer } from 'electron'
|
// import { ipcRenderer } from 'electron'
|
||||||
|
import Layout from '../Layout'
|
||||||
|
|
||||||
import '../global.css'
|
import '../global.css'
|
||||||
import Layout from '../Layout'
|
|
||||||
|
|
||||||
export default function App({ Component, pageProps }) {
|
export default function App({ Component, pageProps }) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,120 +1,81 @@
|
|||||||
import React, { PureComponent } from 'react'
|
import React, { useContext, useState, useEffect } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import ms from 'ms'
|
import ms from 'ms'
|
||||||
// import { ipcRenderer } from 'electron'
|
// import { ipcRenderer } from 'electron'
|
||||||
import Store from 'electron-store'
|
import Store from 'electron-store'
|
||||||
import { AppContext } from './createContext'
|
import unit from 'ethjs-unit'
|
||||||
|
import { AppContext, PriceContext } from './createContext'
|
||||||
import { fetchData } from '../../utils'
|
import { fetchData } from '../../utils'
|
||||||
import { refreshInterval, conversions, oceanTokenContract } from '../../config'
|
import { refreshInterval, conversions, oceanTokenContract } from '../../config'
|
||||||
|
|
||||||
// construct initial prices Map to get consistent
|
async function getBalance(account) {
|
||||||
// order for Ticker and Touchbar
|
const json = await fetchData(
|
||||||
let pricesMap = new Map()
|
`https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=${oceanTokenContract}&address=${account}&tag=latest`
|
||||||
pricesMap.set('ocean', 1)
|
)
|
||||||
conversions.map(key => pricesMap.set(key, 0))
|
|
||||||
|
|
||||||
export default class AppProvider extends PureComponent {
|
const balance = unit.fromWei(`${json.result}`, 'ether')
|
||||||
static propTypes = {
|
return balance
|
||||||
children: PropTypes.any.isRequired
|
}
|
||||||
}
|
|
||||||
|
|
||||||
store = process.env.NODE_ENV === 'test' ? new Store() : global.store
|
export default function AppProvider({ children }) {
|
||||||
|
const { prices } = useContext(PriceContext)
|
||||||
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
|
const [accounts, setAccounts] = useState([])
|
||||||
|
const [needsConfig, setNeedsConfig] = useState(false)
|
||||||
|
const [currency, setCurrency] = useState('ocean')
|
||||||
|
const [accentColor, setAccentColor] = useState('#f6388a')
|
||||||
|
|
||||||
state = {
|
useEffect(() => {
|
||||||
isLoading: true,
|
|
||||||
accounts: [],
|
|
||||||
currency: 'ocean',
|
|
||||||
needsConfig: false,
|
|
||||||
prices: pricesMap,
|
|
||||||
priceChanges: Object.assign(
|
|
||||||
...conversions.map(key => ({
|
|
||||||
[key]: 0
|
|
||||||
}))
|
|
||||||
),
|
|
||||||
toggleCurrencies: currency => this.toggleCurrencies(currency),
|
|
||||||
setBalances: () => this.setBalances(),
|
|
||||||
accentColor: '#f6388a'
|
|
||||||
}
|
|
||||||
|
|
||||||
async componentDidMount() {
|
|
||||||
// listener for accent color
|
// listener for accent color
|
||||||
global.ipcRenderer.on('accent-color', (evt, accentColor) => {
|
global.ipcRenderer.on('accent-color', (evt, accentColor) => {
|
||||||
this.setState({ accentColor })
|
setAccentColor(accentColor)
|
||||||
})
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
// listener for touchbar
|
useEffect(() => {
|
||||||
global.ipcRenderer.on('setCurrency', (evt, currency) =>
|
async function init() {
|
||||||
this.state.toggleCurrencies(currency)
|
await setBalances()
|
||||||
)
|
setIsLoading(false)
|
||||||
|
|
||||||
const newPrizes = await this.fetchAndSetPrices()
|
// listener for touchbar
|
||||||
this.setState({ prices: newPrizes })
|
global.ipcRenderer.on('setCurrency', (evt, currency) =>
|
||||||
|
toggleCurrencies(currency)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await this.setBalances()
|
init()
|
||||||
|
setInterval(init, ms(refreshInterval))
|
||||||
|
|
||||||
setInterval(this.fetchAndSetPrices, ms(refreshInterval))
|
return () => {
|
||||||
setInterval(this.setBalances, ms(refreshInterval))
|
clearInterval(init)
|
||||||
|
}
|
||||||
|
}, [prices])
|
||||||
|
|
||||||
this.setState({ isLoading: false })
|
function getAccounts() {
|
||||||
}
|
|
||||||
|
|
||||||
getAccounts() {
|
|
||||||
let accountsPref
|
let accountsPref
|
||||||
|
const store = process.env.NODE_ENV === 'test' ? new Store() : global.store
|
||||||
|
|
||||||
if (this.store.has('accounts')) {
|
if (store.has('accounts')) {
|
||||||
accountsPref = this.store.get('accounts')
|
accountsPref = store.get('accounts')
|
||||||
|
!accountsPref.length ? setNeedsConfig(true) : setNeedsConfig(false)
|
||||||
!accountsPref.length
|
|
||||||
? this.setState({ needsConfig: true })
|
|
||||||
: this.setState({ needsConfig: false })
|
|
||||||
} else {
|
} else {
|
||||||
accountsPref = []
|
accountsPref = []
|
||||||
this.setState({ needsConfig: true })
|
setNeedsConfig(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return accountsPref
|
return accountsPref
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBalance(account) {
|
async function setBalances() {
|
||||||
const json = await fetchData(
|
|
||||||
`https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=${oceanTokenContract}&address=${account}&tag=latest`
|
|
||||||
)
|
|
||||||
|
|
||||||
const balance = json.result / 1e18 // Convert from vodka 10^18
|
|
||||||
return balance
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchAndSetPrices = async () => {
|
|
||||||
const currencies = conversions.join(',')
|
|
||||||
const json = await fetchData(
|
|
||||||
`https://api.coingecko.com/api/v3/simple/price?ids=ocean-protocol&vs_currencies=${currencies}&include_24hr_change=true`
|
|
||||||
)
|
|
||||||
|
|
||||||
let newPrices = new Map(this.state.prices) // make a shallow copy of the Map
|
|
||||||
conversions.map(key => newPrices.set(key, json['ocean-protocol'][key])) // modify the copy
|
|
||||||
|
|
||||||
const newPriceChanges = await Object.assign(
|
|
||||||
...conversions.map(key => ({
|
|
||||||
[key]: json['ocean-protocol'][key + '_24h_change']
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
|
|
||||||
global.ipcRenderer.send('prices-updated', Array.from(newPrices)) // convert Map to array, ipc messages seem to kill it
|
|
||||||
this.setState({ prices: newPrices, priceChanges: newPriceChanges })
|
|
||||||
return newPrices
|
|
||||||
}
|
|
||||||
|
|
||||||
setBalances = async () => {
|
|
||||||
const accountsPref = await this.getAccounts()
|
|
||||||
|
|
||||||
let newAccounts = []
|
let newAccounts = []
|
||||||
|
const accountsPref = await getAccounts()
|
||||||
|
|
||||||
for (const account of accountsPref) {
|
for (const account of accountsPref) {
|
||||||
const oceanBalance = await this.getBalance(account)
|
const oceanBalance = await getBalance(account)
|
||||||
|
|
||||||
const conversionsBalance = Object.assign(
|
const conversionsBalance = Object.assign(
|
||||||
...conversions.map(key => ({
|
...conversions.map(key => ({
|
||||||
[key]: oceanBalance * this.state.prices.get(key) || 0
|
[key]: oceanBalance * prices.get(key) || 0
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -129,22 +90,30 @@ export default class AppProvider extends PureComponent {
|
|||||||
newAccounts.push(newAccount)
|
newAccounts.push(newAccount)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newAccounts !== this.state.accounts) {
|
if (newAccounts !== accounts) {
|
||||||
this.setState({ accounts: newAccounts })
|
setAccounts(newAccounts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleCurrencies(currency) {
|
function toggleCurrencies(currency) {
|
||||||
const pricesNew = Array.from(this.state.prices)
|
const pricesNew = Array.from(prices)
|
||||||
global.ipcRenderer.send('currency-updated', pricesNew, currency)
|
global.ipcRenderer.send('currency-updated', pricesNew, currency)
|
||||||
this.setState({ currency })
|
setCurrency(currency)
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
const context = {
|
||||||
return (
|
isLoading,
|
||||||
<AppContext.Provider value={this.state}>
|
accounts,
|
||||||
{this.props.children}
|
currency,
|
||||||
</AppContext.Provider>
|
needsConfig,
|
||||||
)
|
accentColor,
|
||||||
|
toggleCurrencies: currency => toggleCurrencies(currency),
|
||||||
|
setBalances: () => setBalances()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return <AppContext.Provider value={context}>{children}</AppContext.Provider>
|
||||||
|
}
|
||||||
|
|
||||||
|
AppProvider.propTypes = {
|
||||||
|
children: PropTypes.any.isRequired
|
||||||
}
|
}
|
||||||
|
67
src/renderer/store/PriceProvider.jsx
Normal file
67
src/renderer/store/PriceProvider.jsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import ms from 'ms'
|
||||||
|
import { PriceContext } from './createContext'
|
||||||
|
import { fetchData } from '../../utils'
|
||||||
|
import { refreshInterval, conversions } from '../../config'
|
||||||
|
|
||||||
|
export default function PriceProvider({ children }) {
|
||||||
|
// construct initial prices Map to get consistent
|
||||||
|
// order for Ticker and Touchbar
|
||||||
|
let pricesMap = new Map()
|
||||||
|
pricesMap.set('ocean', 1)
|
||||||
|
conversions.map(key => pricesMap.set(key, 0))
|
||||||
|
|
||||||
|
const [prices, setPrices] = useState(pricesMap)
|
||||||
|
const [priceChanges, setPriceChanges] = useState(
|
||||||
|
Object.assign(
|
||||||
|
...conversions.map(key => ({
|
||||||
|
[key]: 0
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
async function fetchAndSetPrices() {
|
||||||
|
const currencies = conversions.join(',')
|
||||||
|
const json = await fetchData(
|
||||||
|
`https://api.coingecko.com/api/v3/simple/price?ids=ocean-protocol&vs_currencies=${currencies}&include_24hr_change=true`
|
||||||
|
)
|
||||||
|
|
||||||
|
let newPrices = new Map(prices) // make a shallow copy of the Map
|
||||||
|
conversions.map(key => newPrices.set(key, json['ocean-protocol'][key])) // modify the copy
|
||||||
|
|
||||||
|
const newPriceChanges = await Object.assign(
|
||||||
|
...conversions.map(key => ({
|
||||||
|
[key]: json['ocean-protocol'][key + '_24h_change']
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
|
||||||
|
return { newPrices, newPriceChanges }
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function init() {
|
||||||
|
const { newPrices, newPriceChanges } = await fetchAndSetPrices()
|
||||||
|
setPrices(newPrices)
|
||||||
|
setPriceChanges(newPriceChanges)
|
||||||
|
global.ipcRenderer.send('prices-updated', Array.from(newPrices)) // convert Map to array, ipc messages seem to kill it
|
||||||
|
}
|
||||||
|
|
||||||
|
init()
|
||||||
|
setInterval(init, ms(refreshInterval))
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearInterval(init)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PriceContext.Provider value={{ prices, priceChanges }}>
|
||||||
|
{children}
|
||||||
|
</PriceContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
PriceProvider.propTypes = {
|
||||||
|
children: PropTypes.any.isRequired
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import { createContext } from 'react'
|
import { createContext } from 'react'
|
||||||
|
|
||||||
const AppContext = createContext()
|
const AppContext = createContext()
|
||||||
|
const PriceContext = createContext()
|
||||||
|
|
||||||
export { AppContext }
|
export { AppContext, PriceContext }
|
||||||
|
12
src/utils.js
12
src/utils.js
@ -1,20 +1,18 @@
|
|||||||
const { app, shell } = require('electron')
|
const { app, shell } = require('electron')
|
||||||
const { formatCurrency } = require('@coingecko/cryptoformat')
|
const { formatCurrency } = require('@coingecko/cryptoformat')
|
||||||
|
const axios = require('axios')
|
||||||
|
|
||||||
const fetchData = async url => {
|
const fetchData = async url => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url)
|
const response = await axios(url)
|
||||||
|
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
return console.log('Non-200 response: ' + response.status) // eslint-disable-line
|
return console.error('Non-200 response: ' + response.status)
|
||||||
}
|
}
|
||||||
|
|
||||||
const json = await response.json()
|
return response.data
|
||||||
if (!json) return
|
|
||||||
|
|
||||||
return json
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('Error parsing json:' + error) // eslint-disable-line
|
console.error('Error parsing json: ' + error.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { render } from '@testing-library/react'
|
import { render, wait } from '@testing-library/react'
|
||||||
import Layout from '../src/renderer/Layout'
|
import Layout from '../src/renderer/Layout'
|
||||||
|
|
||||||
describe('Layout', () => {
|
describe('Layout', () => {
|
||||||
it('renders correctly', () => {
|
it('renders correctly', async () => {
|
||||||
const { container } = render(<Layout>Hello</Layout>)
|
const { container } = render(<Layout>Hello</Layout>)
|
||||||
|
await wait()
|
||||||
expect(container.firstChild).toBeInTheDocument()
|
expect(container.firstChild).toBeInTheDocument()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -12,7 +12,12 @@ const priceChanges = {
|
|||||||
eth: -17.538786176215627
|
eth: -17.538786176215627
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export const priceContext = {
|
||||||
|
prices,
|
||||||
|
priceChanges
|
||||||
|
}
|
||||||
|
|
||||||
|
export const appContext = {
|
||||||
accentColor: '#0a5fff',
|
accentColor: '#0a5fff',
|
||||||
accounts: [
|
accounts: [
|
||||||
{
|
{
|
||||||
@ -28,7 +33,5 @@ export default {
|
|||||||
],
|
],
|
||||||
currency: 'ocean',
|
currency: 'ocean',
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
needsConfig: false,
|
needsConfig: false
|
||||||
prices,
|
|
||||||
priceChanges
|
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,10 @@ const remote = {
|
|||||||
getCurrentWindow: jest.fn()
|
getCurrentWindow: jest.fn()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ipcRenderer = {
|
||||||
|
on: jest.fn()
|
||||||
|
}
|
||||||
|
|
||||||
// for the shell module above
|
// for the shell module above
|
||||||
const shell = {
|
const shell = {
|
||||||
openExternal: jest.fn()
|
openExternal: jest.fn()
|
||||||
@ -19,5 +23,6 @@ const shell = {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
electron,
|
electron,
|
||||||
remote,
|
remote,
|
||||||
shell
|
shell,
|
||||||
|
ipcRenderer
|
||||||
}
|
}
|
||||||
|
3
tests/__mocks__/electronStore.js
Normal file
3
tests/__mocks__/electronStore.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
has: () => jest.fn()
|
||||||
|
}
|
10
tests/__mocks__/global.js
Normal file
10
tests/__mocks__/global.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const global = {
|
||||||
|
ipcRenderer: {
|
||||||
|
on: () => jest.fn()
|
||||||
|
},
|
||||||
|
store: {
|
||||||
|
has: () => jest.fn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = global
|
@ -19,7 +19,7 @@ module.exports = {
|
|||||||
'<rootDir>/coverage'
|
'<rootDir>/coverage'
|
||||||
],
|
],
|
||||||
testURL: 'http://localhost',
|
testURL: 'http://localhost',
|
||||||
setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
|
setupFilesAfterEnv: ['<rootDir>/tests/setupTests.js'],
|
||||||
runner: '@jest-runner/electron',
|
runner: '@jest-runner/electron',
|
||||||
testEnvironment: '@jest-runner/electron/environment',
|
testEnvironment: '@jest-runner/electron/environment',
|
||||||
coverageDirectory: '../../coverage/',
|
coverageDirectory: '../../coverage/',
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { render, fireEvent } from '@testing-library/react'
|
import { render, fireEvent } from '@testing-library/react'
|
||||||
import { AppContext } from '../../src/renderer/store/createContext'
|
import {
|
||||||
import context from '../__fixtures__/context'
|
AppContext,
|
||||||
|
PriceContext
|
||||||
|
} from '../../src/renderer/store/createContext'
|
||||||
|
import { appContext, priceContext } from '../__fixtures__/context'
|
||||||
import Home from '../../src/renderer/pages/index'
|
import Home from '../../src/renderer/pages/index'
|
||||||
|
|
||||||
describe('Home', () => {
|
describe('Home', () => {
|
||||||
it('renders correctly', () => {
|
it('renders correctly', () => {
|
||||||
const { container, getByText } = render(
|
const { container, getByText } = render(
|
||||||
<AppContext.Provider value={context}>
|
<PriceContext.Provider value={priceContext}>
|
||||||
<Home />
|
<AppContext.Provider value={appContext}>
|
||||||
</AppContext.Provider>
|
<Home />
|
||||||
|
</AppContext.Provider>
|
||||||
|
</PriceContext.Provider>
|
||||||
)
|
)
|
||||||
expect(container.firstChild).toBeInTheDocument()
|
expect(container.firstChild).toBeInTheDocument()
|
||||||
fireEvent.click(getByText(/Ξ/))
|
fireEvent.click(getByText(/Ξ/))
|
||||||
@ -18,9 +23,11 @@ describe('Home', () => {
|
|||||||
|
|
||||||
it('renders Welcome without config', () => {
|
it('renders Welcome without config', () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<AppContext.Provider value={{ ...context, needsConfig: true }}>
|
<PriceContext.Provider value={priceContext}>
|
||||||
<Home />
|
<AppContext.Provider value={{ ...appContext, needsConfig: true }}>
|
||||||
</AppContext.Provider>
|
<Home />
|
||||||
|
</AppContext.Provider>
|
||||||
|
</PriceContext.Provider>
|
||||||
)
|
)
|
||||||
expect(container.firstChild).toHaveTextContent(
|
expect(container.firstChild).toHaveTextContent(
|
||||||
'Add your first address to get started.'
|
'Add your first address to get started.'
|
||||||
|
3
tests/setupTests.js
Normal file
3
tests/setupTests.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import '@testing-library/jest-dom/extend-expect'
|
||||||
|
|
||||||
|
jest.mock('electron-store')
|
Loading…
Reference in New Issue
Block a user