Couple of people has written here that there is a problem of using Appium XCUITest driver pushFile() method.
This method will import file into the iPhone device under test.
I’ve made a solution to easily push file into real iPhone 14 device.
I’ve followed all the steps from this document: Appium pull/push file
In the document it is recommended to use the pushFile via Keynote application, because it has UIFileSharingEnabled set to true. Only the applications with this permission will allow your Appium test script to import the file into the device.
We wanted to do this scenario using our own application, but our app wasn’t have UIFileSharingEnabled
. So, our developers added this permission.
Also, when file is pushed into device, there is additional permission LSSupportsOpeningDocumentsInPlace
, which has to be enabled so file can be visible later into Files application.
In our case, we had to push image file into device.
That image still won’t be visible into Photos
gallery app. So, test script had to open that image from Files
app and save it to gallery.
Then when application test is run, logged user has to upload his/her profile picture.
Environment:
- Appium to 2.11.4
- XCUITest driver to 7.26.4
- iPhone 14
- iOS 18.0.1
Code:
Page object elements:
public static WebElement getIosOpenFolderBtn(final String folderName) {
// Open folder by its name
return appiumDriver.findElement(AppiumBy.xpath(String.format("//XCUIElementTypeStaticText[@name='%s']", folderName)));
}
public static WebElement getIosImageFileOpen(final String imgName) {
// Open uploaded image file by name
return appiumDriver.findElement(AppiumBy.xpath(String.format("//XCUIElementTypeStaticText[@name='%s']", imgName)));
}
public static WebElement getIosImageOpenedView() {
// When image is opened, this will display Share actions button
return appiumDriver.findElement(AppiumBy.accessibilityId("QLPreviewControllerView"));
}
public static WebElement getIosImageShareOptsBtn() {
// Open image Share options
return appiumDriver.findElement(AppiumBy.accessibilityId("QLOverlayDefaultActionButtonAccessibilityIdentifier"));
}
public static WebElement getIosImageSaveImageBtn() {
// Save Image button
return appiumDriver.findElement(AppiumBy.xpath("//XCUIElementTypeStaticText[@name='Save Image']"));
}
- Test constants:
// path to your images
public static final String IMAGE_FILES_PATH = "src/test/resources/media/";
// Activate/terminate app executable scripts
public static final String ACTIVATE_APP_SCRIPT = "mobile: activateApp";
public static final String TERMINATE_APP_SCRIPT = "mobile: terminateApp";
// Your app bundle id
public static final String IOS_APP_BUNDLE_ID = "io.app.bundle";
// Files app bundle id
public static final String FILES_BUNDLE_ID = "com.apple.DocumentsApp";
// Device remote path
public static final String DEVICE_PATH = "@" + IOS_APP_BUNDLE_ID + ":documents/";
public static final String FOLDER_NAME = "your folder name";
- Map methods for application arguments:
public static Map<String, Object> appArguments() {
final Map<String, Object> appArgs = new HashMap<>();
appArgs.put(BUNDLE_ID_OPTION, IOS_APP_BUNDLE_ID);
return appArgs;
}
public static Map<String, Object> filesAppArguments() {
final Map<String, Object> appArgs = new HashMap<>();
appArgs.put(BUNDLE_ID_OPTION, FILES_BUNDLE_ID);
return appArgs;
}
- Push file and save to Photos method:
public static void pushImageToDevice(final String imgName) {
try {
((IOSDriver) appiumDriver).pushFile(DEVICE_PATH + imgName, new File(IMAGE_FILES_PATH + imgName));
appiumDriver.executeScript(ACTIVATE_APP_SCRIPT, filesAppArguments());
getIosOpenFolderBtn(FOLDER_NAME).click();
getIosImageFileOpen(imgName.split("\\.")[0]).click(); // split if img extension is turned of
getIosImageOpenedView().click();
getIosImageShareOptsBtn().click();
getIosImageSaveImageBtn().click();
appiumDriver.executeScript(TERMINATE_APP_SCRIPT, filesAppArguments());
appiumDriver.executeScript(ACTIVATE_APP_SCRIPT, appArguments()); / / returns to your app
} catch(IOException e) {
e.printStackTrace();
}
}