├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── .npmignore
├── .travis.yml
├── CONTRIBUTING.md
├── History.md
├── README.md
├── bin
└── bin.js
├── browser
└── reporter.js
├── example
├── error.js
└── simple.js
├── index.js
├── lib
└── launch.js
├── package-lock.json
├── package.json
├── static
└── index.html
├── tea.yaml
└── test
├── close.js
├── electron.js
├── empty.js
├── error.js
├── input.js
├── spawn.js
├── static.js
└── stream.js
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | - push
4 | - pull_request
5 | jobs:
6 | test:
7 | runs-on: ubuntu-latest
8 | strategy:
9 | matrix:
10 | node: ['14', '16', '18']
11 | steps:
12 | - uses: actions/checkout@v2
13 | - uses: actions/setup-node@v2
14 | with:
15 | node-version: ${{ matrix.node }}
16 | - run: npm ci
17 | - run: sudo apt-get install xvfb
18 | - run: xvfb-run --auto-servernum npm test
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.sw*
2 | node_modules
3 | static/reporter.js
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | browser/
2 | test/
3 | .*
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 10
4 | - 12
5 | - 14
6 | addons:
7 | apt:
8 | packages:
9 | - xvfb
10 | install:
11 | - export DISPLAY=':99.0'
12 | - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
13 | - npm install
14 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## `browser-run` is an **OPEN Open Source Projects**
2 | -----------------------------------------
3 |
4 | ## What?
5 |
6 | Individuals making significant and valuable contributions are given commit-access to a project to contribute as they see fit. A project is more like an open wiki than a standard guarded open source project.
7 |
8 | ## Rules
9 |
10 | There are a few basic ground-rules for contributors:
11 |
12 | 1. **No `--force` pushes** or modifying the Git history in any way.
13 | 1. **Non-master branches** ought to be used for ongoing work.
14 | 1. **External API changes and significant modifications** ought to be subject to an **internal pull-request** to solicit feedback from other contributors.
15 | 1. Internal pull-requests to solicit feedback are *encouraged* for any other non-trivial contribution but left to the discretion of the contributor.
16 | 1. Contributors should attempt to adhere to the prevailing code-style.
17 |
18 | ## Releases
19 |
20 | Declaring formal releases remains the prerogative of the project maintainer(s).
21 |
22 | ## Changes to this arrangement
23 |
24 | This is an experiment and feedback is welcome! This document may also be subject to pull-requests or changes by contributors where you believe you have something valuable to add or change.
25 |
26 | -----------------------------------------
27 |
28 | Taken with much kudos from https://github.com/Level/community/blob/master/CONTRIBUTING.md#level-projects-are-open-open-source-projects
29 |
--------------------------------------------------------------------------------
/History.md:
--------------------------------------------------------------------------------
1 |
2 | 0.4.0 / 2014-08-12
3 | ==================
4 |
5 | * update browserify for security reasons
6 | * add history
7 |
8 | 0.3.0 / 2014-07-13
9 | ==================
10 |
11 | * attempt fixing unicode problems
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # browser-run
2 |
3 | The easiest way of running code in a browser environment.
4 |
5 | Bundles `electronjs` by default!
6 |
7 | [](https://github.com/juliangruber/browser-run/actions/workflows/ci.yml)
8 | [](https://www.npmjs.org/package/browser-run)
9 |
10 | ## Usage
11 |
12 | ```bash
13 | $ echo "console.log('Hey from ' + location); window.close()" | browser-run
14 | Hey from http://localhost:53227/
15 | $
16 | ```
17 |
18 | Or use `browser-run` programmatically:
19 |
20 | ```js
21 | var run = require('browser-run');
22 |
23 | var browser = run();
24 | browser.pipe(process.stdout);
25 | browser.end('console.log(location); window.close()');
26 | ```
27 |
28 | ## Example with browserify
29 |
30 | ```bash
31 | $ browserify main.js | browser-run
32 | ```
33 |
34 | or
35 |
36 | ```js
37 | var browserify = require('browserify');
38 | var browser = require('browser-run');
39 |
40 | browserify('main.js').bundle().pipe(browser()).pipe(process.stdout);
41 | ```
42 |
43 | ## CLI
44 |
45 | ```bash
46 | $ browser-run --help
47 | Run JavaScript in a browser.
48 | Write code to stdin and receive console output on stdout.
49 | Usage: browser-run [OPTIONS]
50 |
51 | Options:
52 | --version Show version number [boolean]
53 | -b, --browser Browser to use. Always available: electron. Available if
54 | installed: chrome, firefox, ie, safari [default: "electron"]
55 | --sandbox Enable electron sandbox [boolean] [default: true]
56 | --basedir Set this if you need to require node modules in node mode
57 | -h, --help Print help [boolean]
58 | -p, --port Starts listening on that port and waits for you to open a
59 | browser
60 | -s, --static Serve static assets from this directory
61 | -m, --mock Path to code to handle requests for mocking a dynamic back-end
62 | -i, --input Input type. Defaults to 'javascript', can be set to 'html'.
63 | -n, --node Enable nodejs apis in electron
64 | ```
65 |
66 | ## Custom html file
67 |
68 | By using `--input html` or `{ input: 'html' }` you can provide a custom html file for browser-run to use. Keep in mind though that it always needs to have `` above other script tags so browser-run is able to properly forward your `console.log`s etc to the terminal.
69 |
70 | ## Dynamic back-end mock
71 |
72 | By using `--mock mock.js` or `{ mock: 'mock.js'}` you can provide a custom server-side implementation and handle all requests that are sent to paths beginning with `/mock`
73 |
74 | mock.js needs to export a function that accepts `req` and `res` arguments for handling requests.
75 |
76 | Example:
77 |
78 | ```js
79 | module.exports = function(req,res){
80 | if (req.url === '/mock/echo') {
81 | req.pipe(res)
82 | }
83 | }
84 | ```
85 |
86 | ## API
87 |
88 | ### run([opts])
89 |
90 | Returns a duplex stream and starts a webserver.
91 |
92 | `opts` can be:
93 |
94 | * `port`: If speficied, no browser will be started, so you can point one yourself to `http://localhost/`
95 | * `browser`: Browser to use. Defaults to `electron`. Available if installed:
96 | * `chrome`
97 | * `firefox`
98 | * `ie`
99 | * `safari`
100 | * `static`: Serve static files from this directory
101 | * `mock`: Path to code to handle requests for mocking a dynamic back-end
102 | * `input`: Input type. Defaults to `javascript`, can be set to `html`.
103 | * `node`: Enable nodejs integration in electron
104 | * `sandbox`: Enable electron sandbox. Default: `true`.
105 | * `basedir`: Set this if you need to require node modules in `node` mode
106 |
107 | If only an empty string is written to it, an error will be thrown as there is nothing to execute.
108 |
109 | If you call `window.close()` inside the script, the browser will exit.
110 |
111 | ### run#stop()
112 |
113 | Stop the underlying webserver.
114 |
115 | ## Headless testing
116 |
117 | In environments without a screen, you can use `Xvfb` to simulate one.
118 |
119 | ### GitHub Actions
120 |
121 | This is a full example to run `npm test`. Refer to the last 2 lines in the YAML config:
122 |
123 | ```yml
124 | on:
125 | - pull_request
126 | - push
127 |
128 | jobs:
129 | test:
130 | runs-on: ubuntu-latest
131 | steps:
132 | - uses: actions/checkout@v4
133 | - run: npm install
134 | - run: xvfb-run npm test
135 | timeout-minutes: 5 # If the tests fails, the browser will hang open indefinitely
136 | ```
137 |
138 | ### Travis
139 |
140 | Add this to your travis.yml:
141 |
142 | ```yml
143 | addons:
144 | apt:
145 | packages:
146 | - xvfb
147 | install:
148 | - export DISPLAY=':99.0'
149 | - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
150 | - npm install
151 | ```
152 |
153 | [Full example](https://github.com/rhysd/Shiba/blob/055a11a0a2b4f727577fe61371a88d8db9277de5/.travis.yml).
154 |
155 | ### Any gnu/linux box
156 |
157 | ```bash
158 | $ sudo apt-get install xvfb # or equivalent
159 | $ export DISPLAY=':99.0'
160 | $ Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
161 | $ browser-run ...
162 | ```
163 |
164 | ### Docker
165 |
166 | There is also an example [Docker image](https://hub.docker.com/r/kipparker/docker-tape-run). [Source](https://github.com/fraserxu/docker-tape-run)
167 |
168 | ## Installation
169 |
170 | With [npm](http://npmjs.org) do
171 |
172 | ```bash
173 | $ npm install browser-run # for library
174 | $ npm install -g browser-run # for cli
175 | ```
176 |
177 | ## Sponsors
178 |
179 | This module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)!
180 |
181 | Do you want to support modules like this to improve their quality, stability and weigh in on new features? Then please consider donating to my [Patreon](https://www.patreon.com/juliangruber). Not sure how much of my modules you're using? Try [feross/thanks](https://github.com/feross/thanks)!
182 |
183 | ## License
184 |
185 | (MIT)
186 |
--------------------------------------------------------------------------------
/bin/bin.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var run = require('..');
4 | var yargs = require('yargs/yargs')
5 |
6 | var argv = yargs(process.argv.slice(2))
7 | .usage(
8 | 'Run JavaScript in a browser.\n' +
9 | 'Write code to stdin and receive console output on stdout.\n' +
10 | 'Usage: $0 [OPTIONS]'
11 | )
12 |
13 | .describe('browser', 'Browser to use. '
14 | + 'Always available: electron. '
15 | + 'Available if installed: '
16 | + 'chrome, firefox, ie, safari')
17 | .alias('browser', 'b')
18 | .default('browser', 'electron')
19 |
20 | .describe('port', 'Starts listening on that port and waits for you to open a browser')
21 | .alias('p', 'port')
22 |
23 | .describe('static', 'Serve static assets from this directory')
24 | .alias('s', 'static')
25 |
26 | .describe('mock', 'Path to code to handle requests for mocking a dynamic back-end')
27 | .alias('m', 'mock')
28 |
29 | .describe('input', 'Input type. Defaults to \'javascript\', can be set to \'html\'.')
30 | .alias('i', 'input')
31 |
32 | .describe('node', 'Enable nodejs apis in electron')
33 | .alias('n', 'node')
34 |
35 | .describe('sandbox', 'Enable electron sandbox')
36 | .boolean('sandbox')
37 | .default('sandbox', true)
38 |
39 | .describe('basedir', 'Set this if you need to require node modules in node mode')
40 |
41 | .help('h')
42 | .describe('help', 'Print help')
43 | .alias('h', 'help')
44 |
45 | .argv;
46 |
47 | argv.nodeIntegration = argv['node-integration']
48 |
49 | process.stdin
50 | .pipe(run(argv))
51 | .pipe(process.stdout);
52 |
--------------------------------------------------------------------------------
/browser/reporter.js:
--------------------------------------------------------------------------------
1 | ;(function () {
2 | require('source-map-support').install();
3 |
4 | if (!/Electron/.test(window.navigator.userAgent)) {
5 | var close = window.close;
6 | window.close = function () {
7 | setTimeout(function () {
8 | close.call(window);
9 | }, 1000);
10 | };
11 |
12 | window.onerror = function (msg, file, line, column, err) {
13 | if (err && msg.indexOf(err.stack) > -1) {
14 | err.stack = err.stack + '\n at ' + file + ':' + line + ':' + column
15 | }
16 | console.error(err && err.stack
17 | || err
18 | || back);
19 | };
20 |
21 | var xws = require('xhr-write-stream')('/xws');
22 | var ws = require('utf8-stream')();
23 | ws.pipe(xws);
24 |
25 | var console = window.console || {};
26 | var methods = ['log', 'error', 'warn', 'dir', 'debug', 'info', 'trace'];
27 | for (var i = 0; i < methods.length; i++) (function (method) {
28 | var old = console[method];
29 | console[method] = function (msg) {
30 | ws.write(Array.prototype.slice.call(arguments, 0).join(' ') + '\n');
31 | if (old) old.apply(console, arguments);
32 | if (msg instanceof Error && typeof JSON != 'undefined') {
33 | ws.write(JSON.stringify(msg) + '\n');
34 | }
35 | }
36 | })(methods[i]);
37 | }
38 |
39 | })();
40 |
--------------------------------------------------------------------------------
/example/error.js:
--------------------------------------------------------------------------------
1 | function foo(){ throw new Error('bar') }
2 | console.log('about to call foo');
3 | foo();
4 |
--------------------------------------------------------------------------------
/example/simple.js:
--------------------------------------------------------------------------------
1 | console.log(location);
2 | window.close();
3 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var http = require('http');
2 | var path = require('path');
3 | var spawn = require('child_process').spawn;
4 | var through = require('through');
5 | var duplex = require('duplexer');
6 | var fs = require('fs');
7 | var xws = require('xhr-write-stream')();
8 | var enstore = require('enstore');
9 | var launch = require('./lib/launch');
10 | var ecstatic = require('ecstatic');
11 | var injectScript = require('html-inject-script');
12 | var destroyable = require('server-destroy');
13 | var extend = require('xtend')
14 |
15 | try {
16 | fs.statSync(__dirname + '/static/reporter.js')
17 | } catch (_) {
18 | console.error('Reporter script missing. Run `npm run build` first.')
19 | }
20 |
21 | module.exports = function (opts) {
22 | if (!opts) opts = {};
23 | if ('number' == typeof opts) opts = { port: opts };
24 | if (!opts.browser) opts.browser = 'electron';
25 | if (!opts.input) opts.input = 'javascript';
26 | return runner(opts);
27 | };
28 |
29 | function runner (opts) {
30 | var empty = true;
31 | var input = through(function (chunk) {
32 | if (empty && chunk.toString().trim() != '') empty = false;
33 | this.queue(chunk);
34 | }, function () {
35 | if (empty) dpl.emit('error', new Error('javascript required'));
36 | this.queue(null);
37 | });
38 | var bundle = enstore();
39 | input.pipe(bundle.createWriteStream());
40 | var output = through();
41 | var dpl = duplex(input, output);
42 |
43 | var mockHandler = opts.mock && require(path.resolve('./', opts.mock))
44 |
45 | var server = http.createServer(function (req, res) {
46 | if (opts.input === 'javascript') {
47 | if (/^\/bundle\.js/.test(req.url)) {
48 | res.setHeader('content-type', 'application/javascript');
49 | res.setHeader('cache-control', 'no-cache');
50 | bundle.createReadStream().pipe(res);
51 | return;
52 | }
53 |
54 | if (req.url == '/') {
55 | fs.createReadStream(__dirname + '/static/index.html').pipe(res);
56 | return;
57 | }
58 | } else if (opts.input === 'html') {
59 | if (req.url == '/') {
60 | bundle.createReadStream().pipe(injectScript(['/reporter.js'])).pipe(res);
61 | return;
62 | }
63 | }
64 |
65 | if (req.url == '/xws') {
66 | req.pipe(xws(function (stream) {
67 | stream.pipe(output);
68 | }));
69 | return req.on('end', res.end.bind(res));
70 | }
71 | if (req.url == '/reporter.js') {
72 | res.setHeader('content-type', 'application/javascript');
73 | fs.createReadStream(__dirname + '/static/reporter.js').pipe(res);
74 | return;
75 | }
76 | if (opts.static) {
77 | ecstatic({ root: opts.static })(req, res);
78 | return;
79 | }
80 | if (mockHandler && '/mock' === req.url.substr(0,5)){
81 | return mockHandler(req, res);
82 | }
83 |
84 | res.end('not supported');
85 | });
86 | destroyable(server);
87 |
88 | var browser;
89 |
90 | if (opts.port) {
91 | server.listen(opts.port);
92 | } else {
93 | server.listen(function () {
94 | var address = server.address();
95 | if (!address) return; // already closed
96 | var port = address.port;
97 |
98 | launch(extend(opts, {
99 | loc: 'http://localhost:' + port,
100 | name: opts.browser,
101 | bundle: bundle
102 | }), function(err, _browser){
103 | if (err) return dpl.emit('error', err);
104 | browser = _browser;
105 |
106 | // electron
107 | if (browser.pipe) {
108 | browser.setEncoding('utf8');
109 | browser.pipe(output);
110 | }
111 |
112 | browser.on('exit', function (code, signal) {
113 | try { server.destroy() } catch (e) {}
114 | dpl.emit('exit', code, signal);
115 | });
116 | });
117 | });
118 | }
119 |
120 | dpl.stop = function () {
121 | try { server.destroy(); } catch (e) {}
122 | if (browser) browser.kill();
123 | };
124 |
125 | return dpl;
126 | }
127 |
--------------------------------------------------------------------------------
/lib/launch.js:
--------------------------------------------------------------------------------
1 | var launcher = require('browser-launcher');
2 | var Electron = require('electron-stream');
3 |
4 | module.exports = function(opts, cb){
5 | if (/^electron/.test(opts.name)) {
6 | var browser = Electron(opts);
7 | if (opts.input === 'javascript') {
8 | opts.bundle.createReadStream().pipe(browser);
9 | } else {
10 | browser.end('location = ' + JSON.stringify(opts.loc));
11 | }
12 | process.nextTick(cb.bind(null, null, browser));
13 | } else {
14 | launcher(function(err, launch){
15 | if (err) return cb(err);
16 | launch(opts.loc, {
17 | headless: false,
18 | browser: opts.name
19 | }, cb);
20 | });
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "browser-run",
3 | "description": "Transform stream that executes JavaScript it receives in a real browser and outputs console output",
4 | "version": "12.0.0",
5 | "repository": {
6 | "type": "git",
7 | "url": "git://github.com/juliangruber/browser-run.git"
8 | },
9 | "homepage": "https://github.com/juliangruber/browser-run",
10 | "main": "index.js",
11 | "bin": {
12 | "browser-run": "./bin/bin.js"
13 | },
14 | "scripts": {
15 | "build": "browserify browser/reporter.js -o static/reporter.js",
16 | "prepublish": "npm run build",
17 | "release": "np",
18 | "test": "npm run build && node--test"
19 | },
20 | "dependencies": {
21 | "browser-launcher": "^3.0.1",
22 | "duplexer": "^0.1.1",
23 | "ecstatic": "^4.1.2",
24 | "electron-stream": "^11.0.0",
25 | "enstore": "^1.0.1",
26 | "html-inject-script": "^2.0.0",
27 | "server-destroy": "^1.0.1",
28 | "source-map-support": "^0.4.0",
29 | "through": "^2.3.8",
30 | "xhr-write-stream": "^0.1.2",
31 | "xtend": "^4.0.1",
32 | "yargs": "^16.2.0"
33 | },
34 | "devDependencies": {
35 | "browserify": "^14.1.0",
36 | "concat-stream": "^1.5.1",
37 | "np": "^8.0.4",
38 | "test": "^3.0.0",
39 | "tree-kill": "^1.0.0",
40 | "utf8-stream": "^0.0.0"
41 | },
42 | "keywords": [
43 | "browser",
44 | "stream",
45 | "test",
46 | "headless",
47 | "duplex"
48 | ],
49 | "author": {
50 | "name": "Julian Gruber",
51 | "email": "mail@juliangruber.com",
52 | "url": "http://juliangruber.com"
53 | },
54 | "license": "MIT",
55 | "engines": {
56 | "node": ">=14"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/tea.yaml:
--------------------------------------------------------------------------------
1 | # https://tea.xyz/what-is-this-file
2 | ---
3 | version: 1.0.0
4 | codeOwners:
5 | - '0xE7DEE1B8Bb97C3065850Cf582D6DED57C6009587'
6 | quorum: 1
7 |
--------------------------------------------------------------------------------
/test/close.js:
--------------------------------------------------------------------------------
1 | var test = require('test');
2 | var assert = require('assert');
3 | var run = require('..');
4 |
5 | test('window.close()', function (t, done) {
6 | var browser = run();
7 | var eventCount = 0;
8 |
9 | browser.on('data', function (data) {
10 | assert.strictEqual(data, 'foo\n', 'data');
11 | if (++eventCount === 2) done();
12 | });
13 |
14 | browser.on('exit', function (code) {
15 | assert.strictEqual(code, 0, 'exit');
16 | if (++eventCount === 2) done();
17 | });
18 |
19 | browser.write('console.log("foo");');
20 | browser.write('window.close();');
21 | browser.end();
22 | });
23 |
--------------------------------------------------------------------------------
/test/electron.js:
--------------------------------------------------------------------------------
1 | var test = require('test');
2 | var assert = require('assert');
3 | var run = require('..');
4 | var concat = require('concat-stream');
5 |
6 | test('electron', async function (t) {
7 | await t.test('nodeIntegration off by default', function (t, done) {
8 | var browser = run({
9 | browser: 'electron'
10 | });
11 | let eventCount = 0;
12 |
13 | browser.pipe(concat(function(data){
14 | assert(!/electron\.asar/.test(data.toString()));
15 | if (++eventCount === 2) done();
16 | }));
17 |
18 | browser.on('exit', function (code) {
19 | assert.strictEqual(code, 0, 'exit');
20 | if (++eventCount === 2) done();
21 | });
22 |
23 | browser.write('console.log(__dirname);');
24 | browser.write('window.close();');
25 | browser.end();
26 | });
27 | await t.test('nodeIntegration on', function (t) {
28 | var browser = run({
29 | browser: 'electron',
30 | nodeIntegration: true
31 | });
32 | let eventCount = 0;
33 |
34 | browser.pipe(concat(function(data){
35 | assert(/browser-run/.test(data.toString()));
36 | if (++eventCount === 2) done();
37 | }));
38 |
39 | browser.on('exit', function (code) {
40 | assert.strictEqual(code, 0, 'exit');
41 | if (++eventCount === 2) done();
42 | });
43 |
44 | browser.write('console.log(__dirname);');
45 | browser.write('window.close();');
46 | browser.end();
47 | });
48 | await t.test('basedir option', function (t) {
49 | var browser = run({
50 | browser: 'electron',
51 | node: true,
52 | basedir: __dirname + '/../'
53 | });
54 | let eventCount = 0;
55 |
56 | browser.pipe(concat(function(data){
57 | assert(/^true\n$/.test(data.toString()));
58 | if (++eventCount === 2) done();
59 | }));
60 |
61 | browser.on('exit', function (code) {
62 | assert.strictEqual(code, 0, 'exit');
63 | if (++eventCount === 2) done();
64 | });
65 |
66 | browser.write('console.log(!!require.resolve("test"));');
67 | browser.write('window.close();');
68 | browser.end();
69 | });
70 | await t.test('supports async functions', function (t) {
71 | var browser = run({
72 | browser: 'electron'
73 | });
74 | let eventCount = 0;
75 |
76 | browser.pipe(concat(function(data){
77 | assert.strictEqual(data.toString(), 'ok\n');
78 | if (++eventCount === 2) done();
79 | }));
80 |
81 | browser.on('exit', function (code) {
82 | assert.strictEqual(code, 0, 'exit');
83 | if (++eventCount === 2) done();
84 | });
85 |
86 | browser.write('const fn = async () => \'ok\';');
87 | browser.write('fn().then(text => { console.log(text); window.close(); })');
88 | browser.end();
89 | });
90 | });
91 |
--------------------------------------------------------------------------------
/test/empty.js:
--------------------------------------------------------------------------------
1 | var test = require('test');
2 | var assert = require('assert');
3 | var run = require('..');
4 |
5 | test('empty', function (t, done) {
6 | var browser = run();
7 |
8 | browser.on('data', function (data) {
9 | throw new Error(data.toString());
10 | });
11 |
12 | browser.on('error', function (err) {
13 | browser.stop();
14 | assert(err);
15 | done();
16 | });
17 |
18 | browser.write(' ');
19 | browser.end();
20 | });
21 |
--------------------------------------------------------------------------------
/test/error.js:
--------------------------------------------------------------------------------
1 | var test = require('test');
2 | var assert = require('assert');
3 | var run = require('..');
4 |
5 | test('error', function (t, done) {
6 | var browser = run({ browser: 'foobar' });
7 |
8 | browser.on('error', function (err) {
9 | browser.stop();
10 | assert(err);
11 | done();
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/test/input.js:
--------------------------------------------------------------------------------
1 | var test = require('test');
2 | var assert = require('assert');
3 | var run = require('..');
4 | var concat = require('concat-stream');
5 |
6 | test('input=javascript (default)', function (t, done) {
7 | var browser = run();
8 | let eventCount = 0;
9 |
10 | browser.pipe(concat(function(data){
11 | assert.strictEqual('\n', data.toString());
12 | if (++eventCount === 2) done();
13 | }));
14 |
15 | browser.on('exit', function (code) {
16 | assert.strictEqual(code, 0, 'exit');
17 | if (++eventCount === 2) done();
18 | });
19 |
20 | browser.write('console.log(document.title);');
21 | browser.write('window.close();');
22 | browser.end();
23 | });
24 |
25 | test('input=html', function (t, done) {
26 | var browser = run({
27 | input: 'html'
28 | });
29 | let eventCount = 0;
30 |
31 | browser.pipe(concat(function(data){
32 | assert.strictEqual('FOO\n', data.toString());
33 | if (++eventCount === 2) done();
34 | }));
35 |
36 | browser.on('exit', function (code) {
37 | assert.strictEqual(code, 0, 'exit');
38 | if (++eventCount === 2) done();
39 | });
40 |
41 | browser.write('FOO');
42 | browser.write('');
43 | browser.end();
44 | });
45 |
--------------------------------------------------------------------------------
/test/spawn.js:
--------------------------------------------------------------------------------
1 | var test = require('test');
2 | var assert = require('assert');
3 | var spawn = require('child_process').spawn;
4 | var kill = require('tree-kill');
5 |
6 | test('spawn', function (t, done) {
7 | var ps = spawn(__dirname + '/../bin/bin.js');
8 |
9 | ps.stdout.on('data', function (data) {
10 | assert.strictEqual(data.toString(), 'foo\n');
11 | kill(ps.pid);
12 | done();
13 | });
14 | ps.stderr.on('data', d => { throw new Error(d.toString()) });
15 |
16 | ps.stdin.write('console.log("foo");');
17 | ps.stdin.end();
18 | });
19 |
--------------------------------------------------------------------------------
/test/static.js:
--------------------------------------------------------------------------------
1 | var test = require('test');
2 | var assert = require('assert');
3 | var run = require('..');
4 | var fs = require('fs');
5 |
6 | test('static', function (t, done) {
7 | var browser = run({ static: __dirname });
8 |
9 | browser.on('data', function (data) {
10 | assert.strictEqual(data.trim(), fs.readFileSync(`${__dirname}/static.js`).toString().trim());
11 | done();
12 | });
13 |
14 | browser.write('fetch("/static.js").then(res => res.text()).then(body => {console.log(body); window.close()})');
15 | browser.end();
16 | });
17 |
--------------------------------------------------------------------------------
/test/stream.js:
--------------------------------------------------------------------------------
1 | var test = require('test');
2 | var assert = require('assert');
3 | var run = require('..');
4 |
5 | test('stream', function (t, done) {
6 | var browser = run();
7 |
8 | browser.on('data', function (data) {
9 | browser.stop();
10 | assert.strictEqual(data, 'foo\n', 'correct stdout');
11 | done();
12 | });
13 |
14 | browser.end('console.log("foo")');
15 | });
16 |
--------------------------------------------------------------------------------