From e1dfb0a9a5de10ddbbe66b5bf747b55d5e0f94d9 Mon Sep 17 00:00:00 2001 From: Sammy Jelin Date: Wed, 9 Nov 2016 15:14:21 -0800 Subject: [PATCH] chore(tests): e2e tests Travis only runs a subset of tests via `npm run test_travis`, but `npm test` runs a full suite. See https://github.com/angular/webdriver-manager/issues/165 for details on why travis cannot run all tests. --- .npmignore | 2 + .travis.yml | 2 +- e2e_spec/browser_spec.ts | 56 ++++++++++++++++++++++++++ e2e_spec/server_spec.ts | 28 +++++++++++++ e2e_spec/support/headless.json | 8 ++++ e2e_spec/support/jasmine.json | 8 ++++ e2e_spec/target_browsers.ts | 3 ++ gulpfile.js | 72 +++++++++++++++++++++++++++------- lib/binaries/android_sdk.ts | 5 +++ package.json | 5 ++- 10 files changed, 172 insertions(+), 17 deletions(-) create mode 100644 e2e_spec/browser_spec.ts create mode 100644 e2e_spec/server_spec.ts create mode 100644 e2e_spec/support/headless.json create mode 100644 e2e_spec/support/jasmine.json create mode 100644 e2e_spec/target_browsers.ts diff --git a/.npmignore b/.npmignore index c836d257..ab2aa636 100644 --- a/.npmignore +++ b/.npmignore @@ -2,6 +2,8 @@ lib/ selenium/ spec/ built/spec/ +e2e_spec/ +built/e2e_spec/ .clang-format .gitattributes diff --git a/.travis.yml b/.travis.yml index 1b6eb336..9ab774a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,4 +20,4 @@ before_install: script: - npm run check_format - - npm test + - npm run test_travis diff --git a/e2e_spec/browser_spec.ts b/e2e_spec/browser_spec.ts new file mode 100644 index 00000000..6fd21859 --- /dev/null +++ b/e2e_spec/browser_spec.ts @@ -0,0 +1,56 @@ +import * as os from 'os'; +import * as webdriver from 'selenium-webdriver'; +import {AndroidSDK} from '../lib/binaries' + +let browsers: string[] = require('./target_browsers')[os.type()]; +let versions: {androidsdk: string, appium: string} = require('../config.json').webdriverVersions; + + +describe('browser smoke tests', () => { + browsers.forEach((browserName) => { + if (browserName == 'android') { + it('should be able to boot up android chrome', (done) => { + let driver = + new webdriver.Builder() + .usingServer('http://localhost:4723/wd/hub') + .withCapabilities({ + browserName: 'chrome', + platformName: 'Android', + platformVersion: + AndroidSDK.VERSIONS[parseInt(AndroidSDK.DEFAULT_API_LEVELS.split(',')[0])], + deviceName: 'Android Emulator' + }) + .build(); + driver.get('http://10.0.2.2:4723/wd/hub/status') + .then(() => { + return driver.getPageSource(); + }) + .then((source: string) => { + expect(source).toContain('"status":0'); + return driver.quit(); + }) + .then(() => { + done(); + }); + }, 60 * 1000); + } else { + it('should be able to boot up ' + browserName, (done) => { + let driver = new webdriver.Builder() + .usingServer('http://localhost:4444/wd/hub') + .withCapabilities({browserName: browserName}) + .build(); + driver.get('http://localhost:4444/selenium-server/driver/?cmd=getLogMessages') + .then(() => { + return driver.getPageSource(); + }) + .then((source: string) => { + expect(source).toContain('OK'); + return driver.quit(); + }) + .then(() => { + done(); + }); + }); + } + }); +}); diff --git a/e2e_spec/server_spec.ts b/e2e_spec/server_spec.ts new file mode 100644 index 00000000..b05be222 --- /dev/null +++ b/e2e_spec/server_spec.ts @@ -0,0 +1,28 @@ +import * as http from 'http'; + + +describe('sever smoke tests', () => { + it('should be able to ping selenium server', (done) => { + http.get('http://localhost:4444/selenium-server/driver/?cmd=getLogMessages', (resp) => { + expect(resp.statusCode).toBe(200); + let logs = ''; + resp.on('data', (chunk) => logs += chunk); + resp.on('end', () => { + expect(logs).toContain('OK'); + done() + }); + }); + }); + + it('should be able to ping appium server', (done) => { + http.get('http://localhost:4723/wd/hub/status', (resp) => { + expect(resp.statusCode).toBe(200); + let data = ''; + resp.on('data', (chunk) => data += chunk); + resp.on('end', () => { + expect(JSON.parse(data).status).toBe(0); + done() + }); + }); + }); +}); diff --git a/e2e_spec/support/headless.json b/e2e_spec/support/headless.json new file mode 100644 index 00000000..32c06353 --- /dev/null +++ b/e2e_spec/support/headless.json @@ -0,0 +1,8 @@ +{ + "spec_dir": "built/e2e_spec", + "spec_files": [ + "**/server_spec.js" + ], + "stopSpecOnExpectationFailure": false, + "random": false +} diff --git a/e2e_spec/support/jasmine.json b/e2e_spec/support/jasmine.json new file mode 100644 index 00000000..bd10dc59 --- /dev/null +++ b/e2e_spec/support/jasmine.json @@ -0,0 +1,8 @@ +{ + "spec_dir": "built/e2e_spec", + "spec_files": [ + "**/*_spec.js" + ], + "stopSpecOnExpectationFailure": false, + "random": false +} diff --git a/e2e_spec/target_browsers.ts b/e2e_spec/target_browsers.ts new file mode 100644 index 00000000..dfcbb03b --- /dev/null +++ b/e2e_spec/target_browsers.ts @@ -0,0 +1,3 @@ +export let Linux = ['chrome', 'firefox', 'android']; +export let Darwin = ['chrome', 'firefox', 'android']; +export let Windows_NT = ['chrome', 'firefox', 'internet explorer']; diff --git a/gulpfile.js b/gulpfile.js index cad71bdb..6630771f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,34 +1,37 @@ 'use strict'; +var path = require('path'); var gulp = require('gulp'); var runSequence = require('run-sequence'); var spawn = require('child_process').spawn; -var runSpawn = function(done, task, opt_arg) { - opt_arg = typeof opt_arg !== 'undefined' ? opt_arg : []; - var child = spawn(task, opt_arg, {stdio: 'inherit'}); +var runSpawn = function(task, args, done) { + done = done || function() {}; + var child = spawn(task, args, {stdio: 'inherit'}); var running = false; - child.on('close', function() { + child.on('close', function(code) { if (!running) { running = true; - done(); + done(code); } }); - child.on('error', function() { + child.on('error', function(err) { if (!running) { console.error('gulp encountered a child error'); running = true; - done(); + done(err || 1); } }); + return child; }; +// Build gulp.task('copy', function() { return gulp.src(['config.json', 'package.json']) .pipe(gulp.dest('built/')); }); -var tsGlobs = ['lib/**/*.ts', 'spec/**/*.ts']; +var tsGlobs = ['lib/**/*.ts', '*spec/**/*.ts']; gulp.task('format:enforce', () => { const format = require('gulp-clang-format'); @@ -45,18 +48,57 @@ gulp.task('format', () => { }); gulp.task('tsc', function(done) { - runSpawn(done, process.execPath, ['node_modules/typescript/bin/tsc']); + runSpawn(process.execPath, ['node_modules/typescript/bin/tsc'], done); }); gulp.task('prepublish', function(done) { runSequence('tsc', 'copy', done); }); -gulp.task('default',['prepublish']); -gulp.task('build',['prepublish']); +gulp.task('default', ['prepublish']); +gulp.task('build', ['prepublish']); -gulp.task('test', ['format', 'build'], function(done) { - var opt_arg = []; - opt_arg.push('node_modules/jasmine/bin/jasmine.js'); - runSpawn(done, process.execPath, opt_arg); +// Command line commands +gulp.task('update', ['build'], function(done) { + runSpawn(process.execPath, ['bin/webdriver-manager', 'update', '--android', + '--android-accept-licenses'], done); }); +gulp.task('start', ['build', 'shutdown'], function(done) { + runSpawn(process.execPath, ['bin/webdriver-manager', 'start', '--detach', '--seleniumPort', + '4444', '--android', '--appium-port', '4723', '--quiet'], done); +}); +gulp.task('start:headless', ['build', 'shutdown'], function(done) { + runSpawn(process.execPath, ['bin/webdriver-manager', 'start', '--detach', '--seleniumPort', + '4444', '--android', '--appium-port', '4723', '--quiet', '--avds', 'none'], done); +}); +gulp.task('shutdown', ['build'], function(done) { + runSpawn(process.execPath, ['bin/webdriver-manager', 'shutdown'], done); +}); + +// Test +gulp.task('test:unit', ['build'], function(done) { + runSpawn(process.execPath, ['node_modules/jasmine/bin/jasmine.js'], done); +}); + +gulp.task('test:e2e:inner', ['build'], function(done) { + runSpawn(process.execPath, ['node_modules/jasmine/bin/jasmine.js', 'JASMINE_CONFIG_PATH=' + + path.join('e2e_spec', 'support', 'jasmine.json')], done); +}); +gulp.task('test:e2e:inner:headless', ['build'], function(done) { + runSpawn(process.execPath, ['node_modules/jasmine/bin/jasmine.js', 'JASMINE_CONFIG_PATH=' + + path.join('e2e_spec', 'support', 'headless.json')], done); +}); +gulp.task('test:e2e:no_update', function(done) { + runSequence('start', 'test:e2e:inner', 'shutdown', done); +}); +gulp.task('test:e2e', function(done) { + runSequence('update', 'test:e2e:no_update', done); +}); +gulp.task('test:e2e:headless', function(done) { + runSequence('update', 'start:headless', 'test:e2e:inner:headless', 'shutdown', done); +}); + + +gulp.task('test', ['format', 'test:unit', 'test:e2e']); +gulp.task('test:no_update', ['format', 'test:unit', 'test:e2e:no_update']); +gulp.task('test:headless', ['format', 'test:unit', 'test:e2e:headless']); diff --git a/lib/binaries/android_sdk.ts b/lib/binaries/android_sdk.ts index 64876187..a8278cfe 100644 --- a/lib/binaries/android_sdk.ts +++ b/lib/binaries/android_sdk.ts @@ -39,6 +39,11 @@ export class AndroidSDK extends Binary { static DEFAULT_API_LEVELS = '24'; static DEFAULT_ARCHITECTURES = getAndroidArch(); static DEFAULT_PLATFORMS = 'google_apis'; + static VERSIONS: {[api_level: number]: string} = { + // Before 24 is not supported + 24: '7.0', + 25: '7.1' + } constructor(alternateCDN?: string) { super(alternateCDN || Config.cdnUrls().android); diff --git a/package.json b/package.json index 4791144d..e6e7e818 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "check_format": "gulp format:enforce", "format": "gulp format", "prepublish": "gulp prepublish", - "test": "gulp test" + "test": "gulp test", + "test_travis": "gulp test:headless" }, "keywords": [ "angular", @@ -53,12 +54,14 @@ "@types/q": "^0.0.32", "@types/request": "^0.0.33", "@types/rimraf": "^0.0.28", + "@types/selenium-webdriver": "^2.53.35", "@types/semver": "^5.3.30", "clang-format": "^1.0.35", "gulp": "^3.9.1", "gulp-clang-format": "^1.0.23", "jasmine": "^2.4.1", "run-sequence": "^1.1.5", + "selenium-webdriver": "2.53.1", "typescript": "^2.1.1" } }