You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by al...@apache.org on 2017/02/22 09:31:20 UTC

cordova-plugin-camera git commit: CB-12469 (ios) Appium tests can now run on iOS 10

Repository: cordova-plugin-camera
Updated Branches:
  refs/heads/master dfbca19a7 -> 7f616d16f


CB-12469 (ios) Appium tests can now run on iOS 10


Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/commit/7f616d16
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/tree/7f616d16
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/diff/7f616d16

Branch: refs/heads/master
Commit: 7f616d16f175fd33514e8dda14ea9ebe79533340
Parents: dfbca19
Author: Alexander Sorokin <al...@akvelon.com>
Authored: Mon Feb 13 17:46:00 2017 +0300
Committer: Alexander Sorokin <al...@akvelon.com>
Committed: Mon Feb 20 13:16:53 2017 +0300

----------------------------------------------------------------------
 appium-tests/ios/ios.spec.js | 218 +++++++++++++++++++++++++-------------
 1 file changed, 145 insertions(+), 73 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/7f616d16/appium-tests/ios/ios.spec.js
----------------------------------------------------------------------
diff --git a/appium-tests/ios/ios.spec.js b/appium-tests/ios/ios.spec.js
index cab45f6..bf3b33e 100644
--- a/appium-tests/ios/ios.spec.js
+++ b/appium-tests/ios/ios.spec.js
@@ -21,10 +21,10 @@
  *
 */
 
-// these tests are meant to be executed by Cordova Medic Appium runner
-// you can find it here: https://github.com/apache/cordova-medic/
+// these tests are meant to be executed by Cordova Paramedic test runner
+// you can find it here: https://github.com/apache/cordova-paramedic/
 // it is not necessary to do a full CI setup to run these tests
-// just run "node cordova-medic/medic/medic.js appium --platform android --plugins cordova-plugin-camera"
+// just run "node cordova-paramedic/main.js --platform ios --plugin cordova-plugin-camera"
 
 'use strict';
 
@@ -37,6 +37,7 @@ var cameraHelper = require('../helpers/cameraHelper');
 var MINUTE = 60 * 1000;
 var DEFAULT_WEBVIEW_CONTEXT = 'WEBVIEW_1';
 var PROMISE_PREFIX = 'appium_camera_promise_';
+var CONTEXT_NATIVE_APP = 'NATIVE_APP';
 
 describe('Camera tests iOS.', function () {
     var driver;
@@ -45,6 +46,10 @@ describe('Camera tests iOS.', function () {
     var promiseCount = 0;
     // going to set this to false if session is created successfully
     var failedToStart = true;
+    // points out which UI automation to use
+    var isXCUI = false;
+    // spec counter to restart the session
+    var specsRun = 0;
 
     function getNextPromiseId() {
         promiseCount += 1;
@@ -55,10 +60,9 @@ describe('Camera tests iOS.', function () {
         return PROMISE_PREFIX + promiseCount;
     }
 
-    function saveScreenshotAndFail(error) {
+    function gracefullyFail(error) {
         fail(error);
-        return screenshotHelper
-            .saveScreenshot(driver)
+        return driver
             .quit()
             .then(function () {
                 return getDriver();
@@ -82,11 +86,43 @@ describe('Camera tests iOS.', function () {
             .elementByXPath('//*[@label="Use"]')
             .click()
             .fail(function () {
-                // For some reason "Choose" element is not clickable by standard Appium methods
+                if (isXCUI) {
+                    return driver
+                        .waitForElementByAccessibilityId('Choose', MINUTE / 3)
+                        .click();
+                }
+                // For some reason "Choose" element is not clickable by standard Appium methods on iOS <= 9
                 return wdHelper.tapElementByXPath('//UIAButton[@label="Choose"]', driver);
             });
     }
 
+    function clickPhoto() {
+        if (isXCUI) {
+            // iOS >=10
+            return driver
+                .context(CONTEXT_NATIVE_APP)
+                .elementsByXPath('//XCUIElementTypeCell')
+                .then(function(photos) {
+                    if (photos.length == 0) {
+                        return driver
+                            .sleep(0) // driver.source is not a function o.O
+                            .source()
+                            .then(function (src) {
+                                console.log(src);
+                                gracefullyFail('Couldn\'t find an image to click');
+                            });
+                    }
+                    // intentionally clicking the second photo here
+                    // the first one is not clickable for some reason
+                    return photos[1].click();
+                });
+        }
+        // iOS <10
+        return driver
+            .elementByXPath('//UIACollectionCell')
+            .click();
+    }
+
     function getPicture(options, cancelCamera, skipUiInteractions) {
         var promiseId = getNextPromiseId();
         if (!options) {
@@ -96,18 +132,19 @@ describe('Camera tests iOS.', function () {
         return driver
             .context(webviewContext)
             .execute(cameraHelper.getPicture, [options, promiseId])
-            .context('NATIVE_APP')
+            .context(CONTEXT_NATIVE_APP)
             .then(function () {
                 if (skipUiInteractions) {
                     return;
                 }
                 if (options.hasOwnProperty('sourceType') && options.sourceType === cameraConstants.PictureSourceType.PHOTOLIBRARY) {
                     return driver
-                        .waitForElementByXPath('//*[@label="Camera Roll"]', MINUTE / 2)
-                        .click()
-                        .elementByXPath('//UIACollectionCell')
+                        .waitForElementByAccessibilityId('Camera Roll', MINUTE / 2)
                         .click()
                         .then(function () {
+                            return clickPhoto();
+                        })
+                        .then(function () {
                             if (!options.allowEdit) {
                                 return driver;
                             }
@@ -115,9 +152,7 @@ describe('Camera tests iOS.', function () {
                         });
                 }
                 if (options.hasOwnProperty('sourceType') && options.sourceType === cameraConstants.PictureSourceType.SAVEDPHOTOALBUM) {
-                    return driver
-                        .waitForElementByXPath('//UIACollectionCell', MINUTE / 2)
-                        .click()
+                    return clickPhoto()
                         .then(function () {
                             if (!options.allowEdit) {
                                 return driver;
@@ -127,15 +162,13 @@ describe('Camera tests iOS.', function () {
                 }
                 if (cancelCamera) {
                     return driver
-                        .waitForElementByXPath('//*[@label="Cancel"]', MINUTE / 2)
-                        .elementByXPath('//*[@label="Cancel"]')
-                        .elementByXPath('//*[@label="Cancel"]')
+                        .waitForElementByAccessibilityId('Cancel', MINUTE / 2)
                         .click();
                 }
                 return driver
-                    .waitForElementByXPath('//*[@label="Take Picture"]', MINUTE / 2)
+                    .waitForElementByAccessibilityId('Take Picture', MINUTE / 2)
                     .click()
-                    .waitForElementByXPath('//*[@label="Use Photo"]', MINUTE / 2)
+                    .waitForElementByAccessibilityId('Use Photo', MINUTE / 2)
                     .click();
             })
             .fail(fail);
@@ -164,7 +197,12 @@ describe('Camera tests iOS.', function () {
 
     // takes a picture with the specified options
     // and then verifies it
-    function runSpec(options) {
+    function runSpec(options, done, pending) {
+        if (options.sourceType === cameraConstants.PictureSourceType.CAMERA && !isDevice) {
+            pending('Camera is not available on iOS simulator');
+        }
+        checkSession(done);
+        specsRun += 1;
         return driver
             .then(function () {
                 return getPicture(options);
@@ -172,10 +210,11 @@ describe('Camera tests iOS.', function () {
             .then(function () {
                 return checkPicture(true, options);
             })
-            .fail(saveScreenshotAndFail);
+            .fail(gracefullyFail);
     }
 
     function getDriver() {
+        failedToStart = true;
         driver = wdHelper.getDriver('iOS');
         return wdHelper.getWebviewContext(driver)
             .then(function(context) {
@@ -187,6 +226,42 @@ describe('Camera tests iOS.', function () {
             })
             .then(function () {
                 return wdHelper.injectLibraries(driver);
+            })
+            .sessionCapabilities()
+            .then(function (caps) {
+                var platformVersion = parseFloat(caps.platformVersion);
+                isXCUI = platformVersion >= 10.0;
+            })
+            .then(function () {
+                var options = {
+                    quality: 50,
+                    allowEdit: false,
+                    sourceType: cameraConstants.PictureSourceType.SAVEDPHOTOALBUM,
+                    saveToPhotoAlbum: false,
+                    targetWidth: 210,
+                    targetHeight: 210
+                };
+                return driver
+                    .then(function () { return getPicture(options, false, true); })
+                    .context(CONTEXT_NATIVE_APP)
+                    .acceptAlert()
+                    .then(function alertDismissed() {
+                        // TODO: once we move to only XCUITest-based (which is force on you in either iOS 10+ or Xcode 8+)
+                        // UI tests, we will have to:
+                        // a) remove use of autoAcceptAlerts appium capability since it no longer functions in XCUITest
+                        // b) can remove this entire then() clause, as we do not need to explicitly handle the acceptAlert
+                        //    failure callback, since we will be guaranteed to hit the permission dialog on startup.
+                    }, function noAlert() {
+                        // in case the contacts permission alert never showed up: no problem, don't freak out.
+                        // This can happen if:
+                        // a) The application-under-test already had photos permissions granted to it
+                        // b) Appium's autoAcceptAlerts capability is provided (and functioning)
+                    })
+                    .elementByAccessibilityId('Cancel', 10000)
+                    .click();
+            })
+            .then(function () {
+                failedToStart = false;
             });
     }
 
@@ -199,27 +274,46 @@ describe('Camera tests iOS.', function () {
 
     it('camera.ui.util configure driver and start a session', function (done) {
         getDriver()
-            .then(function () {
-                failedToStart = false;
-            }, fail)
+            .fail(fail)
             .done(done);
-    }, 10 * MINUTE);
+    }, 15 * MINUTE);
 
     describe('Specs.', function () {
+        afterEach(function (done) {
+            if (specsRun >= 15) {
+                specsRun = 0;
+                // we need to restart the session regularly because for some reason
+                // when running against iOS 10 simulator on SauceLabs, 
+                // Appium cannot handle more than ~20 specs at one session
+                // the error would be as follows:
+                // "Could not proxy command to remote server. Original error: Error: connect ECONNREFUSED 127.0.0.1:8100"
+                checkSession(done);
+                return driver
+                    .quit()
+                    .then(function () {
+                        return getDriver();
+                    })
+                    .done(done);
+            } else {
+                done();
+            }
+        }, 15 * MINUTE);
+
         // getPicture() with mediaType: VIDEO, sourceType: PHOTOLIBRARY
         it('camera.ui.spec.1 Selecting only videos', function (done) {
             checkSession(done);
+            specsRun += 1;
             var options = { sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
                             mediaType: cameraConstants.MediaType.VIDEO };
             driver
                 // skip ui unteractions
                 .then(function () { return getPicture(options, false, true); })
                 .waitForElementByXPath('//*[contains(@label,"Videos")]', MINUTE / 2)
-                .elementByXPath('//*[@label="Cancel"]')
+                .elementByAccessibilityId('Cancel')
                 .click()
-                .fail(saveScreenshotAndFail)
+                .fail(gracefullyFail)
                 .done(done);
-        }, 3 * MINUTE);
+        }, 7 * MINUTE);
 
         // getPicture(), then dismiss
         // wait for the error callback to be called
@@ -228,6 +322,7 @@ describe('Camera tests iOS.', function () {
             if (!isDevice) {
                 pending('Camera is not available on iOS simulator');
             }
+            specsRun += 1;
             var options = { sourceType: cameraConstants.PictureSourceType.CAMERA,
                             saveToPhotoAlbum: false };
             driver
@@ -237,15 +332,11 @@ describe('Camera tests iOS.', function () {
                 .then(function () {
                     return checkPicture(false);
                 })
-                .fail(saveScreenshotAndFail)
+                .fail(gracefullyFail)
                 .done(done);
-        }, 3 * MINUTE);
+        }, 7 * 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');
-            }
             var options = {
                 quality: 50,
                 allowEdit: false,
@@ -255,11 +346,10 @@ describe('Camera tests iOS.', function () {
                 targetHeight: 210
             };
 
-            runSpec(options).done(done);
-        }, 3 * MINUTE);
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
 
         it('camera.ui.spec.4 Verifying target image size, sourceType=SAVEDPHOTOALBUM', function (done) {
-            checkSession(done);
             var options = {
                 quality: 50,
                 allowEdit: false,
@@ -269,11 +359,10 @@ describe('Camera tests iOS.', function () {
                 targetHeight: 210
             };
 
-            runSpec(options).done(done);
-        }, 3 * MINUTE);
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
 
         it('camera.ui.spec.5 Verifying target image size, sourceType=PHOTOLIBRARY', function (done) {
-            checkSession(done);
             var options = {
                 quality: 50,
                 allowEdit: false,
@@ -283,17 +372,13 @@ describe('Camera tests iOS.', function () {
                 targetHeight: 210
             };
 
-            runSpec(options).done(done);
-        }, 3 * MINUTE);
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
 
         it('camera.ui.spec.6 Verifying target image size, sourceType=CAMERA, destinationType=FILE_URL', 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');
-            }
             var options = {
                 quality: 50,
                 allowEdit: false,
@@ -304,11 +389,10 @@ describe('Camera tests iOS.', function () {
                 targetHeight: 210
             };
 
-            runSpec(options).done(done);
-        }, 3 * MINUTE);
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
 
         it('camera.ui.spec.7 Verifying target image size, sourceType=SAVEDPHOTOALBUM, destinationType=FILE_URL', function (done) {
-            checkSession(done);
             var options = {
                 quality: 50,
                 allowEdit: false,
@@ -319,11 +403,10 @@ describe('Camera tests iOS.', function () {
                 targetHeight: 210
             };
 
-            runSpec(options).done(done);
-        }, 3 * MINUTE);
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
 
         it('camera.ui.spec.8 Verifying target image size, sourceType=PHOTOLIBRARY, destinationType=FILE_URL', function (done) {
-            checkSession(done);
             var options = {
                 quality: 50,
                 allowEdit: false,
@@ -334,17 +417,13 @@ describe('Camera tests iOS.', function () {
                 targetHeight: 210
             };
 
-            runSpec(options).done(done);
-        }, 3 * MINUTE);
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
 
         it('camera.ui.spec.9 Verifying target image size, sourceType=CAMERA, destinationType=FILE_URL, 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');
-            }
             var options = {
                 quality: 100,
                 allowEdit: false,
@@ -354,11 +433,10 @@ describe('Camera tests iOS.', function () {
                 targetWidth: 305,
                 targetHeight: 305
             };
-            runSpec(options).done(done);
-        }, 3 * MINUTE);
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
 
         it('camera.ui.spec.10 Verifying target image size, sourceType=SAVEDPHOTOALBUM, destinationType=FILE_URL, quality=100', function (done) {
-            checkSession(done);
             var options = {
                 quality: 100,
                 allowEdit: false,
@@ -369,11 +447,10 @@ describe('Camera tests iOS.', function () {
                 targetHeight: 305
             };
 
-            runSpec(options).done(done);
-        }, 3 * MINUTE);
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
 
         it('camera.ui.spec.11 Verifying target image size, sourceType=PHOTOLIBRARY, destinationType=FILE_URL, quality=100', function (done) {
-            checkSession(done);
             var options = {
                 quality: 100,
                 allowEdit: false,
@@ -384,17 +461,12 @@ describe('Camera tests iOS.', function () {
                 targetHeight: 305
             };
 
-            runSpec(options).done(done);
-        }, 3 * MINUTE);
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
 
         // 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) {
@@ -402,8 +474,8 @@ describe('Camera tests iOS.', function () {
                         'For more info, see iOS quirks here: https://github.com/apache/cordova-plugin-camera#ios-quirks-1');
                 }
 
-                runSpec(spec.options).done(done);
-            }, 3 * MINUTE);
+                runSpec(spec.options, done, pending).done(done);
+            }, 7 * MINUTE);
         });
 
     });


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org