Skip to content

Commit

Permalink
test(e2e): migrate e2e test suite to testcafe
Browse files Browse the repository at this point in the history
  • Loading branch information
mrfelton committed Jan 16, 2019
1 parent d951809 commit 6ae0ed7
Show file tree
Hide file tree
Showing 18 changed files with 1,595 additions and 415 deletions.
13 changes: 12 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
'eslint:recommended',
'plugin:react/recommended',
'plugin:flowtype/recommended',
'plugin:testcafe/recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:jsx-a11y/strict',
Expand Down Expand Up @@ -74,7 +75,17 @@ module.exports = {
'prefer-promise-reject-errors': 0,
'no-param-reassign': [2, { props: false }]
},
plugins: ['flowtype', 'import', 'json', 'markdown', 'prettier', 'promise', 'compat', 'react'],
plugins: [
'flowtype',
'import',
'json',
'markdown',
'prettier',
'promise',
'testcafe',
'compat',
'react'
],
settings: {
'import/resolver': {
node: {
Expand Down
4 changes: 4 additions & 0 deletions .testcafe-electron-rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"mainWindowUrl": "./app/dist/index.html",
"appPath": "./app"
}
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ addons:
packages:
- xvfb

before_install:
- stty cols 80

install:
- yarn
- |
Expand All @@ -41,7 +44,6 @@ before_script:

script:
- yarn lint-ci || travis_terminate 1
- yarn build || travis_terminate 1
- yarn test-ci || travis_terminate 1
- yarn coveralls || travis_terminate 1

Expand Down
8 changes: 4 additions & 4 deletions app/main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// If we are running in test mode, set the userData to a temporary location.
// This ensure that the app starts with a clean environment.
/**
* This module executes inside of electron's main process. You can start
* electron renderer process from here and communicate with the other processes
Expand All @@ -26,7 +24,9 @@ import ZapUpdater from './lib/zap/updater'
import themes from './themes'
import { getDbName } from './store/db'

if (process.env.USER_DIR) {
// Set the Electron userDir to a temporary directory if the ELECTRON_USER_DIR_TEMP env var is set.
// This provides an easy way to run the app with a completely fresh environment, useful for e2e tests.
if (process.env.ELECTRON_USER_DIR_TEMP) {
const folder = fs.mkdtempSync(path.join(os.tmpdir(), 'zap-'))
mainLog.info('Using temporary directory %s for userData', folder)
app.setPath('userData', folder)
Expand Down Expand Up @@ -240,7 +240,7 @@ app.on('ready', async () => {
/**
* In development mode or when DEBUG_PROD is set, enable debugging tools.
*/
if (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD) {
if (process.env.NODE_ENV !== 'production' || process.env.DEBUG_PROD) {
installExtension(REACT_DEVELOPER_TOOLS)
.then(name => mainLog.debug(`Added Extension: ${name}`))
.catch(err => mainLog.warn(`An error occurred when installing REACT_DEVELOPER_TOOLS: ${err}`))
Expand Down
28 changes: 3 additions & 25 deletions app/store/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,19 @@ import Dexie from 'dexie'

// Suffex the database name with NODE_ENV so that wer can have per-env databases.
export const getDbName = () => {
let name = `ZapDesktop`
if (process.env.NODE_ENV) {
name += `.${process.env.NODE_ENV}`
}
return name
const env = process.env.NODE_ENV || 'development'
return `ZapDesktop.${env}`
}

// Define the database.
const db = new Dexie(getDbName())

db.version(1).stores({
settings: 'key',
wallets: '++id, type, chain, network',
nodes: 'id'
})

// Set initial active wallet.
db.on('populate', async function() {
// If there are already some bitcoin testnet wallet before the database has been created, import them into the
// database and set the active wallet as wallet 1. This is for users upgrading from versions prior to 0.3.0.
const fsWallets = await window.Zap.getLocalWallets('bitcoin', 'testnet')
if (fsWallets.length > 0) {
await fsWallets
.filter(wallet => wallet !== 'wallet-tmp')
.forEach(async wallet => {
await db.wallets.add({
type: 'local',
chain: 'bitcoin',
network: 'testnet',
wallet
})
})
await db.settings.add({ key: 'activeWallet', value: 1 })
}
})

/**
* @class Wallet
* Wallet helper class.
Expand Down
1 change: 0 additions & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ install:

test_script:
- yarn lint-ci
- yarn build
- yarn test-ci

deploy_script:
Expand Down
6 changes: 5 additions & 1 deletion internals/webpack/webpack.config.renderer.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ export default merge.smart(baseConfig, {
debug: true
}),

new webpack.EnvironmentPlugin({
NODE_ENV: 'development'
}),

new HtmlWebpackPlugin({
template: path.join('app', 'app.html')
}),
Expand Down Expand Up @@ -149,7 +153,7 @@ export default merge.smart(baseConfig, {
historyApiFallback: true,
// Start the main process as soon as the server is listening.
after: () => {
if (process.env.START_HOT) {
if (process.env.HOT) {
spawn('npm', ['run', 'start-main-dev'], {
shell: true,
env: process.env,
Expand Down
13 changes: 13 additions & 0 deletions internals/webpack/webpack.config.renderer.e2e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Build config for electron renderer process (e2e)
*/

import merge from 'webpack-merge'
import rendererProdConf from './webpack.config.renderer.prod'

// Disable minification for compatibility with testcafe-react-selectors.
export default merge.smart(rendererProdConf, {
optimization: {
minimizer: []
}
})
6 changes: 5 additions & 1 deletion internals/webpack/webpack.config.renderer.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/

import path from 'path'
import { ExternalsPlugin } from 'webpack'
import { EnvironmentPlugin, ExternalsPlugin } from 'webpack'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import CspHtmlWebpackPlugin from 'csp-html-webpack-plugin'
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
Expand Down Expand Up @@ -50,6 +50,10 @@ export default merge.smart(baseConfig, {
root: path.resolve('..', '..')
}),

new EnvironmentPlugin({
NODE_ENV: 'production'
}),

new HtmlWebpackPlugin({
template: path.join('app', 'app.html')
}),
Expand Down
25 changes: 17 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
"description": "desktop application for the lightning network",
"scripts": {
"build": "concurrently --raw \"npm:build-main\" \"npm:build-renderer\"",
"build-e2e": "concurrently \"npm run build-main\" \"npm run build-renderer-e2e\"",
"build-dll": "webpack -r @babel/register --config internals/webpack/webpack.config.renderer.dev.dll.js",
"build-main": "webpack -r @babel/register --config internals/webpack/webpack.config.main.prod.js",
"build-main": "webpack -r @babel/register --config internals/webpack/webpack.config.main.prod.js",
"build-renderer": "webpack -r @babel/register --config internals/webpack/webpack.config.renderer.prod.js",
"build-renderer-e2e": "webpack -r @babel/register --config internals/webpack/webpack.config.renderer.e2e.js",
"clean": "rimraf node_modules app/node_modules dll app/dist coverage .eslintcache",
"coverage": "open coverage/index.html",
"coveralls": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
"dev": "cross-env START_HOT=1 npm run start-renderer-dev",
"dev": "cross-env HOT=1 npm run start-renderer-dev",
"extract-messages": "extract-messages -l=af-ZA,ca-ES,de-DE,es-ES,ga-IE,hr-HR,ja-JP,no-NO,pt-PT,sr-SP,uk-UA,zh-TW,ar-SA,cs-CZ,el-GR,fi-FI,he-IL,hu-HU,ko-KR,pl-PL,ro-RO,sv-SE,vi-VN,bg-BG,da-DK,en,fr-FR,hi-IN,it-IT,nl-NL,pt-BR,ru-RU,tr-TR,zh-CN -o app/translations -d en --flat true 'app/**/messages.js'",
"fetch-lnd": "node ./internals/scripts/fetch-lnd-for-packaging.js",
"flow": "flow",
Expand All @@ -32,16 +34,19 @@
"postinstall": "concurrently --raw \"npm:flow-typed\" \"npm:build-dll\" \"build install-app-deps\"",
"prestart": "npm run build",
"start": "cross-env NODE_ENV=production electron ./app",
"start-main-dev": "cross-env HOT=1 NODE_ENV=development electron -r @babel/register ./app/main.js",
"start-main-dev": "electron -r @babel/register ./app/main.js",
"start-renderer-dev": "webpack-dev-server -r @babel/register --config internals/webpack/webpack.config.renderer.dev.js --progress",
"storybook": "start-storybook -p 6006",
"storybook:build": "build-storybook",
"storybook:deploy": "npm run storybook:build && gh-pages -t -d storybook-static -o origin -b gh-pages",
"test": "npm run lint && npm run lint-styles && npm run flow && npm run build && npm run test-unit && npm run test-e2e",
"test-base": "cross-env NODE_ENV=test BABEL_DISABLE_CACHE=true DISABLE_INIT=true ELECTRON_DISABLE_SECURITY_WARNINGS=true node --trace-warnings ./node_modules/jest/bin/jest --maxWorkers=2 --forceExit",
"test-base": "cross-env NODE_ENV=test BABEL_DISABLE_CACHE=true DISABLE_INIT=true ELECTRON_DISABLE_SECURITY_WARNINGS=true node --trace-warnings ./node_modules/jest/bin/jest",
"test-unit": "npm run test-base -- --coverage ./test/unit",
"test-e2e": "npm run test-base -- ./test/e2e",
"test-ci": "npm run test-e2e && npm run test-unit"
"test-ci": "npm run test-e2e && npm run test-unit",
"pretest-e2e": "npm run build-e2e",
"test-e2e": "cross-env ELECTRON_USER_DIR_TEMP=1 testcafe electron:./ ./test/e2e",
"pretest-e2e-live": "npm run build-e2e",
"test-e2e-live": "cross-env ELECTRON_USER_DIR_TEMP=1 testcafe-live electron:./ ./test/e2e"
},
"config": {
"style_paths": "app/components/**/*.js",
Expand Down Expand Up @@ -179,7 +184,7 @@
"app/node_modules",
"node_modules"
],
"setupTestFrameworkScriptFile": "./test/setup.js",
"setupTestFrameworkScriptFile": "./test/unit/__helpers__/setup.js",
"transform": {
"^.+\\.js$": "babel-jest"
}
Expand Down Expand Up @@ -246,6 +251,7 @@
"eslint-plugin-prettier": "3.0.1",
"eslint-plugin-promise": "4.0.1",
"eslint-plugin-react": "7.11.1",
"eslint-plugin-testcafe": "0.2.1",
"extract-react-intl-messages": "0.11.1",
"fake-indexeddb": "2.0.4",
"flow-bin": "0.89.0",
Expand All @@ -267,7 +273,6 @@
"react-test-renderer": "16.7.0",
"redux-logger": "3.0.6",
"rimraf": "2.6.3",
"spectron": "5.0.0",
"storybook-addon-intl": "2.3.2",
"storybook-react-router": "1.0.2",
"storybook-styled-components": "1.1.3",
Expand All @@ -276,6 +281,10 @@
"stylelint-config-styled-components": "0.1.1",
"stylelint-formatter-pretty": "1.0.3",
"stylelint-processor-styled-components": "1.5.1",
"testcafe": "0.23.3",
"testcafe-browser-provider-electron": "0.0.8",
"testcafe-live": "0.1.4",
"testcafe-react-selectors": "3.0.3",
"url-loader": "1.1.2",
"webpack": "4.28.3",
"webpack-bundle-analyzer": "3.0.3",
Expand Down
29 changes: 29 additions & 0 deletions test/e2e/app.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { waitForReact } from 'testcafe-react-selectors'
import { getBaseUrl, getPageTitle, assertNoConsoleErrors } from './utils/helpers'
import Loading from './pages/loading'

const loadingPage = new Loading()

fixture('Onboarding')
.page(getBaseUrl())
.beforeEach(async () => {
await waitForReact()
})
.afterEach(assertNoConsoleErrors)

fixture('App')
.page(getBaseUrl())
.beforeEach(async () => {
await waitForReact()
})
.afterEach(assertNoConsoleErrors)

test('should open window and show loading screen', async t => {
const { loadingBolt } = loadingPage

await t
.expect(getPageTitle())
.eql('Zap')
.expect(loadingBolt.exists)
.ok()
})
32 changes: 0 additions & 32 deletions test/e2e/e2e.spec.js

This file was deleted.

38 changes: 0 additions & 38 deletions test/e2e/helpers.js

This file was deleted.

7 changes: 7 additions & 0 deletions test/e2e/pages/loading.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ReactSelector } from 'testcafe-react-selectors'

class Syncing {
loadingBolt = ReactSelector('LoadingBolt')
}

export default Syncing
9 changes: 9 additions & 0 deletions test/e2e/pages/syncing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ReactSelector } from 'testcafe-react-selectors'

class Syncing {
loadingBolt = ReactSelector('LoadingBolt')
syncing = ReactSelector('Syncing')
qrcode = ReactSelector('QRCode')
}

export default Syncing
12 changes: 12 additions & 0 deletions test/e2e/utils/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ClientFunction } from 'testcafe'

export const getBaseUrl = () => '../../app/dist/index.html'

export const getPageUrl = ClientFunction(() => window.location.href)

export const getPageTitle = ClientFunction(() => document.title)

export const assertNoConsoleErrors = async t => {
const { error } = await t.getBrowserConsoleMessages()
await t.expect(error).eql([])
}
File renamed without changes.
Loading

0 comments on commit 6ae0ed7

Please sign in to comment.