How to upload / attach file using Appium

We often come across scenarios where we have to upload a file/image while testing an application. There are multiple ways to upload a file which we have seen using Selenium like using sendkeys() or using JavaScript() or Robot Class.

Now, I have seen people asking for 'How to upload/attach file using Appium' .

Unfortunately, there is no way like Selenium SendKeys() or javascript options to work for file upload in mobile application using Appium. We literally have to do everything via UI - as we manually do like click upload button, open image selection, select image and etc.

The only thing that Appium can assist with is to upload files to device, so your device can be cleaned and populated only during the test automation using pushFile method. We will discuss below on this with example.

When we try to upload using sendKeys() with file path from the device itself, webdriver will throw below exception:

org.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. Original error: unknown error: path is not absolute: /sdcard/download/test.pdf 

In this post, we’ll discuss on uploading a file from Mobile device to a web application (chromer browser).

When automating a file upload, after clicking on 'Upload' button, it will prompt you with a dialog box that is just out of reach for Appium web. Like Selenium, In Appium also, we can't perform actions once the view is changed from 'Chrome' web to 'NATIVE' app.

To perform operations, we have to switch the context from Web view to Native view to attach a file using Appium. Let’s first try to understand 'How to Switch from Chrome to Native app' using Appium with example.

"One of the core principles of Appium is that you shouldn't have to change your app to test it. In line with that methodology, it is possible to test hybrid apps the same way you can with Selenium for web apps".

In order to let Appium know whether you want to automate the native aspects of the app or the web views, we have to set the 'context' being automated.

Syntax : - To move to Native view context

driver.context("NATIVE_APP");

Syntax : - To move to Chrome browser context

driver.context("CHROMIUM");

If you are moving into a web view context it will involve attempting to connect to that web view and in the same way, If you are moving into a native context it will involve attempting to connect to Native view.

Code Example to Upload File using Appium

Before we step forward, it’s important to understand that this is a simple example using Android Emulator version 10. Please check that the locators may differ on your device based on the version selected.

Please find below steps :

Step 1: Open URL
Step 2: Click on upload button
Step 3: Switch to Context (NATIVE_APP)
Step 4: Push file from your locale machine to device
Step 5: Click on 'Allow' - permission

Appium Click Allow

Step 6: Click on files

Click on File

Step 7: Select file to upload (Should see the file we pushed to device under downloads)

Appium Select file to upload

Step 8: Switch to Context (CHROMIUM)
Step 9: Click on Upload button on browser
Step 10: Assertion to validate file/image uploaded successfully using Appium

import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.MobileCapabilityType;
import org.openqa.selenium.By;

import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.*;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Set;

public class AppiumTest {

    AndroidDriver driver;
    WebDriverWait wait;
    String AppURL = "http://cgi-lib.berkeley.edu/ex/fup.html";

    @BeforeTest
    public void setup() throws MalformedURLException {

        // Create an object for Desired Capabilities
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
        capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "10.0");
        capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Pixel");
        capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "UIAutomator2");
        capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "Chrome");

        // Initialize the driver object with the URL to Appium Server and
        // passing the capabilities
        driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
        wait = new WebDriverWait(driver, 5);
        driver.setFileDetector(new LocalFileDetector());
    }

    @Test
    public void testSearchAppium() throws IOException {

        //Navigate to app url
        driver.get(AppURL);

        //Click on upload button
        By uploadBtn = By.name("upfile");
        wait.until(ExpectedConditions.visibilityOfElementLocated(uploadBtn));
        driver.findElement(uploadBtn).click();

        //Push file to device
        driver.pushFile("/sdcard/download/test.pdf", new File("C:\\Users\\HarryDev\\Downloads\\cmp_html_page_size.pdf"));

       //Switch to Native_App
        Set<String> contextNames = driver.getContextHandles();
        for (String strContextName : contextNames) {
            if (strContextName.contains("NATIVE_APP")) {
                driver.context("NATIVE_APP");
                break;
            }
        }

        //Click on 'Allow' - permission
        By elementView = By.id("com.android.permissioncontroller:id/permission_allow_button");
        wait.until(ExpectedConditions.visibilityOfElementLocated(elementView));
        driver.findElement(elementView).click();

        //Click on files
        By eleFile = By.xpath("//*[@text="Files"]");
        wait.until(ExpectedConditions.visibilityOfElementLocated(eleFile));
        driver.findElement(eleFile).click();

        //select pdf file from downloads (location of pdf file)
        By eleDoc = By.id("com.android.documentsui:id/thumbnail");
        wait.until(ExpectedConditions.visibilityOfElementLocated(eleDoc));
        driver.findElement(eleDoc).click();

        //Switch to Chrome browser
        Set<String> contextNames1 = driver.getContextHandles();
        for (String strContextName : contextNames1) {
            if (strContextName.contains("CHROMIUM")) {
                driver.context("CHROMIUM");
                break;
            }
        }

        //Click on submit button
        WebElement btnElement = driver.findElement(By.cssSelector("input[type=submit]"));
        wait.until(ExpectedConditions.visibilityOf(btnElement));
        btnElement.click();

        //Add a simple assertion
        By nextPageHeader = By.cssSelector("h1");
        wait.until(ExpectedConditions.visibilityOfElementLocated(nextPageHeader));
        Assert.assertTrue(driver.findElement(nextPageHeader).getText().equals("File Upload Results"));

    }

    @AfterTest
    public void tearDown() {
        if(driver !=null)
            driver.quit();
    }

}

On executing the above code, the file will be uploaded successfully and test should PASS.

If you want to add a file manually to the emulated device, you can drag the file onto the emulator screen. The file will be placed in the /sdcard/Download/ directory. You can also view the file from Android Studio using the Device File Explorer, or find it from the device using the Downloads or Files app, depending on the device version.

If you have any questions/suggesstions, please add a comment.

Appium Tutorials: 

Comments

How to push a file from local machine to emulator and check if the file name is same as the file name in the local machine

Add new comment

CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.