;(function() { 'use strict'; var ecstatic = require('ecstatic'), http = require('http'), path = require('path'), request = require('request'), SauceTunnel = require('sauce-tunnel'), url = require('url'); var port = 8081, username = process.env.SAUCE_USERNAME, accessKey = process.env.SAUCE_ACCESS_KEY; var platforms = [ ['Windows 7', 'chrome', ''], ['Windows 7', 'firefox', '25'], ['Windows 7', 'firefox', '20'], ['Windows 7', 'firefox', '10'], ['Windows 7', 'firefox', '6'], ['Windows 7', 'firefox', '4'], ['Windows 7', 'firefox', '3'], ['WIN8.1', 'internet explorer', '11'] ['Windows 7', 'internet explorer', '10'], ['Windows 7', 'internet explorer', '9'], ['Windows 7', 'internet explorer', '8'], ['Windows XP', 'internet explorer', '7'], ['Windows XP', 'internet explorer', '6'], ['OS X 10.8', 'safari', '6'], ['Windows 7', 'safari', '5'] ]; // create a web server for the local dir var mount = ecstatic({ root: path.resolve(__dirname, '..'), cache: false }); http.createServer(function(req, res) { var parsedUrl = url.parse(req.url, true); var compat = parsedUrl.query.compat; if (compat) { // see http://msdn.microsoft.com/en-us/library/ff955275(v=vs.85).aspx res.setHeader('X-UA-Compatible', 'IE=' + compat); } mount(req, res); }).listen(port); // set up sauce connect so we can use this server from saucelabs var tunnelTimeout = 10000, tunnel = new SauceTunnel(username, accessKey, null, true, tunnelTimeout); console.log('Opening sauce connect tunnel...'); tunnel.start(function(success) { if (success) { console.log('Sauce connect tunnel opened'); runTests(); } else { // fail without an exit code for pull requests console.error('Failed to open sauce connect tunnel'); process.exit(0); } }); function runTests() { var testDefinition = { 'framework': 'qunit', 'platforms': platforms, 'url': 'http://localhost:' + port + '/test/index.html' }; console.log('Starting saucelabs tests: ' + JSON.stringify(testDefinition)); request.post('https://saucelabs.com/rest/v1/' + username + '/js-tests', { 'auth': { 'user': username, 'pass': accessKey }, 'json': testDefinition }, function(error, response, body) { if (response.statusCode == 200) { waitForTestCompletion(body); } else { console.error('Failed to submit test to Sauce Labs, status ' + response.statusCode + ', body:\n' + JSON.stringify(body)); process.exit(3); } }); } function waitForTestCompletion(testIdentifier) { request.post('https://saucelabs.com/rest/v1/' + username + '/js-tests/status', { 'auth': { 'user': username, 'pass': accessKey }, 'json': testIdentifier }, function(error, response, body) { if (response.statusCode == 200) { if (body.completed) { handleTestResults(body['js tests']); } else { waitForTestCompletion(testIdentifier); } } else { console.error('Failed to check test status on Sauce Labs, status ' + response.statusCode + ', body:\n' + JSON.stringify(body)); process.exit(4); } }); } function handleTestResults(results) { var failingTests = results.filter(function(test) { return !test.result || test.result.failed; }); var failingPlatforms = failingTests.map(function(test) { return test.platform; }); if (!failingTests.length) { console.log('Tests passed'); } else { console.error('Tests failed on platforms: ' + JSON.stringify(failingPlatforms)); failingTests.forEach(function(test) { var details = 'See ' + test.url + ' for details.', platform = JSON.stringify(test.platform), result = test.result; if (result && result.failed) { console.error(result.failed + ' failures on ' + platform + '. ' + details); } else { console.error('Testing on ' + platform + ' failed; no results available. ' + details); } }); } console.log('Shutting down sauce connect tunnel...'); tunnel.stop(function() { process.exit(allTestsSuccessful ? 0 : 1); }); } }());