UNPKG

yeti

Version:

Yeti automates browser testing.

407 lines (367 loc) 14.4 kB
"use strict"; var vows = require("vows"); var assert = require("assert"); var portfinder = require("portfinder"); var streams = require("mock-utf8-stream"); var hub = require("../lib/hub"); var EventEmitter2 = require("../../lib/event-emitter"); var cli = require("../../lib/cli"); var YetiCLI = cli.CLI; function cliTopic(fn) { return function () { var vow = this, context, topic, emitter = new EventEmitter2(); topic = { fe: null, stdin: new streams.MockReadableStream(), stdout: new streams.MockWritableStream(), stderr: new streams.MockWritableStream() }; function mockExit(code) { emitter.emit("exit", code); } topic.fe = new YetiCLI({ stdin: topic.stdin, stdout: topic.stdout, stderr: topic.stderr, exitFn: mockExit }); context = { callback: function (port, err, expectedString) { vow.callback(err, { port: port, output: expectedString, config: topic, emitter: emitter }); } }; return fn.call(context, topic); }; } function expectThenCallback(vow, stream, expectedString, mixins) { stream.expect(expectedString, function (err, finalString) { var topic = { output: finalString }; if (mixins) { Object.keys(mixins).forEach(function (key) { topic[key] = mixins[key]; }); } vow.callback(err, topic); }); } vows.describe("Yeti CLI").addBatch({ "A Yeti CLI without any test arguments": { topic: cliTopic(function (topic) { var vow = this; // We need to override the default port, // otherwise Yeti will auto-start if a Yeti // server is listening on the same machine. // So, there's one argument. portfinder.getPort(function (err, port) { if (err) { vow.callback(err); return; } port = String(port); topic.stderr.expect("usage", vow.callback.bind(vow, port)); topic.fe.route([ "node", "cli.js", "-p", port ]); }); }), "returns usage on stderr": function (topic) { assert.ok(topic.output.indexOf("usage:") === 0); }, "returns helpful information on stderr": function (topic) { assert.include(topic.output, "launch the Yeti server"); } }, "A Yeti CLI with --server": { topic: cliTopic(function (topic) { var vow = this; portfinder.getPort(function (err, port) { if (err) { vow.callback(err); return; } port = String(port); topic.stderr.expect("started", vow.callback.bind(vow, port)); topic.fe.route([ "node", "cli.js", "-s", "-p", port ]); }); }), "returns startup message on stderr": function (topic) { assert.ok(topic.output.indexOf("Yeti Hub started") === 0); } }, "A Yeti CLI with files": { topic: cliTopic(function (topic) { var vow = this; portfinder.getPort(function (err, port) { if (err) { vow.callback(err); return; } port = String(port); topic.stderr.expect("When ready", vow.callback.bind(vow, port)); topic.fe.route([ "node", "cli.js", "-p", port, __dirname + "/fixture/basic.html", __dirname + "/fixture/qunit.html", __dirname + "/fixture/jasmine.html", __dirname + "/fixture/mocha.html", __dirname + "/fixture/doh.html" ]); }); }), "prints hub creation message on stderr": function (topic) { assert.ok(topic.output.indexOf("Creating a Hub.") === 0); }, "waits for agents to connect on stderr": function (topic) { assert.include(topic.output, "Waiting for agents to connect"); }, "prompts on the writableStream": function (topic) { assert.include(topic.output, "When ready, press Enter"); }, "a browser": hub.phantomContext({ "visits Yeti": { topic: function (browser, cli) { var vow = this; expectThenCallback(vow, cli.config.stderr, "Agent connected"); function onPageOpen(err, status) { if (err) { vow.callback(err); } } browser.createPage(function (err, page) { page.open("http://localhost:" + cli.port, onPageOpen); }); }, "is ok": function (topic) { assert.isUndefined(topic.stack); }, "the stderr output contains the User-Agent": function (topic) { assert.include(topic.output, "PhantomJS"); }, "when Enter is pressed": { topic: function (connectionSnapshot, browser, cli) { expectThenCallback(this, cli.config.stdout, "pass", { cli: cli }); cli.config.stdin.write("\n"); // Enter }, "is ok": function (topic) { assert.isUndefined(topic.stack); }, "the stderr output contains the test results": function (topic) { assert.include(topic.output, "5 tests passed"); }, "the stderr output contains Agent complete": function (topic) { assert.include(topic.output, "Agent complete"); }, "should exit": { topic: function (topic) { var vow = this; topic.cli.emitter.once("exit", function (code) { vow.callback(null, code); }); }, "with status code 0": function (topic) { assert.strictEqual(topic, 0); } } } } }) }, "A Yeti CLI with a failing file": { topic: cliTopic(function (topic) { var vow = this; portfinder.getPort(function (err, port) { if (err) { vow.callback(err); return; } port = String(port); topic.stderr.expect("When ready", vow.callback.bind(vow, port)); topic.fe.route([ "node", "cli.js", "--coverage", "-p", port, __dirname + "/fixture/query-string.html", ]); }); }), "prints hub creation message on stderr": function (topic) { assert.ok(topic.output.indexOf("Creating a Hub.") === 0); }, "waits for agents to connect on stderr": function (topic) { assert.include(topic.output, "Waiting for agents to connect"); }, "prompts on the writableStream": function (topic) { assert.include(topic.output, "When ready, press Enter"); }, "a browser": hub.phantomContext({ "visits Yeti": { topic: function (browser, cli) { var vow = this; expectThenCallback(vow, cli.config.stderr, "Agent connected"); function onPageOpen(err, status) { if (err) { vow.callback(err); } } browser.createPage(function (err, page) { page.open("http://localhost:" + cli.port, onPageOpen); }); }, "is ok": function (topic) { assert.isUndefined(topic.stack); }, "the stderr output contains the User-Agent": function (topic) { assert.include(topic.output, "PhantomJS"); }, "when Enter is pressed": { topic: function (connectionSnapshot, browser, cli) { expectThenCallback(this, cli.config.stdout, "failed", { cli: cli }); cli.config.stderr.captureData(); cli.config.stdin.write("\n"); // Enter }, "is ok": function (topic) { assert.isUndefined(topic.stack); }, "the stdout output contains the failing test details": function (topic) { assert.include(topic.output, "testMoof"); assert.include(topic.output, "Values should be equal."); assert.include(topic.output, "Expected: moof (string)"); assert.include(topic.output, "Actual: ? (string)"); assert.include(topic.output, "1 of 1 tests failed"); }, "the stdout output contains Agent complete": function (topic) { assert.include(topic.output, "Agent complete"); }, "the stderr output contains coverage summary": function (topic) { var capture = topic.cli.config.stderr.capturedData; assert.include(capture, "Coverage summary"); assert.include(capture, "Statements"); assert.include(capture, "Branches"); assert.include(capture, "Functions"); assert.include(capture, "Lines"); assert.throws(function () { assert.include(capture, "0.00"); }, Error); // Coverage should not be zero }, "should exit": { topic: function (topic) { var vow = this; topic.cli.emitter.once("exit", function (code) { vow.callback(null, code); }); }, "with status code 3": function (topic) { assert.strictEqual(topic, 3); } } } } }) } }).addBatch({ "parseArgv when given arguments": { topic: function () { return cli.parseArgv([ "node", // program name is argv[0] "cli.js", // script name is argv[1] "--server", "--port", "4080", "--version", "--bogus-does-not-exist", "foo", "--hub", "http://example.net:3010", "--no-help", "--query", "'foo bar'", "-vv", "test/*/dogcow.html", "--", "-p/orts.html" ]); }, "server should be true": function (topic) { assert.isTrue(topic.server); }, "port should be Number(4080)": function (topic) { assert.strictEqual(topic.port, 4080); }, "version should be true": function (topic) { assert.isTrue(topic.version); }, "help should be false": function (topic) { assert.isFalse(topic.help); }, "timeout should not be defined": function (topic) { assert.isUndefined(topic.timeout); }, "hub should be a valid URL": function (topic) { assert.strictEqual(topic.hub, "http://example.net:3010/"); }, "loglevel should be debug": function (topic) { assert.strictEqual(topic.loglevel, "debug"); }, "remain should be 2 files": function (topic) { assert.include(topic.argv.remain, "test/*/dogcow.html"); assert.include(topic.argv.remain, "-p/orts.html"); } }, "parseArgv when given Boolean hub shorthand option": { topic: function () { return cli.parseArgv([ "node", // program name is argv[0] "cli.js", // script name is argv[1] "--no-hub" ]); }, "hub should be false": function (topic) { assert.isFalse(topic.hub); } }, "parseArgv when given Boolean hub option": { topic: function () { return cli.parseArgv([ "node", // program name is argv[0] "cli.js", // script name is argv[1] "--hub", "false" ]); }, "hub should be false": function (topic) { assert.isFalse(topic.hub); } }, "parseArgv when given an invalid URL as hub option": { topic: function () { return cli.parseArgv([ "node", // program name is argv[0] "cli.js", // script name is argv[1] "--hub", "clarisworks" ]); }, "hub should be true": function (topic) { // hub coerced into Boolean assert.isTrue(topic.hub); } } }).export(module);