зеркало из https://github.com/microsoft/appium.git
289 строки
7.7 KiB
JavaScript
289 строки
7.7 KiB
JavaScript
"use strict";
|
|
|
|
var argv = require('yargs').argv;
|
|
|
|
var gulp = require('gulp'),
|
|
path = require('path'),
|
|
mochaStream = require('spawn-mocha-parallel').mochaStream,
|
|
jshint = require('gulp-jshint'),
|
|
jshintStylish = require('jshint-stylish'),
|
|
jscs = require('gulp-jscs'),
|
|
Q = require('q'),
|
|
runSequence = Q.denodeify(require('run-sequence')),
|
|
cp = require('child_process'),
|
|
spawn = cp.spawn,
|
|
exec = Q.denodeify(cp.exec),
|
|
stream = require('stream'),
|
|
fs = require('fs'),
|
|
split = require('split'),
|
|
os = require('os'),
|
|
_ = require('underscore'),
|
|
through = require('through'),
|
|
promisePipe = require("promisepipe"),
|
|
assert = require('assert'),
|
|
splitArray = require('./test/helpers/split-array');
|
|
|
|
var childProcs = [];
|
|
|
|
function newMochaOpts() {
|
|
return {
|
|
flags: {
|
|
u: 'bdd-with-opts',
|
|
R: process.env.MOCHA_REPORTER || 'nyan',
|
|
'c': true
|
|
},
|
|
env: _.clone(process.env),
|
|
bin: path.join(__dirname, 'node_modules/.bin/mocha'),
|
|
concurrency: 5
|
|
};
|
|
}
|
|
|
|
var JS_SOURCES = ['*.js', 'bin/**/*.js', 'ci/**/*.js', 'new-ci/**/*.js', 'lib/**/*.js', 'test/**/*.js'];
|
|
|
|
gulp.task('jshint', function () {
|
|
return gulp.src(JS_SOURCES)
|
|
.pipe(jshint())
|
|
.pipe(jshint.reporter(jshintStylish))
|
|
.pipe(jshint.reporter('fail'));
|
|
});
|
|
|
|
gulp.task('jscs', function () {
|
|
return gulp.src(JS_SOURCES)
|
|
.pipe(jscs({configPath: __dirname + '/.jscsrc'}));
|
|
});
|
|
|
|
gulp.task('lint', ['jshint', 'jscs']);
|
|
|
|
gulp.task('test-unit', function () {
|
|
var opts = newMochaOpts();
|
|
var mocha = mochaStream(opts);
|
|
return gulp.src('test/unit/**/*-specs.js', {read: false})
|
|
.pipe(mocha)
|
|
.on('error', console.warn.bind(console));
|
|
});
|
|
|
|
function splitE2ETests(srcGlobPattern) {
|
|
var testFiles = [];
|
|
var groups = {};
|
|
return promisePipe(
|
|
gulp.src(srcGlobPattern , {read: false})
|
|
.pipe(through(function (file) {
|
|
testFiles.push(path.relative(file.cwd ,file.path));
|
|
})).on('close', function () {
|
|
testFiles.sort();
|
|
groups = splitArray(testFiles, argv.testSplit);
|
|
})).then(function () {
|
|
assert(groups.length === argv.testSplit);
|
|
return groups;
|
|
});
|
|
}
|
|
|
|
function splitAndroidE2ETests() {
|
|
return splitE2ETests([
|
|
'test/functional/common/**/*-specs.js',
|
|
'test/functional/android/**/*-specs.js',
|
|
'!test/functional/android/chrome/**'
|
|
]);
|
|
}
|
|
|
|
function splitIosE2ETests() {
|
|
return splitE2ETests([
|
|
'test/functional/common/**/*-specs.js',
|
|
'test/functional/ios/**/*-specs.js'
|
|
]);
|
|
}
|
|
|
|
function killProcs() {
|
|
_(childProcs).each(function (child) {
|
|
try { child.kill(); } catch (err) {}
|
|
});
|
|
}
|
|
|
|
gulp.task('kill-procs', function () {
|
|
killProcs();
|
|
});
|
|
|
|
function showSplit(splitPromise, prefix) {
|
|
return splitPromise
|
|
.then(function (groups) {
|
|
console.log(prefix + ' groups:');
|
|
_(groups).each(function (group, i) {
|
|
console.log(i + 1, '-->', group);
|
|
});
|
|
});
|
|
}
|
|
|
|
gulp.task('show-android-e2e-tests-split', function () {
|
|
return showSplit(splitAndroidE2ETests(), 'Android');
|
|
});
|
|
|
|
gulp.task('show-ios-e2e-tests-split', function () {
|
|
return showSplit(splitIosE2ETests(), 'iOS');
|
|
});
|
|
|
|
function newMochaE2EOpts() {
|
|
var opts = newMochaOpts();
|
|
opts.concurrency = 1;
|
|
opts.liveOutput = true;
|
|
opts.liveOutputPrepend= 'client -> ';
|
|
opts.fileOutput = 'client.log';
|
|
return opts;
|
|
}
|
|
|
|
gulp.task('test-android-e2e', function () {
|
|
return splitAndroidE2ETests().then(function (testGroups) {
|
|
var opts = newMochaE2EOpts();
|
|
opts.env.DEVICE='android';
|
|
opts.env.VERBOSE=1;
|
|
opts.flags.g = '@skip-android-all|@android-arm-only|@skip-ci';
|
|
opts.flags.i = true;
|
|
var mocha = mochaStream(opts);
|
|
var testGroup = testGroups[argv.testGroup - 1];
|
|
console.log('running tests for:' + testGroup);
|
|
return promisePipe( gulp.src(testGroup, {read: false})
|
|
.pipe(mocha)
|
|
.on('error', function (err) {
|
|
killProcs();
|
|
throw err;
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
gulp.task('test-ios-e2e', function () {
|
|
return splitIosE2ETests().then(function (testGroups) {
|
|
var opts = newMochaE2EOpts();
|
|
opts.env.DEVICE='ios81'; // TODO: make that configurable
|
|
opts.env.VERBOSE=1;
|
|
opts.flags.g = '@skip-ios81|@skip-ios8|@skip-ios-all|@skip-ios7up';
|
|
opts.flags.i = true;
|
|
var mocha = mochaStream(opts);
|
|
var testGroup = testGroups[argv.testGroup - 1];
|
|
console.log('running tests for:' + testGroup);
|
|
return promisePipe( gulp.src(testGroup, {read: false})
|
|
.pipe(mocha)
|
|
.on('error', function (err) {
|
|
killProcs();
|
|
throw err;
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
gulp.task('launch-appium', function () {
|
|
var deferred = Q.defer();
|
|
var out = new stream.PassThrough();
|
|
|
|
out.pipe(split())
|
|
.on('data', function (line) {
|
|
if (line.match(/Appium REST http interface listener started/)) {
|
|
deferred.resolve();
|
|
}
|
|
console.log('server -->', line);
|
|
});
|
|
out.pipe(fs.createWriteStream('appium.log'));
|
|
var child = spawn("node", ['.'], { detached: false });
|
|
childProcs.push(child);
|
|
child.stdout.pipe(out);
|
|
child.stderr.pipe(out);
|
|
child.on('close', function () {
|
|
deferred.reject('Something went wrong!');
|
|
});
|
|
return deferred.promise;
|
|
});
|
|
|
|
gulp.task('launch-emu', function () {
|
|
var LOG_PREPEND= 'emu --> ';
|
|
var deferred = Q.defer();
|
|
|
|
var emuErrored = false;
|
|
function waitForEmu() {
|
|
var INIT_WAIT = 15000;
|
|
var MAX_WAIT_MS = 300000;
|
|
var POOL_MS = 5000;
|
|
var startMs = Date.now();
|
|
function _waitForEmu () {
|
|
function retry() {
|
|
if (emuErrored) {
|
|
throw new Error('Emulator errored');
|
|
}
|
|
if (Date.now() - startMs > MAX_WAIT_MS) {
|
|
throw new Error('Emulator did not show up');
|
|
}
|
|
console.log(LOG_PREPEND + 'Waiting for emu...');
|
|
return Q.delay(POOL_MS).then(_waitForEmu);
|
|
}
|
|
return exec('adb shell getprop sys.boot_completed')
|
|
.spread(function (stdout) {
|
|
if (stdout && stdout.trim() === '1') {
|
|
console.log(LOG_PREPEND + 'emulator started');
|
|
return;
|
|
}
|
|
return retry();
|
|
}, function (err) {
|
|
if (err.toString().match(/device not found/)) {
|
|
console.log(LOG_PREPEND + 'Device not found, it should be there, killing adb server.');
|
|
return exec('adb kill-server').then(retry);
|
|
}
|
|
return retry();
|
|
});
|
|
}
|
|
return Q.delay(INIT_WAIT).then(_waitForEmu)
|
|
.then(function () {deferred.resolve();});
|
|
}
|
|
|
|
var out = new stream.PassThrough();
|
|
out.pipe(split())
|
|
.on('data', function (line) {
|
|
console.log(LOG_PREPEND + line);
|
|
});
|
|
out.pipe(fs.createWriteStream('emulator.log'));
|
|
var emuBin = os.platform() === 'linux' ? 'emulator64-x86' : 'emulator';
|
|
var emuArgs = [
|
|
'-avd', argv.avd,
|
|
'-no-snapshot-load', '-no-snapshot-save',
|
|
'-no-audio', '-netfast'
|
|
];
|
|
if (os.platform() === 'linux') {
|
|
emuArgs = emuArgs.concat([
|
|
'-qemu', '-m', '512', '-enable-kvm'
|
|
]);
|
|
}
|
|
console.log(LOG_PREPEND + 'executing', emuBin, emuArgs.join(' '));
|
|
var child = spawn(emuBin, emuArgs);
|
|
childProcs.push(child);
|
|
child.stdout.pipe(out);
|
|
child.stderr.pipe(out);
|
|
child.on('error', function (err) {
|
|
emuErrored = true;
|
|
deferred.reject(err);
|
|
});
|
|
child.on('close', function () {
|
|
deferred.reject('Something went wrong!');
|
|
});
|
|
return Q.all([
|
|
waitForEmu(),
|
|
deferred.promise
|
|
]);
|
|
});
|
|
|
|
gulp.task('run-android-e2e', function () {
|
|
return runSequence(['launch-emu', 'launch-appium'], 'test-android-e2e', 'kill-procs')
|
|
.catch(function (err) {
|
|
killProcs();
|
|
throw err;
|
|
});
|
|
});
|
|
|
|
gulp.task('run-ios-e2e', function () {
|
|
return runSequence('launch-appium', 'test-ios-e2e', 'kill-procs')
|
|
.catch(function (err) {
|
|
killProcs();
|
|
throw err;
|
|
});
|
|
});
|
|
|
|
gulp.task('default', function () {
|
|
return runSequence('lint', 'test-unit');
|
|
});
|