├── .gitignore ├── .travis.yml ├── README.md ├── cli.js ├── index.js ├── package.json └── test ├── client-test.js └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 'iojs' 4 | before_script: 5 | - export DISPLAY=:99.0; sh -e /etc/init.d/xvfb start 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # testron 2 | CI your client side tests with Electron 3 | 4 | [![build status](https://secure.travis-ci.org/shama/testron.svg)](https://travis-ci.org/shama/testron) 5 | [![NPM version](https://badge.fury.io/js/testron.svg)](https://badge.fury.io/js/testron) 6 | [![experimental](http://hughsk.github.io/stability-badges/dist/experimental.svg)](http://github.com/hughsk/stability-badges) 7 | 8 | # about 9 | This uses [Electron](https://github.com/atom/electron) to run tests in 10 | [Chromium](http://www.chromium.org/). 11 | 12 | # usage 13 | 14 | * Install to your project: `npm install testron --save-dev` 15 | * Install Electron: `npm install electron-prebuilt --save-dev` 16 | * Add a `test` script to your `package.json`: 17 | ```json 18 | { 19 | "name": "my-project", 20 | "scripts": { 21 | "test": "testron test/client.js" 22 | }, 23 | } 24 | ``` 25 | * Run `npm test` to run the test script in Electron 26 | 27 | ## writing tests 28 | Currently this only supports TAP. Here is an example test written using [tape](https://www.npmjs.com/package/tape): 29 | 30 | ```js 31 | var test = require('tape') 32 | 33 | test('test this', function (t) { 34 | t.plan(1) 35 | var ul = document.createElement('ul') 36 | var li = document.createElement('li') 37 | ul.appendChild(li) 38 | li.textContent = 'it works' 39 | t.equal(ul.outerHTML, '') 40 | t.end() 41 | }) 42 | ``` 43 | 44 | It is recommended bundling your tests and piping to `testron`: 45 | 46 | ```json 47 | { 48 | "name": "my-project", 49 | "scripts": { 50 | "test": "browserify test/client.js | testron" 51 | }, 52 | } 53 | ``` 54 | 55 | ## travis-ci integration 56 | Add a `.travis.yml` file to your project: 57 | 58 | ```yml 59 | language: node_js 60 | node_js: 61 | - 'iojs' 62 | before_script: 63 | - export DISPLAY=:99.0; sh -e /etc/init.d/xvfb start 64 | ``` 65 | 66 | ## API 67 | There is also an API: 68 | 69 | ```js 70 | var testron = require('testron') 71 | var tests = testron('test/client.js') 72 | tests.stdout.on('data', function (data) { 73 | console.log('line: ' + data.toString()) 74 | }) 75 | tests.on('exit', function () { 76 | console.log('Tests are done!') 77 | }) 78 | ``` 79 | 80 | ## similar projects 81 | These are similar projects that also (can) use Electron for testing: 82 | 83 | * [hihat](https://github.com/Jam3/hihat) 84 | small tool for running browser tests locally 85 | * [zuul](https://github.com/defunctzombie/zuul) 86 | multi-framework javascript browser testing 87 | 88 | # license 89 | (c) 2018 Kyle Robinson Young. MIT License 90 | -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | process.title = 'testron' 4 | var path = require('path') 5 | var argv = require('minimist')(process.argv.slice(2)) 6 | var testron = require('./index.js') 7 | var tests 8 | 9 | if (argv._.length > 0) { 10 | tests = testron(argv._[0]) 11 | } else { 12 | process.stdin.resume() 13 | process.stdin.setEncoding('utf8') 14 | tests = testron() 15 | process.stdin.pipe(tests.stdin) 16 | } 17 | 18 | tests.stdout.pipe(process.stdout) 19 | if (argv['errors'] || argv['e']) { 20 | tests.stderr.pipe(process.stderr) 21 | } 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | if (process.versions['electron']) { 2 | module.exports = function (args) { 3 | var filename = args[1] || 'test.js' 4 | var old = process.stdout.write 5 | process.stdout.write = function (msg) { 6 | if (msg.toString().slice(0, 4) === '# ok' || msg.toString().slice(0, 6) === '# fail') { 7 | process.nextTick(function () { 8 | require('remote').require('app').quit() 9 | }) 10 | } 11 | old.apply(process.stdout, arguments) 12 | } 13 | process.nextTick(function () { 14 | require(filename) 15 | }) 16 | } 17 | } else { 18 | var fs = require('fs') 19 | var path = require('path') 20 | var through = require('through2') 21 | var tempfile = require('tempfile') 22 | var electronSpawn = require('electron-spawn') 23 | 24 | module.exports = function (filename) { 25 | if (filename) { 26 | return electronSpawn(__filename, filename) 27 | } else { 28 | return stream() 29 | } 30 | } 31 | 32 | function stream () { 33 | var tmpname = tempfile('.js') 34 | var s = { 35 | stdin: fs.createWriteStream(tmpname), 36 | stdout: through(), 37 | stderr: through() 38 | } 39 | s.stdin.on('close', function () { 40 | var electron = electronSpawn(__filename, tmpname) 41 | electron.stdout.pipe(s.stdout) 42 | electron.stderr.pipe(s.stderr) 43 | electron.on('exit', function () { 44 | fs.unlink(tmpname, function (err) { 45 | if (err) console.error(err) 46 | }) 47 | }) 48 | }) 49 | return s 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "testron", 3 | "version": "1.2.1", 4 | "description": "CI your client side tests with Electron", 5 | "main": "index.js", 6 | "bin": { 7 | "testron": "cli.js" 8 | }, 9 | "scripts": { 10 | "test": "node test/test.js" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+ssh://git@github.com/shama/testron.git" 15 | }, 16 | "keywords": [ 17 | "test", 18 | "client", 19 | "side", 20 | "runner", 21 | "electron", 22 | "ci" 23 | ], 24 | "author": "Kyle Robinson Young (http://dontkry.com)", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/shama/testron/issues" 28 | }, 29 | "homepage": "https://github.com/shama/testron#readme", 30 | "dependencies": { 31 | "electron-spawn": "^3.0.0", 32 | "minimist": "^1.1.2", 33 | "tempfile": "^1.1.1", 34 | "through2": "^2.0.0" 35 | }, 36 | "devDependencies": { 37 | "electron-prebuilt": "^0.30.0", 38 | "tape": "^4.0.1" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/client-test.js: -------------------------------------------------------------------------------- 1 | process.browser = true 2 | var test = require('tape') 3 | 4 | test('test that tests work', function (t) { 5 | t.plan(1) 6 | var ul = document.createElement('ul') 7 | var li = document.createElement('li') 8 | ul.appendChild(li) 9 | li.textContent = 'it works' 10 | t.equal(ul.outerHTML, '', 'client-test should have worked') 11 | t.end() 12 | }) 13 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var path = require('path') 3 | var testron = require('../index.js') 4 | 5 | test('runs some tests on client side', function (t) { 6 | t.plan(1) 7 | var tests = testron(path.resolve(__dirname, 'client-test.js')) 8 | var result = [] 9 | tests.stdout.on('data', function (data) { 10 | result.push(data.toString()) 11 | }) 12 | tests.on('exit', function () { 13 | result = result.join('') 14 | t.ok(result.indexOf('client-test should have worked') != -1, 'should have been notified it worked') 15 | t.end() 16 | }) 17 | }) 18 | --------------------------------------------------------------------------------