diff --git a/.travis.yml b/.travis.yml index 164dd52f4981..59d95359a4c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,8 @@ env: - LOGS_DIR=/tmp/angular-build/logs - SAUCE_USERNAME=angular-ci - SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987 + - BROWSER_STACK_USERNAME=angularteam1 + - BROWSER_STACK_ACCESS_KEY=BWCd4SynLzdDcv8xtzsB - ARCH=linux-x64 - DART_DEV_VERSION=latest - DART_STABLE_VERSION=latest @@ -36,6 +38,7 @@ env: - MODE=dart DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION - MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION - MODE=saucelabs DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION + - MODE=browserstack DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION - MODE=dart_experimental DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION - MODE=js DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION - MODE=router DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION @@ -44,6 +47,7 @@ env: matrix: allow_failures: - env: "MODE=saucelabs DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION" + - env: "MODE=browserstack DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION" - env: "MODE=dart_experimental DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION" addons: diff --git a/sauce.conf.js b/browser-providers.conf.js similarity index 87% rename from sauce.conf.js rename to browser-providers.conf.js index 16fa46ccec67..00775a9a2b12 100644 --- a/sauce.conf.js +++ b/browser-providers.conf.js @@ -124,10 +124,17 @@ var customLaunchers = { browserName: 'android', platform: 'Linux', version: '5.1' + }, + + 'BS_Chrome': { + base: 'BrowserStack', + browser: 'chrome', + os: 'OS X', + os_version: 'Yosemite' } }; -var aliases = { +var sauceAliases = { 'ALL': Object.keys(customLaunchers).filter(function(item) {return customLaunchers[item].base == 'SauceLabs';}), 'DESKTOP': ['SL_CHROME', 'SL_FIREFOX', 'SL_IE9', 'SL_IE10', 'SL_IE11', 'SL_EDGE', 'SL_SAFARI7', 'SL_SAFARI8', 'SL_SAFARI9.0'], 'MOBILE': ['SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5.1', 'SL_IOS7', 'SL_IOS8', 'SL_IOS9'], @@ -142,11 +149,19 @@ var aliases = { 'SL_CHROMEDEV', 'SL_FIREFOXBETA'] }; +var browserstackAliases = { + 'ALL': Object.keys(customLaunchers).filter(function(item) {return customLaunchers[item].base == 'BrowserStack';}), + 'DESKTOP': ['BS_Chrome'], + 'CI': ['BS_Chrome'], +}; + module.exports = { customLaunchers: customLaunchers, - aliases: aliases + sauceAliases: sauceAliases, + browserstackAliases: browserstackAliases } if (process.env.TRAVIS) { process.env.SAUCE_ACCESS_KEY = process.env.SAUCE_ACCESS_KEY.split('').reverse().join(''); + process.env.BROWSER_STACK_ACCESS_KEY = process.env.BROWSER_STACK_ACCESS_KEY.split('').reverse().join(''); } diff --git a/gulpfile.js b/gulpfile.js index 5368d54ef79e..ce23094eb891 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -43,7 +43,7 @@ var buildRouter = require('./modules/angular1_router/build'); var uglify = require('gulp-uglify'); var shouldLog = require('./tools/build/logging'); var dartSdk = require('./tools/build/dart'); -var sauceConf = require('./sauce.conf'); +var browserProvidersConf = require('./browser-providers.conf.js'); var os = require('os'); require('./tools/check-environment')({ @@ -477,17 +477,17 @@ function getBrowsersFromCLI() { for (var i = 0; i < inputList.length; i++) { var input = inputList[i]; var karmaChromeLauncher = require('karma-chrome-launcher'); - if (sauceConf.customLaunchers.hasOwnProperty(input) || karmaChromeLauncher.hasOwnProperty("launcher:" + input)) { + if (browserProvidersConf.customLaunchers.hasOwnProperty(input) || karmaChromeLauncher.hasOwnProperty("launcher:" + input)) { // In case of non-sauce browsers, or browsers defined in karma-chrome-launcher (Chrome, ChromeCanary and Dartium): // overrides everything, ignoring other options outputList = [input]; isSauce = false; break; - } else if (sauceConf.customLaunchers.hasOwnProperty("SL_" + input.toUpperCase())) { + } else if (browserProvidersConf.customLaunchers.hasOwnProperty("SL_" + input.toUpperCase())) { isSauce = true; outputList.push("SL_" + input.toUpperCase()); - } else if (sauceConf.aliases.hasOwnProperty(input.toUpperCase())) { - outputList = outputList.concat(sauceConf.aliases[input]); + } else if (browserProvidersConf.sauceAliases.hasOwnProperty(input.toUpperCase())) { + outputList = outputList.concat(browserProvidersConf.sauceAliases[input]); isSauce = true; } else { throw new Error('ERROR: unknown browser found in getBrowsersFromCLI()'); @@ -667,12 +667,25 @@ gulp.task('test.unit.js.sauce/ci', function (done) { browserNoActivityTimeout: 240000, captureTimeout: 120000, reporters: ['dots', 'saucelabs'], - browsers: sauceConf.aliases.CI + browsers: browserProvidersConf.sauceAliases.CI }, function(err) {done(); process.exit(err ? 1 : 0);} ).start(); }); +gulp.task('test.unit.js.browserstack/ci', function (done) { + new karma.Server({ + configFile: __dirname + '/karma-js.conf.js', + singleRun: true, + browserNoActivityTimeout: 240000, + captureTimeout: 120000, + reporters: ['dots'], + browsers: browserProvidersConf.browserstackAliases.CI + }, + function(err) {done(); process.exit(err ? 1 : 0);} + ).start(); +}); + gulp.task('test.unit.dart/ci', function (done) { var browserConf = getBrowsersFromCLI(); new karma.Server({ diff --git a/karma-dart.conf.js b/karma-dart.conf.js index 28951466aa63..858c10e44648 100644 --- a/karma-dart.conf.js +++ b/karma-dart.conf.js @@ -1,4 +1,4 @@ -var sauceConf = require('./sauce.conf'); +var browserProvidersConf = require('./browser-providers.conf.js'); var packageSources = { // Dependencies installed with `pub install`. @@ -67,7 +67,7 @@ module.exports = function(config) { // Map packages to the correct urls where Karma serves them. proxies: proxyPaths, - customLaunchers: sauceConf.customLaunchers, + customLaunchers: browserProvidersConf.customLaunchers, browsers: ['DartiumWithWebPlatform'], port: 9877, diff --git a/karma-js.conf.js b/karma-js.conf.js index b054246e39e5..435dc1a8ea24 100644 --- a/karma-js.conf.js +++ b/karma-js.conf.js @@ -1,4 +1,4 @@ -var sauceConf = require('./sauce.conf'); +var browserProvidersConf = require('./browser-providers.conf.js'); // Karma configuration // Generated on Thu Sep 25 2014 11:52:02 GMT-0700 (PDT) @@ -33,7 +33,7 @@ module.exports = function(config) { exclude: ['dist/js/dev/es5/**/e2e_test/**', 'dist/js/dev/es5/angular2/examples/**', 'dist/angular1_router.js'], - customLaunchers: sauceConf.customLaunchers, + customLaunchers: browserProvidersConf.customLaunchers, sauceLabs: { testName: 'Angular2', @@ -48,18 +48,33 @@ module.exports = function(config) { } }, + browserStack: { + project: 'Angular2', + startTunnel: false, + retryLimit: 1, + timeout: 600 + }, + browsers: ['Chrome'], port: 9876 }); - if (process.env.TRAVIS && process.env.MODE === 'saucelabs') { - config.sauceLabs.build = 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')'; - config.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER; + if (process.env.TRAVIS) { + var buildId = 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')'; + if (process.env.MODE === 'saucelabs') { + config.sauceLabs.build = buildId; + config.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER; + + // TODO(mlaval): remove once SauceLabs supports websockets. + // This speeds up the capturing a bit, as browsers don't even try to use websocket. + console.log('>>>> setting socket.io transport to polling <<<<'); + config.transports = ['polling']; + } - // TODO(mlaval): remove once SauceLabs supports websockets. - // This speeds up the capturing a bit, as browsers don't even try to use websocket. - console.log('>>>> setting socket.io transport to polling <<<<'); - config.transports = ['polling']; + if (process.env.MODE === 'browserstack') { + config.browserStack.build = buildId; + config.browserStack.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER; + } } }; diff --git a/modules/angular1_router/karma-router.conf.js b/modules/angular1_router/karma-router.conf.js index 1bfd17d38002..e9980a724f38 100644 --- a/modules/angular1_router/karma-router.conf.js +++ b/modules/angular1_router/karma-router.conf.js @@ -1,6 +1,6 @@ 'use strict'; -var sauceConf = require('../../sauce.conf'); +var browserProvidersConf = require('../../browser-providers.conf.js'); // This runs the tests for the router in Angular 1.x @@ -20,7 +20,7 @@ module.exports = function (config) { 'test/**/*_spec.js' ], - customLaunchers: sauceConf.customLaunchers, + customLaunchers: browserProvidersConf.customLaunchers, browsers: ['ChromeCanary'] }; diff --git a/npm-shrinkwrap.clean.json b/npm-shrinkwrap.clean.json index d01028ded9f4..83fb3f6ec597 100644 --- a/npm-shrinkwrap.clean.json +++ b/npm-shrinkwrap.clean.json @@ -1997,6 +1997,119 @@ } } }, + "browserstacktunnel-wrapper": { + "version": "1.4.2", + "dependencies": { + "unzip": { + "version": "0.1.11", + "dependencies": { + "fstream": { + "version": "0.1.31", + "dependencies": { + "graceful-fs": { + "version": "3.0.8" + }, + "inherits": { + "version": "2.0.1" + }, + "mkdirp": { + "version": "0.5.1", + "dependencies": { + "minimist": { + "version": "0.0.8" + } + } + }, + "rimraf": { + "version": "2.4.3", + "dependencies": { + "glob": { + "version": "5.0.15", + "dependencies": { + "inflight": { + "version": "1.0.4", + "dependencies": { + "wrappy": { + "version": "1.0.1" + } + } + }, + "once": { + "version": "1.3.2", + "dependencies": { + "wrappy": { + "version": "1.0.1" + } + } + }, + "path-is-absolute": { + "version": "1.0.0" + } + } + } + } + } + } + }, + "pullstream": { + "version": "0.4.1", + "dependencies": { + "over": { + "version": "0.0.5" + }, + "slice-stream": { + "version": "1.0.0" + } + } + }, + "binary": { + "version": "0.3.0", + "dependencies": { + "chainsaw": { + "version": "0.1.0", + "dependencies": { + "traverse": { + "version": "0.3.9" + } + } + }, + "buffers": { + "version": "0.1.1" + } + } + }, + "readable-stream": { + "version": "1.0.33", + "dependencies": { + "core-util-is": { + "version": "1.0.1" + }, + "isarray": { + "version": "0.0.1" + }, + "string_decoder": { + "version": "0.10.31" + }, + "inherits": { + "version": "2.0.1" + } + } + }, + "setimmediate": { + "version": "1.0.4" + }, + "match-stream": { + "version": "0.0.2", + "dependencies": { + "buffers": { + "version": "0.1.1" + } + } + } + } + } + } + }, "canonical-path": { "version": "0.0.2" }, @@ -9631,6 +9744,17 @@ } } }, + "karma-browserstack-launcher": { + "version": "0.1.6", + "dependencies": { + "browserstack": { + "version": "1.2.0" + }, + "q": { + "version": "1.4.1" + } + } + }, "karma-chrome-launcher": { "version": "0.2.0", "dependencies": { diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index cb6a950de2e6..faf67897b6bd 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -3082,6 +3082,177 @@ } } }, + "browserstacktunnel-wrapper": { + "version": "1.4.2", + "from": "browserstacktunnel-wrapper@*", + "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-1.4.2.tgz", + "dependencies": { + "unzip": { + "version": "0.1.11", + "from": "unzip@>=0.1.9 <0.2.0", + "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", + "dependencies": { + "fstream": { + "version": "0.1.31", + "from": "fstream@>=0.1.30 <1.0.0", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "dependencies": { + "graceful-fs": { + "version": "3.0.8", + "from": "graceful-fs@>=3.0.2 <3.1.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.8.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + }, + "mkdirp": { + "version": "0.5.1", + "from": "mkdirp@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "dependencies": { + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + } + } + }, + "rimraf": { + "version": "2.4.3", + "from": "rimraf@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.3.tgz", + "dependencies": { + "glob": { + "version": "5.0.15", + "from": "glob@>=5.0.14 <6.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "dependencies": { + "inflight": { + "version": "1.0.4", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.1", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" + } + } + }, + "once": { + "version": "1.3.2", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.2.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.1", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" + } + } + }, + "path-is-absolute": { + "version": "1.0.0", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" + } + } + } + } + } + } + }, + "pullstream": { + "version": "0.4.1", + "from": "pullstream@>=0.4.1 <1.0.0", + "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", + "dependencies": { + "over": { + "version": "0.0.5", + "from": "over@>=0.0.5 <1.0.0", + "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz" + }, + "slice-stream": { + "version": "1.0.0", + "from": "slice-stream@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz" + } + } + }, + "binary": { + "version": "0.3.0", + "from": "binary@>=0.3.0 <1.0.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "dependencies": { + "chainsaw": { + "version": "0.1.0", + "from": "chainsaw@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "dependencies": { + "traverse": { + "version": "0.3.9", + "from": "traverse@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz" + } + } + }, + "buffers": { + "version": "0.1.1", + "from": "buffers@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" + } + } + }, + "readable-stream": { + "version": "1.0.33", + "from": "readable-stream@>=1.0.31 <1.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "setimmediate": { + "version": "1.0.4", + "from": "setimmediate@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz" + }, + "match-stream": { + "version": "0.0.2", + "from": "match-stream@>=0.0.2 <1.0.0", + "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", + "dependencies": { + "buffers": { + "version": "0.1.1", + "from": "buffers@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" + } + } + } + } + } + } + }, "canonical-path": { "version": "0.0.2", "from": "https://registry.npmjs.org/canonical-path/-/canonical-path-0.0.2.tgz", @@ -14873,6 +15044,23 @@ } } }, + "karma-browserstack-launcher": { + "version": "0.1.6", + "from": "karma-browserstack-launcher@*", + "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-0.1.6.tgz", + "dependencies": { + "browserstack": { + "version": "1.2.0", + "from": "browserstack@1.2.0", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.2.0.tgz" + }, + "q": { + "version": "1.4.1", + "from": "q@>=1.4.1 <1.5.0", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz" + } + } + }, "karma-chrome-launcher": { "version": "0.2.0", "from": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-0.2.0.tgz", diff --git a/package.json b/package.json index 8208ab01a400..254e660bb845 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "broccoli-stew": "^0.2.1", "broccoli-writer": "^0.1.1", "browserify": "^10.2.4", + "browserstacktunnel-wrapper": "^1.4.2", "canonical-path": "0.0.2", "chokidar": "^1.1.0", "clang-format": "^1.0.32", @@ -91,6 +92,7 @@ "js-beautify": "^1.5.5", "js-yaml": "^3.2.7", "karma": "^0.13.10", + "karma-browserstack-launcher": "^0.1.6", "karma-chrome-launcher": "^0.2.0", "karma-cli": "^0.1.0", "karma-dart": "^0.3.0", diff --git a/scripts/browserstack/start_tunnel.js b/scripts/browserstack/start_tunnel.js new file mode 100644 index 000000000000..f4ebe0fa8fd4 --- /dev/null +++ b/scripts/browserstack/start_tunnel.js @@ -0,0 +1,50 @@ +'use strict'; + +var fs = require('fs'); +var http = require('http'); +var BrowserStackTunnel = require('browserstacktunnel-wrapper'); + +var HOSTNAME = 'localhost'; +var PORTS = [9876, 9877]; +var ACCESS_KEY = process.env.BROWSER_STACK_ACCESS_KEY; +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 = []; +var hosts = []; + +PORTS.forEach(function(port) { + fakeServers.push(http.createServer(function() {}).listen(port)); + hosts.push({ + name: HOSTNAME, + port: port, + sslFlag: 0 + }); +}); + +var tunnel = new BrowserStackTunnel({ + key: ACCESS_KEY, + localIdentifier: TUNNEL_IDENTIFIER, + hosts: hosts +}); + +console.log('Starting tunnel on ports', PORTS.join(', ')); +tunnel.start(function(error) { + if (error) { + console.error('Can not establish the tunnel', error); + } else { + console.log('Tunnel established.'); + fakeServers.forEach(function(server) { + server.close(); + }); + + if (READY_FILE) { + fs.writeFile(READY_FILE, ''); + } + } +}); + +tunnel.on('error', function(error) { + console.error(error); +}); diff --git a/scripts/browserstack/start_tunnel.sh b/scripts/browserstack/start_tunnel.sh new file mode 100755 index 000000000000..da351371daf7 --- /dev/null +++ b/scripts/browserstack/start_tunnel.sh @@ -0,0 +1,3 @@ +export BROWSER_STACK_ACCESS_KEY=`echo $BROWSER_STACK_ACCESS_KEY | rev` + +node ./scripts/browserstack/start_tunnel.js & diff --git a/scripts/browserstack/teardown_tunnel.sh b/scripts/browserstack/teardown_tunnel.sh new file mode 100755 index 000000000000..86fd334284e3 --- /dev/null +++ b/scripts/browserstack/teardown_tunnel.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -e -o pipefail + + +echo "Shutting down Browserstack tunnel" +echo "TODO: implement me" +exit 1 \ No newline at end of file diff --git a/scripts/browserstack/waitfor_tunnel.sh b/scripts/browserstack/waitfor_tunnel.sh new file mode 100755 index 000000000000..a603a317b066 --- /dev/null +++ b/scripts/browserstack/waitfor_tunnel.sh @@ -0,0 +1,19 @@ +#!/bin/bash + + +# Wait for Connect to be ready before exiting +# Time out if we wait for more than 2 minutes, so that we can print logs. +let "counter=0" + +while [ ! -f $BROWSER_PROVIDER_READY_FILE ]; do + let "counter++" + if [ $counter -gt 240 ]; then + echo "Timed out after 2 minutes waiting for browser provider ready file" + # We must manually print logs here because travis will not run + # after_script commands if the failure occurs before the script + # phase. + ./scripts/ci/print-logs.sh + exit 5 + fi + sleep .5 +done diff --git a/scripts/ci/after-script.sh b/scripts/ci/after-script.sh index 8c444e964f5c..998073c7ccdc 100755 --- a/scripts/ci/after-script.sh +++ b/scripts/ci/after-script.sh @@ -8,6 +8,9 @@ echo '*******************' if [ "$MODE" = "saucelabs" ]; then ./scripts/sauce/sauce_connect_teardown.sh fi +if [ "$MODE" = "browserstack" ]; then + ./scripts/browserstack/teardown_tunnel.sh +fi echo '---------------------' diff --git a/scripts/ci/build_and_test.sh b/scripts/ci/build_and_test.sh index 6b505428295c..d7f832ec0952 100755 --- a/scripts/ci/build_and_test.sh +++ b/scripts/ci/build_and_test.sh @@ -10,7 +10,7 @@ cd $SCRIPT_DIR/../.. if [ "$MODE" = "dart_experimental" ]; then ${SCRIPT_DIR}/build_$MODE.sh -elif [ "$MODE" = "saucelabs" ]; then +elif [ "$MODE" = "saucelabs" ] || [ "$MODE" = "browserstack" ] ; then ${SCRIPT_DIR}/test_$MODE.sh elif [ "$MODE" = "lint" ]; then ./node_modules/.bin/gulp static-checks diff --git a/scripts/ci/test_browserstack.sh b/scripts/ci/test_browserstack.sh new file mode 100755 index 000000000000..9f6c3a834b41 --- /dev/null +++ b/scripts/ci/test_browserstack.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +echo ============================================================================= +# go to project dir +SCRIPT_DIR=$(dirname $0) +cd $SCRIPT_DIR/../.. + +./scripts/browserstack/start_tunnel.sh +./scripts/browserstack/waitfor_tunnel.sh +./node_modules/.bin/gulp build.js.dev +./node_modules/.bin/gulp test.unit.js.browserstack/ci