project organisation, fix build & test runs

This commit is contained in:
Matthias Kretschmann 2020-02-09 17:16:10 +01:00
parent 6a1b1a4c3a
commit 94312a6902
Signed by: m
GPG Key ID: 606EEEF3C479A91F
57 changed files with 101 additions and 104 deletions

View File

@ -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

View File

@ -1,5 +1,6 @@
{ {
"semi": false, "semi": false,
"singleQuote": true, "singleQuote": true,
"trailingComma": "none" "trailingComma": "none",
"tabWidth": 2
} }

View File

@ -1,4 +1,4 @@
const { devDependencies } = require('../../package.json') const { devDependencies } = require('./package.json')
module.exports = { module.exports = {
presets: [ presets: [

View File

@ -6,17 +6,19 @@
"main": "./src/main/index.js", "main": "./src/main/index.js",
"scripts": { "scripts": {
"start": "electron .", "start": "electron .",
"test": "npm run lint && jest", "test": "npm run lint && npm run jest",
"test:watch": "jest --watch", "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}", "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": "electron-builder build -ml -p never",
"build:electron:win": "electron-builder build -w -p never", "build:electron:win": "electron-builder build -w -p never",
"dist": "./scripts/release-prepare.sh", "dist": "./scripts/release-prepare.sh",
"release": "release-it --non-interactive", "release": "release-it --non-interactive",
"changelog": "auto-changelog -p", "changelog": "auto-changelog -p",
"format": "prettier --write 'src/**/*.{js,jsx}' && npm run format:css", "format": "prettier --write --ignore-path .gitignore 'src/**/*.{js,jsx}' && npm run format:css",
"format:css": "prettier-stylelint --write --quiet 'src/**/*.{css,scss}'" "format:css": "prettier-stylelint --write --ignore-path .gitignore --quiet 'src/**/*.{css,scss}'"
}, },
"repository": "https://github.com/kremalicious/blowfish.git", "repository": "https://github.com/kremalicious/blowfish.git",
"homepage": "https://github.com/kremalicious/blowfish", "homepage": "https://github.com/kremalicious/blowfish",
@ -28,6 +30,9 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@coingecko/cryptoformat": "^0.3.3", "@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-address": "^0.0.4",
"ethereum-blockies": "github:MyEtherWallet/blockies", "ethereum-blockies": "github:MyEtherWallet/blockies",
"ms": "^2.1.2", "ms": "^2.1.2",
@ -47,9 +52,6 @@
"electron": "^8.0.0", "electron": "^8.0.0",
"electron-builder": "^22.3.2", "electron-builder": "^22.3.2",
"electron-devtools-installer": "^2.2.4", "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": "^6.8.0",
"eslint-config-prettier": "^6.10.0", "eslint-config-prettier": "^6.10.0",
"eslint-plugin-react": "^7.18.3", "eslint-plugin-react": "^7.18.3",
@ -117,29 +119,5 @@
"npm": { "npm": {
"publish": false "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"
} }
} }

View File

@ -36,9 +36,9 @@ const createWindow = async () => {
autoHideMenuBar: true, autoHideMenuBar: true,
webPreferences: { webPreferences: {
nodeIntegration: true, nodeIntegration: true,
preload: path.join(__dirname, 'preload.js'),
scrollBounce: true, scrollBounce: true,
enableBlinkFeatures: 'OverlayScrollbars' enableBlinkFeatures: 'OverlayScrollbars'
// preload: path.join(__dirname, 'preload.js')
} }
}) })

View File

@ -2,7 +2,7 @@ import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { toDataUrl } from 'ethereum-blockies' import { toDataUrl } from 'ethereum-blockies'
import posed, { PoseGroup } from 'react-pose' import posed, { PoseGroup } from 'react-pose'
import { fadeIn } from '../../Animations' import { fadeIn } from '../Animations'
import styles from './Saved.module.css' import styles from './Saved.module.css'
export default function Saved({ accounts, handleDelete }) { export default function Saved({ accounts, handleDelete }) {

View File

@ -1,15 +1,15 @@
import React, { PureComponent } from 'react' import React, { PureComponent } from 'react'
import ethereum_address from 'ethereum-address' import ethereum_address from 'ethereum-address'
import Store from 'electron-store' import Store from 'electron-store'
import { AppContext } from '../../../store/createContext' import { AppContext } from '../../store/createContext'
import Saved from './Saved' import Saved from './Saved'
import New from './New' import New from './New'
import styles from './index.module.css' import styles from './index.module.css'
export default class Accounts extends PureComponent { export default class AccountsList extends PureComponent {
static contextType = AppContext static contextType = AppContext
store = new Store() store = process.env.NODE_ENV === 'test' ? new Store() : global.store
state = { accounts: [], input: '', error: '' } state = { accounts: [], input: '', error: '' }

View File

@ -1,5 +1,5 @@
.preference { .preference {
composes: box from '../../../components/Box.module.css'; composes: box from '../Box.module.css';
-webkit-app-region: none; -webkit-app-region: none;
-webkit-user-select: text; -webkit-user-select: text;
} }

View File

@ -2,7 +2,7 @@ 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 } from '../store/createContext'
import { cryptoFormatter } from '../../../utils' import { cryptoFormatter } from '../../utils'
import { fadeIn } from './Animations' import { fadeIn } from './Animations'
import Label from './Label' import Label from './Label'
import styles from './Balance.module.css' import styles from './Balance.module.css'

View File

@ -1,5 +1,5 @@
import React, { useContext } from 'react' import React, { useContext } from 'react'
import { openUrl } from '../../../../utils' import { openUrl } from '../../../utils'
import Balance from '../Balance' import Balance from '../Balance'
import { AppContext } from '../../store/createContext' import { AppContext } from '../../store/createContext'
import styles from './Accounts.module.css' import styles from './Accounts.module.css'

View File

@ -2,7 +2,7 @@ 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 } 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'
import { fadeIn } from '../Animations' import { fadeIn } from '../Animations'

View File

@ -1,7 +1,7 @@
import React, { useContext } from 'react' import React, { useContext } from 'react'
import { AppContext } from '../../store/createContext' import { AppContext } from '../../store/createContext'
import Balance from '../Balance' import Balance from '../Balance'
import { conversions } from '../../../../config' import { conversions } from '../../../config'
const calculateTotalBalance = (accounts, currency) => { const calculateTotalBalance = (accounts, currency) => {
const balanceTotalArray = [] const balanceTotalArray = []

View File

@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import pkg from '../../../../package.json' import pkg from '../../../package.json'
import styles from './Titlebar.module.css' import styles from './Titlebar.module.css'
const Titlebar = () => ( const Titlebar = () => (

View File

Before

Width:  |  Height:  |  Size: 871 B

After

Width:  |  Height:  |  Size: 871 B

View File

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 145 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -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()
})
})

View File

@ -1 +0,0 @@
import '@testing-library/jest-dom/extend-expect'

View File

@ -26,16 +26,12 @@ const withSvgr = (nextConfig = {}, nextComposePlugins = {}) => {
module.exports = withSvgr({ module.exports = withSvgr({
webpack: config => { webpack: config => {
config.target = 'electron-renderer' config.target = 'electron-renderer'
return config 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' }
// }
// }
}) })

View File

@ -1,7 +1,7 @@
import React, { useEffect } from 'react' 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 '../global.css' import '../global.css'
import Layout from '../Layout' import Layout from '../Layout'
@ -14,7 +14,7 @@ import Layout from '../Layout'
export default function App({ Component, pageProps }) { export default function App({ Component, pageProps }) {
useEffect(() => { useEffect(() => {
ipcRenderer.on('goTo', (evt, route) => { global.ipcRenderer.on('goTo', (evt, route) => {
Router.push(route) Router.push(route)
}) })
}, []) }, [])

View File

@ -1,6 +1,6 @@
import React from 'react' import React from 'react'
import Link from 'next/link' import Link from 'next/link'
import Accounts from '../components/Preferences/Accounts' import AccountsList from '../components/AccountsList'
import styles from './preferences.module.css' import styles from './preferences.module.css'
const Preferences = () => ( const Preferences = () => (
@ -11,7 +11,7 @@ const Preferences = () => (
&times; &times;
</a> </a>
</Link> </Link>
<Accounts /> <AccountsList />
</div> </div>
) )

View File

@ -1,15 +1,11 @@
import React, { PureComponent } from 'react' import React, { PureComponent } 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 { AppContext } from './createContext'
import { fetchData } from '../../../utils' import { fetchData } from '../../utils'
import { import { refreshInterval, conversions, oceanTokenContract } from '../../config'
refreshInterval,
conversions,
oceanTokenContract
} from '../../../config'
// construct initial prices Map to get consistent // construct initial prices Map to get consistent
// order for Ticker and Touchbar // order for Ticker and Touchbar
@ -22,7 +18,7 @@ export default class AppProvider extends PureComponent {
children: PropTypes.any.isRequired children: PropTypes.any.isRequired
} }
store = new Store() store = process.env.NODE_ENV === 'test' ? new Store() : global.store
state = { state = {
isLoading: true, isLoading: true,
@ -42,12 +38,12 @@ export default class AppProvider extends PureComponent {
async componentDidMount() { async componentDidMount() {
// listener for accent color // listener for accent color
ipcRenderer.on('accent-color', (event, accentColor) => { global.ipcRenderer.on('accent-color', (event, accentColor) => {
this.setState({ accentColor }) this.setState({ accentColor })
}) })
// listener for touchbar // listener for touchbar
ipcRenderer.on('setCurrency', (evt, currency) => global.ipcRenderer.on('setCurrency', (evt, currency) =>
this.state.toggleCurrencies(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 }) this.setState({ prices: newPrices, priceChanges: newPriceChanges })
return newPrices return newPrices
} }
@ -140,7 +136,7 @@ export default class AppProvider extends PureComponent {
toggleCurrencies(currency) { toggleCurrencies(currency) {
const pricesNew = Array.from(this.state.prices) const pricesNew = Array.from(this.state.prices)
ipcRenderer.send('currency-updated', pricesNew, currency) global.ipcRenderer.send('currency-updated', pricesNew, currency)
this.setState({ currency }) this.setState({ currency })
} }

10
tests/Layout.test.jsx Normal file
View 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()
})
})

View File

@ -1,8 +1,8 @@
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 '../../../store/createContext'
import { StateMock } from '@react-mock/state' 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', () => { describe('Accounts', () => {
const ui = ( const ui = (

View 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
View 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/**'
]
}

View File

@ -1,8 +1,8 @@
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 '../store/createContext' import { AppContext } from '../../src/renderer/store/createContext'
import context from './__fixtures__/context' import context from '../__fixtures__/context'
import Home from '.' import Home from '../../src/renderer/pages/index'
describe('Home', () => { describe('Home', () => {
it('renders correctly', () => { it('renders correctly', () => {

View File

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { AppContext } from '../store/createContext' import { AppContext } from '../../src/renderer/store/createContext'
import Preferences from '.' import Preferences from '../../src/renderer/pages/preferences'
describe('Preferences', () => { describe('Preferences', () => {
it('renders correctly', () => { it('renders correctly', () => {