diff --git a/ci/mochas/selendroid-mocha b/ci/mochas/selendroid-mocha new file mode 100755 index 000000000..c35b33e13 --- /dev/null +++ b/ci/mochas/selendroid-mocha @@ -0,0 +1,9 @@ +#!/bin/bash + +SAUCE=1 \ +VERBOSE=1 \ +TARBALL="${TARBALL}" \ +DEVICE="selendroid" \ +./node_modules/.bin/mocha \ +-g "@skip-ci|@skip-selendroid-all" -i \ +"$@" diff --git a/ci/script.sh b/ci/script.sh index cc33b3c46..e7ab4d557 100755 --- a/ci/script.sh +++ b/ci/script.sh @@ -22,7 +22,7 @@ elif [[ $CI_CONFIG == 'build_ios' ]]; then elif [[ $CI_CONFIG == 'build_android' ]]; then source ./ci/android_env echo JAVA_HOME: $JAVA_HOME - ./reset.sh --hardcore --no-npmlink --dev --ios --android + ./reset.sh --hardcore --no-npmlink --dev --android if [[ $TRAVIS_SECURE_ENV_VARS == true ]]; then rm sample-code/apps/ApiDemos mv submodules/ApiDemos sample-code/apps/ @@ -37,8 +37,18 @@ elif [[ $CI_CONFIG == 'build_selendroid' ]]; then source ./ci/android_env echo JAVA_HOME: $JAVA_HOME ./reset.sh --hardcore --no-npmlink --dev --selendroid - #./ci/upload_build_to_sauce.sh - #BRANCH_CAT=selendroid ./ci/git-push.sh + if [[ $TRAVIS_SECURE_ENV_VARS == true ]]; then + rm sample-code/apps/ApiDemos + mv submodules/ApiDemos sample-code/apps/ + rm sample-code/apps/selendroid-test-app.apk + mv submodules/selendroid/selendroid-test-app/target/selendroid-test-app-0.10.0.apk \ + sample-code/apps/selendroid-test-app.apk + ./ci/upload_build_to_sauce.sh + GLOB_PATTERNS='test/functional/selendroid/**/*-specs.js' + node ci/tools/testfiles-tool.js split "${GLOB_PATTERNS}" > ci/test-split.json + cp ci/mochas/selendroid-mocha ci/mocha + BRANCH_CAT=selendroid ./ci/git-push.sh + fi elif [[ $CI_CONFIG == 'build_gappium' ]]; then source ./ci/android_env echo OS X version: `sw_vers -productVersion` diff --git a/test/functional/selendroid/api-specs.js b/test/functional/selendroid/api-specs.js new file mode 100644 index 000000000..bcfe05454 --- /dev/null +++ b/test/functional/selendroid/api-specs.js @@ -0,0 +1,55 @@ +"use strict"; + +var setup = require("../common/setup-base"), + desired = require('./desired'); + +describe('selendroid - api', function () { + + var driver; + setup(this, desired).then(function (d) { driver = d; }); + it('should find and click an element', function (done) { + // selendroid appears to have some issues with implicit waits + // hence the timeouts + driver + .waitForElementByName('App', 10000).click() + .sleep(1000) + .elementByLinkText("Action Bar").should.eventually.exist + .nodeify(done); + }); + + it('should be able to get logcat log type', function (done) { + driver.logTypes().should.eventually.include('logcat') + .nodeify(done); + }); + it('should be able to get logcat logs', function (done) { + driver.log('logcat').then(function (logs) { + logs.length.should.be.above(0); + logs[0].message.should.not.include("\n"); + logs[0].level.should.equal("ALL"); + logs[0].timestamp.should.exist; + }).nodeify(done); + }); + + it('should be able to proxy errors', function (done) { + driver + .elementByCss("foobar").should.be.rejected + .nodeify(done); + }); + + it('should be able to set location', function (done) { + driver + .setGeoLocation("27.17", "78.04") + .nodeify(done); + }); + + it('should error out nicely with incompatible commands', function (done) { + driver + .execute("mobile: flick", [{}]) + .catch(function (err) { + err.cause.value.origValue.should.contain('mobile:'); + throw err; + }).should.be.rejectedWith(/status: 9/) + .nodeify(done); + }); + +}); diff --git a/test/functional/selendroid/app-activities-specs.js b/test/functional/selendroid/app-activities-specs.js new file mode 100644 index 000000000..f12653eb5 --- /dev/null +++ b/test/functional/selendroid/app-activities-specs.js @@ -0,0 +1,45 @@ +"use strict"; + +require('../../helpers/setup-chai'); + +var env = require('../../helpers/env') + , initSession = require('../../helpers/session').initSession + , _ = require('underscore') + , desired = require('./desired'); + +describe('selendroid - app activities', function () { + this.timeout(env.MOCHA_INIT_TIMEOUT); + + // TODO: this does not throw, check why + describe('with no dot @skip-ci', function () { + var session; + var name = this.parent.title + " " + this.title; + + it('should not launch app', function (done) { + var newDesired = _.defaults({'app-activity': 'ApiDemos'}, desired); + session = initSession(newDesired, {'no-retry': true}); + session + .setUp(name) + .should.be.rejected + .nodeify(done); + }); + }); + + describe('fully qualified', function () { + var session; + var name = this.parent.title + " " + this.title; + + afterEach(function (done) { + session + .tearDown(this.currentTest.state === 'passed') + .nodeify(done); + }); + + it('should still launch app', function (done) { + var newDesired = _.defaults({'app-activity': 'com.example.android.apis.ApiDemos'}, desired); + session = initSession(newDesired); + session.setUp(name) + .nodeify(done); + }); + }); +}); diff --git a/test/functional/selendroid/background-app-specs.js b/test/functional/selendroid/background-app-specs.js new file mode 100644 index 000000000..d34edd0d8 --- /dev/null +++ b/test/functional/selendroid/background-app-specs.js @@ -0,0 +1,25 @@ +"use strict"; + +process.env.DEVICE = process.env.DEVICE || "selendroid"; +var setup = require("../common/setup-base") + , desired = require('./desired'); + + +describe('selendroid - background app', function () { + var driver; + setup(this, desired).then(function (d) { driver = d; }); + + it("should background the app", function (done) { + var before = new Date().getTime() / 1000; + driver + .backgroundApp(3) + .then(function () { + ((new Date().getTime() / 1000) - before).should.be.above(2); + // this should not be tested + // ((new Date().getTime() / 1000) - before).should.be.below(5); + }) + .getCurrentActivity() + .should.eventually.include("ApiDemos") + .nodeify(done); + }); +}); diff --git a/test/functional/selendroid/basic-specs.js b/test/functional/selendroid/basic-specs.js deleted file mode 100644 index 428036115..000000000 --- a/test/functional/selendroid/basic-specs.js +++ /dev/null @@ -1,164 +0,0 @@ -"use strict"; - -process.env.DEVICE = process.env.DEVICE || "selendroid"; -var setup = require("../common/setup-base") - , env = require('../../helpers/env') - , initSession = require('../../helpers/session').initSession - , path = require('path') - , Q = require("q") - , _ = require('underscore'); - -var desired = { - app: path.resolve(__dirname, "../../../sample-code/apps/ApiDemos/bin/ApiDemos-debug.apk") -}; - - // , appAct2 = "ApiDemos" - // , appActFull = "com.example.android.apis.ApiDemos" - -describe('selendroid - basic -', function () { - - describe('api', function () { - var driver; - setup(this, desired).then(function (d) { driver = d; }); - it('should find and click an element', function (done) { - // selendroid appears to have some issues with implicit waits - // hence the timeouts - driver - .waitForElementByName('App', 10000).click() - .sleep(1000) - .elementByLinkText("Action Bar").should.eventually.exist - .nodeify(done); - }); - - it('should be able to get logcat log type', function (done) { - driver.logTypes().should.eventually.include('logcat') - .nodeify(done); - }); - it('should be able to get logcat logs', function (done) { - driver.log('logcat').then(function (logs) { - logs.length.should.be.above(0); - logs[0].message.should.not.include("\n"); - logs[0].level.should.equal("ALL"); - logs[0].timestamp.should.exist; - }).nodeify(done); - }); - - it('should be able to proxy errors', function (done) { - driver - .elementByCss("foobar").should.be.rejected - .nodeify(done); - }); - - it('should be able to set location', function (done) { - driver - .setGeoLocation("27.17", "78.04") - .nodeify(done); - }); - - it('should error out nicely with incompatible commands', function (done) { - driver - .execute("mobile: flick", [{}]) - .catch(function (err) { - err.cause.value.origValue.should.contain('mobile:'); - throw err; - }).should.be.rejectedWith(/status: 9/) - .nodeify(done); - }); - - }); - - describe('uninstall app', function () { - var driver; - setup(this, desired).then(function (d) { driver = d; }); - - it('should be able to uninstall the app', function (done) { - driver - .removeApp("com.example.android.apis") - .nodeify(done); - }); - }); - - describe('background app', function () { - var driver; - setup(this, desired).then(function (d) { driver = d; }); - - it("should background the app", function (done) { - var before = new Date().getTime() / 1000; - driver - .backgroundApp(3) - .then(function () { - ((new Date().getTime() / 1000) - before).should.be.above(2); - // this should not be tested - // ((new Date().getTime() / 1000) - before).should.be.below(5); - }) - .getCurrentActivity() - .should.eventually.include("ApiDemos") - .nodeify(done); - }); - }); - - describe('command timeouts', function () { - var driver; - setup(this, _.defaults({newCommandTimeout: 3}, desired)) - .then(function (d) { driver = d; }); - - it('should die with short timeout', function (done) { - driver - .sleep(5000) - .elementByName('Animation') - .should.be.rejectedWith(/(status: (13|6))|(Not JSON response)/) - .nodeify(done); - }); - }); - - describe('command timeouts', function () { - var driver; - setup(this, _.defaults({newCommandTimeout: 3}, desired)) - .then(function (d) { driver = d; }); - - it('should not die if commands come in', function (done) { - var start = Date.now(); - var find = function () { - if ((Date.now() - start) < 5000) { - return driver - .elementByName('Animation').should.eventually.exist - .sleep(500) - .then(find); - } else return new Q(); - }; - find().nodeify(done); - }); - }); - - describe('app activities with no dot', function () { - var session; - after(function () { session.tearDown(this.currentTest.state === 'passed'); }); - - it('should not launch app', function (done) { - var newDesired = _.defaults({'app-activity': 'ApiDemos'}, desired); - if (env.SAUCE) { - newDesired.name = this.currentTest.parent.title + " " + this.currentTest.title; - } - session = initSession(newDesired, {'no-retry': true}); - session.setUp(this.parent.title + " " + this.title) - .should.be.rejected - .nodeify(done); - }); - }); - - - describe('fully qualified app activities', function () { - var session; - after(function () { session.tearDown(this.currentTest.state === 'passed'); }); - - it('should still launch app', function (done) { - var newDesired = _.defaults({'app-activity': 'com.example.android.apis.ApiDemos'}, desired); - if (env.SAUCE) { - newDesired.name = this.currentTest.parent.title + " " + this.currentTest.title; - } - session = initSession(newDesired); - session.setUp(this.parent.title + " " + this.title) - .nodeify(done); - }); - }); -}); diff --git a/test/functional/selendroid/desired.js b/test/functional/selendroid/desired.js new file mode 100644 index 000000000..61b4095cd --- /dev/null +++ b/test/functional/selendroid/desired.js @@ -0,0 +1,5 @@ +"use strict"; + +module.exports = { + app: "sample-code/apps/ApiDemos/bin/ApiDemos-debug.apk" +}; diff --git a/test/functional/selendroid/timeouts-specs.js b/test/functional/selendroid/timeouts-specs.js new file mode 100644 index 000000000..8316845a0 --- /dev/null +++ b/test/functional/selendroid/timeouts-specs.js @@ -0,0 +1,43 @@ +"use strict"; + +var setup = require("../common/setup-base") + , Q = require("q") + , _ = require('underscore') + , desired = require('./desired'); + +describe('timeouts', function () { + + describe('short commands', function () { + var driver; + setup(this, _.defaults({newCommandTimeout: 3}, desired)) + .then(function (d) { driver = d; }); + + it('should die with short timeout', function (done) { + driver + .sleep(5000) + .elementByName('Animation') + .should.be.rejectedWith(/(status: (13|6))|(Not JSON response)/) + .nodeify(done); + }); + }); + + describe('command coming in', function () { + var driver; + setup(this, _.defaults({newCommandTimeout: 3}, desired)) + .then(function (d) { driver = d; }); + + it('should not die if commands come in', function (done) { + var start = Date.now(); + var find = function () { + if ((Date.now() - start) < 5000) { + return driver + .elementByName('Animation').should.eventually.exist + .sleep(500) + .then(find); + } else return new Q(); + }; + find().nodeify(done); + }); + }); + +}); diff --git a/test/functional/selendroid/uninstall-specs.js b/test/functional/selendroid/uninstall-specs.js new file mode 100644 index 000000000..1ca7cfa7d --- /dev/null +++ b/test/functional/selendroid/uninstall-specs.js @@ -0,0 +1,17 @@ +"use strict"; + +var setup = require("../common/setup-base") + , desired = require('./desired'); + +describe('selendroid - uninstall app', function () { + + var driver; + setup(this, desired).then(function (d) { driver = d; }); + + it('should be able to uninstall the app', function (done) { + driver + .removeApp("com.example.android.apis") + .nodeify(done); + }); + +}); diff --git a/test/functional/selendroid/webview-specs.js b/test/functional/selendroid/webview-specs.js index f3d2c331b..6ef8f588a 100644 --- a/test/functional/selendroid/webview-specs.js +++ b/test/functional/selendroid/webview-specs.js @@ -1,7 +1,6 @@ "use strict"; -process.env.DEVICE = process.env.DEVICE || "selendroid"; var androidWebviewTests = require('../common/android-webview-base'); // if it doesn't work run: adb uninstall io.selendroid.testapp -describe('selendroid - web_view -', androidWebviewTests); +describe('selendroid - webview', androidWebviewTests); diff --git a/test/helpers/env.js b/test/helpers/env.js index f63e719cf..7473ef54f 100644 --- a/test/helpers/env.js +++ b/test/helpers/env.js @@ -106,6 +106,7 @@ switch (env.DEVICE) { env.CAPS = { browserName: '' , platformName: 'Android' + , platformVersion: '4.1' , automationName: 'Selendroid' , deviceName: 'Android Emulator' , app: process.env.APP ? path.resolve(__dirname, "../../sample-code/apps/" + process.env.APP + "/bin/" + process.env.APP + "-debug.apk") : '' diff --git a/test/helpers/setup-chai.js b/test/helpers/setup-chai.js new file mode 100644 index 000000000..0c8281956 --- /dev/null +++ b/test/helpers/setup-chai.js @@ -0,0 +1,12 @@ +"use strict"; + +var chai = require('chai') + , chaiAsPromised = require('chai-as-promised') + , wd = require('wd'); + +chai.use(chaiAsPromised); +chai.should(); +chaiAsPromised.transferPromiseness = wd.transferPromiseness; +require("colors"); + +module.exports = chai;