From 0401a0a67ca526c3efd73af9093ad93d30210f86 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Thu, 7 Nov 2013 14:57:53 -0500 Subject: [PATCH 01/20] NEW sauce-tunnel grunt task --- Gruntfile.js | 3 +++ grunt/tasks/sauce-tunnel.js | 36 ++++++++++++++++++++++++++++++++++++ package.json | 3 ++- 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 grunt/tasks/sauce-tunnel.js diff --git a/Gruntfile.js b/Gruntfile.js index 1f4058f2de..6cbbfd4fd0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -6,6 +6,7 @@ var browserifyTask = require('./grunt/tasks/browserify'); var populistTask = require('./grunt/tasks/populist'); var webdriverPhantomJSTask = require('./grunt/tasks/webdriver-phantomjs'); var webdriverJasmineTasks = require('./grunt/tasks/webdriver-jasmine'); +var sauceTunnelTask = require('./grunt/tasks/sauce-tunnel'); var npmTask = require('./grunt/tasks/npm'); var releaseTasks = require('./grunt/tasks/release'); @@ -46,6 +47,8 @@ module.exports = function(grunt) { grunt.registerMultiTask('populist', populistTask); + grunt.registerTask('sauce-tunnel', sauceTunnelTask); + grunt.registerMultiTask('webdriver-jasmine', webdriverJasmineTasks); grunt.registerMultiTask('npm', npmTask); diff --git a/grunt/tasks/sauce-tunnel.js b/grunt/tasks/sauce-tunnel.js new file mode 100644 index 0000000000..dc3de1164a --- /dev/null +++ b/grunt/tasks/sauce-tunnel.js @@ -0,0 +1,36 @@ +var grunt = require('grunt'); +var SauceTunnel = require('sauce-tunnel'); + +module.exports = function(){ + var task = this; + var config = task.data; + var shouldStayAliveForever = task.flags.keepalive; + + var SAUCE_ACCESS_KEY = process.env.SAUCE_ACCESS_KEY; + if (!SAUCE_ACCESS_KEY) grunt.fatal('Requires the environment variable SAUCE_ACCESS_KEY to be set'); + + var SAUCE_USERNAME = process.env.SAUCE_USERNAME; + if (!SAUCE_USERNAME) grunt.fatal('Requires the environment variable SAUCE_USERNAME to be set'); + + var taskCompletedSuccessfully = task.async(); + + var stunnel = new SauceTunnel(SAUCE_USERNAME, SAUCE_ACCESS_KEY, /*identifier*/null, /*tunneled*/true, /*tunnelTimeout*/10e3); + process.on('exit', stunnel.stop.bind(stunnel, function(){})); + + stunnel.on('log:error', grunt.log.error.bind(grunt.log)); + stunnel.on('log:writeln', grunt.log.writeln.bind(grunt.log)); + + stunnel.on('verbose:ok', grunt.verbose.ok.bind(grunt.verbose)); + stunnel.on('verbose:error', grunt.verbose.error.bind(grunt.verbose)); + stunnel.on('verbose:debug', grunt.verbose.debug.bind(grunt.verbose)); + stunnel.on('verbose:writeln', grunt.verbose.writeln.bind(grunt.verbose)); + + stunnel.openTunnel(function(isOpen){ + if (shouldStayAliveForever && isOpen){ + grunt.verbose.writeln('Keeping the sauce-tunnel open forever because you used the keepalive flag `' + task.name + '`'); + return; + } + grunt.verbose.writeln('To keep the sauce-tunnel open forever, use the grunt task `' + task.name + ':keepalive`'); + taskCompletedSuccessfully(isOpen); + }); +}; diff --git a/package.json b/package.json index bb21489676..3788776cae 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,8 @@ "jasmine-tapreporter": "~0.2.2", "grunt-contrib-connect": "~0.5.0", "es5-shim": "~2.1.0", - "wd": "~0.2.2" + "wd": "~0.2.2", + "sauce-tunnel": "~1.1.0" }, "engines": { "node": ">=0.10.0" From ff857efdd24059b265d4c0178ad69f969ab1c919 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Thu, 7 Nov 2013 15:29:51 -0500 Subject: [PATCH 02/20] desiredCapabilities webdriver config --- grunt/tasks/webdriver-jasmine.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/grunt/tasks/webdriver-jasmine.js b/grunt/tasks/webdriver-jasmine.js index bd998dfcb7..ae0ade5008 100644 --- a/grunt/tasks/webdriver-jasmine.js +++ b/grunt/tasks/webdriver-jasmine.js @@ -4,6 +4,12 @@ var wd = require('wd'); module.exports = function(){ var config = this.data; var taskSucceeded = this.async(); + + var desiredCapabilities = {}; + if (config.desiredCapabilities) Object.keys(config.desiredCapabilities).forEach(function(key){ + desiredCapabilities[key] = config.desiredCapabilities[key]; + }); + grunt.verbose.write('webdriver remote', JSON.stringify(config.webdriver.remote)); var browser = wd.promiseChainRemote(config.webdriver.remote); @@ -16,7 +22,7 @@ module.exports = function(){ }); browser - .init(config.browser || {}) + .init(desiredCapabilities) .get(config.url) .then(function(){return browser;}) .then(getJSReport) From 6b1042a6f9f99e3c6661e638395b9dd4f02a7b31 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Thu, 7 Nov 2013 15:33:52 -0500 Subject: [PATCH 03/20] fixup sauce-tunnel --- grunt/tasks/sauce-tunnel.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grunt/tasks/sauce-tunnel.js b/grunt/tasks/sauce-tunnel.js index dc3de1164a..a215e1898c 100644 --- a/grunt/tasks/sauce-tunnel.js +++ b/grunt/tasks/sauce-tunnel.js @@ -27,10 +27,10 @@ module.exports = function(){ stunnel.openTunnel(function(isOpen){ if (shouldStayAliveForever && isOpen){ - grunt.verbose.writeln('Keeping the sauce-tunnel open forever because you used the keepalive flag `' + task.name + '`'); + grunt.verbose.writeln('Keeping the sauce-tunnel open forever because you used the keepalive flag `' + task.nameArgs + '`'); return; } - grunt.verbose.writeln('To keep the sauce-tunnel open forever, use the grunt task `' + task.name + ':keepalive`'); + grunt.verbose.writeln('To keep the sauce-tunnel open forever, use the grunt task `' + task.nameArgs + ':keepalive`'); taskCompletedSuccessfully(isOpen); }); }; From 7ee30554ad7806fb841f3009a02d2dc11532f61e Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Fri, 8 Nov 2013 11:48:05 -0500 Subject: [PATCH 04/20] ignore tunnel logs --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e69b58bd04..d3277019a0 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ docs/js/examples docs/downloads examples/shared/*.js test/the-files-to-test.generated.js +sauce_connect.log* From f12c428c7895a55f227ca0f039e27943abb1c5d3 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Fri, 8 Nov 2013 16:28:42 -0500 Subject: [PATCH 05/20] NEW saucelabs webdriver task --- grunt/config/webdriver-jasmine.js | 28 +++++++++++++++++++++++++++- grunt/tasks/sauce-tunnel.js | 4 +++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/grunt/config/webdriver-jasmine.js b/grunt/config/webdriver-jasmine.js index 1b3a58b4a3..272c7b4ac3 100644 --- a/grunt/config/webdriver-jasmine.js +++ b/grunt/config/webdriver-jasmine.js @@ -7,7 +7,6 @@ exports.local = { }, url: "http://127.0.0.1:9999/test/index.html", onComplete: function(report){ - var browser = this; if (!report.passed){ grunt.fatal("tests failed"); } @@ -16,3 +15,30 @@ exports.local = { grunt.fatal(error); } } + + +exports.saucelabs = { + webdriver: { + remote: { + /* https://github.com/admc/wd/blob/master/README.md#named-parameters */ + user: process.env.SAUCE_USERNAME, + pwd: process.env.SAUCE_ACCESS_KEY, + + protocol: 'http:', + hostname: 'ondemand.saucelabs.com', + port: '80', + path: '/wd/hub' + } + }, + desiredCapabilities: { + "build": process.env.TRAVIS_BUILD_NUMBER, + "tunnel-identifier": process.env.TRAVIS_JOB_NUMBER || 'my awesome tunnel', + "browserName": "chrome" + }, + url: exports.local.url, + onStart: function(browser){ + grunt.log.writeln("Starting WebDriver Test. Watch results here: http://saucelabs.com/tests/" + browser.sessionID); + }, + onComplete: exports.local.onComplete, + onError: exports.local.onError +} diff --git a/grunt/tasks/sauce-tunnel.js b/grunt/tasks/sauce-tunnel.js index a215e1898c..c35b631fa2 100644 --- a/grunt/tasks/sauce-tunnel.js +++ b/grunt/tasks/sauce-tunnel.js @@ -12,9 +12,11 @@ module.exports = function(){ var SAUCE_USERNAME = process.env.SAUCE_USERNAME; if (!SAUCE_USERNAME) grunt.fatal('Requires the environment variable SAUCE_USERNAME to be set'); + var IDENTIFIER = process.env.TRAVIS_JOB_NUMBER || 'my awesome tunnel'; + var taskCompletedSuccessfully = task.async(); - var stunnel = new SauceTunnel(SAUCE_USERNAME, SAUCE_ACCESS_KEY, /*identifier*/null, /*tunneled*/true, /*tunnelTimeout*/10e3); + var stunnel = new SauceTunnel(SAUCE_USERNAME, SAUCE_ACCESS_KEY, IDENTIFIER, /*tunneled*/true, /*tunnelTimeout*/5); process.on('exit', stunnel.stop.bind(stunnel, function(){})); stunnel.on('log:error', grunt.log.error.bind(grunt.log)); From 7c8b70eedbceb63a67baac6cd3e6fcac8a136838 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Fri, 8 Nov 2013 16:29:57 -0500 Subject: [PATCH 06/20] better error handling for jasmine task --- grunt/tasks/webdriver-jasmine.js | 34 ++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/grunt/tasks/webdriver-jasmine.js b/grunt/tasks/webdriver-jasmine.js index ae0ade5008..f79b22e91d 100644 --- a/grunt/tasks/webdriver-jasmine.js +++ b/grunt/tasks/webdriver-jasmine.js @@ -7,10 +7,12 @@ module.exports = function(){ var desiredCapabilities = {}; if (config.desiredCapabilities) Object.keys(config.desiredCapabilities).forEach(function(key){ + if (config.desiredCapabilities[key] === undefined) return; desiredCapabilities[key] = config.desiredCapabilities[key]; }); + grunt.verbose.writeln("desiredCapabilities", JSON.stringify(desiredCapabilities)); - grunt.verbose.write('webdriver remote', JSON.stringify(config.webdriver.remote)); + grunt.verbose.writeln('webdriver remote', JSON.stringify(config.webdriver.remote)); var browser = wd.promiseChainRemote(config.webdriver.remote); browser.on('status', function(info) { @@ -21,21 +23,38 @@ module.exports = function(){ grunt.verbose.writeln(' > ' + meth, path, data || ''); }); + var report = null; + + // browser._debugPromise(); browser .init(desiredCapabilities) + .then(config.onStart && config.onStart.bind(config, browser)) .get(config.url) .then(function(){return browser;}) .then(getJSReport) - .then(config.onComplete && config.onComplete.bind(browser), config.onError && config.onError.bind(browser)) - .fail(grunt.verbose.writeln.bind(grunt.verbose)) - .fin(function(){ + .then(function(data){ report = data; }) + .fail(function(error){ + grunt.log.error(error); + return browser + .eval('document.documentElement.innerText || document.documentElement.textContent') + .then(grunt.verbose.writeln.bind(grunt.verbose)) + .then(function(){throw error}) + ; + }) + .finally(function(){ if (grunt.option('webdriver-keep-open')) return; grunt.verbose.writeln('Closing the browser window. To keep it open, pass the --webdriver-keep-open flag to grunt.'); return browser.quit(); }) .done( - taskSucceeded.bind(null,true), - taskSucceeded.bind(null,false) + function(){ + if (config.onComplete) config.onComplete(report); + taskSucceeded(true); + }, + function(error){ + if (config.onError) config.onError(error); + taskSucceeded(false); + } ) ; } @@ -43,6 +62,9 @@ module.exports = function(){ function getJSReport(browser){ return browser .waitForCondition("typeof window.jasmine != 'undefined'", 500) + .fail(function(error){ + throw Error("The test page didn't load properly. " + error); + }) .waitForCondition("typeof window.jasmine.getJSReport != 'undefined'", 10e3) .waitForCondition("window.testImageURL.running <= 0", 5e3) .eval("jasmine.getJSReport()") From 66a0f2e7bde5b8e38457aab0513b609473be9c83 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Fri, 8 Nov 2013 16:30:27 -0500 Subject: [PATCH 07/20] Suppress encoding warning in Firefox --- grunt/config/server.js | 1 + 1 file changed, 1 insertion(+) diff --git a/grunt/config/server.js b/grunt/config/server.js index cfa4506dcf..ebb03bc6b0 100644 --- a/grunt/config/server.js +++ b/grunt/config/server.js @@ -16,6 +16,7 @@ module.exports = function(grunt){ function testResultLoggerMiddleware(req, res, next) { if (!(req.body && req.body.data)) return next(); grunt.log.writeln('[%s][%s]', req.headers['user-agent'], Date.now(), req.body.data); + res.write(''); res.end('Got it, thanks!'); } From e3ced21c9d5d099cf0fc71ae5b5d7b2c496a0033 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Fri, 8 Nov 2013 16:33:20 -0500 Subject: [PATCH 08/20] postDataToURL using ajax instead of DOM --- grunt/config/server.js | 21 +----- grunt/tasks/webdriver-jasmine.js | 2 +- test/lib/reportTestResults.browser.js | 94 ++++++++++----------------- 3 files changed, 38 insertions(+), 79 deletions(-) diff --git a/grunt/config/server.js b/grunt/config/server.js index ebb03bc6b0..c91165b1de 100644 --- a/grunt/config/server.js +++ b/grunt/config/server.js @@ -1,25 +1,12 @@ -var pxlgif = Buffer('R0lGODlhAQABAIAAAP///wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==', 'base64'); - module.exports = function(grunt){ - - function printMiddleware(req, res, next) { - if (req._parsedUrl.pathname != '/print') return next(); - if (req.query.message.indexOf('ok') === 0){ - grunt.log.ok(req.query.message); - } else if (req.query.message.indexOf('not ok') === 0){ - grunt.log.error(req.query.message); - } else { - grunt[req.query.type || 'log'].writeln('[%s][%s]', req.headers['user-agent'], Date.now(), req.query.message); - } - res.end(pxlgif); - } + function testResultLoggerMiddleware(req, res, next) { if (!(req.body && req.body.data)) return next(); grunt.log.writeln('[%s][%s]', req.headers['user-agent'], Date.now(), req.body.data); res.write(''); res.end('Got it, thanks!'); } - + return { server: { options: { @@ -27,13 +14,11 @@ module.exports = function(grunt){ hostname: '*', port: 9999, middleware: function(connect, options) { + connect.logger.token('user-agent', function(req, res){ return req.headers['user-agent']; }); connect.logger.token('timestamp', function(req, res){ return Date.now(); }); return [ - connect.query(), - printMiddleware, - connect.logger({format:'[:user-agent][:timestamp] :method :url', stream:grunt.verbose}), connect.bodyParser(), testResultLoggerMiddleware, diff --git a/grunt/tasks/webdriver-jasmine.js b/grunt/tasks/webdriver-jasmine.js index f79b22e91d..34063e1271 100644 --- a/grunt/tasks/webdriver-jasmine.js +++ b/grunt/tasks/webdriver-jasmine.js @@ -66,7 +66,7 @@ function getJSReport(browser){ throw Error("The test page didn't load properly. " + error); }) .waitForCondition("typeof window.jasmine.getJSReport != 'undefined'", 10e3) - .waitForCondition("window.testImageURL.running <= 0", 5e3) + .waitForCondition("window.postDataToURL.running <= 0", 30e3) .eval("jasmine.getJSReport()") ; } diff --git a/test/lib/reportTestResults.browser.js b/test/lib/reportTestResults.browser.js index de65053399..d18ea2ff7f 100644 --- a/test/lib/reportTestResults.browser.js +++ b/test/lib/reportTestResults.browser.js @@ -1,31 +1,16 @@ -console._error = console.error; -console._warn = console.warn; -console._log = console.log; - -console.log = window.print = function(message){ - console._log(message); - testImageURL('/print?type=log&message=' + encodeURIComponent(message) + '&_=' + Date.now().toString(36)); -}; - -console.error = function(message){ - console._error(message); - testImageURL('/print?type=error&message=' + encodeURIComponent(message) + '&_=' + Date.now().toString(36)); -}; - -console.warn = function(message){ - console._warn(message); - testImageURL('/print?type=warn&message=' + encodeURIComponent(message) + '&_=' + Date.now().toString(36)); -}; - ;(function(env){ - env.addReporter(new jasmine.JSReporter()); - env.addReporter(new TAPReporter(window.print)); function report(){ - if (typeof jasmine.getJSReport != 'function') return setTimeout(report, 100); - postDataToURL(JSON.stringify(jasmine.getJSReport()), '/reportTestResults', function(error, event){ + console.log('report'); + if (typeof jasmine.getJSReport != 'function') { + console.log("typeof jasmine.getJSReport != 'function'"); + return setTimeout(report, 100); + } + postDataToURL(jasmine.getJSReport(), '/reportTestResults', function(error, event){ + console.log(error, event); if (error) return console.error(error); + console.log(event); }); } @@ -35,42 +20,31 @@ console.warn = function(message){ report(); }; - function postDataToURL(data, url, callback){ - var id = '$' + (+new Date()).toString(36); - - var postReportingTarget = document.createElement('iframe'); - postReportingTarget.id = postReportingTarget.name = 'postReportingTarget' + id; - - var postReportingForm = document.createElement('form'); - postReportingForm.method = 'POST'; - postReportingForm.action = url; - postReportingForm.target = postReportingTarget.name; - - var postReportingData = document.createElement('input'); - postReportingData.type = 'hidden'; - postReportingData.name = 'data'; - postReportingData.value = data || '{"error":"unknown error in postReportingData"}'; - - postReportingForm.appendChild(postReportingData); - postReportingForm.appendChild(postReportingTarget); - postReportingForm.style.cssText = "visibility:hidden; position:absolute; bottom:100%; right:100%"; - - function done(error, event){ - postReportingForm.parentNode.removeChild(postReportingForm); - callback(error, event); - } - - postReportingTarget.onerror = function(error){ - done(error); - } - postReportingTarget.onload = function(event){ - done(null, event); - } - document.body.appendChild(postReportingForm); - setTimeout(function(){ - postReportingForm.submit(); - },0); - } - }(window.jasmine.getEnv())); +function createXMLHttpRequest(){ + try{return new XMLHttpRequest();} + catch(e){} + try {return new ActiveXObject("Msxml2.XMLHTTP");} + catch (e) {} + try {return new ActiveXObject("Microsoft.XMLHTTP");} + catch (e) {} +} +function postDataToURL(data, url, callback) { + if (!callback) callback = postDataToURL.defaultCallback; + var request = createXMLHttpRequest(); + if (!request) return callback(Error('XMLHttpRequest is unsupported')); + postDataToURL.running = (postDataToURL.running||0) + 1; + request.onreadystatechange = function(){ + if (request.readyState != 4) return; + request.onreadystatechange = null; + postDataToURL.running = (postDataToURL.running||0) - 1; + callback(request.status == 200 ? null : request.status, request.responseText); + }; + request.open('POST', url); + request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + request.send('data=' + encodeURIComponent(JSON.stringify(data))); +} +postDataToURL.defaultCallback = function(error){ + // console.log('postDataToURL.defaultCallback', arguments) +} From 39ba5f90b128401a875aca2330f63017b4872096 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Fri, 8 Nov 2013 16:34:32 -0500 Subject: [PATCH 09/20] no need to pass jasmine through jsx --- Gruntfile.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index 6cbbfd4fd0..ba03dd9c49 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -74,7 +74,6 @@ module.exports = function(grunt) { grunt.registerTask('build:min', ['jsx:release', 'version-check', 'browserify:min']); grunt.registerTask('build:addons-min', ['jsx:debug', 'browserify:addonsMin']); grunt.registerTask('build:test', [ - 'jsx:jasmine', 'jsx:test', 'version-check', 'populist:test' From 37bb9b76aba0deb445874273b93955ffb1c18bf8 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Mon, 11 Nov 2013 15:07:55 -0500 Subject: [PATCH 10/20] remove old browser logger --- test/lib/testImageURL.browser.js | 62 -------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 test/lib/testImageURL.browser.js diff --git a/test/lib/testImageURL.browser.js b/test/lib/testImageURL.browser.js deleted file mode 100644 index b02dd899a6..0000000000 --- a/test/lib/testImageURL.browser.js +++ /dev/null @@ -1,62 +0,0 @@ -testImageURL._recycle = function(img){ - console.log('_recycle', img); - try { - img.src = ''; - img.onload = img.onerror = null; - } catch(e){} - testImageURL._recycleBin.push(img); -} -testImageURL.getImage = function(callback){ - // if (!testImageURL._recycleBin) testImageURL._recycleBin = [new Image(),new Image(),new Image(),new Image()]; - // function get(){ - // if (testImageURL._recycleBin.length === 0) return setTimeout(get, 100); - // callback(testImageURL._recycleBin.shift(), testImageURL._recycle); - // } - // get(); - callback(new Image(), function recycle(){}); -} - -testImageURL.defaultCallback = function(error, event){} - -function testImageURL(url, timeout, callback){ - if (typeof timeout == 'function'){ - callback = timeout; - timeout = testImageURL.timeout; - } - if (typeof callback != 'function') callback = testImageURL.defaultCallback; - - testImageURL.getImage(function(img, done){ - function callbackWrapper(error, event){ - callbackWrapper = testImageURL.noop; - testImageURL.running = (testImageURL.running || 0) - 1; - clearTimeout(timer); - done(img); - img = url = timeout = null; - callback(error, event); - error = event = callback = null; - } - - var timer = setTimeout(function(){callbackWrapper(Error('timeout'));}, timeout); - - try { - img.onload = function(event){ callbackWrapper(null, event || window.event); }; - img.onerror = function(error){ callbackWrapper(error); }; - img.src = url; - testImageURL.running = (testImageURL.running || 0) + 1; - - if (img.complete === true - || img.readyState == 4 - || img.width > 0 - || img.height > 0 - || img.readyState == 'complete' - ) callbackWrapper(null, null); - } - catch(error){ - callbackWrapper(error); - } - }); -} - -testImageURL.noop = function(){}; - -testImageURL.timeout = 5000; From b845134151638b1ef05b838eaf4a7d11cf6df898 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Mon, 11 Nov 2013 15:09:33 -0500 Subject: [PATCH 11/20] user JSON encoding for browser logger Fixes a strange issue in IE --- grunt/config/server.js | 18 ++++++++++++++---- test/lib/reportTestResults.browser.js | 4 ++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/grunt/config/server.js b/grunt/config/server.js index c91165b1de..3e43e07f7c 100644 --- a/grunt/config/server.js +++ b/grunt/config/server.js @@ -1,8 +1,18 @@ module.exports = function(grunt){ function testResultLoggerMiddleware(req, res, next) { - if (!(req.body && req.body.data)) return next(); - grunt.log.writeln('[%s][%s]', req.headers['user-agent'], Date.now(), req.body.data); + if (!(req.method == 'POST' && req._parsedUrl.pathname.indexOf('/reportTestResults') === 0)) return next(); + var logType = 'writeln'; + var message = req.body; + + if (req.body.type && req.body.message){ + if (req.body.type == 'error') logType = 'error'; + else if (req.body.message.indexOf('ok') === 0) logType = 'ok'; + else if (req.body.message.indexOf('not ok') === 0) logType = 'error'; + message = req.body.message; + } + if (typeof message != 'string') message = JSON.stringify(message, null, 2); + grunt.log[logType]('[%s][%s]', req.headers['user-agent'], Date.now(), message); res.write(''); res.end('Got it, thanks!'); } @@ -19,10 +29,10 @@ module.exports = function(grunt){ connect.logger.token('timestamp', function(req, res){ return Date.now(); }); return [ - connect.logger({format:'[:user-agent][:timestamp] :method :url', stream:grunt.verbose}), - connect.bodyParser(), + connect.json(), testResultLoggerMiddleware, + connect.logger({format:'[:user-agent][:timestamp] :method :url', stream:grunt.verbose}), connect.static(options.base), connect.directory(options.base) ]; diff --git a/test/lib/reportTestResults.browser.js b/test/lib/reportTestResults.browser.js index d18ea2ff7f..ea4435ea47 100644 --- a/test/lib/reportTestResults.browser.js +++ b/test/lib/reportTestResults.browser.js @@ -42,8 +42,8 @@ function postDataToURL(data, url, callback) { callback(request.status == 200 ? null : request.status, request.responseText); }; request.open('POST', url); - request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); - request.send('data=' + encodeURIComponent(JSON.stringify(data))); + request.setRequestHeader('Content-Type', 'application/json'); + request.send(JSON.stringify(data)); } postDataToURL.defaultCallback = function(error){ // console.log('postDataToURL.defaultCallback', arguments) From d9b7e478241a029fbb2cd09ad2c373f8c5504050 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Mon, 11 Nov 2013 15:11:18 -0500 Subject: [PATCH 12/20] sped up the webdriver tests --- grunt/config/webdriver-jasmine.js | 4 ++-- grunt/tasks/webdriver-jasmine.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/grunt/config/webdriver-jasmine.js b/grunt/config/webdriver-jasmine.js index 272c7b4ac3..3a9cf1eab0 100644 --- a/grunt/config/webdriver-jasmine.js +++ b/grunt/config/webdriver-jasmine.js @@ -6,8 +6,8 @@ exports.local = { remote: { protocol: 'http:', hostname: '127.0.0.1', port: 9515, path: '/' } }, url: "http://127.0.0.1:9999/test/index.html", - onComplete: function(report){ - if (!report.passed){ + onComplete: function(passed){ + if (!passed){ grunt.fatal("tests failed"); } }, diff --git a/grunt/tasks/webdriver-jasmine.js b/grunt/tasks/webdriver-jasmine.js index 34063e1271..bf5a534901 100644 --- a/grunt/tasks/webdriver-jasmine.js +++ b/grunt/tasks/webdriver-jasmine.js @@ -23,7 +23,7 @@ module.exports = function(){ grunt.verbose.writeln(' > ' + meth, path, data || ''); }); - var report = null; + var results = null; // browser._debugPromise(); browser @@ -32,7 +32,7 @@ module.exports = function(){ .get(config.url) .then(function(){return browser;}) .then(getJSReport) - .then(function(data){ report = data; }) + .then(function(data){ results = data; }) .fail(function(error){ grunt.log.error(error); return browser @@ -48,7 +48,7 @@ module.exports = function(){ }) .done( function(){ - if (config.onComplete) config.onComplete(report); + if (config.onComplete) config.onComplete(results); taskSucceeded(true); }, function(error){ @@ -67,6 +67,6 @@ function getJSReport(browser){ }) .waitForCondition("typeof window.jasmine.getJSReport != 'undefined'", 10e3) .waitForCondition("window.postDataToURL.running <= 0", 30e3) - .eval("jasmine.getJSReport()") + .eval("jasmine.getJSReport().passed") ; } From cd24cbdbf4745e81d02b57269ac89be03fd37b9b Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Mon, 11 Nov 2013 15:11:52 -0500 Subject: [PATCH 13/20] name local saucelabs tests too --- grunt/config/webdriver-jasmine.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grunt/config/webdriver-jasmine.js b/grunt/config/webdriver-jasmine.js index 3a9cf1eab0..f088cb83ef 100644 --- a/grunt/config/webdriver-jasmine.js +++ b/grunt/config/webdriver-jasmine.js @@ -31,7 +31,7 @@ exports.saucelabs = { } }, desiredCapabilities: { - "build": process.env.TRAVIS_BUILD_NUMBER, + "build": process.env.TRAVIS_BUILD_NUMBER || 'dev' + Date.now(), "tunnel-identifier": process.env.TRAVIS_JOB_NUMBER || 'my awesome tunnel', "browserName": "chrome" }, From c1925db06752f4bc875d5a979336228db1d54f30 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Mon, 11 Nov 2013 15:12:35 -0500 Subject: [PATCH 14/20] cleanup --- test/lib/reportTestResults.browser.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/lib/reportTestResults.browser.js b/test/lib/reportTestResults.browser.js index ea4435ea47..f467ee04f3 100644 --- a/test/lib/reportTestResults.browser.js +++ b/test/lib/reportTestResults.browser.js @@ -2,15 +2,12 @@ env.addReporter(new jasmine.JSReporter()); function report(){ - console.log('report'); if (typeof jasmine.getJSReport != 'function') { console.log("typeof jasmine.getJSReport != 'function'"); return setTimeout(report, 100); } - postDataToURL(jasmine.getJSReport(), '/reportTestResults', function(error, event){ - console.log(error, event); + postDataToURL(jasmine.getJSReport(), '/reportTestResults', function(error, results){ if (error) return console.error(error); - console.log(event); }); } From 4daeda1490bd12b64f1bb7a9bae017f957adb89f Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Mon, 11 Nov 2013 15:13:46 -0500 Subject: [PATCH 15/20] log individual test results when in --debug mode --- grunt/config/webdriver-jasmine.js | 2 ++ test/lib/reportTestResults.browser.js | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/grunt/config/webdriver-jasmine.js b/grunt/config/webdriver-jasmine.js index f088cb83ef..7825d3d4d8 100644 --- a/grunt/config/webdriver-jasmine.js +++ b/grunt/config/webdriver-jasmine.js @@ -16,6 +16,8 @@ exports.local = { } } +if (grunt.option('debug')) exports.local.url += '?debug=' + grunt.option('debug'); + exports.saucelabs = { webdriver: { diff --git a/test/lib/reportTestResults.browser.js b/test/lib/reportTestResults.browser.js index f467ee04f3..740f6fbd40 100644 --- a/test/lib/reportTestResults.browser.js +++ b/test/lib/reportTestResults.browser.js @@ -1,5 +1,19 @@ +console._log = console.log; +console.log = function(message){ + console._log(message); + postDataToURL({type:'log', message:message}, '/reportTestResults'); +} +console._error = console.error; +console.error = function(message){ + console._error(message); + postDataToURL({type:'error', message:message}, '/reportTestResults'); +} + ;(function(env){ env.addReporter(new jasmine.JSReporter()); + if (location.search.substring(1).indexOf('debug') != -1){ + env.addReporter(new TAPReporter(console.log.bind(console))); + } function report(){ if (typeof jasmine.getJSReport != 'function') { From 2d6eb3d8fca77c57b96159fbe44bd3342cba3414 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Mon, 11 Nov 2013 15:14:39 -0500 Subject: [PATCH 16/20] don't log your password to the console --- grunt/tasks/webdriver-jasmine.js | 1 - 1 file changed, 1 deletion(-) diff --git a/grunt/tasks/webdriver-jasmine.js b/grunt/tasks/webdriver-jasmine.js index bf5a534901..5d4fd3c802 100644 --- a/grunt/tasks/webdriver-jasmine.js +++ b/grunt/tasks/webdriver-jasmine.js @@ -12,7 +12,6 @@ module.exports = function(){ }); grunt.verbose.writeln("desiredCapabilities", JSON.stringify(desiredCapabilities)); - grunt.verbose.writeln('webdriver remote', JSON.stringify(config.webdriver.remote)); var browser = wd.promiseChainRemote(config.webdriver.remote); browser.on('status', function(info) { From 08bd1f98e5694088c21caf6085ac64afb755d1fd Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Mon, 11 Nov 2013 16:23:18 -0500 Subject: [PATCH 17/20] wait a little longer for the page to load --- grunt/tasks/webdriver-jasmine.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grunt/tasks/webdriver-jasmine.js b/grunt/tasks/webdriver-jasmine.js index 5d4fd3c802..29e54d2d87 100644 --- a/grunt/tasks/webdriver-jasmine.js +++ b/grunt/tasks/webdriver-jasmine.js @@ -60,7 +60,7 @@ module.exports = function(){ function getJSReport(browser){ return browser - .waitForCondition("typeof window.jasmine != 'undefined'", 500) + .waitForCondition("typeof window.jasmine != 'undefined'", 5e3) .fail(function(error){ throw Error("The test page didn't load properly. " + error); }) From d1fd4058daa79535f45ced936b33f891876ed95b Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Mon, 11 Nov 2013 16:23:50 -0500 Subject: [PATCH 18/20] sauce labs browser configs for running manually --- grunt/config/webdriver-jasmine.js | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/grunt/config/webdriver-jasmine.js b/grunt/config/webdriver-jasmine.js index 7825d3d4d8..2859da9d66 100644 --- a/grunt/config/webdriver-jasmine.js +++ b/grunt/config/webdriver-jasmine.js @@ -44,3 +44,45 @@ exports.saucelabs = { onComplete: exports.local.onComplete, onError: exports.local.onError } + +/* https://saucelabs.com/docs/platforms */ +exports.saucelabs_ios = +exports.saucelabs_ios6_1 = sauceItUp({ browserName: 'iphone', version: '6.1', platform:'OS X 10.8' }); +exports.saucelabs_ios6 = sauceItUp({ browserName: 'iphone', version: '6', platform:'OS X 10.8' }); +exports.saucelabs_ios5_1 = sauceItUp({ browserName: 'iphone', version: '5.1', platform:'OS X 10.8' }); +exports.saucelabs_ios5 = sauceItUp({ browserName: 'iphone', version: '5', platform:'OS X 10.6' }); +exports.saucelabs_ios4 = sauceItUp({ browserName: 'iphone', version: '4', platform:'OS X 10.6' }); + +exports.saucelabs_ipad = +exports.saucelabs_ipad6_1 = sauceItUp({ browserName: 'ipad', version: '6.1', platform:'OS X 10.8' }); +exports.saucelabs_ipad6 = sauceItUp({ browserName: 'ipad', version: '6', platform:'OS X 10.8' }); +exports.saucelabs_ipad5_1 = sauceItUp({ browserName: 'ipad', version: '5.1', platform:'OS X 10.8' }); +exports.saucelabs_ipad5 = sauceItUp({ browserName: 'ipad', version: '5', platform:'OS X 10.6' }); +exports.saucelabs_ipad4 = sauceItUp({ browserName: 'ipad', version: '4', platform:'OS X 10.6' }); + +exports.saucelabs_android = sauceItUp({ browserName: 'android', version: '4.0', platform:'Linux' }); +exports.saucelabs_android_tablet = sauceItUp({ browserName: 'android', version: '4.0', platform:'Linux', 'device-type':'tablet' }); + +exports.saucelabs_safari = sauceItUp({ browserName: 'safari' }); +exports.saucelabs_chrome = sauceItUp({ browserName: 'chrome' }); +exports.saucelabs_firefox = sauceItUp({ browserName: 'firefox' }); + +exports.saucelabs_ie = +exports.saucelabs_ie8 = sauceItUp({ browserName: 'internet explorer', version: 8 }); +exports.saucelabs_ie9 = sauceItUp({ browserName: 'internet explorer', version: 9 }); +exports.saucelabs_ie10 = sauceItUp({ browserName: 'internet explorer', version: 10 }); +exports.saucelabs_ie11 = sauceItUp({ browserName: 'internet explorer', version: 11, platform:'Windows 8.1' }); + + +function sauceItUp(desiredCapabilities){ + desiredCapabilities["build"] = exports.saucelabs.desiredCapabilities["build"]; + desiredCapabilities["tunnel-identifier"] = exports.saucelabs.desiredCapabilities["tunnel-identifier"]; + return { + webdriver: exports.saucelabs.webdriver, + url: exports.saucelabs.url, + onStart: exports.saucelabs.onStart, + onComplete: exports.saucelabs.onComplete, + onError: exports.saucelabs.onError, + desiredCapabilities: desiredCapabilities, + }; +} From c4cd02efc5fa8724dc1a6915ec7f076bdd384186 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Mon, 11 Nov 2013 18:30:58 -0500 Subject: [PATCH 19/20] fixes #513 --- test/lib/reportTestResults.browser.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/lib/reportTestResults.browser.js b/test/lib/reportTestResults.browser.js index 740f6fbd40..92010ecd7a 100644 --- a/test/lib/reportTestResults.browser.js +++ b/test/lib/reportTestResults.browser.js @@ -1,3 +1,9 @@ +if (typeof console == 'undefined') console = { + log: function(){}, + warn: function(){}, + error: function(){} +}; + console._log = console.log; console.log = function(message){ console._log(message); From 22829b552993cb7f751259e29448b37b054b29f5 Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Wed, 13 Nov 2013 16:49:08 -0500 Subject: [PATCH 20/20] remove unnecessary task config --- grunt/config/jsx/jsx.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/grunt/config/jsx/jsx.js b/grunt/config/jsx/jsx.js index a23ce02732..e327c5ab77 100644 --- a/grunt/config/jsx/jsx.js +++ b/grunt/config/jsx/jsx.js @@ -24,15 +24,6 @@ var debug = { outputDir: "build/modules" }; -var jasmine = { - rootIDs: [ - "all" - ], - getConfig: getDebugConfig, - sourceDir: "vendor/jasmine", - outputDir: "build/jasmine" -}; - var test = { rootIDs: rootIDs.concat([ "test/all.js", @@ -71,7 +62,6 @@ var release = { module.exports = { debug: debug, - jasmine: jasmine, test: test, release: release };