mirror of
https://github.com/apache/cordova-plugin-camera.git
synced 2025-05-06 05:43:00 +08:00
CB-11073 Appium tests stability improvements
This commit is contained in:
parent
a9c18710f2
commit
82c9f4524a
@ -1,4 +1,5 @@
|
|||||||
/*jshint node: true, jasmine: true */
|
/*jshint node: true, jasmine: true */
|
||||||
|
/* global navigator, Q */
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
@ -27,18 +28,18 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var wdHelper = require('../helpers/wdHelper');
|
var wdHelper = global.WD_HELPER;
|
||||||
|
var screenshotHelper = global.SCREENSHOT_HELPER;
|
||||||
var wd = wdHelper.getWD();
|
var wd = wdHelper.getWD();
|
||||||
var cameraConstants = require('../../www/CameraConstants');
|
var cameraConstants = require('../../www/CameraConstants');
|
||||||
var cameraHelper = require('../helpers/cameraHelper');
|
var cameraHelper = require('../helpers/cameraHelper');
|
||||||
var screenshotHelper = require('../helpers/screenshotHelper');
|
|
||||||
|
|
||||||
var STARTING_MESSAGE = 'Ready for action!';
|
|
||||||
var RETRY_COUNT = 3; // how many times to retry taking a picture before failing
|
|
||||||
var MINUTE = 60 * 1000;
|
var MINUTE = 60 * 1000;
|
||||||
|
var BACK_BUTTON = 4;
|
||||||
var DEFAULT_SCREEN_WIDTH = 360;
|
var DEFAULT_SCREEN_WIDTH = 360;
|
||||||
var DEFAULT_SCREEN_HEIGHT = 567;
|
var DEFAULT_SCREEN_HEIGHT = 567;
|
||||||
var DEFAULT_WEBVIEW_CONTEXT = 'WEBVIEW';
|
var DEFAULT_WEBVIEW_CONTEXT = 'WEBVIEW';
|
||||||
|
var PROMISE_PREFIX = 'appium_camera_promise_';
|
||||||
|
|
||||||
describe('Camera tests Android.', function () {
|
describe('Camera tests Android.', function () {
|
||||||
var driver;
|
var driver;
|
||||||
@ -46,33 +47,29 @@ describe('Camera tests Android.', function () {
|
|||||||
var webviewContext = DEFAULT_WEBVIEW_CONTEXT;
|
var webviewContext = DEFAULT_WEBVIEW_CONTEXT;
|
||||||
// this indicates that the device library has the test picture:
|
// this indicates that the device library has the test picture:
|
||||||
var isTestPictureSaved = false;
|
var isTestPictureSaved = false;
|
||||||
// this indicates that there was a critical error and we should try to recover:
|
|
||||||
var errorFlag = false;
|
|
||||||
// this indicates that we couldn't restore Appium session and should fail fast:
|
|
||||||
var stopFlag = false;
|
|
||||||
// we need to know the screen width and height to properly click on an image in the gallery:
|
// we need to know the screen width and height to properly click on an image in the gallery:
|
||||||
var screenWidth = DEFAULT_SCREEN_WIDTH;
|
var screenWidth = DEFAULT_SCREEN_WIDTH;
|
||||||
var screenHeight = DEFAULT_SCREEN_HEIGHT;
|
var screenHeight = DEFAULT_SCREEN_HEIGHT;
|
||||||
|
// promise count to use in promise ID
|
||||||
|
var promiseCount = 0;
|
||||||
|
|
||||||
function win() {
|
function getNextPromiseId() {
|
||||||
expect(true).toBe(true);
|
promiseCount += 1;
|
||||||
|
return getCurrentPromiseId();
|
||||||
}
|
}
|
||||||
|
|
||||||
function fail(error) {
|
function getCurrentPromiseId() {
|
||||||
screenshotHelper.saveScreenshot(driver);
|
return PROMISE_PREFIX + promiseCount;
|
||||||
if (error && error.message) {
|
}
|
||||||
console.log('An error occured: ' + error.message);
|
|
||||||
expect(true).toFailWithMessage(error.message);
|
function saveScreenshotAndFail(error) {
|
||||||
throw error.message;
|
fail(error);
|
||||||
}
|
return screenshotHelper
|
||||||
if (error) {
|
.saveScreenshot(driver)
|
||||||
console.log('Failed expectation: ' + error);
|
.quit()
|
||||||
expect(true).toFailWithMessage(error);
|
.then(function () {
|
||||||
throw error;
|
return getDriver();
|
||||||
}
|
});
|
||||||
// no message provided :(
|
|
||||||
expect(true).toBe(false);
|
|
||||||
throw 'An error without description occured';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// generates test specs by combining all the specified options
|
// generates test specs by combining all the specified options
|
||||||
@ -95,152 +92,110 @@ describe('Camera tests Android.', function () {
|
|||||||
return cameraHelper.generateSpecs(sourceTypes, destinationTypes, encodingTypes, allowEditOptions);
|
return cameraHelper.generateSpecs(sourceTypes, destinationTypes, encodingTypes, allowEditOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPicture(options, skipUiInteractions, retry) {
|
// invokes Camera.getPicture() with the specified options
|
||||||
|
// and goes through all UI interactions unless 'skipUiInteractions' is true
|
||||||
|
function getPicture(options, skipUiInteractions) {
|
||||||
|
var promiseId = getNextPromiseId();
|
||||||
if (!options) {
|
if (!options) {
|
||||||
options = {};
|
options = {};
|
||||||
}
|
}
|
||||||
if (typeof retry === 'undefined') {
|
|
||||||
retry = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var command = "navigator.camera.getPicture(function (result) { document.getElementById('info').innerHTML = result.slice(0, 100); }, " +
|
|
||||||
"function (err) { document.getElementById('info').innerHTML = 'ERROR: ' + err; }," + JSON.stringify(options) + ");";
|
|
||||||
return driver
|
return driver
|
||||||
.context(webviewContext)
|
.context(webviewContext)
|
||||||
.execute(command)
|
.execute(cameraHelper.getPicture, [options, promiseId])
|
||||||
.sleep(7000)
|
|
||||||
.context('NATIVE_APP')
|
.context('NATIVE_APP')
|
||||||
.sleep(5000)
|
|
||||||
.then(function () {
|
.then(function () {
|
||||||
if (skipUiInteractions) {
|
if (skipUiInteractions) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// selecting a picture from gallery
|
||||||
if (options.hasOwnProperty('sourceType') &&
|
if (options.hasOwnProperty('sourceType') &&
|
||||||
(options.sourceType === cameraConstants.PictureSourceType.PHOTOLIBRARY ||
|
(options.sourceType === cameraConstants.PictureSourceType.PHOTOLIBRARY ||
|
||||||
options.sourceType === cameraConstants.PictureSourceType.SAVEDPHOTOALBUM)) {
|
options.sourceType === cameraConstants.PictureSourceType.SAVEDPHOTOALBUM)) {
|
||||||
var touchTile = new wd.TouchAction(),
|
var tapTile = new wd.TouchAction();
|
||||||
swipeRight = new wd.TouchAction();
|
var swipeRight = new wd.TouchAction();
|
||||||
touchTile.press({x: Math.round(screenWidth / 4), y: Math.round(screenHeight / 5)}).release();
|
tapTile.tap({x: Math.round(screenWidth / 4), y: Math.round(screenHeight / 5)});
|
||||||
swipeRight.press({x: 10, y: Math.round(screenHeight * 0.8)})
|
swipeRight.press({x: 10, y: 100})
|
||||||
.wait(300)
|
.wait(300)
|
||||||
.moveTo({x: Math.round(screenWidth / 2), y: Math.round(screenHeight / 2)})
|
.moveTo({x: Math.round(screenWidth / 2), y: 100})
|
||||||
.release();
|
.release();
|
||||||
return driver
|
return driver
|
||||||
.performTouchAction(swipeRight)
|
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
|
||||||
.sleep(3000)
|
.fail(function () {
|
||||||
.elementByXPath('//*[@text="Gallery"]')
|
return driver
|
||||||
|
.performTouchAction(swipeRight)
|
||||||
|
.elementByXPath('//android.widget.TextView[@text="Gallery"]');
|
||||||
|
})
|
||||||
.then(function (element) {
|
.then(function (element) {
|
||||||
return element.click().sleep(5000);
|
return element
|
||||||
|
.click()
|
||||||
|
// we need to sleep here to give a sidebar some time to close
|
||||||
|
// if we don't sleep here, sometimes we would click on a sidebar
|
||||||
|
// in the next step
|
||||||
|
.sleep(3000);
|
||||||
}, function () {
|
}, function () {
|
||||||
// if the gallery is already opened, we'd just go on:
|
// the gallery is already opened, just go on:
|
||||||
return driver;
|
return driver;
|
||||||
})
|
})
|
||||||
.performTouchAction(touchTile);
|
.performTouchAction(tapTile);
|
||||||
}
|
}
|
||||||
|
// taking a picture from camera
|
||||||
return driver
|
return driver
|
||||||
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'shutter\')]')
|
.waitForElementByXPath('//android.widget.ImageView[contains(@resource-id,\'shutter\')]', MINUTE)
|
||||||
.click()
|
.click()
|
||||||
.sleep(3000)
|
.waitForElementByXPath('//android.widget.ImageView[contains(@resource-id,\'done\')]', MINUTE)
|
||||||
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'done\')]')
|
.click();
|
||||||
.click()
|
|
||||||
.sleep(10000);
|
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
if (skipUiInteractions) {
|
if (skipUiInteractions) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.hasOwnProperty('allowEdit') && options.allowEdit === true) {
|
if (options.allowEdit) {
|
||||||
return driver
|
return driver
|
||||||
.elementByXPath('//*[contains(@resource-id,\'save\')]')
|
.waitForElementByXPath('//*[contains(@resource-id,\'save\')]', MINUTE)
|
||||||
.click();
|
.click();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(function () {
|
.fail(fail);
|
||||||
if (!skipUiInteractions) {
|
|
||||||
return driver.sleep(10000);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.fail(function (error) {
|
|
||||||
if (retry < RETRY_COUNT) {
|
|
||||||
console.log('Failed to get a picture. Let\'s try it again... ');
|
|
||||||
return getPicture(options, skipUiInteractions, ++retry);
|
|
||||||
} else {
|
|
||||||
console.log('Tried ' + RETRY_COUNT + ' times but couldn\'t get the picture. Failing...');
|
|
||||||
fail(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function enterTest() {
|
|
||||||
return driver
|
|
||||||
// trying to determine where we are
|
|
||||||
.context(webviewContext)
|
|
||||||
.fail(function (error) {
|
|
||||||
fail(error);
|
|
||||||
})
|
|
||||||
.elementById('info')
|
|
||||||
.then(function () {
|
|
||||||
return driver; //we're already on the test screen
|
|
||||||
}, function () {
|
|
||||||
return driver
|
|
||||||
.elementById('middle')
|
|
||||||
.then(function () {
|
|
||||||
return driver
|
|
||||||
// we're on autotests page, we should go to start page
|
|
||||||
.execute('window.location = "../index.html"')
|
|
||||||
.sleep(5000)
|
|
||||||
.fail(function () {
|
|
||||||
errorFlag = true;
|
|
||||||
throw 'Couldn\'t find start page.';
|
|
||||||
});
|
|
||||||
}, function () {
|
|
||||||
return; // no-op
|
|
||||||
})
|
|
||||||
// unknown starting page: no 'info' div
|
|
||||||
// adding it manually
|
|
||||||
.execute('var info = document.createElement("div"); ' +
|
|
||||||
'info.id = "info"; ' +
|
|
||||||
'document.body.appendChild(info);');
|
|
||||||
})
|
|
||||||
.sleep(5000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checks if the picture was successfully taken
|
||||||
|
// if shouldLoad is falsy, ensures that the error callback was called
|
||||||
function checkPicture(shouldLoad) {
|
function checkPicture(shouldLoad) {
|
||||||
return driver
|
return driver
|
||||||
.context(webviewContext)
|
.context(webviewContext)
|
||||||
.elementById('info')
|
.setAsyncScriptTimeout(MINUTE)
|
||||||
.getAttribute('innerHTML')
|
.executeAsync(cameraHelper.checkPicture, [getCurrentPromiseId()])
|
||||||
.then(function (html) {
|
.then(function (result) {
|
||||||
if (html.indexOf(STARTING_MESSAGE) >= 0) {
|
if (shouldLoad) {
|
||||||
expect(true).toFailWithMessage('No callback was fired');
|
expect(result.length).toBeGreaterThan(0);
|
||||||
} else if (shouldLoad) {
|
if (result.indexOf('ERROR') >= 0) {
|
||||||
expect(html.length).toBeGreaterThan(0);
|
return fail(result);
|
||||||
if (html.indexOf('ERROR') >= 0) {
|
|
||||||
fail(html);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (html.indexOf('ERROR') === -1) {
|
if (result.indexOf('ERROR') === -1) {
|
||||||
fail('Unexpected success callback with result: ' + html);
|
return fail('Unexpected success callback with result: ' + result);
|
||||||
}
|
}
|
||||||
expect(html.indexOf('ERROR')).toBe(0);
|
expect(result.indexOf('ERROR')).toBe(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function runCombinedSpec(spec) {
|
function runCombinedSpec(spec) {
|
||||||
return enterTest()
|
return driver
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return getPicture(spec.options);
|
return getPicture(spec.options);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return checkPicture(true);
|
return checkPicture(true);
|
||||||
})
|
})
|
||||||
.then(win, fail);
|
.fail(saveScreenshotAndFail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// deletes the latest image from the gallery
|
||||||
function deleteImage() {
|
function deleteImage() {
|
||||||
var holdTile = new wd.TouchAction();
|
var holdTile = new wd.TouchAction();
|
||||||
holdTile.press({x: Math.round(screenWidth / 3), y: Math.round(screenHeight / 5)}).wait(1000).release();
|
holdTile.press({x: Math.round(screenWidth / 4), y: Math.round(screenHeight / 5)}).wait(1000).release();
|
||||||
return driver
|
return driver
|
||||||
.performTouchAction(holdTile)
|
.performTouchAction(holdTile)
|
||||||
.elementByXPath('//android.widget.TextView[@text="Delete"]')
|
.elementByXPath('//android.widget.TextView[@text="Delete"]')
|
||||||
@ -251,141 +206,48 @@ describe('Camera tests Android.', function () {
|
|||||||
.click();
|
.click();
|
||||||
}, function () {
|
}, function () {
|
||||||
// couldn't find Delete menu item. Possibly there is no image.
|
// couldn't find Delete menu item. Possibly there is no image.
|
||||||
return;
|
return driver;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDriver() {
|
function getDriver() {
|
||||||
driver = wdHelper.getDriver('Android');
|
driver = wdHelper.getDriver('Android');
|
||||||
return driver;
|
return wdHelper.getWebviewContext(driver)
|
||||||
|
.then(function(context) {
|
||||||
|
webviewContext = context;
|
||||||
|
return driver.context(webviewContext);
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return wdHelper.waitForDeviceReady(driver);
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return wdHelper.injectLibraries(driver);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkStopFlag() {
|
|
||||||
if (stopFlag) {
|
|
||||||
fail('Something went wrong: the stopFlag is on. Please see the log for more details.');
|
|
||||||
}
|
|
||||||
return stopFlag;
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
jasmine.addMatchers({
|
|
||||||
toFailWithMessage : function () {
|
|
||||||
return {
|
|
||||||
compare: function (actual, msg) {
|
|
||||||
console.log('Failing with message: ' + msg);
|
|
||||||
var result = {
|
|
||||||
pass: false,
|
|
||||||
message: msg
|
|
||||||
};
|
|
||||||
// status 6 means that we've lost the session
|
|
||||||
// status 7 means that Appium couldn't find an element
|
|
||||||
// both these statuses mean that the test has failed but
|
|
||||||
// we should try to recreate the session for the following tests
|
|
||||||
if (msg.indexOf('Error response status: 6') >= 0 ||
|
|
||||||
msg.indexOf('Error response status: 7') >= 0) {
|
|
||||||
errorFlag = true;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('camera.ui.util configuring driver and starting a session', function (done) {
|
it('camera.ui.util configuring driver and starting a session', function (done) {
|
||||||
stopFlag = true; // just in case of timeout
|
getDriver()
|
||||||
getDriver().then(function () {
|
.fail(fail)
|
||||||
stopFlag = false;
|
.done(done);
|
||||||
}, function (error) {
|
|
||||||
fail(error);
|
|
||||||
})
|
|
||||||
.finally(done);
|
|
||||||
}, 5 * MINUTE);
|
}, 5 * MINUTE);
|
||||||
|
|
||||||
it('camera.ui.util determine webview context name', function (done) {
|
|
||||||
var i = 0;
|
|
||||||
return driver
|
|
||||||
.contexts(function (err, contexts) {
|
|
||||||
if (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
for (i = 0; i < contexts.length; i++) {
|
|
||||||
if (contexts[i].indexOf('mobilespec') >= 0) {
|
|
||||||
webviewContext = contexts[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
}, MINUTE);
|
|
||||||
|
|
||||||
it('camera.ui.util determine screen dimensions', function (done) {
|
it('camera.ui.util determine screen dimensions', function (done) {
|
||||||
return enterTest()
|
return driver
|
||||||
.execute('document.getElementById(\'info\').innerHTML = window.innerWidth;')
|
.context(webviewContext)
|
||||||
.sleep(5000)
|
.execute(function () {
|
||||||
.elementById('info')
|
return {
|
||||||
.getAttribute('innerHTML')
|
'width': window.innerWidth,
|
||||||
.then(function (html) {
|
'height': window.innerHeight
|
||||||
if (html !== STARTING_MESSAGE) {
|
};
|
||||||
screenWidth = Number(html);
|
}, [])
|
||||||
}
|
.then(function (size) {
|
||||||
|
screenWidth = Number(size.width);
|
||||||
|
screenHeight = Number(size.height);
|
||||||
})
|
})
|
||||||
.execute('document.getElementById(\'info\').innerHTML = \'' + STARTING_MESSAGE + '\';')
|
.done(done);
|
||||||
.execute('document.getElementById(\'info\').innerHTML = window.innerHeight;')
|
|
||||||
.sleep(5000)
|
|
||||||
.elementById('info')
|
|
||||||
.getAttribute('innerHTML')
|
|
||||||
.then(function (html) {
|
|
||||||
if (html !== STARTING_MESSAGE) {
|
|
||||||
screenHeight = Number(html);
|
|
||||||
}
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
}, MINUTE);
|
}, MINUTE);
|
||||||
|
|
||||||
describe('Specs.', function () {
|
describe('Specs.', function () {
|
||||||
beforeEach(function (done) {
|
|
||||||
// prepare the app for the test
|
|
||||||
if (!stopFlag) {
|
|
||||||
return driver
|
|
||||||
.context(webviewContext)
|
|
||||||
.then(function () {
|
|
||||||
return driver; // no-op
|
|
||||||
}, function (error) {
|
|
||||||
expect(true).toFailWithMessage(error);
|
|
||||||
})
|
|
||||||
.execute('document.getElementById("info").innerHTML = "' + STARTING_MESSAGE + '";')
|
|
||||||
.finally(done);
|
|
||||||
}
|
|
||||||
done();
|
|
||||||
}, 3 * MINUTE);
|
|
||||||
|
|
||||||
afterEach(function (done) {
|
|
||||||
if (!errorFlag || stopFlag) {
|
|
||||||
// either there's no error or we've failed irrecoverably
|
|
||||||
// nothing to worry about!
|
|
||||||
done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// recreate the session if there was a critical error in a previous spec
|
|
||||||
stopFlag = true; // we're going to set this to false if we're able to restore the session
|
|
||||||
return driver
|
|
||||||
.quit()
|
|
||||||
.then(function () {
|
|
||||||
return getDriver()
|
|
||||||
.then(function () {
|
|
||||||
errorFlag = false;
|
|
||||||
stopFlag = false;
|
|
||||||
}, function (error) {
|
|
||||||
fail(error);
|
|
||||||
stopFlag = true;
|
|
||||||
});
|
|
||||||
}, function (error) {
|
|
||||||
fail(error);
|
|
||||||
stopFlag = true;
|
|
||||||
})
|
|
||||||
.finally(done);
|
|
||||||
}, 3 * MINUTE);
|
|
||||||
|
|
||||||
// getPicture() with saveToPhotoLibrary = true
|
// getPicture() with saveToPhotoLibrary = true
|
||||||
it('camera.ui.spec.1 Saving the picture to photo library', function (done) {
|
it('camera.ui.spec.1 Saving the picture to photo library', function (done) {
|
||||||
var options = {
|
var options = {
|
||||||
@ -394,8 +256,7 @@ describe('Camera tests Android.', function () {
|
|||||||
sourceType: cameraConstants.PictureSourceType.CAMERA,
|
sourceType: cameraConstants.PictureSourceType.CAMERA,
|
||||||
saveToPhotoAlbum: true
|
saveToPhotoAlbum: true
|
||||||
};
|
};
|
||||||
enterTest()
|
driver
|
||||||
.context(webviewContext)
|
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return getPicture(options);
|
return getPicture(options);
|
||||||
})
|
})
|
||||||
@ -403,40 +264,26 @@ describe('Camera tests Android.', function () {
|
|||||||
isTestPictureSaved = true;
|
isTestPictureSaved = true;
|
||||||
return checkPicture(true);
|
return checkPicture(true);
|
||||||
})
|
})
|
||||||
.then(win, fail)
|
.fail(saveScreenshotAndFail)
|
||||||
.finally(done);
|
.done(done);
|
||||||
}, 3 * MINUTE);
|
}, 3 * MINUTE);
|
||||||
|
|
||||||
// getPicture() with mediaType: VIDEO, sourceType: PHOTOLIBRARY
|
// getPicture() with mediaType: VIDEO, sourceType: PHOTOLIBRARY
|
||||||
it('camera.ui.spec.2 Selecting only videos', function (done) {
|
it('camera.ui.spec.2 Selecting only videos', function (done) {
|
||||||
if (checkStopFlag()) {
|
|
||||||
done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var options = { sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
|
var options = { sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
|
||||||
mediaType: cameraConstants.MediaType.VIDEO };
|
mediaType: cameraConstants.MediaType.VIDEO };
|
||||||
enterTest()
|
driver
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return getPicture(options, true);
|
return getPicture(options, true);
|
||||||
})
|
})
|
||||||
.sleep(5000)
|
|
||||||
.context(webviewContext)
|
|
||||||
.elementById('info')
|
|
||||||
.getAttribute('innerHTML')
|
|
||||||
.then(function (html) {
|
|
||||||
if (html.indexOf('ERROR') >= 0) {
|
|
||||||
throw html;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.context('NATIVE_APP')
|
.context('NATIVE_APP')
|
||||||
.sleep(5000)
|
|
||||||
.then(function () {
|
.then(function () {
|
||||||
// try to find "Gallery" menu item
|
// try to find "Gallery" menu item
|
||||||
// if there's none, the gallery should be already opened
|
// if there's none, the gallery should be already opened
|
||||||
return driver
|
return driver
|
||||||
.elementByXPath('//*[@text="Gallery"]')
|
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
|
||||||
.then(function (element) {
|
.then(function (element) {
|
||||||
return element.click().sleep(2000);
|
return element.click();
|
||||||
}, function () {
|
}, function () {
|
||||||
return driver;
|
return driver;
|
||||||
});
|
});
|
||||||
@ -450,143 +297,115 @@ describe('Camera tests Android.', function () {
|
|||||||
throw 'Couldn\'t find "Choose video" element.';
|
throw 'Couldn\'t find "Choose video" element.';
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(win, fail)
|
.deviceKeyEvent(BACK_BUTTON)
|
||||||
.deviceKeyEvent(4)
|
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
|
||||||
.sleep(2000)
|
.deviceKeyEvent(BACK_BUTTON)
|
||||||
.deviceKeyEvent(4)
|
.finally(function () {
|
||||||
.sleep(2000)
|
|
||||||
.elementById('action_bar_title')
|
|
||||||
.then(function () {
|
|
||||||
// success means we're still in native app
|
|
||||||
return driver
|
return driver
|
||||||
.deviceKeyEvent(4)
|
.elementById('action_bar_title')
|
||||||
.sleep(2000);
|
.then(function () {
|
||||||
}, function () {
|
// success means we're still in native app
|
||||||
// error means we're already in webview
|
return driver
|
||||||
return driver;
|
.deviceKeyEvent(BACK_BUTTON);
|
||||||
|
}, function () {
|
||||||
|
// error means we're already in webview
|
||||||
|
return driver;
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.finally(done);
|
.fail(saveScreenshotAndFail)
|
||||||
|
.done(done);
|
||||||
}, 3 * MINUTE);
|
}, 3 * MINUTE);
|
||||||
|
|
||||||
// getPicture(), then dismiss
|
// getPicture(), then dismiss
|
||||||
// wait for the error callback to bee called
|
// wait for the error callback to be called
|
||||||
it('camera.ui.spec.3 Dismissing the camera', function (done) {
|
it('camera.ui.spec.3 Dismissing the camera', function (done) {
|
||||||
if (checkStopFlag()) {
|
|
||||||
done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var options = { quality: 50,
|
var options = { quality: 50,
|
||||||
allowEdit: true,
|
allowEdit: true,
|
||||||
sourceType: cameraConstants.PictureSourceType.CAMERA,
|
sourceType: cameraConstants.PictureSourceType.CAMERA,
|
||||||
destinationType: cameraConstants.DestinationType.FILE_URI };
|
destinationType: cameraConstants.DestinationType.FILE_URI };
|
||||||
enterTest()
|
driver
|
||||||
.context(webviewContext)
|
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return getPicture(options, true);
|
return getPicture(options, true);
|
||||||
})
|
})
|
||||||
.sleep(5000)
|
|
||||||
.context("NATIVE_APP")
|
.context("NATIVE_APP")
|
||||||
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'cancel\')]')
|
.waitForElementByXPath('//android.widget.ImageView[contains(@resource-id,\'cancel\')]', MINUTE / 2)
|
||||||
.click()
|
.click()
|
||||||
.context(webviewContext)
|
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return driver
|
return checkPicture(false);
|
||||||
.elementByXPath('//*[contains(text(),"Camera cancelled")]')
|
|
||||||
.then(function () {
|
|
||||||
return checkPicture(false);
|
|
||||||
}, function () {
|
|
||||||
throw 'Couldn\'t find "Camera cancelled" message.';
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.then(win, fail)
|
.fail(saveScreenshotAndFail)
|
||||||
.finally(done);
|
.done(done);
|
||||||
}, 3 * MINUTE);
|
}, 3 * MINUTE);
|
||||||
|
|
||||||
// getPicture(), then take picture but dismiss the edit
|
// getPicture(), then take picture but dismiss the edit
|
||||||
// wait for the error cllback to be called
|
// wait for the error callback to be called
|
||||||
it('camera.ui.spec.4 Dismissing the edit', function (done) {
|
it('camera.ui.spec.4 Dismissing the edit', function (done) {
|
||||||
if (checkStopFlag()) {
|
|
||||||
done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var options = { quality: 50,
|
var options = { quality: 50,
|
||||||
allowEdit: true,
|
allowEdit: true,
|
||||||
sourceType: cameraConstants.PictureSourceType.CAMERA,
|
sourceType: cameraConstants.PictureSourceType.CAMERA,
|
||||||
destinationType: cameraConstants.DestinationType.FILE_URI };
|
destinationType: cameraConstants.DestinationType.FILE_URI };
|
||||||
enterTest()
|
driver
|
||||||
.context(webviewContext)
|
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return getPicture(options, true);
|
return getPicture(options, true);
|
||||||
})
|
})
|
||||||
.sleep(5000)
|
|
||||||
.context('NATIVE_APP')
|
.context('NATIVE_APP')
|
||||||
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'shutter\')]')
|
.waitForElementByXPath('//android.widget.ImageView[contains(@resource-id,\'shutter\')]', MINUTE / 2)
|
||||||
.click()
|
.click()
|
||||||
.elementByXPath('//android.widget.ImageView[contains(@resource-id,\'done\')]')
|
.waitForElementByXPath('//android.widget.ImageView[contains(@resource-id,\'done\')]', MINUTE / 2)
|
||||||
.click()
|
.click()
|
||||||
.elementByXPath('//*[contains(@resource-id,\'discard\')]')
|
.waitForElementByXPath('//*[contains(@resource-id,\'discard\')]', MINUTE / 2)
|
||||||
.click()
|
.click()
|
||||||
.sleep(5000)
|
|
||||||
.context(webviewContext)
|
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return driver
|
return checkPicture(false);
|
||||||
.elementByXPath('//*[contains(text(),"Camera cancelled")]')
|
|
||||||
.then(function () {
|
|
||||||
return checkPicture(false);
|
|
||||||
}, function () {
|
|
||||||
throw 'Couldn\'t find "Camera cancelled" message.';
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.then(win, fail)
|
.fail(saveScreenshotAndFail)
|
||||||
.finally(done);
|
.done(done);
|
||||||
}, 3 * MINUTE);
|
}, 3 * MINUTE);
|
||||||
|
|
||||||
// combine various options for getPicture()
|
// combine various options for getPicture()
|
||||||
generateSpecs().forEach(function (spec) {
|
generateSpecs().forEach(function (spec) {
|
||||||
it('camera.ui.spec.5.' + spec.id + ' Combining options', function (done) {
|
it('camera.ui.spec.5.' + spec.id + ' Combining options', function (done) {
|
||||||
if (checkStopFlag()) {
|
runCombinedSpec(spec)
|
||||||
done();
|
.done(done);
|
||||||
return;
|
|
||||||
}
|
|
||||||
runCombinedSpec(spec).then(done);
|
|
||||||
}, 3 * MINUTE);
|
}, 3 * MINUTE);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('camera.ui.util Delete test image from device library', function (done) {
|
it('camera.ui.util Delete test image from device library', function (done) {
|
||||||
if (checkStopFlag()) {
|
if (!isTestPictureSaved) {
|
||||||
|
// couldn't save test picture earlier, so nothing to delete here
|
||||||
done();
|
done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isTestPictureSaved) {
|
// delete exactly one latest picture
|
||||||
// delete exactly one last picture
|
// this should be the picture we've taken in the first spec
|
||||||
// this should be the picture we've taken in the first spec
|
return driver
|
||||||
return driver
|
.context('NATIVE_APP')
|
||||||
.context('NATIVE_APP')
|
.deviceKeyEvent(BACK_BUTTON)
|
||||||
.deviceKeyEvent(3)
|
.sleep(1000)
|
||||||
.sleep(5000)
|
.deviceKeyEvent(BACK_BUTTON)
|
||||||
.elementByName('Apps')
|
.sleep(1000)
|
||||||
.click()
|
.deviceKeyEvent(BACK_BUTTON)
|
||||||
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
|
.elementById('Apps')
|
||||||
.click()
|
.click()
|
||||||
.elementByXPath('//android.widget.TextView[contains(@text,"Pictures")]')
|
.elementByXPath('//android.widget.TextView[@text="Gallery"]')
|
||||||
.then(function (element) {
|
.click()
|
||||||
return element
|
.elementByXPath('//android.widget.TextView[contains(@text,"Pictures")]')
|
||||||
.click()
|
.click()
|
||||||
.sleep(3000)
|
.then(deleteImage)
|
||||||
.then(deleteImage)
|
.deviceKeyEvent(BACK_BUTTON)
|
||||||
.then(function () { done(); }, function () { done(); });
|
.sleep(1000)
|
||||||
}, function () {
|
.deviceKeyEvent(BACK_BUTTON)
|
||||||
done();
|
.sleep(1000)
|
||||||
});
|
.deviceKeyEvent(BACK_BUTTON)
|
||||||
}
|
.fail(fail)
|
||||||
// couldn't save test picture earlier, so nothing to delete here
|
.finally(done);
|
||||||
done();
|
|
||||||
}, 3 * MINUTE);
|
}, 3 * MINUTE);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('camera.ui.util Destroy the session', function (done) {
|
it('camera.ui.util Destroy the session', function (done) {
|
||||||
return driver.quit(done);
|
driver
|
||||||
|
.quit()
|
||||||
|
.done(done);
|
||||||
}, MINUTE);
|
}, MINUTE);
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/*jshint node: true */
|
/*jshint node: true */
|
||||||
|
/* global Q */
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
@ -84,3 +85,21 @@ module.exports.generateSpecs = function (sourceTypes, destinationTypes, encoding
|
|||||||
}
|
}
|
||||||
return specs;
|
return specs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports.getPicture = function (opts, pid) {
|
||||||
|
navigator._appiumPromises[pid] = Q.defer();
|
||||||
|
navigator.camera.getPicture(function (result) {
|
||||||
|
navigator._appiumPromises[pid].resolve(result);
|
||||||
|
}, function (err) {
|
||||||
|
navigator._appiumPromises[pid].reject(err);
|
||||||
|
}, opts);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.checkPicture = function (pid, cb) {
|
||||||
|
navigator._appiumPromises[pid].promise
|
||||||
|
.then(function (result) {
|
||||||
|
cb(result);
|
||||||
|
}, function (err) {
|
||||||
|
cb('ERROR: ' + err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
/* jshint node: true */
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var path = require('path');
|
|
||||||
var screenshotPath = global.SCREENSHOT_PATH || path.join(__dirname, '../../../appium_screenshots/');
|
|
||||||
|
|
||||||
function generateScreenshotName() {
|
|
||||||
var date = new Date();
|
|
||||||
|
|
||||||
var month = date.getMonth() + 1;
|
|
||||||
var day = date.getDate();
|
|
||||||
var hour = date.getHours();
|
|
||||||
var min = date.getMinutes();
|
|
||||||
var sec = date.getSeconds();
|
|
||||||
|
|
||||||
month = (month < 10 ? "0" : "") + month;
|
|
||||||
day = (day < 10 ? "0" : "") + day;
|
|
||||||
hour = (hour < 10 ? "0" : "") + hour;
|
|
||||||
min = (min < 10 ? "0" : "") + min;
|
|
||||||
sec = (sec < 10 ? "0" : "") + sec;
|
|
||||||
|
|
||||||
return date.getFullYear() + '-' + month + '-' + day + '_' + hour + '.' + min + '.' + sec + '.png';
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports.saveScreenshot = function (driver) {
|
|
||||||
var oldContext;
|
|
||||||
return driver
|
|
||||||
.currentContext()
|
|
||||||
.then(function (cc) {
|
|
||||||
oldContext = cc;
|
|
||||||
})
|
|
||||||
.context('NATIVE_APP')
|
|
||||||
.saveScreenshot(path.join(screenshotPath, generateScreenshotName()))
|
|
||||||
.then(function () {
|
|
||||||
return driver.context(oldContext);
|
|
||||||
});
|
|
||||||
};
|
|
@ -1,68 +0,0 @@
|
|||||||
/* jshint node: true */
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var wd = global.WD || require('wd');
|
|
||||||
var driver;
|
|
||||||
|
|
||||||
module.exports.getDriver = function (platform, callback) {
|
|
||||||
var serverConfig = {
|
|
||||||
host: 'localhost',
|
|
||||||
port: 4723
|
|
||||||
},
|
|
||||||
driverConfig = {
|
|
||||||
browserName: '',
|
|
||||||
'appium-version': '1.5',
|
|
||||||
platformName: platform,
|
|
||||||
platformVersion: global.PLATFORM_VERSION || '',
|
|
||||||
deviceName: global.DEVICE_NAME || '',
|
|
||||||
app: global.PACKAGE_PATH,
|
|
||||||
autoAcceptAlerts: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (process.env.CHROMEDRIVER_EXECUTABLE) {
|
|
||||||
driverConfig.chromedriverExecutable = process.env.CHROMEDRIVER_EXECUTABLE;
|
|
||||||
}
|
|
||||||
driver = wd.promiseChainRemote(serverConfig);
|
|
||||||
module.exports.configureLogging(driver);
|
|
||||||
|
|
||||||
return driver.init(driverConfig).setImplicitWaitTimeout(10000)
|
|
||||||
.sleep(20000) // wait for the app to load
|
|
||||||
.then(callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.getWD = function () {
|
|
||||||
return wd;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.configureLogging = function (driver) {
|
|
||||||
driver.on('status', function (info) {
|
|
||||||
console.log(info);
|
|
||||||
});
|
|
||||||
driver.on('command', function (meth, path, data) {
|
|
||||||
console.log(' > ' + meth, path, data || '');
|
|
||||||
});
|
|
||||||
driver.on('http', function (meth, path, data) {
|
|
||||||
console.log(' > ' + meth, path, data || '');
|
|
||||||
});
|
|
||||||
};
|
|
@ -1,4 +1,5 @@
|
|||||||
/*jshint node: true, jasmine: true */
|
/*jshint node: true, jasmine: true */
|
||||||
|
/* global navigator, Q */
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
@ -27,41 +28,40 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var wdHelper = require('../helpers/wdHelper');
|
var wdHelper = global.WD_HELPER;
|
||||||
|
var screenshotHelper = global.SCREENSHOT_HELPER;
|
||||||
var wd = wdHelper.getWD();
|
var wd = wdHelper.getWD();
|
||||||
var isDevice = global.DEVICE;
|
var isDevice = global.DEVICE;
|
||||||
var cameraConstants = require('../../www/CameraConstants');
|
var cameraConstants = require('../../www/CameraConstants');
|
||||||
var cameraHelper = require('../helpers/cameraHelper');
|
var cameraHelper = require('../helpers/cameraHelper');
|
||||||
var screenshotHelper = require('../helpers/screenshotHelper');
|
|
||||||
|
|
||||||
var MINUTE = 60 * 1000;
|
var MINUTE = 60 * 1000;
|
||||||
var DEFAULT_WEBVIEW_CONTEXT = 'WEBVIEW_1';
|
var DEFAULT_WEBVIEW_CONTEXT = 'WEBVIEW_1';
|
||||||
|
var PROMISE_PREFIX = 'appium_camera_promise_';
|
||||||
|
|
||||||
describe('Camera tests iOS.', function () {
|
describe('Camera tests iOS.', function () {
|
||||||
|
|
||||||
var driver;
|
var driver;
|
||||||
var webviewContext = DEFAULT_WEBVIEW_CONTEXT;
|
var webviewContext = DEFAULT_WEBVIEW_CONTEXT;
|
||||||
var startingMessage = 'Ready for action!';
|
// promise count to use in promise ID
|
||||||
|
var promiseCount = 0;
|
||||||
|
|
||||||
function win() {
|
function getNextPromiseId() {
|
||||||
expect(true).toBe(true);
|
promiseCount += 1;
|
||||||
|
return getCurrentPromiseId();
|
||||||
}
|
}
|
||||||
|
|
||||||
function fail(error) {
|
function getCurrentPromiseId() {
|
||||||
screenshotHelper.saveScreenshot(driver);
|
return PROMISE_PREFIX + promiseCount;
|
||||||
if (error && error.message) {
|
}
|
||||||
console.log('An error occured: ' + error.message);
|
|
||||||
expect(true).toFailWithMessage(error.message);
|
function saveScreenshotAndFail(error) {
|
||||||
throw error.message;
|
fail(error);
|
||||||
}
|
return screenshotHelper
|
||||||
if (error) {
|
.saveScreenshot(driver)
|
||||||
console.log('Failed expectation: ' + error);
|
.quit()
|
||||||
expect(true).toFailWithMessage(error);
|
.then(function () {
|
||||||
throw error;
|
return getDriver();
|
||||||
}
|
});
|
||||||
// no message provided :(
|
|
||||||
expect(true).toBe(false);
|
|
||||||
throw 'An error without description occured';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// generates test specs by combining all the specified options
|
// generates test specs by combining all the specified options
|
||||||
@ -84,17 +84,34 @@ describe('Camera tests iOS.', function () {
|
|||||||
return cameraHelper.generateSpecs(sourceTypes, destinationTypes, encodingTypes, allowEditOptions);
|
return cameraHelper.generateSpecs(sourceTypes, destinationTypes, encodingTypes, allowEditOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function usePicture() {
|
||||||
|
return driver
|
||||||
|
.elementByXPath('//*[@label="Use"]')
|
||||||
|
.click()
|
||||||
|
.fail(function () {
|
||||||
|
return driver
|
||||||
|
// For some reason "Choose" element is not clickable by standard Appium methods
|
||||||
|
// So getting its position and tapping there using TouchAction
|
||||||
|
.elementByXPath('//UIAButton[@label="Choose"]')
|
||||||
|
.getLocation()
|
||||||
|
.then(function (loc) {
|
||||||
|
var tapChoose = new wd.TouchAction();
|
||||||
|
tapChoose.tap(loc);
|
||||||
|
return driver
|
||||||
|
.performTouchAction(tapChoose);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function getPicture(options, cancelCamera, skipUiInteractions) {
|
function getPicture(options, cancelCamera, skipUiInteractions) {
|
||||||
|
var promiseId = getNextPromiseId();
|
||||||
if (!options) {
|
if (!options) {
|
||||||
options = {};
|
options = {};
|
||||||
}
|
}
|
||||||
var command = "navigator.camera.getPicture(function (result) { document.getElementById('info').innerHTML = 'Success: ' + result.slice(0, 100); }, " +
|
|
||||||
"function (err) { document.getElementById('info').innerHTML = 'ERROR: ' + err; }," + JSON.stringify(options) + ");";
|
|
||||||
return driver
|
return driver
|
||||||
.sleep(2000)
|
|
||||||
.context(webviewContext)
|
.context(webviewContext)
|
||||||
.execute(command)
|
.execute(cameraHelper.getPicture, [options, promiseId])
|
||||||
.sleep(5000)
|
|
||||||
.context('NATIVE_APP')
|
.context('NATIVE_APP')
|
||||||
.then(function () {
|
.then(function () {
|
||||||
if (skipUiInteractions) {
|
if (skipUiInteractions) {
|
||||||
@ -102,187 +119,146 @@ describe('Camera tests iOS.', function () {
|
|||||||
}
|
}
|
||||||
if (options.hasOwnProperty('sourceType') && options.sourceType === cameraConstants.PictureSourceType.PHOTOLIBRARY) {
|
if (options.hasOwnProperty('sourceType') && options.sourceType === cameraConstants.PictureSourceType.PHOTOLIBRARY) {
|
||||||
return driver
|
return driver
|
||||||
.elementByName('Camera Roll')
|
.waitForElementByXPath('//*[@label="Camera Roll"]', MINUTE / 2)
|
||||||
.click()
|
.click()
|
||||||
.elementByXPath('//UIACollectionCell')
|
.elementByXPath('//UIACollectionCell')
|
||||||
.click()
|
.click()
|
||||||
.then(function () {
|
.then(function () {
|
||||||
if (options.hasOwnProperty('allowEdit') && options.allowEdit === true) {
|
if (!options.allowEdit) {
|
||||||
return driver
|
return driver;
|
||||||
.elementByName('Use')
|
|
||||||
.click();
|
|
||||||
}
|
}
|
||||||
return driver;
|
return usePicture();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (options.hasOwnProperty('sourceType') && options.sourceType === cameraConstants.PictureSourceType.SAVEDPHOTOALBUM) {
|
if (options.hasOwnProperty('sourceType') && options.sourceType === cameraConstants.PictureSourceType.SAVEDPHOTOALBUM) {
|
||||||
return driver
|
return driver
|
||||||
.elementByXPath('//UIACollectionCell')
|
.waitForElementByXPath('//UIACollectionCell', MINUTE / 2)
|
||||||
.click()
|
.click()
|
||||||
.then(function () {
|
.then(function () {
|
||||||
if (options.hasOwnProperty('allowEdit') && options.allowEdit === true) {
|
if (!options.allowEdit) {
|
||||||
return driver
|
return driver;
|
||||||
.elementByName('Use')
|
|
||||||
.click();
|
|
||||||
}
|
}
|
||||||
return driver;
|
return usePicture();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (cancelCamera) {
|
if (cancelCamera) {
|
||||||
return driver
|
return driver
|
||||||
.elementByName('Cancel')
|
.waitForElementByXPath('//*[@label="Cancel"]', MINUTE / 2)
|
||||||
.click();
|
.click();
|
||||||
}
|
}
|
||||||
return driver
|
return driver
|
||||||
.elementByName('PhotoCapture')
|
.waitForElementByXPath('//*[@label="Take Picture"]', MINUTE / 2)
|
||||||
.click()
|
.click()
|
||||||
.elementByName('Use Photo')
|
.elementByXPath('//*[@label="Use Photo"]')
|
||||||
.click();
|
.click();
|
||||||
})
|
})
|
||||||
.sleep(3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function enterTest() {
|
|
||||||
return driver
|
|
||||||
.contexts(function (err, contexts) {
|
|
||||||
if (err) {
|
|
||||||
fail(err);
|
|
||||||
} else {
|
|
||||||
// if WEBVIEW context is available, use it
|
|
||||||
// if not, use NATIVE_APP
|
|
||||||
webviewContext = contexts[contexts.length - 1];
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
return driver
|
|
||||||
.context(webviewContext);
|
|
||||||
})
|
|
||||||
.fail(fail)
|
|
||||||
.elementById('info')
|
|
||||||
.fail(function () {
|
|
||||||
// unknown starting page: no 'info' div
|
|
||||||
// adding it manually
|
|
||||||
return driver
|
|
||||||
.execute('var info = document.createElement("div"); ' +
|
|
||||||
'info.id = "info"' +
|
|
||||||
'document.body.appendChild(info);')
|
|
||||||
.fail(fail);
|
|
||||||
})
|
|
||||||
.execute('document.getElementById("info").innerHTML = "' + startingMessage + '";')
|
|
||||||
.fail(fail);
|
.fail(fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checks if the picture was successfully taken
|
||||||
|
// if shouldLoad is falsy, ensures that the error callback was called
|
||||||
function checkPicture(shouldLoad) {
|
function checkPicture(shouldLoad) {
|
||||||
return driver
|
return driver
|
||||||
.contexts(function (err, contexts) {
|
|
||||||
// if WEBVIEW context is available, use it
|
|
||||||
// if not, use NATIVE_APP
|
|
||||||
webviewContext = contexts[contexts.length - 1];
|
|
||||||
})
|
|
||||||
.context(webviewContext)
|
.context(webviewContext)
|
||||||
.elementById('info')
|
.setAsyncScriptTimeout(MINUTE)
|
||||||
.getAttribute('innerHTML')
|
.executeAsync(cameraHelper.checkPicture, [getCurrentPromiseId()])
|
||||||
.then(function (html) {
|
.then(function (result) {
|
||||||
if (html.indexOf(startingMessage) >= 0) {
|
if (shouldLoad) {
|
||||||
expect(true).toFailWithMessage('No callback was fired');
|
expect(result.length).toBeGreaterThan(0);
|
||||||
} else if (shouldLoad) {
|
if (result.indexOf('ERROR') >= 0) {
|
||||||
expect(html.length).toBeGreaterThan(0);
|
return fail(result);
|
||||||
if (html.indexOf('ERROR') >= 0) {
|
|
||||||
expect(true).toFailWithMessage(html);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (html.indexOf('ERROR') === -1) {
|
if (result.indexOf('ERROR') === -1) {
|
||||||
expect(true).toFailWithMessage('Unexpected success callback with result: ' + html);
|
return fail('Unexpected success callback with result: ' + result);
|
||||||
}
|
}
|
||||||
expect(html.indexOf('ERROR')).toBe(0);
|
expect(result.indexOf('ERROR')).toBe(0);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
.context('NATIVE_APP');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function runCombinedSpec(spec) {
|
function runCombinedSpec(spec) {
|
||||||
return enterTest()
|
return driver
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return getPicture(spec.options);
|
return getPicture(spec.options);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return checkPicture(true);
|
return checkPicture(true);
|
||||||
})
|
})
|
||||||
.then(win, fail);
|
.fail(saveScreenshotAndFail);
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(function () {
|
function getDriver() {
|
||||||
jasmine.addMatchers({
|
driver = wdHelper.getDriver('iOS');
|
||||||
toFailWithMessage : function () {
|
return wdHelper.getWebviewContext(driver)
|
||||||
return {
|
.then(function(context) {
|
||||||
compare: function (actual, msg) {
|
webviewContext = context;
|
||||||
console.log('Failing with message: ' + msg);
|
return driver.context(webviewContext);
|
||||||
var result = {
|
})
|
||||||
pass: false,
|
.then(function () {
|
||||||
message: msg
|
return wdHelper.waitForDeviceReady(driver);
|
||||||
};
|
})
|
||||||
return result;
|
.then(function () {
|
||||||
}
|
return wdHelper.injectLibraries(driver);
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('camera.ui.util Configuring driver and starting a session', function (done) {
|
it('camera.ui.util configure driver and start a session', function (done) {
|
||||||
driver = wdHelper.getDriver('iOS', done);
|
getDriver()
|
||||||
}, 3 * MINUTE);
|
.fail(fail)
|
||||||
|
.finally(done);
|
||||||
|
}, 5 * MINUTE);
|
||||||
|
|
||||||
describe('Specs.', function () {
|
describe('Specs.', function () {
|
||||||
// getPicture() with mediaType: VIDEO, sourceType: PHOTOLIBRARY
|
// getPicture() with mediaType: VIDEO, sourceType: PHOTOLIBRARY
|
||||||
it('camera.ui.spec.1 Selecting only videos', function (done) {
|
it('camera.ui.spec.1 Selecting only videos', function (done) {
|
||||||
var options = { sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
|
var options = { sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
|
||||||
mediaType: cameraConstants.MediaType.VIDEO };
|
mediaType: cameraConstants.MediaType.VIDEO };
|
||||||
enterTest()
|
driver
|
||||||
.then(function () { return getPicture(options, false, true); }) // skip ui unteractions
|
// skip ui unteractions
|
||||||
.sleep(5000)
|
.then(function () { return getPicture(options, false, true); })
|
||||||
.elementByName('Videos')
|
.waitForElementByXPath('//*[contains(@label,"Videos")]', MINUTE / 2)
|
||||||
.then(win, fail)
|
.elementByXPath('//*[@label="Cancel"]')
|
||||||
.elementByName('Cancel')
|
|
||||||
.click()
|
.click()
|
||||||
.finally(done);
|
.fail(saveScreenshotAndFail)
|
||||||
|
.done(done);
|
||||||
}, 3 * MINUTE);
|
}, 3 * MINUTE);
|
||||||
|
|
||||||
// getPicture(), then dismiss
|
// getPicture(), then dismiss
|
||||||
// wait for the error callback to bee called
|
// wait for the error callback to be called
|
||||||
it('camera.ui.spec.2 Dismissing the camera', function (done) {
|
it('camera.ui.spec.2 Dismissing the camera', function (done) {
|
||||||
// camera is not available on iOS simulator
|
// camera is not available on the iOS simulator
|
||||||
if (!isDevice) {
|
if (!isDevice) {
|
||||||
pending();
|
pending();
|
||||||
}
|
}
|
||||||
var options = { sourceType: cameraConstants.PictureSourceType.CAMERA };
|
var options = { sourceType: cameraConstants.PictureSourceType.CAMERA };
|
||||||
enterTest()
|
driver
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return getPicture(options, true);
|
return getPicture(options, true);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return checkPicture(false);
|
return checkPicture(false);
|
||||||
})
|
})
|
||||||
.elementByXPath('//UIAStaticText[contains(@label,"no image selected")]')
|
.fail(saveScreenshotAndFail)
|
||||||
.then(function () {
|
.done(done);
|
||||||
return checkPicture(false);
|
|
||||||
}, fail)
|
|
||||||
.finally(done);
|
|
||||||
}, 3 * MINUTE);
|
}, 3 * MINUTE);
|
||||||
|
|
||||||
// combine various options for getPicture()
|
// combine various options for getPicture()
|
||||||
generateSpecs().forEach(function (spec) {
|
generateSpecs().forEach(function (spec) {
|
||||||
it('camera.ui.spec.3.' + spec.id + ' Combining options', function (done) {
|
it('camera.ui.spec.3.' + spec.id + ' Combining options', function (done) {
|
||||||
// camera is not available on iOS simulator
|
// camera is not available on iOS simulator
|
||||||
if (!isDevice) {
|
if (!isDevice && spec.options.sourceType === cameraConstants.PictureSourceType.CAMERA) {
|
||||||
pending();
|
pending();
|
||||||
}
|
}
|
||||||
runCombinedSpec(spec).then(done);
|
runCombinedSpec(spec).done(done);
|
||||||
}, 3 * MINUTE);
|
}, 3 * MINUTE);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('camera.ui.util.4 Destroy the session', function (done) {
|
it('camera.ui.util.4 Destroy the session', function (done) {
|
||||||
driver.quit(done);
|
driver
|
||||||
|
.quit()
|
||||||
|
.done(done);
|
||||||
}, MINUTE);
|
}, MINUTE);
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user