├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── api.js ├── appveyor.yml ├── cli.js ├── docs └── capture.png ├── fixture.html ├── index.js ├── lib ├── cli.js └── fork.js ├── main ├── create-window.js ├── initialize-renderer.js ├── messages.js ├── renderer-console.js └── starter.js ├── package.json ├── renderer ├── console.js ├── index.html ├── process-adapter.js ├── starter.js └── test-helper.js ├── test ├── common │ ├── add.test.js │ ├── async.test.js │ ├── log.test.js │ ├── snapshot.test.js │ └── snapshots │ │ ├── snapshot.test.js.md │ │ └── snapshot.test.js.snap ├── main │ └── main.test.js ├── renderer │ └── renderer.test.js └── snapshots │ ├── snapshot.test.js.md │ └── snapshot.test.js.snap └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_STORE 3 | reg 4 | screenshots -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | test 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '10' 4 | - '8' 5 | - '7' 6 | addons: 7 | apt: 8 | packages: 9 | - xvfb 10 | before_install: 11 | - export DISPLAY=':99.0' 12 | - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & 13 | - export ARGOS_TOKEN=4cd2c7e95daddab0eb5e88c61d4425d160553897 14 | 15 | install: 16 | - npm install 17 | - npm install -g argos-cli 18 | - npm install -g glob 19 | script: 20 | - npm run lint 21 | - npm test 22 | - ARGOS_COMMIT=$TRAVIS_COMMIT ARGOS_BRANCH=$TRAVIS_BRANCH argos upload screenshots --token $ARGOS_TOKEN || true 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 bokuweb 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🚀 Avaron 🚀 2 | 3 | 🚀 [AVA](https://ava.li) + Electron = Avaron 🚀 4 | Run your test on real browser with [AVA](https://ava.li). 5 | 6 | [![Build Status](https://travis-ci.org/bokuweb/avaron.svg?branch=master)](https://travis-ci.org/bokuweb/avaron) 7 | [![Build status](https://ci.appveyor.com/api/projects/status/uegh5k030l8xb5nb/branch/master?svg=true)](https://ci.appveyor.com/project/bokuweb/avaron/branch/master) 8 | [![Version](https://img.shields.io/npm/v/avaron.svg)](https://www.npmjs.com/package/avaron) 9 | ![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg) 10 | 11 | Avaron forked from vdbwouter/electron-ava. 12 | 13 | 14 | ## Table of Contents 15 | 16 | - [Why?](#why?) 17 | - [Usage](#usage) 18 | - [Samples](#samples) 19 | - [CI](#ci) 20 | - [Test](#test) 21 | - [Contribute](#contribute) 22 | - [License](#license) 23 | 24 | ## Why? 25 | 26 | - I want to run tests on real browser with `AVA`. 27 | - I want to take screenshot of DOM. 28 | 29 | 30 | You can capture the following image with a real browser when using `Avaron`. 31 | 32 | This sample is using `material-ui`'s `DatePickerDialog` component. 33 | Please see also, screenshot test sample https://github.com/bokuweb/avaron/blob/master/test/renderer/renderer.test.js 34 | 35 | ![](https://github.com/bokuweb/avaron/blob/master/docs/capture.png?raw=true) 36 | 37 | ## Usage 38 | 39 | You can install `avaron` with the following command: 40 | 41 | ```sh 42 | $ npm install avaron --save-dev 43 | ``` 44 | 45 | Or, if you prefer yarn: 46 | 47 | ```sh 48 | $ yarn add avaron -D 49 | ``` 50 | 51 | Then add the following in your `package.json`: 52 | 53 | ```json 54 | "scripts": { 55 | "test": "avaron" 56 | } 57 | ``` 58 | 59 | That's all! You can now run your Electron tests in AVA using `yarn test` or `npm test`. 60 | 61 | ## Command line interface 62 | 63 | ```sh 64 | Usage 65 | avaron [ ...] 66 | 67 | Options 68 | --fail-fast Stop after first test failure 69 | --serial, -s Run tests serially 70 | --tap, -t Generate TAP output 71 | --verbose, -v Enable verbose output 72 | --no-cache Disable the transpiler cache 73 | --no-power-assert Disable Power Assert 74 | --match, -m Only run tests with matching title (Can be repeated) 75 | --watch, -w Re-run tests when tests and source files change 76 | --source, -S Pattern to match source files so tests can be re-run (Can be repeated) 77 | --timeout, -T Set global timeout 78 | --concurrency, -c Maximum number of test files running at the same time (EXPERIMENTAL) 79 | --update-snapshots, -u Update snapshots 80 | --renderer Run the on the renderer process 81 | 82 | Examples 83 | avaron 84 | avaron test.js test2.js 85 | avaron test-*.js 86 | avaron test 87 | avaron test --renderer 88 | 89 | Default patterns when no arguments: 90 | test.js test-*.js test/**/*.js **/__tests__/**/*.js **/*.test.js 91 | ``` 92 | 93 | The CLI has the same options as the 94 | [AVA CLI](https://github.com/avajs/ava/tree/033d4dcdcbdadbf665c740ff450c2a775a8373dc#cli), 95 | except for the options `--init` and `--renderer`. `--init` has not yet been added and 96 | `--renderer` has been added. 97 | 98 | `--renderer` allows you to run the tests in the renderer process instead of the main process. 99 | 100 | ## Renderer process tests 101 | 102 | If you want to run your tests in the renderer process, you can add the `renderer` 103 | option to the `avaron` section in your `package.json` and give it the value `true`. 104 | This config works the same as the [`ava` config](https://github.com/avajs/ava#configuration). 105 | 106 | Your `package.json` then should look like this: 107 | 108 | ```json 109 | { 110 | "scripts": { 111 | "test": "avaron" 112 | }, 113 | "devDependencies": { 114 | "avaron": "*" 115 | }, 116 | "avaron": { 117 | "renderer": true 118 | } 119 | } 120 | ``` 121 | 122 | ### API (Renderer process tests Only) 123 | 124 | ### isAvaronRenderer(): boolean 125 | 126 | Return `true`, when test is running on avaron renderer. 127 | 128 | ### getCurrentWindow(): ?Electron.BrowserWindow 129 | 130 | Return current `BrowserWindow`, when test is running on avaron renderer. 131 | Return `null`, when running on other browser. 132 | 133 | ### screenshot(path: string): Promise\ 134 | 135 | Takes a screenshot of the current test. Useful for visual test. The output is always a png. 136 | 137 | ``` js 138 | import test from 'ava'; 139 | import { screenshot } from 'avaron'; 140 | 141 | test('should capture', async t => { 142 | await screenshot('path_to_screenshot.png'); 143 | t.pass(); 144 | }); 145 | ``` 146 | 147 | Also see, `avaron`'s renderer test. (https://github.com/bokuweb/avaron/blob/master/test/renderer/renderer.test.js) 148 | 149 | ## BrowserWindow options 150 | 151 | If you want to pass options to the browser window for the renderer process, you can do this by 152 | adding the `windowOptions` option to your config. This object will then be passed to the 153 | [`BrowserWindow` constructor](http://electron.atom.io/docs/api/browser-window/#new-browserwindowoptions). 154 | 155 | ```json 156 | { 157 | "scripts": { 158 | "test": "avaron" 159 | }, 160 | "devDependencies": { 161 | "avaron": "*" 162 | }, 163 | "avaron": { 164 | "renderer": true, 165 | "fixture": "./fixture.html", 166 | "windowOptions": { 167 | "title": "avaron" 168 | } 169 | } 170 | } 171 | ``` 172 | 173 | ### Avaron's original options 174 | 175 | | name | Default | Description | 176 | | :--------------------------- | :-----------| :------------------------------------------------------------------------------------------------------------------------------ | 177 | | renderer | `false` | If set `true`, your tests run in the renderer process. In other words you can test with a real browser (chromium) | 178 | | fixture | undefined | You can custom html file for renderer test. If omitted, uses Avaron's own fixture.html file. | 179 | 180 | 181 | ## Samples 182 | 183 | - [react-avaron-sample](https://github.com/bokuweb/react-avaron-sample) - React + avaron test sample 184 | 185 | ## CI 186 | 187 | If you want to run tests on CI, please set xvfb. 188 | Please see also, these files. 189 | 190 | - TravisCI - https://github.com/bokuweb/react-avaron-sample/blob/master/.travis.yml 191 | - CircleCI - https://github.com/bokuweb/react-avaron-sample/blob/master/circle.yml 192 | 193 | 194 | 195 | ## Test 196 | 197 | ``` sh 198 | $ npm t 199 | ``` 200 | 201 | ## Contribute 202 | 203 | PRs welcome. 204 | 205 | ## License 206 | 207 | The MIT License (MIT) 208 | 209 | Copyright (c) 2017 @bokuweb 210 | 211 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 212 | 213 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 214 | 215 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 216 | -------------------------------------------------------------------------------- /api.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const Api = require('ava/api'); 5 | const fork = require('./lib/fork'); 6 | 7 | module.exports = class ElectronApi extends Api { 8 | 9 | _runFile(file, runStatus, execArgv) { 10 | const hash = this.precompiler.precompileFile(file); 11 | const precompiled = Object.assign({}, this._precompiledHelpers); 12 | const resolvedfpath = fs.realpathSync(file); 13 | precompiled[resolvedfpath] = hash; 14 | 15 | const options = Object.assign({}, this.options, {precompiled}); 16 | const emitter = fork(file, options, execArgv); 17 | runStatus.observeFork(emitter); 18 | 19 | return emitter; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | 2 | # Test against the latest version of this Node.js version 3 | environment: 4 | nodejs_version: "8" 5 | 6 | # Install scripts. (runs after repo cloning) 7 | install: 8 | # Get the latest stable version of Node.js or io.js 9 | - ps: Install-Product node $env:nodejs_version 10 | # install modules 11 | - npm install 12 | 13 | # Post-install test scripts. 14 | test_script: 15 | # Output useful info for debugging. 16 | - node --version 17 | - npm --version 18 | # run tests 19 | - npm test 20 | 21 | # Don't actually build. 22 | build: off -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 'use strict'; 4 | 5 | // This file is based https://github.com/avajs/ava/blob/8c35a1a4b61c3f91d8c7b61e185dd5b450402bc0/lib/cli.js. 6 | // 7 | // https://github.com/avajs/ava/blob/master/license 8 | // 9 | // MIT License 10 | // 11 | // Copyright (c) Sindre Sorhus (sindresorhus.com) 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | // 19 | 20 | /* eslint-disable import/no-extraneous-dependencies */ 21 | 22 | const debug = require('debug')('ava'); 23 | const importLocal = require('import-local'); 24 | 25 | // Prefer the local installation of AVA 26 | if (importLocal(__filename)) { 27 | debug('Using local install of AVA'); 28 | } else { 29 | if (debug.enabled) { 30 | require('time-require'); // eslint-disable-line import/no-unassigned-import 31 | } 32 | 33 | try { 34 | require('./lib/cli').run(); 35 | } catch (err) { 36 | console.error(err); 37 | process.exit(1); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /docs/capture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bokuweb/avaron/2820085b88f5e8ce47058cebd4e8e024d7cf3e4f/docs/capture.png -------------------------------------------------------------------------------- /fixture.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 |
This is fixture sample.
14 | 15 | 16 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const helper = require('./renderer/test-helper'); 2 | 3 | module.exports = helper; 4 | -------------------------------------------------------------------------------- /lib/cli.js: -------------------------------------------------------------------------------- 1 | // This file is based https://github.com/avajs/ava/blob/8c35a1a4b61c3f91d8c7b61e185dd5b450402bc0/lib/cli.js. 2 | // 3 | // https://github.com/avajs/ava/blob/master/license 4 | // 5 | // MIT License 6 | // 7 | // Copyright (c) Sindre Sorhus (sindresorhus.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | // 15 | 16 | /* eslint-disable import/no-extraneous-dependencies */ 17 | 18 | 'use strict'; 19 | const path = require('path'); 20 | const updateNotifier = require('update-notifier'); 21 | const figures = require('figures'); 22 | const arrify = require('arrify'); 23 | const meow = require('meow'); 24 | const Promise = require('bluebird'); 25 | const pkgConf = require('pkg-conf'); 26 | const isCi = require('is-ci'); 27 | const hasFlag = require('has-flag'); 28 | const colors = require('ava/lib/colors'); 29 | const VerboseReporter = require('ava/lib/reporters/verbose'); 30 | const MiniReporter = require('ava/lib/reporters/mini'); 31 | const TapReporter = require('ava/lib/reporters/tap'); 32 | const Logger = require('ava/lib/logger'); 33 | const Watcher = require('ava/lib/watcher'); 34 | const babelConfigHelper = require('ava/lib/babel-config'); 35 | const Api = require('../api'); 36 | 37 | // Bluebird specific 38 | Promise.longStackTraces(); 39 | 40 | exports.run = () => { 41 | const conf = pkgConf.sync('avaron'); 42 | 43 | const filepath = pkgConf.filepath(conf); 44 | const projectDir = filepath === null ? process.cwd() : path.dirname(filepath); 45 | 46 | const cli = meow(` 47 | Usage 48 | avaron [ ...] 49 | Options 50 | --fail-fast Stop after first test failure 51 | --serial, -s Run tests serially 52 | --tap, -t Generate TAP output 53 | --verbose, -v Enable verbose output 54 | --no-cache Disable the transpiler cache 55 | --no-power-assert Disable Power Assert 56 | --color Force color output 57 | --no-color Disable color output 58 | --match, -m Only run tests with matching title (Can be repeated) 59 | --watch, -w Re-run tests when tests and source files change 60 | --timeout, -T Set global timeout 61 | --concurrency, -c Maximum number of test files running at the same time (EXPERIMENTAL) 62 | --update-snapshots, -u Update snapshots 63 | --renderer Run test on electron renderer 64 | --fixture Set fixture for renderer test 65 | Examples 66 | avaron 67 | avaron test.js test2.js 68 | avaron test-*.js 69 | avaron test 70 | avaron --init 71 | avaron --init foo.js 72 | Default patterns when no arguments: 73 | test.js test-*.js test/**/*.js **/__tests__/**/*.js **/*.test.js 74 | `, { 75 | string: [ 76 | '_', 77 | 'match', 78 | 'timeout', 79 | 'concurrency', 80 | 'fixture' 81 | 82 | ], 83 | boolean: [ 84 | 'init', 85 | 'fail-fast', 86 | 'serial', 87 | 'tap', 88 | 'verbose', 89 | 'watch', 90 | 'update-snapshots', 91 | 'color', 92 | 'renderer' 93 | ], 94 | default: { 95 | cache: conf.cache, 96 | color: 'color' in conf ? conf.color : require('supports-color') !== false, 97 | concurrency: conf.concurrency, 98 | failFast: conf.failFast, 99 | init: conf.init, 100 | match: conf.match, 101 | powerAssert: conf.powerAssert, 102 | serial: conf.serial, 103 | tap: conf.tap, 104 | timeout: conf.timeout, 105 | updateSnapshots: conf.updateSnapshots, 106 | verbose: conf.verbose, 107 | watch: conf.watch, 108 | renderer: conf.renderer 109 | }, 110 | alias: { 111 | t: 'tap', 112 | v: 'verbose', 113 | s: 'serial', 114 | m: 'match', 115 | w: 'watch', 116 | T: 'timeout', 117 | c: 'concurrency', 118 | u: 'update-snapshots' 119 | } 120 | }); 121 | 122 | updateNotifier({pkg: cli.pkg}).notify(); 123 | 124 | if (cli.flags.init) { 125 | require('ava-init')(); 126 | return; 127 | } 128 | 129 | if ( 130 | ((hasFlag('--watch') || hasFlag('-w')) && (hasFlag('--tap') || hasFlag('-t'))) || 131 | (conf.watch && conf.tap) 132 | ) { 133 | throw new Error(colors.error(figures.cross) + ' The TAP reporter is not available when using watch mode.'); 134 | } 135 | 136 | if ((hasFlag('--watch') || hasFlag('-w')) && isCi) { 137 | throw new Error(colors.error(figures.cross) + ' Watch mode is not available in CI, as it prevents AVA from terminating.'); 138 | } 139 | 140 | if (cli.flags.concurrency === '') { 141 | throw new Error(colors.error(figures.cross) + ' The --concurrency and -c flags must be provided the maximum number of test files to run at once.'); 142 | } 143 | 144 | if (hasFlag('--require') || hasFlag('-r')) { 145 | throw new Error(colors.error(figures.cross) + ' The --require and -r flags are deprecated. Requirements should be configured in package.json - see documentation.'); 146 | } 147 | 148 | // Copy resultant cli.flags into conf for use with Api and elsewhere 149 | Object.assign(conf, cli.flags); 150 | 151 | const api = new Api({ 152 | failFast: conf.failFast, 153 | failWithoutAssertions: conf.failWithoutAssertions !== false, 154 | serial: conf.serial, 155 | require: arrify(conf.require), 156 | cacheEnabled: conf.cache !== false, 157 | powerAssert: conf.powerAssert !== false, 158 | explicitTitles: conf.watch, 159 | match: arrify(conf.match), 160 | babelConfig: babelConfigHelper.validate(conf.babel), 161 | resolveTestsFrom: cli.input.length === 0 ? projectDir : process.cwd(), 162 | projectDir, 163 | timeout: conf.timeout, 164 | concurrency: conf.concurrency ? parseInt(conf.concurrency, 10) : 0, 165 | updateSnapshots: conf.updateSnapshots, 166 | color: conf.color, 167 | // For avaron 168 | renderer: cli.flags.renderer || conf.renderer, 169 | fixture: cli.flags.fixture || conf.fixture, 170 | windowOptions: conf.windowOptions 171 | }); 172 | 173 | let reporter; 174 | 175 | if (conf.tap && !conf.watch) { 176 | reporter = new TapReporter(); 177 | } else if (conf.verbose || isCi) { 178 | reporter = new VerboseReporter({color: conf.color}); 179 | } else { 180 | reporter = new MiniReporter({color: conf.color, watching: conf.watch}); 181 | } 182 | 183 | reporter.api = api; 184 | const logger = new Logger(reporter); 185 | 186 | logger.start(); 187 | 188 | api.on('test-run', runStatus => { 189 | reporter.api = runStatus; 190 | runStatus.on('test', logger.test); 191 | runStatus.on('error', logger.unhandledError); 192 | 193 | runStatus.on('stdout', logger.stdout); 194 | runStatus.on('stderr', logger.stderr); 195 | }); 196 | 197 | const files = cli.input.length ? cli.input : arrify(conf.files); 198 | 199 | if (conf.watch) { 200 | try { 201 | const watcher = new Watcher(logger, api, files, arrify(conf.source)); 202 | watcher.observeStdin(process.stdin); 203 | } catch (err) { 204 | if (err.name === 'AvaError') { 205 | // An AvaError may be thrown if `chokidar` is not installed. Log it nicely. 206 | console.error(` ${colors.error(figures.cross)} ${err.message}`); 207 | logger.exit(1); 208 | } else { 209 | // Rethrow so it becomes an uncaught exception 210 | throw err; 211 | } 212 | } 213 | } else { 214 | api.run(files) 215 | .then(runStatus => { 216 | logger.finish(runStatus); 217 | logger.exit(runStatus.failCount > 0 || runStatus.rejectionCount > 0 || runStatus.exceptionCount > 0 ? 1 : 0); 218 | }) 219 | .catch(err => { 220 | // Don't swallow exceptions. Note that any expected error should already 221 | // have been logged. 222 | setImmediate(() => { 223 | throw err; 224 | }); 225 | }); 226 | } 227 | }; 228 | -------------------------------------------------------------------------------- /lib/fork.js: -------------------------------------------------------------------------------- 1 | // This file is based https://raw.githubusercontent.com/avajs/ava/314ef001ab1c085e2057738e2d2588bde3e792cc/lib/fork.js. 2 | // 3 | // https://github.com/avajs/ava/blob/master/license 4 | // 5 | // MIT License 6 | // 7 | // Copyright (c) Sindre Sorhus (sindresorhus.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | // 15 | 16 | /* eslint-disable import/no-unassigned-import */ 17 | /* eslint-disable import/no-extraneous-dependencies */ 18 | 19 | 'use strict'; 20 | const childProcess = require('child_process'); 21 | const path = require('path'); 22 | const fs = require('fs'); 23 | const Promise = require('bluebird'); 24 | const debug = require('debug')('ava'); 25 | const AvaError = require('ava/lib/ava-error'); 26 | 27 | if (fs.realpathSync(__filename) !== __filename) { 28 | console.warn('WARNING: `npm link ava` and the `--preserve-symlink` flag are incompatible. We have detected that AVA is linked via `npm link`, and that you are using either an early version of Node 6, or the `--preserve-symlink` flag. This breaks AVA. You should upgrade to Node 6.2.0+, avoid the `--preserve-symlink` flag, or avoid using `npm link ava`.'); 29 | } 30 | 31 | let env = process.env; 32 | 33 | // Ensure NODE_PATH paths are absolute 34 | if (env.NODE_PATH) { 35 | env = Object.assign({}, env); 36 | 37 | env.NODE_PATH = env.NODE_PATH 38 | .split(path.delimiter) 39 | .map(x => path.resolve(x)) 40 | .join(path.delimiter); 41 | } 42 | 43 | // In case the test file imports a different AVA install, 44 | // the presence of this variable allows it to require this one instead 45 | env.AVA_PATH = path.resolve(require.resolve('ava'), '..'); 46 | 47 | module.exports = (file, opts, execArgv) => { 48 | opts = Object.assign({ 49 | file, 50 | baseDir: process.cwd(), 51 | tty: process.stdout.isTTY ? { 52 | columns: process.stdout.columns, 53 | rows: process.stdout.rows 54 | } : false 55 | }, opts); 56 | 57 | // Const args = [JSON.stringify(opts), opts.color ? '--color' : '--no-color']; 58 | 59 | // Modified for ava-ron 60 | const ps = childProcess.spawn(require('electron'), [require.resolve('../main/starter'), JSON.stringify(opts)], { 61 | stdio: [null, null, null, 'ipc'], 62 | cwd: opts.projectDir, 63 | silent: false, 64 | env, 65 | execArgv: execArgv || process.execArgv 66 | }); 67 | 68 | const relFile = path.relative('.', file); 69 | 70 | let exiting = false; 71 | const send = (name, data) => { 72 | if (!exiting) { 73 | // This seems to trigger a Node bug which kills the AVA master process, at 74 | // least while running AVA's tests. See 75 | // for more details. 76 | ps.send({ 77 | name: `ava-${name}`, 78 | data, 79 | ava: true 80 | }); 81 | } 82 | }; 83 | 84 | const testResults = []; 85 | let results; 86 | 87 | const promise = new Promise((resolve, reject) => { 88 | ps.on('error', reject); 89 | 90 | // Emit `test` and `stats` events 91 | ps.on('message', event => { 92 | if (!event.ava) { 93 | return; 94 | } 95 | 96 | event.name = event.name.replace(/^ava-/, ''); 97 | event.data.file = relFile; 98 | 99 | debug('ipc %s:\n%o', event.name, event.data); 100 | 101 | ps.emit(event.name, event.data); 102 | }); 103 | 104 | ps.on('test', props => { 105 | testResults.push(props); 106 | }); 107 | 108 | ps.on('results', data => { 109 | results = data; 110 | data.tests = testResults; 111 | send('teardown'); 112 | }); 113 | 114 | ps.on('exit', (code, signal) => { 115 | if (code > 0) { 116 | return reject(new AvaError(`${relFile} exited with a non-zero exit code: ${code}`)); 117 | } 118 | 119 | if (code === null && signal) { 120 | return reject(new AvaError(`${relFile} exited due to ${signal}`)); 121 | } 122 | 123 | if (results) { 124 | resolve(results); 125 | } else { 126 | reject(new AvaError(`Test results were not received from ${relFile}`)); 127 | } 128 | }); 129 | 130 | ps.on('no-tests', data => { 131 | send('teardown'); 132 | 133 | let message = `No tests found in ${relFile}`; 134 | 135 | if (!data.avaRequired) { 136 | message += ', make sure to import "ava" at the top of your test file'; 137 | } 138 | 139 | reject(new AvaError(message)); 140 | }); 141 | }); 142 | 143 | // Teardown finished, now exit 144 | ps.on('teardown', () => { 145 | send('exit'); 146 | exiting = true; 147 | }); 148 | 149 | // Uncaught exception in fork, need to exit 150 | ps.on('uncaughtException', () => { 151 | send('teardown'); 152 | }); 153 | 154 | ps.stdout.on('data', data => { 155 | ps.emit('stdout', data); 156 | }); 157 | 158 | ps.stderr.on('data', data => { 159 | ps.emit('stderr', data); 160 | }); 161 | 162 | promise.on = function () { 163 | ps.on.apply(ps, arguments); 164 | return promise; 165 | }; 166 | 167 | promise.send = (name, data) => { 168 | send(name, data); 169 | return promise; 170 | }; 171 | 172 | promise.exit = () => { 173 | send('init-exit'); 174 | return promise; 175 | }; 176 | 177 | // Send 'run' event only when fork is listening for it 178 | let isReady = false; 179 | 180 | ps.on('stats', () => { 181 | isReady = true; 182 | }); 183 | 184 | promise.run = options => { 185 | if (isReady) { 186 | send('run', options); 187 | return promise; 188 | } 189 | 190 | ps.on('stats', () => { 191 | send('run', options); 192 | }); 193 | 194 | return promise; 195 | }; 196 | 197 | return promise; 198 | }; 199 | -------------------------------------------------------------------------------- /main/create-window.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {BrowserWindow} = require('electron'); 4 | const url = require('url'); 5 | const path = require('path'); 6 | const fs = require('fs'); 7 | 8 | module.exports = (options = {}, argv) => { 9 | const actualOptions = Object.assign({show: false, width: 800, height: 600}, options.windowOptions); 10 | const window = new BrowserWindow(actualOptions); 11 | let fixture; 12 | try { 13 | if (options.fixture) { 14 | fixture = path.resolve(process.cwd(), options.fixture); 15 | fs.statSync(fixture); 16 | } else { 17 | fixture = path.resolve(__dirname, '../renderer/index.html'); 18 | } 19 | } catch (err) { 20 | console.warn('[warning] specified fixture file not found. use default fixture.'); 21 | fixture = path.resolve(__dirname, '../renderer/index.html'); 22 | } 23 | const windowURL = getURL(argv, fixture); 24 | const rendererDir = path.resolve(__dirname, '../renderer'); 25 | const starter = options.fixture ? 26 | './' + path.join(path.relative(path.dirname(fixture), rendererDir), 'starter.js').replace(/\\/g, '/') : 27 | './starter.js'; 28 | window.webContents.on('dom-ready', () => { 29 | window.webContents.executeJavaScript(` 30 | document.body.style.backgroundColor = "#fff"; 31 | require("${starter}"); 32 | `); 33 | }); 34 | // Window.webContents.openDevTools(); 35 | window.loadURL(windowURL); 36 | return window; 37 | }; 38 | 39 | function getURL(argv, fixture) { 40 | const unencodedHash = JSON.stringify(argv); 41 | const hash = encodeURIComponent(unencodedHash); 42 | return url.format({ 43 | pathname: fixture, 44 | protocol: 'file', 45 | slashes: true, 46 | hash 47 | }); 48 | } 49 | -------------------------------------------------------------------------------- /main/initialize-renderer.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-unassigned-import */ 2 | 3 | 'use strict'; 4 | const {ipcMain} = require('electron'); 5 | const createWindow = require('./create-window'); 6 | const messages = require('./messages'); 7 | 8 | require('./renderer-console'); 9 | 10 | module.exports = opts => { 11 | const window = createWindow(opts, process.argv); 12 | addRendererEventHandlers(window); 13 | }; 14 | 15 | function addRendererEventHandlers(window) { 16 | ipcMain.on('ava-message', (event, name, data) => { 17 | messages.sendToProcess(name, data); 18 | }); 19 | 20 | process.on('message', message => { 21 | if (!message.ava) { 22 | return; 23 | } 24 | messages.sendToWindow(window, message); 25 | }); 26 | 27 | window.webContents.once('did-finish-load', () => { 28 | window.webContents.send('test-start'); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /main/messages.js: -------------------------------------------------------------------------------- 1 | function sendMessageToProcess(name, data) { 2 | process.send({name: `ava-${name}`, data, ava: true}); 3 | } 4 | 5 | function sendMessageToWindow(window, message) { 6 | window.webContents.send('ava-message', message.name, message.data); 7 | } 8 | 9 | module.exports = { 10 | sendToProcess: sendMessageToProcess, 11 | sendToWindow: sendMessageToWindow 12 | }; 13 | -------------------------------------------------------------------------------- /main/renderer-console.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {ipcMain} = require('electron'); 4 | 5 | const listenToOutput = (channel, outputMethod) => { 6 | ipcMain.on(channel, (event, output) => outputMethod(output)); 7 | }; 8 | 9 | listenToOutput('console-log', console.log); 10 | listenToOutput('console-warn', console.warn); 11 | listenToOutput('console-error', console.error); 12 | -------------------------------------------------------------------------------- /main/starter.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {app} = require('electron'); 4 | const serializeError = require('ava/lib/serialize-error'); 5 | const messages = require('./messages'); 6 | const initializeRenderer = require('./initialize-renderer'); 7 | 8 | function onUncaughtException(err) { 9 | console.error(err); 10 | messages.sendToProcess('uncaughtException', { 11 | exception: serializeError(err) 12 | }); 13 | } 14 | 15 | process.on('uncaughtException', onUncaughtException); 16 | 17 | function startMainTests() { 18 | require('ava/lib/test-worker'); // eslint-disable-line import/no-unassigned-import 19 | } 20 | 21 | app.on('ready', () => { 22 | const opts = JSON.parse(process.argv[2]); 23 | if (opts.renderer) { 24 | initializeRenderer(opts); 25 | } else { 26 | startMainTests(); 27 | // Disable duplicate reporting 28 | process.removeListener('uncaughtException', onUncaughtException); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "avaron", 3 | "version": "0.1.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "lint": "xo", 8 | "test:renderer": "node cli.js test/common/*.test.js test/renderer/*.test.js --renderer", 9 | "test:main": "node cli.js test/common/*.test.js test/main/*.test.js", 10 | "test:renderer-update": "npm run test:renderer -- -u", 11 | "test:main-update": "npm run test:main -- -u", 12 | "test": "run-s test:renderer test:main", 13 | "test:update": "run-s test:renderer-update test:main-update" 14 | }, 15 | "repository": "https://github.com/bokuweb/avaron", 16 | "keywords": [ 17 | "ava", 18 | "test", 19 | "electron", 20 | "snapshot", 21 | "screenshot" 22 | ], 23 | "author": "bokuweb", 24 | "license": "MIT", 25 | "devDependencies": { 26 | "babel-polyfill": "^6.26.0", 27 | "babel-preset-es2015": "^6.24.1", 28 | "babel-preset-react": "^6.24.1", 29 | "babel-preset-stage-0": "^6.24.1", 30 | "material-ui": "^0.19.1", 31 | "npm-run-all": "^4.1.1", 32 | "react": "^15.6.1", 33 | "react-dom": "^15.6.1", 34 | "react-tap-event-plugin": "^2.0.1", 35 | "react-test-renderer": "^15.6.1", 36 | "reg-suit": "^0.5.2", 37 | "xo": "^0.18.2" 38 | }, 39 | "xo": { 40 | "ignores": [ 41 | "test/**" 42 | ], 43 | "envs": [ 44 | "node", 45 | "browser" 46 | ], 47 | "rules": { 48 | "no-use-extend-native/no-use-extend-native": "off" 49 | } 50 | }, 51 | "babel": { 52 | "presets": [ 53 | "es2015", 54 | "stage-0", 55 | "react" 56 | ] 57 | }, 58 | "avaron": { 59 | "babel": "inherit", 60 | "require": [ 61 | "babel-register", 62 | "babel-polyfill" 63 | ], 64 | "windowOptions": { 65 | "title": "avaron" 66 | }, 67 | "fixture": "./fixture.html" 68 | }, 69 | "dependencies": { 70 | "ava": "^0.22.0", 71 | "electron": "2.0.2", 72 | "make-dir": "^1.0.0" 73 | }, 74 | "bin": { 75 | "avaron": "./cli.js" 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /renderer/console.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const util = require('util'); 4 | const {ipcRenderer} = require('electron'); 5 | 6 | const createOutput = channel => (format, ...args) => { 7 | const output = util.format(format, ...args); 8 | ipcRenderer.send(channel, output); 9 | }; 10 | 11 | console.log = createOutput('console-log'); 12 | console.warn = createOutput('console-warn'); 13 | console.error = createOutput('console-error'); 14 | -------------------------------------------------------------------------------- /renderer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /renderer/process-adapter.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-extraneous-dependencies */ 2 | 3 | 'use strict'; 4 | const {ipcRenderer} = require('electron'); 5 | const serializeError = require('ava/lib/serialize-error'); 6 | const currentlyUnhandled = require('currently-unhandled')(); 7 | const processAdapter = require('ava/lib/process-adapter'); 8 | const isObj = require('is-obj'); 9 | 10 | let tearingDown = false; 11 | 12 | processAdapter.exit = window.close; 13 | 14 | processAdapter.send = (name, data) => { 15 | ipcRenderer.send('ava-message', name, data); 16 | }; 17 | 18 | const dependencies = new Set(); 19 | processAdapter.installDependencyTracking(dependencies, processAdapter.opts.file); 20 | 21 | const teardown = () => { 22 | // AVA-teardown can be sent more than once 23 | if (tearingDown) { 24 | return; 25 | } 26 | tearingDown = true; 27 | 28 | let rejections = currentlyUnhandled(); 29 | 30 | if (rejections.length > 0) { 31 | rejections = rejections.map(rejection => { 32 | let reason = rejection.reason; 33 | if (!isObj(reason) || typeof reason.message !== 'string') { 34 | reason = { 35 | message: String(reason) 36 | }; 37 | } 38 | return serializeError(reason); 39 | }); 40 | processAdapter.send('unhandledRejections', {rejections}); 41 | } 42 | processAdapter.send('teardown', {dependencies: Array.from(dependencies)}); 43 | }; 44 | 45 | ipcRenderer.on('ava-message', (event, name, data) => { 46 | switch (name) { 47 | case 'ava-teardown': return teardown(); 48 | case 'ava-exit': return processAdapter.exit(0); // eslint-disable-line xo/no-process-exit; 49 | default: return process.emit(name, data); 50 | } 51 | }); 52 | -------------------------------------------------------------------------------- /renderer/starter.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* eslint-disable import/no-unassigned-import */ 4 | 5 | const {ipcRenderer} = require('electron'); 6 | const serializeError = require('ava/lib/serialize-error'); 7 | 8 | window.__avaron__ = true; 9 | 10 | // Below code is stub for ava process.send. 11 | process.send = () => { }; 12 | 13 | // Below code is stub for Node.js process.channel or process._channel. 14 | process.channel = { 15 | unref() { }, 16 | ref() { } 17 | }; 18 | 19 | function onUncaughtException(err) { 20 | ipcRenderer.send('ava-message', 'uncaughtException', { 21 | exception: serializeError(err) 22 | }); 23 | } 24 | 25 | process.on('uncaughtException', onUncaughtException); 26 | 27 | function parseArgv() { 28 | const unencodedHash = decodeURIComponent(window.location.hash.substr(1)); 29 | return JSON.parse(unencodedHash); 30 | } 31 | 32 | process.argv = parseArgv(); 33 | 34 | require('./console'); 35 | require('./process-adapter'); 36 | 37 | // Ensure the tests only run once 38 | ipcRenderer.once('test-start', () => { 39 | require('ava/lib/test-worker'); 40 | // Disable duplicate reporting 41 | process.removeListener('uncaughtException', onUncaughtException); 42 | }); 43 | -------------------------------------------------------------------------------- /renderer/test-helper.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | isAvaronRenderer() { 3 | if (typeof window === 'undefined') { 4 | return false; 5 | } 6 | return Boolean(window && window.__avaron__); 7 | }, 8 | getCurrentWindow() { 9 | if (typeof window === 'undefined') { 10 | return; 11 | } 12 | if (window.__avaron__) { 13 | const {remote} = require('electron'); 14 | return remote.getCurrentWindow(); 15 | } 16 | }, 17 | screenshot(imagePath) { 18 | return new Promise((resolve, reject) => { 19 | if (typeof window === 'undefined') { 20 | return resolve(); 21 | } 22 | if (!window.__avaron__) { 23 | return resolve(); 24 | } 25 | const fs = require('fs'); 26 | const {remote} = require('electron'); 27 | const mkdirp = require('make-dir'); 28 | const path = require('path'); 29 | const win = remote.getCurrentWindow(); 30 | requestIdleCallback(() => { 31 | win.capturePage(img => { 32 | const size = img.getSize(); 33 | const ratio = window.devicePixelRatio; 34 | const png = img.resize({width: size.width / ratio, height: size.height / ratio}).toDataURL(); 35 | const data = png.split(',')[1]; 36 | mkdirp(path.dirname(imagePath)) 37 | .then(() => { 38 | fs.writeFile(imagePath, data, 'base64', resolve); 39 | }) 40 | .catch(err => { 41 | reject(err); 42 | }); 43 | }); 44 | }, {timeout: 1000}); 45 | }); 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /test/common/add.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | 3 | const add = (a, b) => a + b; 4 | 5 | test('add test', async t => { 6 | t.is(add(1, 2), 3); 7 | }); 8 | -------------------------------------------------------------------------------- /test/common/async.test.js: -------------------------------------------------------------------------------- 1 | 2 | import test from 'ava'; 3 | 4 | test('async test', async t => { 5 | const wait = (time) => new Promise(resolve => { 6 | setTimeout(() => resolve(), time); 7 | }); 8 | await wait(1000); 9 | t.pass(); 10 | }); 11 | -------------------------------------------------------------------------------- /test/common/log.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | 3 | test('log test', t => { 4 | t.log('log'); 5 | t.pass(); 6 | }); 7 | -------------------------------------------------------------------------------- /test/common/snapshot.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import React from 'react'; 3 | import render from 'react-test-renderer'; 4 | 5 | const HelloWorld = () =>

Hello World.....!

; 6 | const HelloReact = (props) =>
{props.children}
; 7 | 8 | test('React Component snapshot test', t => { 9 | const tree = render.create( 10 | 11 | 12 | 13 | ).toJSON(); 14 | t.snapshot(tree); 15 | }); 16 | -------------------------------------------------------------------------------- /test/common/snapshots/snapshot.test.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `test/common/snapshot.test.js` 2 | 3 | The actual snapshot is saved in `snapshot.test.js.snap`. 4 | 5 | Generated by [AVA](https://ava.li). 6 | 7 | ## React Component snapshot test 8 | 9 | > Snapshot 1 10 | 11 |
12 |

13 | Hello World.....! 14 |

15 |

16 | Hello World.....! 17 |

18 |
19 | -------------------------------------------------------------------------------- /test/common/snapshots/snapshot.test.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bokuweb/avaron/2820085b88f5e8ce47058cebd4e8e024d7cf3e4f/test/common/snapshots/snapshot.test.js.snap -------------------------------------------------------------------------------- /test/main/main.test.js: -------------------------------------------------------------------------------- 1 | 2 | import test from 'ava'; 3 | import { BrowserWindow } from 'electron'; 4 | import { isAvaronRenderer } from '../../'; 5 | 6 | test('should create browserWindow', async t => { 7 | const window = new BrowserWindow({}); 8 | t.is(!!window, true); 9 | }); 10 | 11 | test('should isAvaronRenderer return false', async t => { 12 | t.is(Boolean(isAvaronRenderer()), false); 13 | }); 14 | -------------------------------------------------------------------------------- /test/renderer/renderer.test.js: -------------------------------------------------------------------------------- 1 | 2 | import test from 'ava'; 3 | import React from 'react'; 4 | import { readFileSync } from 'fs'; 5 | import { render } from 'react-dom'; 6 | import { screenshot, isAvaronRenderer, getCurrentWindow } from '../../'; 7 | import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; 8 | import DatePickerDialog from 'material-ui/DatePicker/DatePickerDialog'; 9 | import injectTapEventPlugin from 'react-tap-event-plugin'; 10 | 11 | injectTapEventPlugin(); 12 | 13 | let datePicker; 14 | 15 | const Example = () => ( 16 | 17 | { datePicker = e; }} 19 | initialDate={new Date(2017, 4, 1)} 20 | firstDayOfWeek={0} 21 | mode="landscape" 22 | /> 23 | 24 | ); 25 | 26 | test('should capture react component screenshot', async t => { 27 | render(, document.querySelector('.main')); 28 | datePicker.show(); 29 | const path = 'screenshots/should_capture_react_component_screenshot.png'; 30 | await new Promise((resolve) => setTimeout(() => resolve(), 200)); 31 | await screenshot(path); 32 | try { 33 | const png = readFileSync(path); 34 | t.is(!!png, true); 35 | } catch (e) { 36 | console.error(e); 37 | t.fail(); 38 | } 39 | }); 40 | 41 | test('should isAvaron return true', async t => { 42 | t.is(Boolean(isAvaronRenderer()), true); 43 | }); 44 | 45 | test('should get currentWindow', async t => { 46 | const win = getCurrentWindow(); 47 | t.is(Boolean(getCurrentWindow()), true); 48 | }); 49 | -------------------------------------------------------------------------------- /test/snapshots/snapshot.test.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `test/snapshot.test.js` 2 | 3 | The actual snapshot is saved in `snapshot.test.js.snap`. 4 | 5 | Generated by [AVA](https://ava.li). 6 | 7 | ## HelloWorld component 8 | 9 | > Snapshot 1 10 | 11 |

12 | Hello World.....! 13 |

14 | -------------------------------------------------------------------------------- /test/snapshots/snapshot.test.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bokuweb/avaron/2820085b88f5e8ce47058cebd4e8e024d7cf3e4f/test/snapshots/snapshot.test.js.snap --------------------------------------------------------------------------------