diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b7b7c40 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +firefox diff --git a/HISTORY.md b/HISTORY.md new file mode 100644 index 0000000..fc21344 --- /dev/null +++ b/HISTORY.md @@ -0,0 +1,3 @@ +# 0.0.1 +- Initial release with very basic firefox launching +- Each launch gets a clean profile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..51bf3be --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +default: test +firefox: + mozilla-download --product firefox firefox + +node_modules: + npm install + +.PHONY: test +test: node_modules + ./node_modules/.bin/mocha $(shell find . -name "*_test.js") diff --git a/README.md b/README.md index b1c162c..1daa9ef 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,19 @@ -firefox-launcher -================ +# Test Agent Firefox Launcher -test-agent firefox launcher +The intent is this module is never used directly as it is very low level +guts for launching firefox with a clean profile each time... + +This should be used in conjunction with (test-agent)[https://github.com/test-agent/test-agent] + +## Usage + +(there is no node interface) + +```sh +# if you installed with npm install -g +EXEC=test-agent-firefox-launcher +# if you installed with npm install +EXEC=./node_modules/.bin/test-aget-firefox-launcher + +$EXEC --exec /path/to/firefox/folder $URL +``` diff --git a/bin/test-agent-firefox-launcher b/bin/test-agent-firefox-launcher new file mode 100755 index 0000000..777641a --- /dev/null +++ b/bin/test-agent-firefox-launcher @@ -0,0 +1,67 @@ +#! /usr/bin/env node +/** +TestAgent firefox launcher plugin executable. Handles the details of launching +the firefox instance. + +Why would we have a binary that wraps the launch of other binaries??? + + - auto detection of exectuable firefox + - better control of logging + - unified? spot where we can alter how the binary is launched for firefox + +*/ + +var program = require('commander'), + mozrunner = require('mozilla-runner'), + mozprofile = require('mozilla-profile-builder'), + fs = require('fs'); + +program. + option( + '--exec-name ', + 'Name of executable to launch (like b2g-bin or firefox)', + 'firefox' + ). + option('--exec ', 'Path to the firefox executable'). + option('--profile ', 'path to base profile'). + parse(process.argv); + +if (!program.exec) { + console.error('must pass an --exec flag') + program.outputHelp(); + process.exit(1); +} + +if (!fs.existsSync(program.exec)) { + console.error( + '--exec must be a path on the file system (maybe you need to use which?)' + ); + program.outputHelp(); + process.exit(1); +} + +// options for the run +var profileOptions = {}; +var runnerOptions = { argv: program.args }; + +/** +Utility for managing the death of the parent (current) process. +*/ +function handleFirefoxProcess(proc) { + process.once('SIGTERM', proc.kill.bind(proc)); +} + +mozprofile.create(profileOptions, function(err, instance) { + if (err) throw err; + + // set the profile path + runnerOptions.profile = instance.path; + mozrunner.run( + program.execName, + program.exec, runnerOptions, + function(err, child) { + if (err) throw err; + handleFirefoxProcess(child); + } + ); +}); diff --git a/index.js b/index.js new file mode 100644 index 0000000..2b392a0 --- /dev/null +++ b/index.js @@ -0,0 +1 @@ +throw new Error('no public node interface'); diff --git a/package.json b/package.json new file mode 100644 index 0000000..40805d3 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "test-agent-firefox-launcher", + "version": "0.0.1", + "description": "Test agent firefox launcher executable", + "main": "index.js", + "scripts": { + "test": "make test" + }, + "bin": { + "test-agent-firefox-launcher": "./bin/test-agent-firefox-launcher" + }, + "repository": { + "type": "git", + "url": "https://github.com/test-agent/firefox-launcher.git" + }, + "author": "", + "license": "Apache2", + "dependencies": { + "mozilla-runner": "0.0.1", + "ws": "~0.4.31", + "commander": "~2.0.0", + "mozilla-profile-builder": "~0.3.0" + }, + "devDependencies": { + "mocha": "~1.13.0", + "node-static": "~0.7.1", + "mozilla-download": "~0.2.1" + } +} diff --git a/test/bin/test-agent-firefox-launcher_test.js b/test/bin/test-agent-firefox-launcher_test.js new file mode 100644 index 0000000..a847566 --- /dev/null +++ b/test/bin/test-agent-firefox-launcher_test.js @@ -0,0 +1,56 @@ +suite('test-agent-firefox-launcher', function() { + var spawn = require('child_process').spawn, + executable = __dirname + '/../../bin/test-agent-firefox-launcher', + firefox = __dirname + '/../../firefox', + // this also spawns the server! + url = testServer(), + WebSocketServer = require('ws').Server; + + function launch(args) { + var proc = spawn(executable, args); + if (process.env.DEBUG) { + proc.stdout.pipe(process.stdout); + proc.stderr.pipe(process.stderr); + } + return proc; + } + + function verifyNonZeroExit(proc, done) { + proc.on('exit', function(status) { + assert(status !== 0, 'should exit process with a status other than 0'); + done(); + }); + } + + test('failure - no exec argument', function(done) { + var proc = launch(); + verifyNonZeroExit(proc, done); + }); + + test('failure - missing firefox', function(done) { + var proc = launch(['--exec', '/iam/not/heere']); + verifyNonZeroExit(proc, done); + }); + + suite('success - launch', function() { + var wsServer, proc; + setup(function() { + wsServer = new WebSocketServer({ port: 60001 }); + }); + + teardown(function() { + wsServer.close(); + }); + + test('client connects to ws server', function(done) { + proc = launch(['--exec', firefox, url]); + wsServer.on('connection', function() { + proc.kill(); + proc.on('exit', function() { + done(); + }); + }); + }); + }); + +}); diff --git a/test/fixtures/index.html b/test/fixtures/index.html new file mode 100644 index 0000000..e16859e --- /dev/null +++ b/test/fixtures/index.html @@ -0,0 +1,10 @@ + + + + + Head + + + + + diff --git a/test/fixtures/websocket.js b/test/fixtures/websocket.js new file mode 100644 index 0000000..afbe760 --- /dev/null +++ b/test/fixtures/websocket.js @@ -0,0 +1,5 @@ +(function() { + // all we need to do is verify that the socket is opened that is + // enough to tell us that the plugin works.... + new WebSocket('ws://localhost:60001'); +}()); diff --git a/test/helper.js b/test/helper.js new file mode 100644 index 0000000..16869d6 --- /dev/null +++ b/test/helper.js @@ -0,0 +1,27 @@ +global.assert = require('assert'); +var TEST_PORT = 8787; + +global.testServer = function() { + // reference to the sever must be at this function scope so + // suiteTeardown can actually close it. + var server; + + suiteSetup(function() { + var static = require('node-static'); + // root of the project + var file = new static.Server(__dirname + '/fixtures/'); + + server = require('http').createServer(function(request, response) { + request.addListener('end', function() { + // Serve files! + file.serve(request, response); + }).resume(); + }).listen(8787); + }); + + suiteTeardown(function() { + server.close(); + }); + + return 'http://localhost:' + TEST_PORT + '/index.html'; +}; diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 0000000..a61c3e1 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1,2 @@ +--require test/helper +--ui tdd