project organisation, fix build & test runs
@ -1,10 +0,0 @@
|
||||
# EditorConfig is awesome: http://EditorConfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none"
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
const { devDependencies } = require('../../package.json')
|
||||
const { devDependencies } = require('./package.json')
|
||||
|
||||
module.exports = {
|
||||
presets: [
|
42
package.json
@ -6,17 +6,19 @@
|
||||
"main": "./src/main/index.js",
|
||||
"scripts": {
|
||||
"start": "electron .",
|
||||
"test": "npm run lint && jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test": "npm run lint && npm run jest",
|
||||
"test:watch": "npm run jest -- --watch",
|
||||
"jest": "NODE_ENV=test jest -c tests/jest.config.js",
|
||||
"lint": "eslint --ignore-path .gitignore ./src/**/*.{js,jsx} && stylelint --ignore-path .gitignore ./src/**/*.{css,scss}",
|
||||
"build:react": "next build src/renderer && next export src/renderer",
|
||||
"copy": "rsync src/renderer/images/icon* build/",
|
||||
"build:react": "next build src/renderer && next export src/renderer && npm run copy",
|
||||
"build:electron": "electron-builder build -ml -p never",
|
||||
"build:electron:win": "electron-builder build -w -p never",
|
||||
"dist": "./scripts/release-prepare.sh",
|
||||
"release": "release-it --non-interactive",
|
||||
"changelog": "auto-changelog -p",
|
||||
"format": "prettier --write 'src/**/*.{js,jsx}' && npm run format:css",
|
||||
"format:css": "prettier-stylelint --write --quiet 'src/**/*.{css,scss}'"
|
||||
"format": "prettier --write --ignore-path .gitignore 'src/**/*.{js,jsx}' && npm run format:css",
|
||||
"format:css": "prettier-stylelint --write --ignore-path .gitignore --quiet 'src/**/*.{css,scss}'"
|
||||
},
|
||||
"repository": "https://github.com/kremalicious/blowfish.git",
|
||||
"homepage": "https://github.com/kremalicious/blowfish",
|
||||
@ -28,6 +30,9 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@coingecko/cryptoformat": "^0.3.3",
|
||||
"electron-is-dev": "^1.1.0",
|
||||
"electron-next": "^3.1.5",
|
||||
"electron-store": "^5.1.0",
|
||||
"ethereum-address": "^0.0.4",
|
||||
"ethereum-blockies": "github:MyEtherWallet/blockies",
|
||||
"ms": "^2.1.2",
|
||||
@ -47,9 +52,6 @@
|
||||
"electron": "^8.0.0",
|
||||
"electron-builder": "^22.3.2",
|
||||
"electron-devtools-installer": "^2.2.4",
|
||||
"electron-is-dev": "^1.1.0",
|
||||
"electron-next": "^3.1.5",
|
||||
"electron-store": "^5.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-prettier": "^6.10.0",
|
||||
"eslint-plugin-react": "^7.18.3",
|
||||
@ -117,29 +119,5 @@
|
||||
"npm": {
|
||||
"publish": false
|
||||
}
|
||||
},
|
||||
"jest": {
|
||||
"rootDir": "src/renderer",
|
||||
"transform": {
|
||||
"^.+\\.jsx?$": "babel-jest"
|
||||
},
|
||||
"moduleNameMapper": {
|
||||
".+\\.(css|styl|less|sass|scss)$": "identity-obj-proxy",
|
||||
".+\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/jest/__mocks__/file-mock.js",
|
||||
"\\.svg": "<rootDir>/jest/__mocks__/svgr-mock.js"
|
||||
},
|
||||
"testURL": "http://localhost",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/jest/setup-test-env.js"
|
||||
],
|
||||
"coverageDirectory": "../../coverage/",
|
||||
"collectCoverage": true,
|
||||
"collectCoverageFrom": [
|
||||
"<rootDir>/**/*.{js,jsx}",
|
||||
"!<rootDir>/jest/**/*.{js,jsx}",
|
||||
"!**/node_modules/**"
|
||||
],
|
||||
"runner": "@jest-runner/electron",
|
||||
"testEnvironment": "@jest-runner/electron/environment"
|
||||
}
|
||||
}
|
||||
|
@ -36,9 +36,9 @@ const createWindow = async () => {
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
scrollBounce: true,
|
||||
enableBlinkFeatures: 'OverlayScrollbars'
|
||||
// preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { toDataUrl } from 'ethereum-blockies'
|
||||
import posed, { PoseGroup } from 'react-pose'
|
||||
import { fadeIn } from '../../Animations'
|
||||
import { fadeIn } from '../Animations'
|
||||
import styles from './Saved.module.css'
|
||||
|
||||
export default function Saved({ accounts, handleDelete }) {
|
@ -1,15 +1,15 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import ethereum_address from 'ethereum-address'
|
||||
import Store from 'electron-store'
|
||||
import { AppContext } from '../../../store/createContext'
|
||||
import { AppContext } from '../../store/createContext'
|
||||
import Saved from './Saved'
|
||||
import New from './New'
|
||||
import styles from './index.module.css'
|
||||
|
||||
export default class Accounts extends PureComponent {
|
||||
export default class AccountsList extends PureComponent {
|
||||
static contextType = AppContext
|
||||
|
||||
store = new Store()
|
||||
store = process.env.NODE_ENV === 'test' ? new Store() : global.store
|
||||
|
||||
state = { accounts: [], input: '', error: '' }
|
||||
|
@ -1,5 +1,5 @@
|
||||
.preference {
|
||||
composes: box from '../../../components/Box.module.css';
|
||||
composes: box from '../Box.module.css';
|
||||
-webkit-app-region: none;
|
||||
-webkit-user-select: text;
|
||||
}
|
@ -2,7 +2,7 @@ import React, { useContext } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import posed, { PoseGroup } from 'react-pose'
|
||||
import { AppContext } from '../store/createContext'
|
||||
import { cryptoFormatter } from '../../../utils'
|
||||
import { cryptoFormatter } from '../../utils'
|
||||
import { fadeIn } from './Animations'
|
||||
import Label from './Label'
|
||||
import styles from './Balance.module.css'
|
@ -1,5 +1,5 @@
|
||||
import React, { useContext } from 'react'
|
||||
import { openUrl } from '../../../../utils'
|
||||
import { openUrl } from '../../../utils'
|
||||
import Balance from '../Balance'
|
||||
import { AppContext } from '../../store/createContext'
|
||||
import styles from './Accounts.module.css'
|
@ -2,7 +2,7 @@ import React, { useContext } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import posed, { PoseGroup } from 'react-pose'
|
||||
import { AppContext } from '../../store/createContext'
|
||||
import { cryptoFormatter } from '../../../../utils'
|
||||
import { cryptoFormatter } from '../../../utils'
|
||||
import stylesIndex from '../../pages/index.module.css'
|
||||
import styles from './Ticker.module.css'
|
||||
import { fadeIn } from '../Animations'
|
@ -1,7 +1,7 @@
|
||||
import React, { useContext } from 'react'
|
||||
import { AppContext } from '../../store/createContext'
|
||||
import Balance from '../Balance'
|
||||
import { conversions } from '../../../../config'
|
||||
import { conversions } from '../../../config'
|
||||
|
||||
const calculateTotalBalance = (accounts, currency) => {
|
||||
const balanceTotalArray = []
|
@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import pkg from '../../../../package.json'
|
||||
import pkg from '../../../package.json'
|
||||
import styles from './Titlebar.module.css'
|
||||
|
||||
const Titlebar = () => (
|
Before Width: | Height: | Size: 871 B After Width: | Height: | Size: 871 B |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 145 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
@ -1,15 +0,0 @@
|
||||
import React from 'react'
|
||||
import { render } from '@testing-library/react'
|
||||
import AppProvider from '../store/AppProvider'
|
||||
import App from './App'
|
||||
|
||||
describe('App', () => {
|
||||
it('renders correctly', () => {
|
||||
const { container } = render(
|
||||
<AppProvider>
|
||||
<App />
|
||||
</AppProvider>
|
||||
)
|
||||
expect(container.firstChild).toBeInTheDocument()
|
||||
})
|
||||
})
|
@ -1 +0,0 @@
|
||||
import '@testing-library/jest-dom/extend-expect'
|
@ -26,16 +26,12 @@ const withSvgr = (nextConfig = {}, nextComposePlugins = {}) => {
|
||||
module.exports = withSvgr({
|
||||
webpack: config => {
|
||||
config.target = 'electron-renderer'
|
||||
|
||||
return config
|
||||
},
|
||||
exportPathMap() {
|
||||
return {
|
||||
'/': { page: '/' },
|
||||
'/preferences': { page: '/preferences' }
|
||||
}
|
||||
}
|
||||
// exportPathMap() {
|
||||
// // Let Next.js know where to find the entry page
|
||||
// // when it's exporting the static bundle for the use
|
||||
// // in the production version of your app
|
||||
// return {
|
||||
// '/': { page: '/' },
|
||||
// '/preferences': { page: '/preferences' }
|
||||
// }
|
||||
// }
|
||||
})
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Router from 'next/router'
|
||||
import { ipcRenderer } from 'electron'
|
||||
// import { ipcRenderer } from 'electron'
|
||||
|
||||
import '../global.css'
|
||||
import Layout from '../Layout'
|
||||
@ -14,7 +14,7 @@ import Layout from '../Layout'
|
||||
|
||||
export default function App({ Component, pageProps }) {
|
||||
useEffect(() => {
|
||||
ipcRenderer.on('goTo', (evt, route) => {
|
||||
global.ipcRenderer.on('goTo', (evt, route) => {
|
||||
Router.push(route)
|
||||
})
|
||||
}, [])
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
import Accounts from '../components/Preferences/Accounts'
|
||||
import AccountsList from '../components/AccountsList'
|
||||
import styles from './preferences.module.css'
|
||||
|
||||
const Preferences = () => (
|
||||
@ -11,7 +11,7 @@ const Preferences = () => (
|
||||
×
|
||||
</a>
|
||||
</Link>
|
||||
<Accounts />
|
||||
<AccountsList />
|
||||
</div>
|
||||
)
|
||||
|
@ -1,15 +1,11 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import ms from 'ms'
|
||||
import { ipcRenderer } from 'electron'
|
||||
// import { ipcRenderer } from 'electron'
|
||||
import Store from 'electron-store'
|
||||
import { AppContext } from './createContext'
|
||||
import { fetchData } from '../../../utils'
|
||||
import {
|
||||
refreshInterval,
|
||||
conversions,
|
||||
oceanTokenContract
|
||||
} from '../../../config'
|
||||
import { fetchData } from '../../utils'
|
||||
import { refreshInterval, conversions, oceanTokenContract } from '../../config'
|
||||
|
||||
// construct initial prices Map to get consistent
|
||||
// order for Ticker and Touchbar
|
||||
@ -22,7 +18,7 @@ export default class AppProvider extends PureComponent {
|
||||
children: PropTypes.any.isRequired
|
||||
}
|
||||
|
||||
store = new Store()
|
||||
store = process.env.NODE_ENV === 'test' ? new Store() : global.store
|
||||
|
||||
state = {
|
||||
isLoading: true,
|
||||
@ -42,12 +38,12 @@ export default class AppProvider extends PureComponent {
|
||||
|
||||
async componentDidMount() {
|
||||
// listener for accent color
|
||||
ipcRenderer.on('accent-color', (event, accentColor) => {
|
||||
global.ipcRenderer.on('accent-color', (event, accentColor) => {
|
||||
this.setState({ accentColor })
|
||||
})
|
||||
|
||||
// listener for touchbar
|
||||
ipcRenderer.on('setCurrency', (evt, currency) =>
|
||||
global.ipcRenderer.on('setCurrency', (evt, currency) =>
|
||||
this.state.toggleCurrencies(currency)
|
||||
)
|
||||
|
||||
@ -103,7 +99,7 @@ export default class AppProvider extends PureComponent {
|
||||
}))
|
||||
)
|
||||
|
||||
ipcRenderer.send('prices-updated', Array.from(newPrices)) // convert Map to array, ipc messages seem to kill it
|
||||
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
|
||||
}
|
||||
@ -140,7 +136,7 @@ export default class AppProvider extends PureComponent {
|
||||
|
||||
toggleCurrencies(currency) {
|
||||
const pricesNew = Array.from(this.state.prices)
|
||||
ipcRenderer.send('currency-updated', pricesNew, currency)
|
||||
global.ipcRenderer.send('currency-updated', pricesNew, currency)
|
||||
this.setState({ currency })
|
||||
}
|
||||
|
10
tests/Layout.test.jsx
Normal file
@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import { render } from '@testing-library/react'
|
||||
import Layout from '../src/renderer/Layout'
|
||||
|
||||
describe('Layout', () => {
|
||||
it('renders correctly', () => {
|
||||
const { container } = render(<Layout>Hello</Layout>)
|
||||
expect(container.firstChild).toBeInTheDocument()
|
||||
})
|
||||
})
|
@ -1,8 +1,8 @@
|
||||
import React from 'react'
|
||||
import { render, fireEvent } from '@testing-library/react'
|
||||
import { AppContext } from '../../../store/createContext'
|
||||
import { StateMock } from '@react-mock/state'
|
||||
import Accounts from '.'
|
||||
import { AppContext } from '../../src/renderer/store/createContext'
|
||||
import Accounts from '../../src/renderer/components/AccountsList'
|
||||
|
||||
describe('Accounts', () => {
|
||||
const ui = (
|
10
tests/components/Spinner.test.jsx
Normal file
@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import { render } from '@testing-library/react'
|
||||
import Spinner from '../../src/renderer/components/Spinner'
|
||||
|
||||
describe('Spinner', () => {
|
||||
it('renders correctly', () => {
|
||||
const { container } = render(<Spinner />)
|
||||
expect(container.firstChild).toBeInTheDocument()
|
||||
})
|
||||
})
|
32
tests/jest.config.js
Normal file
@ -0,0 +1,32 @@
|
||||
module.exports = {
|
||||
rootDir: '../',
|
||||
transform: {
|
||||
'^.+\\.jsx?$': 'babel-jest'
|
||||
},
|
||||
moduleNameMapper: {
|
||||
'.+\\.(css|styl|less|sass|scss)$': 'identity-obj-proxy',
|
||||
'.+\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
|
||||
'<rootDir>/tests/__mocks__/file-mock.js',
|
||||
'\\.svg': '<rootDir>/tests/__mocks__/svgr-mock.js'
|
||||
},
|
||||
testMatch: ['**/?(*.)+(spec|test).jsx'],
|
||||
testPathIgnorePatterns: [
|
||||
'<rootDir>/src/renderer/.next',
|
||||
'<rootDir>/src/renderer/out',
|
||||
'<rootDir>/node_modules',
|
||||
'<rootDir>/build',
|
||||
'<rootDir>/dist',
|
||||
'<rootDir>/coverage'
|
||||
],
|
||||
testURL: 'http://localhost',
|
||||
setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
|
||||
runner: '@jest-runner/electron',
|
||||
testEnvironment: '@jest-runner/electron/environment',
|
||||
coverageDirectory: '../../coverage/',
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: [
|
||||
'<rootDir>/src/renderer/**/*.jsx',
|
||||
'!<rootDir>/dist',
|
||||
'!**/node_modules/**'
|
||||
]
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
import React from 'react'
|
||||
import { render, fireEvent } from '@testing-library/react'
|
||||
import { AppContext } from '../store/createContext'
|
||||
import context from './__fixtures__/context'
|
||||
import Home from '.'
|
||||
import { AppContext } from '../../src/renderer/store/createContext'
|
||||
import context from '../__fixtures__/context'
|
||||
import Home from '../../src/renderer/pages/index'
|
||||
|
||||
describe('Home', () => {
|
||||
it('renders correctly', () => {
|
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import { render } from '@testing-library/react'
|
||||
import { AppContext } from '../store/createContext'
|
||||
import Preferences from '.'
|
||||
import { AppContext } from '../../src/renderer/store/createContext'
|
||||
import Preferences from '../../src/renderer/pages/preferences'
|
||||
|
||||
describe('Preferences', () => {
|
||||
it('renders correctly', () => {
|