From 22d48ee0db4911ce60b98dbf0d0ba552b09599e8 Mon Sep 17 00:00:00 2001 From: rissem Date: Wed, 24 Sep 2014 18:24:33 -0700 Subject: [PATCH] add --test flag to Meteor CLI for velociy CI support - establish a DDP connection to Meteor - subscribe to test results - hit running web server - exit with appropriate status code after tests have completed --- tools/commands.js | 120 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/tools/commands.js b/tools/commands.js index d1895df568..894c013d54 100644 --- a/tools/commands.js +++ b/tools/commands.js @@ -25,6 +25,9 @@ var cordova = require('./commands-cordova.js'); var commandsPackages = require('./commands-packages.js'); var execFileSync = require('./utils.js').execFileSync; var Console = require('./console.js').Console; +var uniload = require('./uniload.js'); +var phantomjs = require('phantomjs'); +var child_process = require('child_process'); // The architecture used by Galaxy servers; it's the architecture used // by 'meteor deploy'. @@ -164,6 +167,7 @@ main.registerCommand({ 'raw-logs': { type: Boolean }, settings: { type: String }, program: { type: String }, + test: {type: Boolean, default: false}, verbose: { type: Boolean, short: "v" }, // With --once, meteor does not re-run the project if it crashes // and does not monitor for file changes. Intentionally @@ -303,6 +307,122 @@ main.registerCommand({ if (options['raw-logs']) runLog.setRawLogs(true); + // If `--test` is specified we need to start the app server, poke + // it with PhantomJS, and listen for test results. + // + // More specifically: + // 1. Establish a DDP connection to Meteor + // 2. Subscribe to the Velocity subscriptions that tell us + // which tests pass/fail and when all tests have completed. + // 3. Poke an app server with PhantomJS to run client side tests. + // 4. Print the results and exit with the appropriate exit code. + if (options['test']){ + var unipackages = uniload.load({ + packages: [ 'ddp'] + }); + var DDP = unipackages.ddp.DDP; + + var ddpConnection = DDP.connect("http://localhost:3000"); + + var interval = setInterval(function(){ + if (ddpConnection.status().status === "connected"){ + clearInterval(interval); + + ddpConnection.subscribe("VelocityTestReports", { + onError: function(){ + Console.stderr.write("failed to subscribe to VelocityTestReports " ++ "subscription"); + }, onReady: function(){ + this.connection.registerStore("velocityTestReports", { + update: function(msg){ + if (msg.msg == "added"){ + var testDesc = msg.fields.framework + " : " + + msg.fields.ancestors.join(":") + " => " + msg.fields.name; + if(msg.fields.result == "passed"){ + console.log("PASSED ", testDesc); + } else if (msg.fields.result == "failed"){ + console.error("FAILED ", testDesc); + console.log(msg.fields.failureStackTrace) + } + } + } + }); + } + }); + + var reports = {}; + function updateReport(msg){ + var report = reports[msg.id]; + if (! report){ + reports[msg.id] = msg.fields; + } else { + _.extend(report, msg.fields); + } + } + var aggregateResult = null; + var isFinished = false; + ddpConnection.subscribe("VelocityAggregateReports", { + onError: function(){ + Console.stderr.write("failed to subscribe to " + + "VelocityAggregateReports subscription"); + }, onReady: function(){ + this.connection.registerStore("velocityAggregateReports", { + update: function(msg){ + if (msg.msg === "added" || msg.msg == "changed"){ + updateReport(msg); + var report = reports[msg.id]; + + if (report.name === "aggregateResult"){ + aggregateResult = report.result; + } + + if(report.name === "aggregateComplete" && + report.result === "completed"){ + setTimeout(function(){ + if (aggregateResult === "passed"){ + console.log("TESTS RAN SUCCESSFULLY :-)") + //better way to exit here? + process.exit(0); + } + if (aggregateResult === "failed"){ + console.log("FAILURE :-("); + process.exit(1); + } + }, 2000); + } + } + } + }) + } + }); + + function visitWithPhantom(url){ + var phantomScript = "require('webpage').create().open('" + url + "');"; + child_process.execFile( + '/bin/bash', + ['-c', + ("exec " + phantomjs.path + " /dev/stdin <<'END'\n" + + phantomScript + "END\n")]); + } + + ddpConnection.subscribe("VelocityMirrors", { + onError: function(err){ + Console.stderr.write("failed to subscribe to VelocityMirrors " + + "subscription", err); + }, onReady: function(){ + this.connection.registerStore("velocityMirrors", { + update: function(msg){ + if (msg.msg === "added"){ + visitWithPhantom(msg.fields.rootUrl); + } + } + }) + } + }); + } + }, 2000); + } + var runAll = require('./run-all.js'); return runAll.run(options.appDir, { proxyPort: parsedHostPort.port,