From 8aa0e3479112f6b630fc223b7709bbda44e31f88 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Wed, 27 Sep 2017 13:20:10 -0700 Subject: [PATCH 1/2] run browser tests concurrently to avoid SauceLabs flake - remove some "unit" tests of questionable value - linting of `karma.conf.js` --- .travis.yml | 29 +-------- karma.conf.js | 79 ++++++++++++++---------- test/node-unit/fs.spec.js | 22 ------- test/node-unit/http-meta-2.spec.js | 96 ------------------------------ test/node-unit/http-meta.spec.js | 69 --------------------- test/node-unit/http.spec.js | 18 ------ 6 files changed, 49 insertions(+), 264 deletions(-) delete mode 100644 test/node-unit/fs.spec.js delete mode 100644 test/node-unit/http-meta-2.spec.js delete mode 100644 test/node-unit/http-meta.spec.js delete mode 100644 test/node-unit/http.spec.js diff --git a/.travis.yml b/.travis.yml index 7e849ccc35..d385ca9226 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,36 +25,8 @@ matrix: env: TARGET=test-node - node_js: '8' env: TARGET=lint - # phantomjs - node_js: '8' env: TARGET=test-browser - # chrome - - node_js: '8' - env: TARGET=test-browser BROWSER="chrome@latest" PLATFORM="Windows 8" - # edge - - node_js: '8' - env: TARGET=test-browser BROWSER="MicrosoftEdge@latest" PLATFORM="Windows 10" - # ie11 - - node_js: '8' - env: TARGET=test-browser BROWSER="internet explorer@11.0" PLATFORM="Windows 8.1" - # ie10 - - node_js: '8' - env: TARGET=test-browser BROWSER="internet explorer@10.0" PLATFORM="Windows 8" - # ie9 - - node_js: '8' - env: TARGET=test-browser BROWSER="internet explorer@9.0" PLATFORM="Windows 7" - # ie8 - - node_js: '8' - env: TARGET=test-browser BROWSER="internet explorer@8.0" PLATFORM="Windows 7" - # ie7 - - node_js: '8' - env: TARGET=test-browser BROWSER="internet explorer@7.0" PLATFORM="Windows XP" - # firefox - - node_js: '8' - env: TARGET=test-browser BROWSER="firefox@latest" PLATFORM="Windows 8.1" - # safari - - node_js: '8' - env: TARGET=test-browser BROWSER="safari@latest" PLATFORM="OS X 10.11" before_install: scripts/travis-before-install.sh @@ -76,3 +48,4 @@ addons: paths: - .karma/ - ./mocha.js + sauce_connect: true diff --git a/karma.conf.js b/karma.conf.js index b8d73fd0e3..21e1e68870 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -6,6 +6,16 @@ var mkdirp = require('mkdirp'); var baseBundleDirpath = path.join(__dirname, '.karma'); var osName = require('os-name'); +var browserPlatformPairs = { + 'chrome@latest': 'Windows 8', + 'MicrosoftEdge@latest': 'Windows 10', + 'internet explorer@11.0': 'Windows 8.1', + 'internet explorer@10.0': 'Windows 8', + 'internet explorer@9.0': 'Windows 7', + 'firefox@latest': 'Windows 10', + 'safari@latest': 'OS X 10.12' +}; + module.exports = function (config) { var bundleDirpath; var cfg = { @@ -51,7 +61,7 @@ module.exports = function (config) { reporters: ['spec'], colors: true, browsers: [osName() === 'macOS Sierra' ? 'Chrome' : 'PhantomJS'], // This is the default browser to run, locally - logLevel: config.LOG_INFO, + logLevel: config.LOG_DEBUG, client: { mocha: { reporter: 'html' @@ -79,18 +89,17 @@ module.exports = function (config) { if (env.TRAVIS) { console.error('Travis-CI detected'); bundleDirpath = path.join(baseBundleDirpath, process.env.TRAVIS_BUILD_ID); - if (env.BROWSER && env.PLATFORM) { - if (env.SAUCE_USERNAME && env.SAUCE_ACCESS_KEY) { - // correlate build/tunnel with Travis - sauceConfig = { - build: 'TRAVIS #' + env.TRAVIS_BUILD_NUMBER + + if (env.SAUCE_USERNAME && env.SAUCE_ACCESS_KEY) { + // correlate build/tunnel with Travis + sauceConfig = { + build: 'TRAVIS #' + env.TRAVIS_BUILD_NUMBER + ' (' + env.TRAVIS_BUILD_ID + ')', - tunnelIdentifier: env.TRAVIS_JOB_NUMBER - }; - console.error('Configured SauceLabs'); - } else { - console.error('No SauceLabs credentials present'); - } + tunnelIdentifier: env.TRAVIS_JOB_NUMBER, + startConnect: false + }; + console.error('Configured SauceLabs'); + } else { + console.error('No SauceLabs credentials present'); } } else if (env.APPVEYOR) { console.error('AppVeyor detected'); @@ -100,9 +109,11 @@ module.exports = function (config) { bundleDirpath = path.join(baseBundleDirpath, 'local'); // don't need to run sauce from appveyor b/c travis does it. if (env.SAUCE_USERNAME || env.SAUCE_ACCESS_KEY) { + var id = require('os').hostname() + ' (' + Date.now() + ')'; sauceConfig = { - build: require('os') - .hostname() + ' (' + Date.now() + ')' + build: id, + tunnelIdentifier: id, + startConnect: true }; console.error('Configured SauceLabs'); } else { @@ -140,31 +151,37 @@ module.exports = function (config) { }; function addSauceTests (cfg) { - var env = process.env; cfg.reporters.push('saucelabs'); - cfg.customLaunchers = {}; - cfg.customLaunchers[env.BROWSER] = { - base: 'SauceLabs', - browserName: env.BROWSER.split('@')[0], - version: env.BROWSER.split('@')[1], - platform: env.PLATFORM - }; - cfg.browsers = [env.BROWSER]; + var browsers = Object.keys(browserPlatformPairs); + cfg.browsers = cfg.browsers.concat(browsers); + cfg.customLaunchers = browsers.reduce(function (acc, browser) { + var platform = browserPlatformPairs[browser]; + var browserParts = browser.split('@'); + var browserName = browserParts[0]; + var version = browserParts[1]; + acc[browser] = { + base: 'SauceLabs', + browserName: browserName, + version: version, + platform: platform + }; + return acc; + }, {}); // See https://github.com/karma-runner/karma-sauce-launcher // See https://github.com/bermi/sauce-connect-launcher#advanced-usage - cfg.sauceLabs = { + Object.assign(cfg.sauceLabs, { public: 'public', - startConnect: true, connectOptions: { - connectRetries: 10, - connectRetryTimeout: 60000 + connectRetries: 2, + connectRetryTimeout: 30000, + detached: cfg.sauceLabs.startConnect, + tunnelIdentifier: cfg.sauceLabs.tunnelIdentifier } - }; - - cfg.concurrency = 5; + }); - cfg.retryLimit = 5; + cfg.concurrency = Infinity; + cfg.retryLimit = 1; // for slow browser booting, ostensibly cfg.captureTimeout = 120000; diff --git a/test/node-unit/fs.spec.js b/test/node-unit/fs.spec.js deleted file mode 100644 index 9d0357c382..0000000000 --- a/test/node-unit/fs.spec.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -var fs = require('fs'); -var path = require('path'); -var os = require('os'); -var tmpFile = path.join.bind(path, os.tmpdir()); - -describe('fs.readFile()', function () { - describe('when the file exists', function () { - it('should succeed', function (done) { - fs.writeFile(tmpFile('mocha'), 'wahoo', done); - }); - }); - - describe('when the file does not exist', function () { - it('should fail', function (done) { - // uncomment - // fs.readFile(tmpFile('does-not-exist'), done); - done(); - }); - }); -}); diff --git a/test/node-unit/http-meta-2.spec.js b/test/node-unit/http-meta-2.spec.js deleted file mode 100644 index 18b4158467..0000000000 --- a/test/node-unit/http-meta-2.spec.js +++ /dev/null @@ -1,96 +0,0 @@ -'use strict'; - -var http = require('http'); - -var PORT = 8899; - -var server = http.createServer(function (req, res) { - var accept = req.headers.accept || ''; - var json = ~accept.indexOf('json'); - - switch (req.url) { - case '/': - res.end('hello'); - break; - case '/users': - if (json) { - res.end('["tobi","loki","jane"]'); - } else { - res.end('tobi, loki, jane'); - } - break; - } -}); - -function get (url) { - var fields; - var expected; - var header = {}; - - function request (done) { - http.get({ path: url, port: PORT, headers: header }, function (res) { - var buf = ''; - res.should.have.property('statusCode', 200); - res.setEncoding('utf8'); - res.on('data', function (chunk) { buf += chunk; }); - res.on('end', function () { - buf.should.equal(expected); - done(); - }); - }); - } - - return { - set: function (field, val) { - header[field] = val; - return this; - }, - - should: { - respond: function (body) { - fields = Object.keys(header).map(function (field) { - return field + ': ' + header[field]; - }).join(', '); - - expected = body; - describe('GET ' + url, function () { - this.timeout(500); - if (fields) { - describe('when given ' + fields, function () { - it('should respond with "' + body + '"', request); - }); - } else { - it('should respond with "' + body + '"', request); - } - }); - } - } - }; -} - -describe('http server', function () { - before(function (done) { - server.listen(PORT, done); - }); - - beforeEach(function () { - this.timeout(2000); - }); - - after(function () { - server.close(); - }); - - get('/') - .should - .respond('hello'); - - get('/users') - .should - .respond('tobi, loki, jane'); - - get('/users') - .set('Accept', 'application/json') - .should - .respond('["tobi","loki","jane"]'); -}); diff --git a/test/node-unit/http-meta.spec.js b/test/node-unit/http-meta.spec.js deleted file mode 100644 index 2ed7ed9204..0000000000 --- a/test/node-unit/http-meta.spec.js +++ /dev/null @@ -1,69 +0,0 @@ -'use strict'; - -var http = require('http'); - -var PORT = 8889; - -var server = http.createServer(function (req, res) { - var accept = req.headers.accept || ''; - var json = ~accept.indexOf('json'); - - switch (req.url) { - case '/': - res.end('hello'); - break; - case '/users': - if (json) { - res.end('["tobi","loki","jane"]'); - } else { - res.end('tobi, loki, jane'); - } - break; - } -}); - -function get (url, body, header) { - return function (done) { - http.get({ - path: url, - port: PORT, - headers: header || {} - }, function (res) { - var buf = ''; - res.should.have.property('statusCode', 200); - res.setEncoding('utf8'); - res.on('data', function (chunk) { buf += chunk; }); - res.on('end', function () { - buf.should.equal(body); - done(); - }); - }); - }; -} - -describe('http requests', function () { - before(function (done) { - server.listen(PORT, done); - }); - - beforeEach(function () { - this.timeout(2000); - }); - - after(function () { - server.close(); - }); - - describe('GET /', function () { - it('should respond with hello', - get('/', 'hello')); - }); - - describe('GET /users', function () { - it('should respond with users', - get('/users', 'tobi, loki, jane')); - - it('should respond with users', - get('/users', '["tobi","loki","jane"]', { Accept: 'application/json' })); - }); -}); diff --git a/test/node-unit/http.spec.js b/test/node-unit/http.spec.js deleted file mode 100644 index b8bc2f7e26..0000000000 --- a/test/node-unit/http.spec.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -var http = require('http'); - -var server = http.createServer(function (req, res) { - res.end('Hello World\n'); -}); - -server.listen(8888); - -describe('http', function () { - it('should provide an example', function (done) { - http.get({ path: '/', port: 8888 }, function (res) { - expect(res).to.have.property('statusCode', 200); - done(); - }); - }); -}); From a67bb6c0a5aa2b28c7076e2bed5a06eddf08013d Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Wed, 27 Sep 2017 22:33:27 -0700 Subject: [PATCH 2/2] restore fs.spec.js --- test/node-unit/fs.spec.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 test/node-unit/fs.spec.js diff --git a/test/node-unit/fs.spec.js b/test/node-unit/fs.spec.js new file mode 100644 index 0000000000..9d0357c382 --- /dev/null +++ b/test/node-unit/fs.spec.js @@ -0,0 +1,22 @@ +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var os = require('os'); +var tmpFile = path.join.bind(path, os.tmpdir()); + +describe('fs.readFile()', function () { + describe('when the file exists', function () { + it('should succeed', function (done) { + fs.writeFile(tmpFile('mocha'), 'wahoo', done); + }); + }); + + describe('when the file does not exist', function () { + it('should fail', function (done) { + // uncomment + // fs.readFile(tmpFile('does-not-exist'), done); + done(); + }); + }); +});