CB-11296: Appium: Better element clicking and session error handling

This commit is contained in:
Alexander Sorokin 2016-05-19 18:08:07 +03:00
parent dcc81bfbe1
commit a05f169984
3 changed files with 99 additions and 14 deletions

View File

@ -52,6 +52,8 @@ describe('Camera tests Android.', function () {
var screenHeight = DEFAULT_SCREEN_HEIGHT;
// promise count to use in promise ID
var promiseCount = 0;
// going to set this to false if session is created successfully
var failedToStart = true;
function getNextPromiseId() {
promiseCount += 1;
@ -127,10 +129,18 @@ describe('Camera tests Android.', function () {
.performTouchAction(tapTile);
}
return driver
.waitForElementByXPath('//android.widget.TextView[@text="Gallery"]', 20000)
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
.fail(function () {
return driver
.performTouchAction(swipeRight)
.waitForElementByXPath('//android.widget.TextView[@text="Gallery"]', 20000)
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
.elementByXPath('//android.widget.TextView[@text="Gallery"]');
})
.click()
@ -140,9 +150,13 @@ describe('Camera tests Android.', function () {
}
// taking a picture from camera
return driver
.waitForElementByXPath('//android.widget.ImageView[contains(@resource-id,\'shutter\')]', MINUTE)
.waitForElementByXPath('//android.widget.ImageView[contains(@resource-id,\'shutter\')]', MINUTE / 2)
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'shutter\')]')
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'shutter\')]')
.click()
.waitForElementByXPath('//android.widget.ImageView[contains(@resource-id,\'done\')]', MINUTE)
.waitForElementByXPath('//android.widget.ImageView[contains(@resource-id,\'done\')]', MINUTE / 2)
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'done\')]')
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'done\')]')
.click();
})
.then(function () {
@ -168,7 +182,7 @@ describe('Camera tests Android.', function () {
}
return driver
.context(webviewContext)
.setAsyncScriptTimeout(MINUTE)
.setAsyncScriptTimeout(MINUTE / 2)
.executeAsync(cameraHelper.checkPicture, [getCurrentPromiseId(), options])
.then(function (result) {
if (shouldLoad) {
@ -253,13 +267,23 @@ describe('Camera tests Android.', function () {
};
}
function checkSession(done) {
if (failedToStart) {
fail('Failed to start a session');
done();
}
}
it('camera.ui.util configuring driver and starting a session', function (done) {
getDriver()
.fail(fail)
.then(function () {
failedToStart = false;
}, fail)
.done(done);
}, 5 * MINUTE);
it('camera.ui.util determine screen dimensions', function (done) {
checkSession(done);
return driver
.context(webviewContext)
.execute(function () {
@ -278,6 +302,7 @@ describe('Camera tests Android.', function () {
describe('Specs.', function () {
// getPicture() with saveToPhotoLibrary = true
it('camera.ui.spec.1 Saving a picture to the photo library', function (done) {
checkSession(done);
var spec = generateSpec({
quality: 50,
allowEdit: false,
@ -294,6 +319,7 @@ describe('Camera tests Android.', function () {
// getPicture() with mediaType: VIDEO, sourceType: PHOTOLIBRARY
it('camera.ui.spec.2 Selecting only videos', function (done) {
checkSession(done);
var spec = function () {
var options = { sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
mediaType: cameraConstants.MediaType.VIDEO };
@ -306,6 +332,8 @@ describe('Camera tests Android.', function () {
// try to find "Gallery" menu item
// if there's none, the gallery should be already opened
return driver
.waitForElementByXPath('//android.widget.TextView[@text="Gallery"]', 20000)
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
.then(function (element) {
return element.click();
@ -344,6 +372,7 @@ describe('Camera tests Android.', function () {
// getPicture(), then dismiss
// wait for the error callback to be called
it('camera.ui.spec.3 Dismissing the camera', function (done) {
checkSession(done);
var spec = function () {
var options = {
quality: 50,
@ -357,6 +386,8 @@ describe('Camera tests Android.', function () {
})
.context("NATIVE_APP")
.waitForElementByXPath('//android.widget.ImageView[contains(@resource-id,\'cancel\')]', MINUTE / 2)
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'cancel\')]')
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'cancel\')]')
.click()
.then(function () {
return checkPicture(false);
@ -369,6 +400,7 @@ describe('Camera tests Android.', function () {
// getPicture(), then take picture but dismiss the edit
// wait for the error callback to be called
it('camera.ui.spec.4 Dismissing the edit', function (done) {
checkSession(done);
var spec = function () {
var options = {
quality: 50,
@ -382,10 +414,16 @@ describe('Camera tests Android.', function () {
})
.context('NATIVE_APP')
.waitForElementByXPath('//android.widget.ImageView[contains(@resource-id,\'shutter\')]', MINUTE / 2)
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'shutter\')]')
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'shutter\')]')
.click()
.waitForElementByXPath('//android.widget.ImageView[contains(@resource-id,\'done\')]', MINUTE / 2)
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'done\')]')
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'done\')]')
.click()
.waitForElementByXPath('//*[contains(@resource-id,\'discard\')]', MINUTE / 2)
.elementByXPath('//*[contains(@resource-id,\'discard\')]')
.elementByXPath('//*[contains(@resource-id,\'discard\')]')
.click()
.then(function () {
return checkPicture(false);
@ -396,6 +434,7 @@ describe('Camera tests Android.', function () {
}, 10 * MINUTE);
it('camera.ui.spec.5 Verifying target image size, sourceType=CAMERA', function (done) {
checkSession(done);
var spec = generateSpec({
quality: 50,
allowEdit: false,
@ -409,6 +448,7 @@ describe('Camera tests Android.', function () {
}, 10 * MINUTE);
it('camera.ui.spec.6 Verifying target image size, sourceType=PHOTOLIBRARY', function (done) {
checkSession(done);
var spec = generateSpec({
quality: 50,
allowEdit: false,
@ -422,6 +462,7 @@ describe('Camera tests Android.', function () {
}, 10 * MINUTE);
it('camera.ui.spec.7 Verifying target image size, sourceType=CAMERA, DestinationType=NATIVE_URI', function (done) {
checkSession(done);
var spec = generateSpec({
quality: 50,
allowEdit: false,
@ -436,6 +477,7 @@ describe('Camera tests Android.', function () {
}, 10 * MINUTE);
it('camera.ui.spec.8 Verifying target image size, sourceType=PHOTOLIBRARY, DestinationType=NATIVE_URI', function (done) {
checkSession(done);
var spec = generateSpec({
quality: 50,
allowEdit: false,
@ -450,6 +492,7 @@ describe('Camera tests Android.', function () {
}, 10 * MINUTE);
it('camera.ui.spec.9 Verifying target image size, sourceType=CAMERA, DestinationType=NATIVE_URI, quality=100', function (done) {
checkSession(done);
var spec = generateSpec({
quality: 100,
allowEdit: true,
@ -464,6 +507,7 @@ describe('Camera tests Android.', function () {
}, 10 * MINUTE);
it('camera.ui.spec.10 Verifying target image size, sourceType=PHOTOLIBRARY, DestinationType=NATIVE_URI, quality=100', function (done) {
checkSession(done);
var spec = generateSpec({
quality: 100,
allowEdit: true,
@ -480,12 +524,14 @@ describe('Camera tests Android.', function () {
// combine various options for getPicture()
generateOptions().forEach(function (spec) {
it('camera.ui.spec.11.' + spec.id + ' Combining options. ' + spec.description, function (done) {
checkSession(done);
var s = generateSpec(spec.options);
tryRunSpec(s).done(done);
}, 10 * MINUTE);
});
it('camera.ui.util Delete test image from device library', function (done) {
checkSession(done);
if (!isTestPictureSaved) {
// couldn't save test picture earlier, so nothing to delete here
done();
@ -518,6 +564,7 @@ describe('Camera tests Android.', function () {
});
it('camera.ui.util Destroy the session', function (done) {
checkSession(done);
driver
.quit()
.done(done);

View File

@ -247,18 +247,22 @@ module.exports.checkPicture = function (pid, options, cb) {
function displayImage(image) {
try {
var imgEl = document.createElement('img');
var imgEl = document.getElementById('camera_test_image');
if (!imgEl) {
imgEl = document.createElement('img');
imgEl.id = 'camera_test_image';
document.body.appendChild(imgEl);
}
var timedOut = false;
var loadTimeout = setTimeout(function () {
timedOut = true;
document.body.removeChild(imgEl);
imgEl.src = '';
errorCallback('The image did not load: ' + image.substring(0, 150));
}, 10000);
var done = function (status) {
if (!timedOut) {
clearTimeout(loadTimeout);
document.body.removeChild(imgEl);
imgEl.src = '';
cb(status);
}
};

View File

@ -30,7 +30,6 @@
var wdHelper = global.WD_HELPER;
var screenshotHelper = global.SCREENSHOT_HELPER;
var wd = wdHelper.getWD();
var isDevice = global.DEVICE;
var cameraConstants = require('../../www/CameraConstants');
var cameraHelper = require('../helpers/cameraHelper');
@ -44,6 +43,8 @@ describe('Camera tests iOS.', function () {
var webviewContext = DEFAULT_WEBVIEW_CONTEXT;
// promise count to use in promise ID
var promiseCount = 0;
// going to set this to false if session is created successfully
var failedToStart = true;
function getNextPromiseId() {
promiseCount += 1;
@ -127,12 +128,14 @@ describe('Camera tests iOS.', function () {
if (cancelCamera) {
return driver
.waitForElementByXPath('//*[@label="Cancel"]', MINUTE / 2)
.elementByXPath('//*[@label="Cancel"]')
.elementByXPath('//*[@label="Cancel"]')
.click();
}
return driver
.waitForElementByXPath('//*[@label="Take Picture"]', MINUTE / 2)
.click()
.elementByXPath('//*[@label="Use Photo"]')
.waitForElementByXPath('//*[@label="Use Photo"]', MINUTE / 2)
.click();
})
.fail(fail);
@ -146,7 +149,7 @@ describe('Camera tests iOS.', function () {
}
return driver
.context(webviewContext)
.setAsyncScriptTimeout(MINUTE)
.setAsyncScriptTimeout(MINUTE / 2)
.executeAsync(cameraHelper.checkPicture, [getCurrentPromiseId(), options])
.then(function (result) {
if (shouldLoad) {
@ -187,15 +190,25 @@ describe('Camera tests iOS.', function () {
});
}
function checkSession(done) {
if (failedToStart) {
fail('Failed to start a session');
done();
}
}
it('camera.ui.util configure driver and start a session', function (done) {
getDriver()
.fail(fail)
.finally(done);
.then(function () {
failedToStart = false;
}, fail)
.done(done);
}, 5 * MINUTE);
describe('Specs.', function () {
// getPicture() with mediaType: VIDEO, sourceType: PHOTOLIBRARY
it('camera.ui.spec.1 Selecting only videos', function (done) {
checkSession(done);
var options = { sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
mediaType: cameraConstants.MediaType.VIDEO };
driver
@ -211,10 +224,12 @@ describe('Camera tests iOS.', function () {
// getPicture(), then dismiss
// wait for the error callback to be called
it('camera.ui.spec.2 Dismissing the camera', function (done) {
checkSession(done);
if (!isDevice) {
pending('Camera is not available on iOS simulator');
}
var options = { sourceType: cameraConstants.PictureSourceType.CAMERA };
var options = { sourceType: cameraConstants.PictureSourceType.CAMERA,
saveToPhotoAlbum: false };
driver
.then(function () {
return getPicture(options, true);
@ -227,6 +242,7 @@ describe('Camera tests iOS.', function () {
}, 3 * MINUTE);
it('camera.ui.spec.3 Verifying target image size, sourceType=CAMERA', function (done) {
checkSession(done);
if (!isDevice) {
pending('Camera is not available on iOS simulator');
}
@ -243,6 +259,7 @@ describe('Camera tests iOS.', function () {
}, 3 * MINUTE);
it('camera.ui.spec.4 Verifying target image size, sourceType=SAVEDPHOTOALBUM', function (done) {
checkSession(done);
var options = {
quality: 50,
allowEdit: false,
@ -256,6 +273,7 @@ describe('Camera tests iOS.', function () {
}, 3 * MINUTE);
it('camera.ui.spec.5 Verifying target image size, sourceType=PHOTOLIBRARY', function (done) {
checkSession(done);
var options = {
quality: 50,
allowEdit: false,
@ -269,6 +287,10 @@ describe('Camera tests iOS.', function () {
}, 3 * MINUTE);
it('camera.ui.spec.6 Verifying target image size, sourceType=CAMERA, destinationType=NATIVE_URI', function (done) {
// remove this line if you don't mind the tests leaving a photo saved on device
pending('Cannot prevent iOS from saving the picture to photo library');
checkSession(done);
if (!isDevice) {
pending('Camera is not available on iOS simulator');
}
@ -286,6 +308,7 @@ describe('Camera tests iOS.', function () {
}, 3 * MINUTE);
it('camera.ui.spec.7 Verifying target image size, sourceType=SAVEDPHOTOALBUM, destinationType=NATIVE_URI', function (done) {
checkSession(done);
var options = {
quality: 50,
allowEdit: false,
@ -300,6 +323,7 @@ describe('Camera tests iOS.', function () {
}, 3 * MINUTE);
it('camera.ui.spec.8 Verifying target image size, sourceType=PHOTOLIBRARY, destinationType=NATIVE_URI', function (done) {
checkSession(done);
var options = {
quality: 50,
allowEdit: false,
@ -314,6 +338,10 @@ describe('Camera tests iOS.', function () {
}, 3 * MINUTE);
it('camera.ui.spec.9 Verifying target image size, sourceType=CAMERA, destinationType=NATIVE_URI, quality=100', function (done) {
// remove this line if you don't mind the tests leaving a photo saved on device
pending('Cannot prevent iOS from saving the picture to photo library');
checkSession(done);
if (!isDevice) {
pending('Camera is not available on iOS simulator');
}
@ -330,6 +358,7 @@ describe('Camera tests iOS.', function () {
}, 3 * MINUTE);
it('camera.ui.spec.10 Verifying target image size, sourceType=SAVEDPHOTOALBUM, destinationType=NATIVE_URI, quality=100', function (done) {
checkSession(done);
var options = {
quality: 100,
allowEdit: false,
@ -344,6 +373,7 @@ describe('Camera tests iOS.', function () {
}, 3 * MINUTE);
it('camera.ui.spec.11 Verifying target image size, sourceType=PHOTOLIBRARY, destinationType=NATIVE_URI, quality=100', function (done) {
checkSession(done);
var options = {
quality: 100,
allowEdit: false,
@ -360,9 +390,12 @@ describe('Camera tests iOS.', function () {
// combine various options for getPicture()
generateOptions().forEach(function (spec) {
it('camera.ui.spec.12.' + spec.id + ' Combining options. ' + spec.description, function (done) {
checkSession(done);
if (!isDevice && spec.options.sourceType === cameraConstants.PictureSourceType.CAMERA) {
pending('Camera is not available on iOS simulator');
}
// remove this check if you don't mind the tests leaving a photo saved on device
if (spec.options.sourceType === cameraConstants.PictureSourceType.CAMERA &&
spec.options.destinationType === cameraConstants.DestinationType.NATIVE_URI) {
pending('Skipping: cannot prevent iOS from saving the picture to photo library and cannot delete it. ' +
@ -376,6 +409,7 @@ describe('Camera tests iOS.', function () {
});
it('camera.ui.util Destroy the session', function (done) {
checkSession(done);
driver
.quit()
.done(done);