Run JavaScript in a browser, forward browser console log to stdout, great for running unit tests in browser.
npm i -D browser-do
Requires minimum Node.js v8.9+.
browser-do is an alternative implementation of browser-run and tape-run, with better Windows support, supports running mocha, jasmine, tape unit tests out of the box.
browser-do offers:
- Browser detection borrowed from various karma browser launchers. Simpler and more reliable on Windows than browser-launcher.
- TAP output support.
- Kept browser-run options
-p, --port
,-b, --browser browser-name
,-s, --static
, and-m, --mock
. - Removed
--input html
as browser-do auto detects input format. - Removed
-n, --node
and--basedir
as browser-do doesn't want to support Node.js code. (In original browser-run, Node.js code only works with electron anyway) - Added options
-t, --tap
to handle generic TAP output. - Added
--jasmine
and--mocha
to conveniently support jasmine/mocha (setup global vars, switch to TAP reporter). - Added
-k, --keep-open
(inherited from tap-run) to keep browser running after TAP finished.
browser-do is simple and flexible. Just pipe your code to browser-do with a browser of your choice (default to a headless electron).
browserify test/all-my-tape-tests.js | browser-do --tap
browserify test/all-my-jasmine-tests.js | browser-do --jasmine
browserify test/all-my-mocha-tests.js | browser-do --mocha --browser chrome-headless
Note browserify doesn't support glob, that's why we cannot use
browserify 'test/**/*.spec.js'
here.
You don't need to use browserify with browser-do. You can prepare a JavaScript bundle with any bundler, then just pipe it to browser-do.
cat dist/my-test-bundle.js | browser-do --tap # or jasmine/mocha
# or avoid "cat" on windows
browser-do --tap < dist/my-test-bundle.js
# Or in PowerShell
Get-Content dist/my-test-bundle.js | browser-do --tap # or jasmine/mocha
One more tip, because browser-do normalises tape/jasmine/mocha into TAP output, you can further pipe it to any TAP pretty reporters
browserify test/all-my-jasmine-tests.js | browser-do --jasmine | tap-dot
electron is the always available default.
macOS | Linux | Windows | |
---|---|---|---|
electron (default) | Yes | Yes | Yes |
chrome | Yes | Yes | Yes |
chrome-headless | Yes | Yes | Yes |
chromium | Yes | Yes | Yes |
chromium-headless | Yes | Yes | Yes |
firefox | Yes | Yes | Yes |
firefox-headless | Yes | Yes | Yes |
ie | Yes | ||
edge | Yes | Yes | |
edge-headless | Yes | Yes | |
safari | Yes |
browser-do latest v2 only supports Chromium based Microsoft Edge. To work with old Microsoft Edge, please use browser-do v1.
Usage: browser-do [options]
Options:
-V, --version output the version number
-b, --browser <name> Browser to use, see available browsers below (default: "electron")
-p, --port <port> Starts listening on that port and waits for you to open a browser
-s, --static <path> Serve static assets from this directory
-m, --mock <path> Path to code to handle requests for mocking a dynamic back-end
-t, --tap Treat output as TAP test result, automatically exit when TAP finishes
--jasmine Support jasmine test, uses jasmine TAP reporter, implicitly turns on option "tap", automatically exit when TAP finishes
--mocha Support mocha test, assumes BDD setup, uses TAP reporter, implicitly turns on option "tap", automatically exit when TAP finishes
-k, --keep-open Only for -t, --tap, --jasmine and --mocha, leave the browser open for debugging after running tests
-h, --help output usage information
Available browsers if installed (for -b, --browser <name>):
electron (embedded, default choice), chrome, chrome-headless, chromium, chromium-headless, firefox, firefox-headless, ie, edge, edge-headless, safari
There is some tolerance on browser name, for example:
-b ChromeHeadless
-b chromeHeadless
-b chrome_headless
-b "chrome headless"
all work just like -b chrome-headless
Your can provide a custom html file for browser-do to use. Keep in mind it always needs to have <script src="/reporter.js"></script>
above other script tags so browser-do is able to properly forward your console.log
s etc to the terminal.
Different from browser-run, you don't need
--input html
, browser-do detects the input automatically.
You would need to combine custom html file with
--static some-dir
or--mock mock-code.js
in order to have some way to load your JavaScript code.
By using --mock mock.js
(or { mock: 'mock.js'}
in code) you can provide a custom server-side implementation and handle all requests that are sent to paths beginning with /mock
mock.js needs to export a function that accepts req
and res
arguments for handling requests.
Example:
module.exports = function(req, res){
if (req.url === '/mock/echo') {
req.pipe(res);
}
};
API: run(opts)
, all the opts have same meaning as the command line options.
port
, browser
, static
, mock
, tap
, jasmine
, mocha
, and keepOpen
.
var run = require('browser-do');
var browser = run();
browser.pipe(process.stdout);
browser.end('console.log(location); window.close()');
Note
window.close()
will quit the default electron browser, but it would not work with some other browsers. Because many browsers rejectwindow.close()
for a window not opened by JavaScript. (In browser perspective, it opened a URL, although browser-do programmatically did that.)
When using browser-do in code with a browser not electron, you have to close the window manually (only if you didn't use tap
, jasmine
or mocha
option).
var run = require('browser-do');
var browser = run({browser: 'chrome'});
browser.pipe(process.stdout);
browser.end('console.log(location);');
setTimeout(function() { browser.stop(); }, 5000);
Follow example takes unit test JS code from stdin, capture final result (either pass or fail).
var run = require('browser-do');
var browser = run({tap: true}); // or jasmine: true, or mocha: true
process.stdin.pipe(browser).pipe(process.stdout);
browser.on('exit', code => {
// the code is 0 for passed tests, 1 for failed tests
});
Note browser-do only generates a simple pass/fail result from the whole TAP output. browser-do retains original TAP output, so if you need detailed TAP output parsing, further pipe the stream to tap-parser.
browser-do conveniently supports running mocha, jasmine, tape unit tests out of the box.
Tape is easy to support, as it doesn't pollute global variables. All browser-do needs to do is to parse TAP output and automatically exit when tests finish.
browserify some-tap-test.js | browser-do -t # or --tap
browser-do helps jasmine test by setup global vars before running your code.
browserify some-jasmine-test.js | browser-do --jasmine
You don't need to load jasmine before running your code, browser-do does that automatically, as long as you did npm i -D jasmine-core
.
FYI, here is the special index.html
browser-do provided for jasmine. Showing here only to help you to understand how browser-do does the magic.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="/reporter.js"></script>
<link rel="stylesheet" href="/jasmine-core/jasmine.css">
</head>
<body>
<script src="/jasmine-core/jasmine.js"></script>
<script src="/jasmine-core/jasmine-html.js"></script>
<script src="/jasmine-core/boot.js"></script>
<script src="/jasmine-tap-reporter.js"></script>
<script src="/bundle.js"></script> <!-- Your code is loaded here! -->
</body>
</html>
browser-do helps mocha test by setup global vars before running your code.
browserify some-mocha-test.js | browser-do --mocha
You don't need to load mocha before running your code, browser-do does that automatically, as long as you did npm i -D mocha
.
FYI, here is the special index.html
browser-do provided for mocha. Showing here only to help you to understand how browser-do does the magic.
Note we use default BDD style in mocha.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="/reporter.js"></script>
<link rel="stylesheet" href="/mocha/mocha.css">
</head>
<body>
<div id="mocha"></div>
<script src="/mocha/mocha.js"></script>
<script class="mocha-init">
mocha.setup({ui: "bdd", reporter: "tap"});
</script>
<script src="/bundle.js"></script> <!-- Your code is loaded here! -->
<script class="mocha-exec">
mocha.run();
</script>
</body>
</html>
The default mocha setup uses "tap" reporter so browser-do can understand tests result.
Only for mocha, when
-k, --keep-open
option is on, it switches setup to use "html" reporter. Because mocha doesn't support multiple reporters, and we want to show user a nice result in browser window. As a result, browser-do cannot detect the final test result inkeepOpen
mode.
If you want to use different setup of mocha, just pipe a custom html file to browser-do
cat my-mocha-index.html | browser-do --mocha --static .
# or avoid "cat" on windows
browser-do --mocha --static . < my-mocha-index.html
In your special html file:
- you need
<script src="/reporter.js"></script>
above any script tags. - you need retain most of the above html file, just modify the mocha setup part.
- you need something like
<script src="/dist/my-prepared-bundle.js"></script>
to replace<script src="/bundle.js"></script>
, you need to make sure you generated that bundle file before using browser-do. - The
--static .
option is to let browser-do to access all the local files including thedist/my-prepared-bundle.js
.
When running unit tests with browser-do, you need xvfb on Linux.
- run: xvfb-run -a npm test
if: runner.os == 'Linux'
- run: npm test
if: runner.os != 'Linux'
You may also need to enlarge xvfb default screen size (640x480x8) for your tests.
xvfb-run -a -s '-screen 0 1024x768x24' npm test
To use browser-do on travis, add this to your .travis.yml
:
addons:
apt:
packages:
- xvfb
before_install:
- export DISPLAY=':99.0'
- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
If you run travis with multiple OS including windows:
os:
- linux
- windows
- osx
addons:
apt:
packages:
- xvfb
before_install:
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export DISPLAY=':99.0' ; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & fi
browser-do supports code coverage in a humble way. To understand how browser-do supports it, first we need to understand how nyc/Istanbul works internally.
To generate code coverage report, when in Node.js environment, nyc/Istanbul needs to
- instrument source code. It injects special code into your source code in order to gather code coverage information.
- when running unit tests, those instrumented source code writes code coverage information into an intermediate JavaScript object
global.__coverage__
. This becomeswindow.__coverage__
in browser. - nyc automatically writes
global.__coverage__
object to a local json file in.nyc_output/
folder. - nyc then uses various reporters to turn the json file into human readable report (text summary, or html file).
When running browser-do, your unit tests is running in browser. All browser-do does is:
- if your source code is instrumented, it will generate
window.__coverage__
object. browser-do does nothing here. - when tape/jasmine/mocha tests finished, browser-do check whether there is
window.__coverage__
. If so, it will write the object to.nyc_output/out.json
(the default nyc output file).
You then can follow it up with another command to turn that json file into readable report!
npx nyc report --reporter=lcov --reporter=text
Here browser-do does the bare minimum job: only writes window.__coverage__
into .nyc_output/out.json
when window.__coverage__
exits.
The task of instrumenting is not handled by browser-do, nor should (as browser-do is the consumer of a piece of JavaScript, not the creator).
For projects using babel, you can easily turn on babel-plugin-istanbul in test environment. That plugin will instrument your code.
I have not found out what's the native way to instrument TypeScript file. But if you use babel to compile ts files, you can continue to use babel-plugin-istanbul.
For example on babel-plugin-istanbul + browser-do + nyc, try to create a SPA app with dumberjs skeleton:
npx makes dumberjs
Choose Aurelia or Vue (but not .vue single file component), babel, jasmine/mocha/tape, (not jest. jest runs in Node.js, not browser, is irrelevant here). Then follow the README file on code coverage. Note the React non-jest setup has some trouble in code coverage right now.
browser-do is licensed under the MIT license.
browser-do borrowed code from many projects, details in ACKNOWLEDGEMENT.