From 2db0aabee340f1e5554c0d321d263177600aff81 Mon Sep 17 00:00:00 2001 From: Vojta Jina Date: Wed, 3 Dec 2014 16:00:55 -0800 Subject: [PATCH] chore(travis): enable both SauceLabs and BrowserStack Setting env var `BROWSER_PROVIDER` to `browserstack` or `saucelabs` determines which browser provider will be used. This does not affect the build as all jobs are set to use SauceLabs. Switch to Karma with Socket.io 1.x, which solves some issues(*) with BS. Thus removing `config.transports` as it is not used anymore (Socket.io 1.x starts with polling and tries to upgrade if available). (*) folks from BS were fiddling with socket.io configuration to get it stable. See https://github.com/dhimil/karma/commit/4c04011850bf66a8a7556cd76ad662c568399481 This is not necessary with Socket.io 1.x. --- .travis.yml | 12 +-- karma-shared.conf.js | 16 ++-- lib/browser-stack/start-tunnel.js | 6 +- lib/browser-stack/start-tunnel.sh | 2 + package.json | 4 +- protractor-travis-conf.js | 95 ++++++++++++++++++------ scripts/travis/build.sh | 11 ++- scripts/travis/start_browser_provider.sh | 11 +++ 8 files changed, 117 insertions(+), 40 deletions(-) create mode 100755 scripts/travis/start_browser_provider.sh diff --git a/.travis.yml b/.travis.yml index dfc8f6f7..65926750 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,14 +8,16 @@ branches: env: matrix: - - JOB=unit - - JOB=e2e TEST_TARGET=jqlite - - JOB=e2e TEST_TARGET=jquery + - JOB=unit BROWSER_PROVIDER=saucelabs + - JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=saucelabs + - JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=saucelabs global: - SAUCE_USERNAME=angular-ci - SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987 + - BROWSER_STACK_USERNAME=VojtaJina + - BROWSER_STACK_ACCESS_KEY=QCQJ1ZpWXpBkSwEdD8ev - LOGS_DIR=/tmp/angular-build/logs - - BROWSER_PROVIDER_READY_FILE=/tmp/sauce-connect-ready + - BROWSER_PROVIDER_READY_FILE=/tmp/browsersprovider-tunnel-ready install: # - npm config set registry http://23.251.144.68 @@ -28,7 +30,7 @@ install: before_script: - mkdir -p $LOGS_DIR - - ./lib/sauce/sauce_connect_setup.sh + - ./scripts/travis/start_browser_provider.sh - npm install -g grunt-cli - grunt package - ./scripts/travis/wait_for_browser_provider.sh diff --git a/karma-shared.conf.js b/karma-shared.conf.js index cd80f1a6..522cdc86 100644 --- a/karma-shared.conf.js +++ b/karma-shared.conf.js @@ -114,26 +114,30 @@ module.exports = function(config, specificOptions) { var buildLabel = 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')'; config.logLevel = config.LOG_DEBUG; - config.transports = ['websocket', 'xhr-polling']; - config.captureTimeout = 0; // rely on SL timeout + // Karma (with socket.io 1.x) buffers by 50 and 50 tests can take a long time on IEs;-) + config.browserNoActivityTimeout = 120000; config.browserStack.build = buildLabel; config.browserStack.startTunnel = false; + config.browserStack.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER; config.sauceLabs.build = buildLabel; config.sauceLabs.startConnect = false; config.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER; config.sauceLabs.recordScreenshots = true; - // TODO(vojta): remove once SauceLabs supports websockets. - // This speeds up the capturing a bit, as browsers don't even try to use websocket. - config.transports = ['xhr-polling']; - // Debug logging into a file, that we print out at the end of the build. config.loggers.push({ type: 'file', filename: process.env.LOGS_DIR + '/' + (specificOptions.logFile || 'karma.log') }); + + if (process.env.BROWSER_PROVIDER === 'saucelabs' || !process.env.BROWSER_PROVIDER) { + // Allocating a browser can take pretty long (eg. if we are out of capacity and need to wait + // for another build to finish) and so the `captureTimeout` typically kills + // an in-queue-pending request, which makes no sense. + config.captureTimeout = 0; + } } diff --git a/lib/browser-stack/start-tunnel.js b/lib/browser-stack/start-tunnel.js index ac242df9..59519a32 100644 --- a/lib/browser-stack/start-tunnel.js +++ b/lib/browser-stack/start-tunnel.js @@ -5,9 +5,10 @@ var http = require('http'); var BrowserStackTunnel = require('browserstacktunnel-wrapper'); var HOSTNAME = 'localhost'; -var PORTS = require('../grunt/utils').availablePorts; +var PORTS = [9876, 8000]; var ACCESS_KEY = process.env.BROWSER_STACK_ACCESS_KEY; -var READY_FILE = process.env.SAUCE_CONNECT_READY_FILE; +var READY_FILE = process.env.BROWSER_PROVIDER_READY_FILE; +var TUNNEL_IDENTIFIER = process.env.TRAVIS_JOB_NUMBER; // We need to start fake servers, otherwise the tunnel does not start. var fakeServers = []; @@ -24,6 +25,7 @@ PORTS.forEach(function(port) { var tunnel = new BrowserStackTunnel({ key: ACCESS_KEY, + tunnelIdentifier: TUNNEL_IDENTIFIER, hosts: hosts }); diff --git a/lib/browser-stack/start-tunnel.sh b/lib/browser-stack/start-tunnel.sh index 51ad07fb..c29ccb69 100755 --- a/lib/browser-stack/start-tunnel.sh +++ b/lib/browser-stack/start-tunnel.sh @@ -1 +1,3 @@ +export BROWSER_STACK_ACCESS_KEY=`echo $BROWSER_STACK_ACCESS_KEY | rev` + node ./lib/browser-stack/start-tunnel.js & diff --git a/package.json b/package.json index 2d5b4863..fc446ebc 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,8 @@ "jasmine-node": "~1.14.5", "jasmine-reporters": "~1.0.1", "jshint-stylish": "~1.0.0", - "karma": "^0.12.0", - "karma-browserstack-launcher": "0.1.1", + "karma": "vojtajina/karma#socketio_10", + "karma-browserstack-launcher": "0.1.2", "karma-chrome-launcher": "0.1.5", "karma-firefox-launcher": "0.1.3", "karma-jasmine": "0.1.5", diff --git a/protractor-travis-conf.js b/protractor-travis-conf.js index b0969b1f..cc235af8 100644 --- a/protractor-travis-conf.js +++ b/protractor-travis-conf.js @@ -2,32 +2,81 @@ var config = require('./protractor-shared-conf').config; -config.sauceUser = process.env.SAUCE_USERNAME; -config.sauceKey = process.env.SAUCE_ACCESS_KEY; +if (process.env.BROWSER_PROVIDER === 'browserstack') { + // Using BrowserStack. + config.seleniumAddress = 'http://hub.browserstack.com/wd/hub'; + config.multiCapabilities = [ + capabilitiesForBrowserStack({ + browserName: 'chrome', + platform: 'MAC', + version: '34' + }), + capabilitiesForBrowserStack({ + browserName: 'firefox', + version: '28' + }), + capabilitiesForBrowserStack({ + browserName: 'safari', + platform: 'MAC', + version: '7' + }) + ]; +} else { + // Using SauceLabs. + config.sauceUser = process.env.SAUCE_USERNAME; + config.sauceKey = process.env.SAUCE_ACCESS_KEY; + config.multiCapabilities = [ + capabilitiesForSauceLabs({ + browserName: 'chrome', + platform: 'OS X 10.9', + version: '34' + }), + capabilitiesForSauceLabs({ + browserName: 'firefox', + version: '28' + }), + capabilitiesForSauceLabs({ + browserName: 'safari', + platform: 'OS X 10.9', + version: '7' + }) + ]; +} -config.multiCapabilities = [{ - 'browserName': 'chrome', - 'platform': 'OS X 10.9', - 'name': 'Angular E2E', - 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER, - 'build': process.env.TRAVIS_BUILD_NUMBER, - 'version': '34' -}, { - 'browserName': 'firefox', - 'name': 'Angular E2E', - 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER, - 'build': process.env.TRAVIS_BUILD_NUMBER, - 'version': '28' -}, { - browserName: 'safari', - 'platform': 'OS X 10.9', - 'version': '7', - 'name': 'Angular E2E', - 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER, - 'build': process.env.TRAVIS_BUILD_NUMBER -}]; config.allScriptsTimeout = 30000; config.getPageTimeout = 30000; exports.config = config; + + +function capabilitiesForBrowserStack(capabilities) { + return { + 'browserstack.user': process.env.BROWSER_STACK_USERNAME, + 'browserstack.key': process.env.BROWSER_STACK_ACCESS_KEY, + 'browserstack.local' : 'true', + 'browserstack.debug': 'true', + 'browserstack.tunnelIdentifier': process.env.TRAVIS_JOB_NUMBER, + 'tunnelIdentifier': process.env.TRAVIS_JOB_NUMBER, + + 'name': 'Angular E2E', + 'build': process.env.TRAVIS_BUILD_NUMBER, + + 'browserName': capabilities.browserName, + 'platform': capabilities.platform, + 'version': capabilities.version + }; +} + +function capabilitiesForSauceLabs(capabilities) { + return { + 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER, + + 'name': 'Angular E2E', + 'build': process.env.TRAVIS_BUILD_NUMBER, + + 'browserName': capabilities.browserName, + 'platform': capabilities.platform, + 'version': capabilities.version + }; +} diff --git a/scripts/travis/build.sh b/scripts/travis/build.sh index 98af57a6..dbdeb5bc 100755 --- a/scripts/travis/build.sh +++ b/scripts/travis/build.sh @@ -2,13 +2,20 @@ set -e +export BROWSER_STACK_ACCESS_KEY=`echo $BROWSER_STACK_ACCESS_KEY | rev` export SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev` if [ $JOB = "unit" ]; then + if [ "$BROWSER_PROVIDER" == "browserstack" ]; then + BROWSERS="BS_Chrome,BS_Safari,BS_Firefox,BS_IE_9,BS_IE_10,BS_IE_11" + else + BROWSERS="SL_Chrome,SL_Safari,SL_Firefox,SL_IE_9,SL_IE_10,SL_IE_11" + fi + grunt test:promises-aplus - grunt test:unit --browsers SL_Chrome,SL_Safari,SL_Firefox,SL_IE_9,SL_IE_10,SL_IE_11 --reporters dots + grunt test:unit --browsers $BROWSERS --reporters dots grunt ci-checks - grunt tests:docs --browsers SL_Chrome,SL_Safari,SL_Firefox,SL_IE_9,SL_IE_10,SL_IE_11 --reporters dots + grunt tests:docs --browsers $BROWSERS --reporters dots grunt test:travis-protractor --specs "docs/app/e2e/**/*.scenario.js" elif [ $JOB = "e2e" ]; then if [ $TEST_TARGET = "jquery" ]; then diff --git a/scripts/travis/start_browser_provider.sh b/scripts/travis/start_browser_provider.sh new file mode 100755 index 00000000..f10829ec --- /dev/null +++ b/scripts/travis/start_browser_provider.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# Has to be run from project root directory. + +# TODO(vojta): normalize paths to lib/$BROWSER_PROVIDER +if [ "$BROWSER_PROVIDER" == "browserstack" ]; then + echo "Using BrowserStack" + ./lib/browser-stack/start-tunnel.sh +else + echo "Using SauceLabs" + ./lib/sauce/sauce_connect_setup.sh +fi