diff --git a/Gruntfile.js b/Gruntfile.js index 1b130c89..9ae71a68 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -7,6 +7,174 @@ module.exports = function (grunt) { var COMPRESS_FOR_TESTS = true; + // Sauce Labs browser + var browsers = [ + // Desktop browsers + { + browserName: "chrome", + version: 'latest', + platform: 'Windows 7' + }, + { + browserName: "firefox", + version: 'latest', + platform: 'Linux' + }, + { + browserName: 'safari', + version: '9', + platform: 'OS X 10.11' + }, + { + browserName: 'safari', + version: '8', + platform: 'OS X 10.10' + }, + { + browserName: "internet explorer", + version: '8', + platform: 'Windows XP' + }, + { + browserName: "internet explorer", + version: '9', + platform: 'Windows 7' + }, + { + browserName: "internet explorer", + version: '11', + platform: 'Windows 8.1' + }, + { + browserName: "edge", + version: '13', + platform: 'Windows 10' + }, + // Mobile browsers + { + browserName: "ipad", + version: '8.0', + platform: 'OS X 10.9', + 'device-orientation': 'portrait' + }, + { + browserName: 'iphone', + version: '7.1', + platform: 'OS X 10.9' + }, + { + browserName: 'iphone', + version: '9.3', + platform: 'OS X 10.10' + }, + { + browerName: 'android', + version: '4.2', + platform: 'Linux' + } + ]; + var browsers = [ + // Desktop browsers + { + browserName: "chrome", + version: 'latest', + platform: 'Windows 7' + }, + { + browserName: "firefox", + version: 'latest', + platform: 'Linux' + }, + { + browserName: 'safari', + version: '9', + platform: 'OS X 10.11' + }, + { + browserName: 'safari', + version: '8', + platform: 'OS X 10.10' + }, + { + browserName: "internet explorer", + version: '8', + platform: 'Windows XP' + }, + { + browserName: "internet explorer", + version: '9', + platform: 'Windows 7' + }, + { + browserName: "internet explorer", + version: '11', + platform: 'Windows 8.1' + }, + { + browserName: "edge", + version: '13', + platform: 'Windows 10' + }, + // Mobile browsers + { + browserName: "ipad", + version: '8.0', + platform: 'OS X 10.9', + 'device-orientation': 'portrait' + }, + { + browserName: 'iphone', + version: '7.1', + platform: 'OS X 10.9' + }, + { + browserName: 'iphone', + version: '9.3', + platform: 'OS X 10.10' + }, + { + browerName: 'android', + version: '4.2', + platform: 'Linux' + } + ]; + + // var sauceJobs = {}; + + // [ "main", + // "filemanager-plugin", + // "visitor-plugin", + // "pre-processor-plugin", + // "post-processor-plugin", + // "global-vars", + // "modify-vars", + // "production", + // "rootpath-relative", + // "rootpath", + // "relative-urls", + // "browser", + // "no-js-errors", + // "legacy", + // "strict-units" + // ].map(function(testName) { + // sauceJobs[testName] = { + // options: { + // urls: ["http://localhost:8081/tmp/browser/test-runner-" + testName + ".html"], + // testname: 'Less.js test - ' + testName, + // browsers: browsers, + // public: 'public', + // recordVideo: false, + // videoUploadOnPass: false, + // recordScreenshots: process.env.TRAVIS_BRANCH !== "master", + // build: process.env.TRAVIS_BRANCH === "master" ? process.env.TRAVIS_JOB_ID : undefined, + // tags: [process.env.TRAVIS_BUILD_NUMBER, process.env.TRAVIS_PULL_REQUEST, process.env.TRAVIS_BRANCH], + // sauceConfig: { + // 'idle-timeout': 100 + // }, + // throttled: 5 + // } + // }; + // }); // Project configuration. grunt.initConfig({ @@ -278,89 +446,56 @@ module.exports = function (grunt) { 'saucelabs-jasmine': { all: { options: { - urls: ["filemanager-plugin","visitor-plugin","pre-processor-plugin","post-processor-plugin","global-vars", "modify-vars", "production", "rootpath-relative", + urls: ["main", "filemanager-plugin","visitor-plugin","pre-processor-plugin","post-processor-plugin","global-vars", "modify-vars", "production", "rootpath-relative", "rootpath", "relative-urls", "browser", "no-js-errors", "legacy", "strict-units" ].map(function(testName) { return "http://localhost:8081/tmp/browser/test-runner-" + testName + ".html"; }), testname: 'Sauce Unit Test for less.js', - browsers: [ - // Desktop browsers - { - browserName: "chrome", - version: 'latest', - platform: 'Windows 7' - }, - { - browserName: "firefox", - version: 'latest', - platform: 'Linux' - }, - { - browserName: 'safari', - version: '9.1', - platform: 'OS X 10.10' - }, - { - browserName: 'safari', - version: '8', - platform: 'OS X 10.10' - }, - { - browserName: "internet explorer", - version: '8', - platform: 'Windows XP' - }, - { - browserName: "internet explorer", - version: '9', - platform: 'Windows 7' - }, - { - browserName: "internet explorer", - version: '11', - platform: 'Windows 8.1' - }, - { - browserName: "edge", - version: '13', - platform: 'Windows 10' - }, - // Mobile browsers - { - browserName: "ipad", - version: '8.0', - platform: 'OS X 10.9', - 'device-orientation': 'portrait' - }, - { - browserName: 'iphone', - version: '7.1', - platform: 'OS X 10.9' - }, - { - browserName: 'iphone', - version: '9.3', - platform: 'OS X 10.10' - }, - { - browerName: 'android', - version: '4.2', - platform: 'Linux' - } - ], + browsers: browsers, public: 'public', - concurrency: 3, + pollInterval: 2000, + statusCheckAttempts: 30, recordVideo: false, videoUploadOnPass: false, recordScreenshots: process.env.TRAVIS_BRANCH !== "master", build: process.env.TRAVIS_BRANCH === "master" ? process.env.TRAVIS_JOB_ID : undefined, tags: [process.env.TRAVIS_BUILD_NUMBER, process.env.TRAVIS_PULL_REQUEST, process.env.TRAVIS_BRANCH], - 'max-duration': 120, sauceConfig: { 'idle-timeout': 100 }, - throttled: 3 + throttled: 5, + onTestComplete: function(result, callback) { + // Called after a unit test is done, per page, per browser + // 'result' param is the object returned by the test framework's reporter + // 'callback' is a Node.js style callback function. You must invoke it after you + // finish your work. + // Pass a non-null value as the callback's first parameter if you want to throw an + // exception. If your function is synchronous you can also throw exceptions + // directly. + // Passing true or false as the callback's second parameter passes or fails the + // test. Passing undefined does not alter the test result. Please note that this + // only affects the grunt task's result. You have to explicitly update the Sauce + // Labs job's status via its REST API, if you want so. + + // This should be the encrypted value in Travis + var user = process.env.SAUCE_USERNAME; + var pass = process.env.SAUCE_ACCESS_KEY; + + require('request').put({ + url: ['https://saucelabs.com/rest/v1', user, 'jobs', result.job_id].join('/'), + auth: { user: user, pass: pass }, + json: { passed: result.passed } + }, function (error, response, body) { + if (error) { + callback(error); + } else if (response.statusCode !== 200) { + callback(new Error('Unexpected response status')); + } else { + callback(null, result.passed); + } + }); + } } } }, diff --git a/package.json b/package.json index f7a706f9..420edac8 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,8 @@ "jit-grunt": "^0.10.0", "performance-now": "^0.2.0", "phantomjs-prebuilt": "^2.1.7", + "promise": "^7.1.1", + "request": "^2.73.0", "time-grunt": "^1.3.0" }, "keywords": [ diff --git a/test/browser/common.js b/test/browser/common.js index 58ef5060..6c9300dc 100644 --- a/test/browser/common.js +++ b/test/browser/common.js @@ -3,6 +3,41 @@ jasmine.getEnv().addReporter(new jasmine.JSReporter2()); jasmine.getEnv().defaultTimeoutInterval = 3000; +// From https://github.com/axemclion/grunt-saucelabs/issues/109#issuecomment-166767282 +// (function () { +// var oldJSReport = window.jasmine.getJSReport; +// window.jasmine.getJSReport = function () { +// var results = oldJSReport(); +// if (results) { +// return { +// durationSec: results.durationSec, +// suites: removePassingTests(results.suites), +// passed: results.passed +// }; +// } else { +// return null; +// } +// }; + +// function removePassingTests (suites) { +// return suites.filter(specFailed) +// .map(mapSuite); +// } + +// function mapSuite (suite) { +// var result = {}; +// for (var s in suite) { +// result[s] = suite[s]; +// } +// result.specs = suite.specs.filter(specFailed); +// result.suites = removePassingTests(suite.suites); +// return result; +// } + +// function specFailed (item) { +// return !item.passed; +// } +// })(); /* record log messages for testing */ var logMessages = []; @@ -45,15 +80,15 @@ less.loggers = [ } ]; -var testLessEqualsInDocument = function () { +testLessEqualsInDocument = function () { testLessInDocument(testSheet); }; -var testLessErrorsInDocument = function (isConsole) { +testLessErrorsInDocument = function (isConsole) { testLessInDocument(isConsole ? testErrorSheetConsole : testErrorSheet); }; -var testLessInDocument = function (testFunc) { +testLessInDocument = function (testFunc) { var links = document.getElementsByTagName('link'), typePattern = /^text\/(x-)?less$/; @@ -65,7 +100,7 @@ var testLessInDocument = function (testFunc) { } }; -var ieFormat = function(text) { +ieFormat = function(text) { var styleNode = document.createElement('style'); styleNode.setAttribute('type', 'text/css'); var headNode = document.getElementsByTagName('head')[0]; @@ -84,7 +119,7 @@ var ieFormat = function(text) { return transformedText; }; -var testSheet = function (sheet) { +testSheet = function (sheet) { it(sheet.id + " should match the expected output", function (done) { var lessOutputId = sheet.id.replace("original-", ""), expectedOutputId = "expected-" + lessOutputId, @@ -123,7 +158,7 @@ function extractId(href) { .replace(/\./g, ':'); // Replace dots with colons(for valid id) } -var waitFor = function (waitFunc) { +waitFor = function (waitFunc) { return new Promise(function (resolve) { var timeoutId = setInterval(function () { if (waitFunc()) { @@ -134,7 +169,7 @@ var waitFor = function (waitFunc) { }); }; -var testErrorSheet = function (sheet) { +testErrorSheet = function (sheet) { it(sheet.id + " should match an error", function (done) { var lessHref = sheet.href, id = "less-error-message:" + extractId(lessHref), @@ -183,7 +218,7 @@ var testErrorSheet = function (sheet) { }); }; -var testErrorSheetConsole = function (sheet) { +testErrorSheetConsole = function (sheet) { it(sheet.id + " should match an error", function (done) { var lessHref = sheet.href, id = sheet.id.replace(/^original-less:/, "less-error-message:"), @@ -212,7 +247,7 @@ var testErrorSheetConsole = function (sheet) { }); }; -var loadFile = function (href) { +loadFile = function (href) { return new Promise(function (resolve, reject) { var request = new XMLHttpRequest(); request.open('GET', href, true); diff --git a/test/browser/test-runner-template.tmpl b/test/browser/test-runner-template.tmpl index 9fef5680..6ef3e46f 100644 --- a/test/browser/test-runner-template.tmpl +++ b/test/browser/test-runner-template.tmpl @@ -3,30 +3,22 @@