diff --git a/.npmignore b/.npmignore index 93508ac..d7d0c8b 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,6 @@ *.log node_modules -resources/buster-test.js +# resources/buster-test.js # gitignored, but publishable .idea .cache-require-paths.json diff --git a/.travis.yml b/.travis.yml index 896e270..7aa3058 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,28 @@ language: node_js sudo: false -node_js: - - "0.10" - - "0.12" - - "4" - - "5" +env: + global: + - CXX=g++-4.8 +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 +matrix: + include: + - node_js: "0.10" + env: JSDOM=3 + - node_js: "0.12" + env: JSDOM=3 + - node_js: "4" + env: JSDOM=3 + - node_js: "4" + env: JSDOM=7 + - node_js: "5" + env: JSDOM=3 + - node_js: "5" + env: JSDOM=7 before_install: - npm i -g npm + - npm i jsdom@$JSDOM # becomes extraneous, but overrides buster-test dependency diff --git a/appveyor.yml b/appveyor.yml index c5c6866..0d71fb4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,14 +1,24 @@ environment: + NO_INTEGRATION: 1 matrix: - nodejs_version: "0.10" + jsdom_version: "3" - nodejs_version: "0.12" + jsdom_version: "3" - nodejs_version: "4" + jsdom_version: "3" + - nodejs_version: "4" + jsdom_version: "7" + - nodejs_version: "5" + jsdom_version: "3" - nodejs_version: "5" + jsdom_version: "7" install: - ps: Install-Product node $env:nodejs_version - - npm install -g npm - - npm install + - npm i -g npm + - npm i jsdom@%jsdom_version% + - npm i test_script: - node --version diff --git a/bin/buster-test b/bin/buster-test index eb163ec..731966c 100755 --- a/bin/buster-test +++ b/bin/buster-test @@ -3,7 +3,7 @@ var path = require("path"); var testCli = require("buster-test-cli"); process.on("uncaughtException", function (err) { - console.log(err.stack); + console.error("Uncaught exception:", err.stack ? err.stack : err); }); var busterPath = path.join(__dirname, "..", "lib", "buster"); @@ -27,5 +27,7 @@ testCli.create(process.stdout, process.stderr, { ] } }).run(process.argv.slice(2), function (err) { - if (err) { setTimeout(process.exit.bind(null, 1), 5); } + if (err) { + console.error("buster-test run failed:", err.stack ? err.stack : err); + } }); diff --git a/build b/build index ce1d2d0..7dfb6de 100755 --- a/build +++ b/build @@ -44,8 +44,8 @@ function finish() { var fileNames = [ // buster/bundle-0.x.js - "when/when", - "lodash/dist/lodash", + "when/dist/browser/when.js", + "lodash/index", "async/lib/async", "platform/platform", "lib/buster/amd-shim.js", diff --git a/jsTestDriver.conf b/jsTestDriver.conf deleted file mode 100644 index 544645f..0000000 --- a/jsTestDriver.conf +++ /dev/null @@ -1,35 +0,0 @@ -server: http://localhost:4224 - -load: - - node_modules/when/when.js - - node_modules/buster-util/lib/buster-util/test-case.js - - node_modules/buster-util/lib/buster-util/jstestdriver-shim.js - - node_modules/buster-core/lib/buster-core.js - - node_modules/buster-core/lib/buster-event-emitter.js - - node_modules/buster-evented-logger/lib/buster-evented-logger.js - - node_modules/buster-assertions/lib/buster-assertions.js - - node_modules/buster-assertions/lib/buster-assertions/expect.js - - node_modules/buster-format/lib/buster-format.js - - node_modules/sinon/lib/sinon.js - - node_modules/sinon/lib/sinon/spy.js - - node_modules/sinon/lib/sinon/stub.js - - node_modules/sinon/lib/sinon/mock.js - - node_modules/sinon/lib/sinon/collection.js - - node_modules/sinon/lib/sinon/sandbox.js - - node_modules/sinon/lib/sinon/test.js - - node_modules/sinon/lib/sinon/test_case.js - - node_modules/sinon/lib/sinon/assert.js - - node_modules/sinon/lib/sinon/util/fake_xml_http_request.js - - node_modules/sinon/lib/sinon/util/fake_timers.js - - node_modules/sinon/lib/sinon/util/fake_server.js - - node_modules/sinon/lib/sinon/util/fake_server_with_clock.js - - node_modules/buster-test/lib/buster-test/browser-env.js - - node_modules/buster-test/lib/buster-test/spec.js - - node_modules/buster-test/lib/buster-test/test-case.js - - node_modules/buster-test/lib/buster-test/test-context.js - - node_modules/buster-test/lib/buster-test/test-runner.js - - node_modules/buster-test/lib/buster-test/reporters/json-proxy.js - - node_modules/buster-sinon/lib/buster-sinon.js - - lib/buster/buster-wiring.js - - lib/buster/browser-wiring.js - - test/browser/*.js diff --git a/lib/buster/framework-extension.js b/lib/buster/framework-extension.js index 39cf074..71d32c8 100644 --- a/lib/buster/framework-extension.js +++ b/lib/buster/framework-extension.js @@ -1,5 +1,7 @@ // WHOA! This will change before 1.0 +var BUSTER_VERSION = require("../../package.json").version; + function resolveModules(resourceSet, modules) { return modules.map(function (module) { var moduleName = module[0]; @@ -22,8 +24,8 @@ var NO_CACHE_HEADERS = { function loadTestFramework(configuration) { configuration.on("load:framework", function (rs) { var files = resolveModules(rs, [ - ["when/", "when.js"], - ["lodash/dist/", "lodash.js"], + ["when/", "dist/browser/when.js"], + ["lodash/", "index.js"], ["async/lib/", "async.js"], ["platform/", "platform.js"], ["../", "buster/amd-shim.js"], @@ -33,20 +35,7 @@ function loadTestFramework(configuration) { ["referee/lib/", "expect.js"], ["referee/lib/", "referee.js"], ["formatio/lib/", "formatio.js"], - ["sinon/lib/", "sinon.js"], - ["sinon/lib/", "sinon/spy.js"], - ["sinon/lib/", "sinon/call.js"], - ["sinon/lib/", "sinon/behavior.js"], - ["sinon/lib/", "sinon/stub.js"], - ["sinon/lib/", "sinon/mock.js"], - ["sinon/lib/", "sinon/collection.js"], - ["sinon/lib/", "sinon/sandbox.js"], - ["sinon/lib/", "sinon/match.js"], - ["sinon/lib/", "sinon/util/event.js"], - ["sinon/lib/", "sinon/util/fake_xml_http_request.js"], - ["sinon/lib/", "sinon/util/fake_timers.js"], - ["sinon/lib/", "sinon/util/fake_server.js"], - ["sinon/lib/", "sinon/util/fake_server_with_clock.js"], + ["sinon/pkg/", "sinon.js"], ["buster-test/lib/", "seedrandom.js"], ["buster-test/lib/", "browser-env.js"], ["buster-test/lib/", "test-context.js"], @@ -63,12 +52,11 @@ function loadTestFramework(configuration) { ]); var ieFiles = resolveModules(rs, [ - ["sinon/lib/", "sinon/util/timers_ie.js"], - ["sinon/lib/", "sinon/util/xhr_ie.js"] + ["sinon/pkg/", "sinon-ie.js"] ]); - var compatResourceName = "/buster/compat-0.7.js"; - var bundleResourceName = "/buster/bundle-0.7.js"; + var compatResourceName = "/buster/compat-" + BUSTER_VERSION + ".js"; + var bundleResourceName = "/buster/bundle-" + BUSTER_VERSION + ".js"; when.all([ rs.addResource({ @@ -81,10 +69,10 @@ function loadTestFramework(configuration) { combine: files, headers: NO_CACHE_HEADERS }) - ], function () { + ]).then(function () { rs.loadPath.prepend(compatResourceName); rs.loadPath.prepend(bundleResourceName); - }.bind(this)); + }); }.bind(this)); } diff --git a/package.json b/package.json index aee1a3e..1c9209b 100644 --- a/package.json +++ b/package.json @@ -1,63 +1,72 @@ { - "name": "buster", - "version": "0.7.18", - "main": "./lib/buster", - "description": "Buster.JS JavaScript Test framework. Meta package that pieces together various sub-projects.", - "homepage": "http://busterjs.org/", - "author": { "name": "August Lilleaas and Christian Johansen" }, - "contributors": [{ - "name": "August Lilleaas", - "email": "august.lilleaas@gmail.com", - "url": "http://augustl.com" - }, { - "name": "Christian Johansen", - "email": "christian@cjohansen.no", - "url": "http://cjohansen.no" - }, { - "name": "Daniel Wittner", - "email": "d.wittner@gmx.de", - "url": "https://github.com/dwittner" - }], - "license": "BSD-3-Clause", - "repository": { - "type": "git", - "url": "https://github.com/busterjs/buster.git" + "name": "buster", + "version": "0.7.18", + "main": "./lib/buster", + "description": "Buster.JS JavaScript Test framework. Meta package that pieces together various sub-projects.", + "homepage": "http://busterjs.org/", + "author": { + "name": "August Lilleaas and Christian Johansen" + }, + "contributors": [ + { + "name": "August Lilleaas", + "email": "august.lilleaas@gmail.com", + "url": "http://augustl.com" }, - "bin": { - "buster": "./bin/buster", - "buster-test": "./bin/buster-test", - "buster-server": "./bin/buster-server", - "buster-autotest": "./bin/buster-autotest", - "buster-static": "./bin/buster-static", - "buster-ci": "./bin/buster-ci" + { + "name": "Christian Johansen", + "email": "christian@cjohansen.no", + "url": "http://cjohansen.no" }, - "scripts": { - "test": "node run-tests.js", - "test-debug": "node --debug-brk run-tests.js" - }, - "dependencies": { - "bane": "~1.0", - "evented-logger": "~1.0", - "referee": "~1.1", - "formatio": "~1.0", - "sinon": "~1.9", - "buster-test": "~0.7", - "buster-sinon": "~0.7", - "referee-sinon": "~1.0", - "buster-test-cli": "~0.8", - "buster-server-cli": "~0.3", - "buster-static": "~0.6", - "buster-autotest": "~0.5", - "buster-ci": "~0.2", - "buster-syntax": "~0.4.2", - "when": "https://github.com/cujojs/when/tarball/1.8.1", - "lodash": "~1.0", - "async": "~0.2", - "platform": "~1.2", - "stack-filter": "~1.0", - "samsam": "~1.1" - }, - "devDependencies": { - "uglify-js": "~1.2.5" + { + "name": "Daniel Wittner", + "email": "d.wittner@gmx.de", + "url": "https://github.com/dwittner" } + ], + "license": "BSD-3-Clause", + "repository": { + "type": "git", + "url": "https://github.com/busterjs/buster.git" + }, + "bin": { + "buster": "./bin/buster", + "buster-test": "./bin/buster-test", + "buster-server": "./bin/buster-server", + "buster-autotest": "./bin/buster-autotest", + "buster-static": "./bin/buster-static", + "buster-ci": "./bin/buster-ci" + }, + "scripts": { + "test": "node run-tests.js && node run-integration-tests.js", + "test-debug": "node --debug-brk run-tests.js" + }, + "dependencies": { + "async": "1.x", + "bane": "1.x", + "buster-autotest": "0.6.x", + "buster-ci": "0.3.x", + "buster-server-cli": "0.4.x", + "buster-sinon": "0.7.x", + "buster-static": "0.7.x", + "buster-syntax": "0.5.x", + "buster-test": "0.8.x", + "buster-test-cli": "0.9.x", + "evented-logger": "1.x", + "formatio": "1.x", + "lodash": "3.x", + "platform": "1.x", + "referee": "1.x", + "referee-sinon": "1.x", + "samsam": "1.x", + "sinon": "1.x", + "stack-filter": "1.x", + "when": "3.x >=3.7.6" + }, + "devDependencies": { + "buster-amd": "0.3.x", + "buster-html-doc": "2.x", + "phantomjs": "1.x", + "uglify-js": "2.x" + } } diff --git a/run-integration-tests.js b/run-integration-tests.js new file mode 100644 index 0000000..1bb5659 --- /dev/null +++ b/run-integration-tests.js @@ -0,0 +1,177 @@ +if (process.env["NO_INTEGRATION"]) { + console.log("Found NO_INTEGRATION environment variable - skipping tests"); + process.exit(0); +} + +var when = require('when'); +var path = require('path'); +var fs = require('fs'); +var nodefn = require('when/node/function'); +var sequence = require('when/sequence'); +var cp = require('child_process'); + +var BUSTER_SERVER_BIN = path.join(__dirname, "bin", "buster-server"); +var BUSTER_TEST_BIN = path.join(__dirname, "bin", "buster-test"); + +function die(code) { + if (code > 0) { + console.error("Exiting with code " + code); + } else { + console.log("Exiting with code " + code); + } + process.exit(code); +} + +function startServer() { + var started = false; + var serverExited = when.defer(); + var serverStarted = when.defer(); + + var serverProcess = cp.spawn("node", [BUSTER_SERVER_BIN, "-c"], {detached: true}); + + serverProcess.stdout.on('data', function (data) { + var msg = data.toString(); + if (!started && /Headless browser was captured/.test(msg)) { + started = true; + serverStarted.resolve(); + clearTimeout(capturedTimeout); + } + console.log("[buster-server][stdout]", msg); + }); + + serverProcess.stderr.on('data', function (data) { + console.error("[buster-server][stderr]", data.toString()); + }); + + serverProcess.on('exit', function (code) { + if (!started) { + serverStarted.reject(new Error("buster-server crashed")); + } + + if (code > 0 || code === 143) { // see: https://github.com/nodejs/node-v0.x-archive/issues/8667 + console.log("buster-server exited with code " + code); + } + + serverExited.resolve(code === 143 ? 0 : code); + }); + + var capturedTimeout = setTimeout(function () { + serverStarted.reject(new Error("Timed out while waiting for buster-server to capture a headless browser")); + }, 5000); + + return { + started: serverStarted.promise, + exited: serverExited.promise, + kill: function () { + var isWin = /^win/.test(process.platform); + if (isWin) { + cp.spawn("taskkill", ["/pid", serverProcess.pid, '/f', '/t']); + } else { + process.kill(-serverProcess.pid); + } + } + } +} + +function readArgs(dirName) { + var fullPath = path.join(__dirname, "test", "integration", dirName); + return nodefn.call(fs.readFile.bind(fs), path.join(fullPath, "args.txt")) + .then(function (contents) { + return { + fullPath: fullPath, + args: contents.toString() + }; + }, function (err) { + if (err && err.code === "ENOENT") { + return { + fullPath: fullPath, + args: undefined + }; + } + throw err; + }); +} + +function readTestFolders() { + return nodefn.call(fs.readdir.bind(fs), path.join(__dirname, "test", "integration")) + .then(function (integrationTests) { + return when.map(integrationTests, readArgs) + }) +} + +function getRunTestFn(integrationTest) { + return function () { + var deferred = when.defer(); + var cmd = ["BUSTER_REPORTER=specification", "node", BUSTER_TEST_BIN]; + if (integrationTest.args) { + cmd.push(integrationTest.args); + } + var execOptions = { + cwd: integrationTest.fullPath + }; + cp.exec(cmd.join(" "), execOptions, function (err, stdout, stderr) { + if (err) { + console.error(err); + } + if (stdout.length) { + console.log("[buster-test][stdout][" + integrationTest.fullPath + "]", stdout); + } + if (stderr.length) { + console.log("[buster-test][stderr][" + integrationTest.fullPath + "]", stderr); + } + deferred.resolver.resolve(err ? 1 : 0); + }); + return deferred.promise; + } +} + +function runIntegrationTests() { + var server = startServer(); + + process.on('SIGINT', function () { + server.kill(); + die(1); + }); + + server.started + .then(function () { + return readTestFolders(); + }) + .then(function (tests) { + var deferred = when.defer(); // @todo: replace with when.race() + + sequence(tests.map(getRunTestFn)) + .then(deferred.resolver.resolve); + + server.exited + .then(function () { + deferred.resolver.reject(new Error("Server exited before test results completed!")); + }); + + return deferred.promise; + }) + .then(function (testResults) { + server.kill(); + return when.all(testResults.concat(server.exited)); + }) + .then(function (exitCodes) { + var nonZero = exitCodes.filter(function (i) { + return i > 0 && i !== 143 + }); + + if (nonZero.length > 0) { + console.log("One or more processes exited with non-zero exit code", exitCodes); + die(1); + return; + } + + die(0); + }) + .then(null, function (err) { + console.error(err); + server.kill(); + die(1); + }); +} + +runIntegrationTests(); diff --git a/test/browser/capture-server-wiring-test.js b/test/browser/capture-server-wiring-test.js deleted file mode 100644 index a45a194..0000000 --- a/test/browser/capture-server-wiring-test.js +++ /dev/null @@ -1,247 +0,0 @@ -(function (B) { - if (typeof require == "function" && typeof module == "object") { - return; - } - - function setUp() { - this.emitter = createRemoteEmitter(); - this.readyListener = sinon.spy(); - this.emitter.on("ready", this.readyListener); - B.configureTestClient(this.emitter); - - this.bnt = buster.nextTick; - sinon.spy(buster.testRunner, "runSuite"); - - buster.nextTick = function (callback) { - callback(); - }; - } - - function tearDown() { - buster.nextTick = this.bnt; - buster.testRunner.runSuite.restore(); - } - - buster.util.testCase("BrowserWiringTest", { - setUp: setUp, - tearDown: tearDown, - - "should connect bayeux emitter": function () { - assertTrue(this.emitter.connect.calledOnce); - }, - - "should not emit ready immediately": function () { - assertFalse(this.readyListener.called); - }, - - "should not emit ready when connected": function () { - this.emitter.connect.args[0][0](); - - assertFalse(this.readyListener.calledOnce); - }, - - "should emit ready when calling buster.ready": function () { - this.emitter.connect.args[0][0](); - buster.ready(); - - assertTrue(this.readyListener.calledOnce); - }, - - "should not emit ready before client is connected": function () { - buster.ready(); - - assertFalse(this.readyListener.calledOnce); - }, - - "should emit ready when connected after calling buster.ready": function () { - buster.ready(); - this.emitter.connect.args[0][0](); - - assertTrue(this.readyListener.calledOnce); - }, - - "should emit user agent string with ready event": function () { - this.emitter.connect.args[0][0](); - buster.ready(); - - assertTrue(/Mozilla/.test(this.readyListener.args[0][0].data)); - }, - - "should set up console and buster.log shortcut": function () { - assertObject(buster.console); - assertFunction(buster.log); - }, - - "should format log messages nicely": function () { - var message; - buster.console.on("log", function (msg) { message = msg.message }); - buster.console.log("Hello world", { id: 42 }); - - assertEquals("Hello world { id: 42 }", message); - }, - - "should log messages through buster.log": function () { - var message; - buster.console.on("log", function (msg) { message = msg.message }); - buster.log("Hello world", { id: 42 }); - - buster.assert.equals(message, "Hello world { id: 42 }"); - }, - - "should send log messages over the wire": function () { - var listener = sinon.spy(); - this.emitter.on("log", listener); - - buster.console.warn("Hello world", { id: 42 }); - assertTrue(listener.calledOnce); - - var msg = listener.args[0][0]; - assertEquals("log", msg.topic); - - assertEquals({ - message: "Hello world { id: 42 }", - level: "warn" - }, msg.data); - }, - - "should start running tests when emitting tests:run": function () { - var listener = sinon.spy(); - this.emitter.on("suite:start", listener); - - buster.testCase("SomeTest", { "should do it": function () {} }); - this.emitter.emit("tests:run", { autoRun: true }); - - assertTrue(listener.calledOnce); - }, - - "should run specs when emitting tests:run": function () { - var listener = sinon.spy(); - this.emitter.on("context:start", listener); - - buster.spec.describe("Spec", function () { - buster.spec.it("does it", function () {}); - }); - - this.emitter.emit("tests:run", { autoRun: true }); - - assertTrue(listener.calledOnce); - assertEquals(listener.args[0][0].data.name, "Spec"); - }, - - "should run parsable context when emitting tests:run": function () { - var context = { name: "Parsed", tests: [{ name: "Yay" }], contexts: [] }; - - buster.addTestContext({ - parse: function () { - return context; - } - }); - - this.emitter.emit("tests:run", { autoRun: true }); - - assertTrue(buster.testRunner.runSuite.calledOnce); - assertEquals(buster.testRunner.runSuite.args[0][0], [context]); - }, - - "should create test runner with options": function () { - this.emitter.emit("tests:run", { - timeout: 25 - }); - - assertEquals(25, buster.wiredRunner.timeout); - }, - - "should configure assertions to throw": function () { - this.emitter.emit("tests:run"); - assertTrue(buster.assertions.throwOnFailure); - }, - - "should count assertions": function () { - var counts = []; - - buster.testCase("AssertionCountTest", { - tearDown: function () { - counts.push(buster.wiredRunner.assertionCount()); - }, - - "test #1": function () { - buster.assert(true); - }, - - "test #2": function () { - buster.assert(true); - buster.assert(true); - } - }); - - this.emitter.emit("tests:run"); - - assertEquals(counts.sort(), [1, 2]); - }, - - "should filter contexts prior to running": function () { - var tests = [this.spy(), this.spy()]; - buster.testCase("AssertionCountTest", { - "test #1": tests[0], - "test #2": tests[1] - }); - - this.emitter.emit("tests:run", { autoRun: true, filters: ["#1"] }); - - assertTrue(tests[0].calledOnce); - assertFalse(tests[1].called); - }, - - "should capture console": function () { - this.stub(buster, "captureConsole"); - this.emitter.emit("tests:run", { captureConsole: true }); - assert(buster.captureConsole.calledOnce); - }, - - "should not always capture console": function () { - this.stub(buster, "captureConsole"); - this.emitter.emit("tests:run", { captureConsole: false }); - assert(!buster.captureConsole.called); - } - }); - - buster.util.testCase("BrowserWiringAutoRunFalseTest", { - setUp: function () { - setUp.call(this); - - this.listener = sinon.spy(); - this.emitter.on("suite:start", this.listener); - buster.testCase("SomeTest", { "should do it": function () {} }); - }, - - tearDown: tearDown, - - "should not start running tests on tests:run when autoRun is false": - function () { - this.emitter.emit("tests:run", { autoRun: false }); - - assertFalse(this.listener.calledOnce); - }, - - "should start running tests when calling run after tests:run": function () { - this.emitter.emit("tests:run", { autoRun: false }); - buster.run(); - - assertTrue(this.listener.calledOnce); - }, - - "should start running tests when calling run before tests:run": function () { - buster.run(); - this.emitter.emit("tests:run", { autoRun: false }); - - assertTrue(this.listener.calledOnce); - }, - - "should remove all script tags": function () { - buster.run(); - this.emitter.emit("tests:run", { autoRun: false }); - - assertEquals(0, document.body.getElementsByTagName("script").length); - } - }); -}(buster)); diff --git a/test/browser/browser-wiring-test.js b/test/integration/browser/browser-wiring-test.js similarity index 73% rename from test/browser/browser-wiring-test.js rename to test/integration/browser/browser-wiring-test.js index aae76e8..c82c8d1 100644 --- a/test/browser/browser-wiring-test.js +++ b/test/integration/browser/browser-wiring-test.js @@ -4,7 +4,7 @@ } function setUp() { - this.runner = B.eventEmitter.create(); + this.runner = B.bane.createEventEmitter(); this.runner.runSuite = sinon.spy(); this.bnt = B.nextTick; this.sandbox = sinon.sandbox.create(); @@ -19,7 +19,7 @@ this.sandbox.restore(); } - B.util.testCase("BrowserWiringLoggerTest", { + B.testCase("BrowserWiringLoggerTest", { setUp: setUp, tearDown: tearDown, @@ -30,11 +30,11 @@ B.wire.logger(this.runner); B.console.log("Hey man"); - assert(listener.calledOnce); + B.referee.assert(listener.calledOnce); } }); - B.util.testCase("BrowserWiringContextsTest", { + B.testCase("BrowserWiringContextsTest", { setUp: setUp, tearDown: tearDown, @@ -42,27 +42,27 @@ var contexts = B.wire.testContexts(); B.testCase("Something", {}); - assertEquals(contexts.length, 1); - assertEquals(contexts[0].name, "Something"); + B.referee.assert.equals(contexts.length, 1); + B.referee.assert.equals(contexts[0].name, "Something"); }, "collects spec": function () { var contexts = B.wire.testContexts(); B.spec.describe("Something", function () {}); - assertEquals(contexts.length, 1); - assertEquals(contexts[0].name, "Something"); + B.referee.assert.equals(contexts.length, 1); + B.referee.assert.equals(contexts[0].name, "Something"); } }); - B.util.testCase("BrowserWiringDocumentStateTest", { + B.testCase("BrowserWiringDocumentStateTest", { setUp: setUp, tearDown: tearDown, "should remove all script tags to avoid re-downloading scripts": function () { B.wire.documentState(this.runner); - assertEquals(document.getElementsByTagName("script").length, 0); + B.referee.assert.equals(document.getElementsByTagName("script").length, 0); }, "should clear document when test succeeds": function () { @@ -70,7 +70,7 @@ document.body.appendChild(document.createElement("h1")); this.runner.emit("test:success", {}); - assertEquals(document.getElementsByTagName("h1").length, 0); + B.referee.assert.equals(document.getElementsByTagName("h1").length, 0); }, "should clear document when test fails": function () { @@ -78,7 +78,7 @@ document.body.appendChild(document.createElement("h1")); this.runner.emit("test:failure", {}); - assertEquals(document.getElementsByTagName("h1").length, 0); + B.referee.assert.equals(document.getElementsByTagName("h1").length, 0); }, "should clear document when test errors": function () { @@ -86,7 +86,7 @@ document.body.appendChild(document.createElement("h1")); this.runner.emit("test:error", {}); - assertEquals(document.getElementsByTagName("h1").length, 0); + B.referee.assert.equals(document.getElementsByTagName("h1").length, 0); }, "should clear document when test times out": function () { @@ -94,7 +94,7 @@ document.body.appendChild(document.createElement("h1")); this.runner.emit("test:timeout", {}); - assertEquals(document.getElementsByTagName("h1").length, 0); + B.referee.assert.equals(document.getElementsByTagName("h1").length, 0); }, "should use snapshot from suite:start": function () { @@ -104,12 +104,12 @@ document.body.appendChild(document.createElement("h2")); this.runner.emit("test:timeout", {}); - assertEquals(document.getElementsByTagName("h1").length, 1); - assertEquals(document.getElementsByTagName("h2").length, 0); + B.referee.assert.equals(document.getElementsByTagName("h1").length, 1); + B.referee.assert.equals(document.getElementsByTagName("h2").length, 0); } }); - B.util.testCase("BrowserWiringTestRunnerTest", { + B.testCase("BrowserWiringTestRunnerTest", { setUp: setUp, tearDown: tearDown, @@ -123,8 +123,8 @@ wire.ready({}); wire.run(); - assert(this.runner.runSuite.calledOnce); - assertEquals(this.runner.runSuite.args[0][0].length, 2); + B.referee.assert(this.runner.runSuite.calledOnce); + B.referee.assert.equals(this.runner.runSuite.args[0][0].length, 2); }, "should copy config properties to test runner": function () { @@ -133,7 +133,7 @@ wire.ready({ timeout: 1200 }); wire.run(); - assertEquals(this.runner.timeout, 1200); + B.referee.assert.equals(this.runner.timeout, 1200); }, "should run parsable context when ready": function () { @@ -144,8 +144,8 @@ wire.ready({}); wire.run(); - assertEquals(this.runner.runSuite.args[0][0].length, 1); - assertEquals(this.runner.runSuite.args[0][0][0].name, "Parsed"); + B.referee.assert.equals(this.runner.runSuite.args[0][0].length, 1); + B.referee.assert.equals(this.runner.runSuite.args[0][0][0].name, "Parsed"); }, "should filter context before running": function () { @@ -155,7 +155,7 @@ wire.ready({ filters: ["Stuff"] }); wire.run(); - assertEquals(this.runner.runSuite.args[0][0].length, 0); + B.referee.assert.equals(this.runner.runSuite.args[0][0].length, 0); }, "should capture console if configured to do so": function () { @@ -165,7 +165,7 @@ wire.ready({ captureConsole: true }); wire.run(); - assert(B.captureConsole.calledOnce); + B.referee.assert(B.captureConsole.calledOnce); }, "should not capture console by default": function () { @@ -175,7 +175,7 @@ wire.ready({}); wire.run(); - assert(!B.captureConsole.called); + B.referee.assert(!B.captureConsole.called); }, "should wire document state": function () { @@ -185,7 +185,7 @@ wire.ready({}); wire.run(); - assert(B.wire.documentState.calledOnce); + B.referee.assert(B.wire.documentState.calledOnce); }, "should optionally not wire document state": function () { @@ -195,7 +195,7 @@ wire.ready({ resetDocument: false }); wire.run(); - assert(!B.wire.documentState.called); + B.referee.assert(!B.wire.documentState.called); }, "should start automatically": function () { @@ -203,7 +203,7 @@ wire.ready({}); - assert(this.runner.runSuite.calledOnce); + B.referee.assert(this.runner.runSuite.calledOnce); }, "should not start automatically if autoRun: false": function () { @@ -211,7 +211,7 @@ wire.ready({ autoRun: false }); - assert(!this.runner.runSuite.calledOnce); + B.referee.assert(!this.runner.runSuite.calledOnce); }, "should start on run() if autoRun: false": function () { @@ -220,7 +220,7 @@ wire.ready({ autoRun: false }); wire.run(); - assert(this.runner.runSuite.calledOnce); + B.referee.assert(this.runner.runSuite.calledOnce); }, "should not run if not ready": function () { @@ -228,7 +228,7 @@ wire.run(); - assert(!this.runner.runSuite.calledOnce); + B.referee.assert(!this.runner.runSuite.calledOnce); }, "should run when ready": function () { @@ -237,7 +237,7 @@ wire.run(); wire.ready(); - assert(this.runner.runSuite.calledOnce); + B.referee.assert(this.runner.runSuite.calledOnce); }, "should receive config when running before ready": function () { @@ -247,7 +247,7 @@ wire.run(); wire.ready({ captureConsole: true }); - assert(B.captureConsole.calledOnce); + B.referee.assert(B.captureConsole.calledOnce); }, "should defer creating test runner": function () { @@ -259,11 +259,11 @@ wire.run(); wire.ready({}); - assert(runSuite.calledOnce); + B.referee.assert(runSuite.calledOnce); } }); - B.util.testCase("BrowserWireTest", { + B.testCase("BrowserWireTest", { setUp: setUp, tearDown: tearDown, @@ -272,7 +272,7 @@ B.ready(); B.run(); - assert(this.runner.runSuite.calledOnce); + B.referee.assert(this.runner.runSuite.calledOnce); } }); }(buster)); diff --git a/test/integration/browser/buster.js b/test/integration/browser/buster.js new file mode 100644 index 0000000..0e97b98 --- /dev/null +++ b/test/integration/browser/buster.js @@ -0,0 +1,13 @@ +var config = module.exports; + + +config["browser tests"] = { + environment: "browser", + tests: [ + "*-test.js" + ], + libs: [ + "capture-server-test-helper.js" + ] +}; + diff --git a/test/browser/capture-server-test-helper.js b/test/integration/browser/capture-server-test-helper.js similarity index 72% rename from test/browser/capture-server-test-helper.js rename to test/integration/browser/capture-server-test-helper.js index aedc318..7bac69a 100644 --- a/test/browser/capture-server-test-helper.js +++ b/test/integration/browser/capture-server-test-helper.js @@ -1,8 +1,8 @@ function createRemoteEmitter() { - var emitter = buster.eventEmitter.create(); + var emitter = buster.bane.createEventEmitter(); emitter.emit = function (event, data) { - return buster.eventEmitter.emit.call(this, event, { + return buster.emit.call(this, event, { data: data, topic: event }); diff --git a/test/integration/browser/capture-server-wiring-test.js b/test/integration/browser/capture-server-wiring-test.js new file mode 100644 index 0000000..44aab69 --- /dev/null +++ b/test/integration/browser/capture-server-wiring-test.js @@ -0,0 +1,247 @@ +(function (B) { + if (typeof require == "function" && typeof module == "object") { + return; + } + + function setUp() { + this.emitter = createRemoteEmitter(); + this.readyListener = sinon.spy(); + this.emitter.on("ready", this.readyListener); + B.configureTestClient(this.emitter); + + this.bnt = B.nextTick; + sinon.spy(B.testRunner, "runSuite"); + + B.nextTick = function (callback) { + callback(); + }; + } + + function tearDown() { + B.nextTick = this.bnt; + B.testRunner.runSuite.restore(); + } + + B.testCase("BrowserWiringTest", { + setUp: setUp, + tearDown: tearDown, + + "//should connect bayeux emitter": function () { + B.referee.assert(this.emitter.connect.calledOnce); + }, + + "should not emit ready immediately": function () { + B.referee.refute(this.readyListener.called); + }, + + "//should not emit ready when connected": function () { + this.emitter.connect.args[0][0](); + + B.referee.refute(this.readyListener.calledOnce); + }, + + "//should emit ready when calling buster.ready": function () { + this.emitter.connect.args[0][0](); + B.ready(); + + B.referee.assert(this.readyListener.calledOnce); + }, + + "//should not emit ready before client is connected": function () { + B.ready(); + + B.referee.refute(this.readyListener.calledOnce); + }, + + "//should emit ready when connected after calling buster.ready": function () { + B.ready(); + this.emitter.connect.args[0][0](); + + B.referee.assert(this.readyListener.calledOnce); + }, + + "//should emit user agent string with ready event": function () { + this.emitter.connect.args[0][0](); + B.ready(); + + B.referee.assert(/Mozilla/.test(this.readyListener.args[0][0].data)); + }, + + "should set up console and buster.log shortcut": function () { + B.referee.assert.isObject(B.console); + B.referee.assert.isFunction(B.log); + }, + + "should format log messages nicely": function () { + var message; + B.console.on("log", function (msg) { message = msg.message }); + B.console.log("Hello world", { id: 42 }); + + B.referee.assert.equals("Hello world { id: 42 }", message); + }, + + "should log messages through buster.log": function () { + var message; + B.console.on("log", function (msg) { message = msg.message }); + B.log("Hello world", { id: 42 }); + + B.assert.equals(message, "Hello world { id: 42 }"); + }, + + "//should send log messages over the wire": function () { + var listener = sinon.spy(); + this.emitter.on("log", listener); + + B.console.warn("Hello world", { id: 42 }); + B.referee.assert(listener.calledOnce); + + var msg = listener.args[0][0]; + B.referee.assert.equals("log", msg.topic); + + B.referee.assert.equals({ + message: "Hello world { id: 42 }", + level: "warn" + }, msg.data); + }, + + "//should start running tests when emitting tests:run": function () { + var listener = sinon.spy(); + this.emitter.on("suite:start", listener); + + B.testCase("SomeTest", { "should do it": function () {} }); + this.emitter.emit("tests:run", { autoRun: true }); + + B.referee.assert(listener.calledOnce); + }, + + "//should run specs when emitting tests:run": function () { + var listener = sinon.spy(); + this.emitter.on("context:start", listener); + + B.spec.describe("Spec", function () { + B.spec.it("does it", function () {}); + }); + + this.emitter.emit("tests:run", { autoRun: true }); + + B.referee.assert(listener.calledOnce); + B.referee.assert.equals(listener.args[0][0].data.name, "Spec"); + }, + + "//should run parsable context when emitting tests:run": function () { + var context = { name: "Parsed", tests: [{ name: "Yay" }], contexts: [] }; + + B.addTestContext({ + parse: function () { + return context; + } + }); + + this.emitter.emit("tests:run", { autoRun: true }); + + B.referee.assert(B.testRunner.runSuite.calledOnce); + B.referee.assert.equals(B.testRunner.runSuite.args[0][0], [context]); + }, + + "//should create test runner with options": function () { + this.emitter.emit("tests:run", { + timeout: 25 + }); + + B.referee.assert.equals(25, B.wiredRunner.timeout); + }, + + "should configure assertions to throw": function () { + this.emitter.emit("tests:run"); + B.referee.assert(B.assertions.throwOnFailure); + }, + + "//should count assertions": function () { + var counts = []; + + B.testCase("AssertionCountTest", { + tearDown: function () { + counts.push(B.wiredRunner.assertionCount()); + }, + + "test #1": function () { + B.referee.assert(true); + }, + + "test #2": function () { + B.referee.assert(true); + B.referee.assert(true); + } + }); + + this.emitter.emit("tests:run"); + + B.referee.assert.equals(counts.sort(), [1, 2]); + }, + + "//should filter contexts prior to running": function () { + var tests = [this.spy(), this.spy()]; + B.testCase("AssertionCountTest", { + "test #1": tests[0], + "test #2": tests[1] + }); + + this.emitter.emit("tests:run", { autoRun: true, filters: ["#1"] }); + + B.referee.assert(tests[0].calledOnce); + B.referee.refute(tests[1].called); + }, + + "//should capture console": function () { + this.stub(B, "captureConsole"); + this.emitter.emit("tests:run", { captureConsole: true }); + B.referee.assert(B.captureConsole.calledOnce); + }, + + "should not always capture console": function () { + this.stub(B, "captureConsole"); + this.emitter.emit("tests:run", { captureConsole: false }); + B.referee.assert(!B.captureConsole.called); + } + }); + + B.testCase("BrowserWiringAutoRunFalseTest", { + setUp: function () { + setUp.call(this); + + this.listener = sinon.spy(); + this.emitter.on("suite:start", this.listener); + B.testCase("SomeTest", { "should do it": function () {} }); + }, + + tearDown: tearDown, + + "should not start running tests on tests:run when autoRun is false": + function () { + this.emitter.emit("tests:run", { autoRun: false }); + + B.referee.refute(this.listener.calledOnce); + }, + + "//should start running tests when calling run after tests:run": function () { + this.emitter.emit("tests:run", { autoRun: false }); + B.run(); + + B.referee.assert(this.listener.calledOnce); + }, + + "//should start running tests when calling run before tests:run": function () { + B.run(); + this.emitter.emit("tests:run", { autoRun: false }); + + B.referee.assert(this.listener.calledOnce); + }, + + "should remove all script tags": function () { + B.run(); + this.emitter.emit("tests:run", { autoRun: false }); + + B.referee.assert.equals(0, document.body.getElementsByTagName("script").length); + } + }); +}(buster)); diff --git a/test/integration/expect/test/test-node.js b/test/integration/expect/test/test-node.js index 79d1fb4..b32ec3c 100644 --- a/test/integration/expect/test/test-node.js +++ b/test/integration/expect/test/test-node.js @@ -1,4 +1,4 @@ -var buster = require("buster"); +var buster = require("../../../.."); var mod = require("../src/mod"); var assert = buster.assert; var expect = buster.expect; diff --git a/test/integration/runAllTests.cmd b/test/integration/runAllTests.cmd deleted file mode 100644 index f786f11..0000000 --- a/test/integration/runAllTests.cmd +++ /dev/null @@ -1,20 +0,0 @@ -@echo off - -set returnCode=0 - -setlocal enabledelayedexpansion -for /F %%x in ('dir /B/D/AD') do ( - echo %%x - cd %%x - if exist %cd%\%%x\args.txt ( - set /p args= < args.txt - call buster-test !args! %* - ) else ( - call buster-test %* - ) - IF ERRORLEVEL 1 set returnCode=!errorlevel! - cd.. -) - -echo exit code %returnCode% -exit /B %returnCode% \ No newline at end of file diff --git a/test/integration/runAllTests.sh b/test/integration/runAllTests.sh deleted file mode 100755 index 64bbe49..0000000 --- a/test/integration/runAllTests.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -returnCode=0 - -for dir in `ls -d */ | cut -f1 -d'/'` -do - echo $dir - cd $dir - if [ -f args.txt ]; - then - args=`cat args.txt` - eval buster-test $args $* - else - buster-test $* - fi - if [ $? -ne 0 ]; then returnCode=1; fi - cd .. -done - -echo exit code $returnCode -exit $returnCode diff --git a/test/integration/sinon-match/test.js b/test/integration/sinon-match/test.js index a44be66..838036c 100644 --- a/test/integration/sinon-match/test.js +++ b/test/integration/sinon-match/test.js @@ -1,5 +1,5 @@ if (typeof module == "object" && typeof require == "function") { - var buster = require("buster"); + var buster = require("../../.."); } var assert = buster.assert; diff --git a/test/integration/test-filter/test.js b/test/integration/test-filter/test.js index f3abb0d..2bcc29a 100644 --- a/test/integration/test-filter/test.js +++ b/test/integration/test-filter/test.js @@ -1,4 +1,4 @@ -var buster = require("buster"); +var buster = require("../../.."); var assert = buster.assert; var fail = buster.referee.fail; @@ -8,7 +8,7 @@ buster.testCase("filter by test name", { "test to run": function () { assert(true); }, - + "test to be filtered out": function () { fail("Test should have been filtered out!"); }