Anyone who is using Selenium eventually reaches a point where they need to perform a file upload.

We'll be using the FileBit site as an example.

I'll also be making some comparisons between Selenium and Endtest:



First, let's see how a file upload usually takes place.

1. You click on the Upload button.

2. A window from the OS opens which allows you to select the file.

On Windows:



On macOS:



After you select the file, the local path of the file is written in the file input.

Every upload form on any site has a file input, you can easily find it by looking for an input element that has the type="file" attribute.

And the file upload is completed:

You might think this will be straightforward:

1. Ask Selenium to click on the Upload button.

2. Ask Selenium to click on the file that we want.

But that won't work.

Why?

Because Selenium can only interact with elements from inside the DOM.

The window from the Operating System is not part of the DOM.

The worst part?

Your test will get stuck because Selenium can't close that window.

The solution is to write the local absolute path of the file directly in file input, without even having to click on the Upload button.

file_input = driver.find_element_by_id("fileField")

file_input.send_keys("C:/files/Sales_April_2019.xlsx")

In case you're using Python and you're running your tests on multiple machines, you can easily get the absolute path of a file from the relative path:

import os

absolute_file_path = os.path.abspath("files/Sales_April_2019.xlsx")

file_input = driver.find_element_by_id("fileField")

file_input.send_keys(absolute_file_path)

Once the site detects that a file path has been written in the file input, it will automatically upload that file.

One inconvenience is that most sites tend to hide that file input and Selenium cannot find an element which is hidden.

The solution?

Execute some JavaScript code that will change the CSS for that file input and make it visible.

If your site is using jQuery:

$("#fileField").css("visibility,"visible");

$("#fileField").css("display,"block");

If your site isn't using jQuery, just use vanilla JavaScript:

document.querySelector("#fileField").style.visibility="visible";

document.querySelector("#fileField").style.display="block";

Remember that you need to execute that JavaScript code before the file upload.

Selenium offers an easy way to execute JavaScript:

change_visibility = '$("#fileField").css("visibility,"visible");'

change_display = '$("#fileField").css("display,"block");'

driver.execute_script(change_visibility)

driver.execute_script(change_display)

That usually does the trick.

But developers have different ways of hiding the file input.

Some might give it a width and height of zero pixels, some might move it outside of the visible area.

You need to figure out what they did to hide it and undo it.

Remember, Selenium cannot interact with an element in these cases:

element is not visible

element does not have a width and a height

element is covered by another element

If you're struggling and can't figure it out, just execute this entire block:

document.querySelector("#fileField").style.visibility="visible";

document.querySelector("#fileField").style.display="block";

document.querySelector("#fileField").style.width="200px";

document.querySelector("#fileField").style.height="200px";

document.querySelector("#fileField").style.position="fixed";

document.querySelector("#fileField").style.overflow="visible";

document.querySelector("#fileField").style.zIndex="999999";

document.querySelector("#fileField").style.top="500px";

document.querySelector("#fileField").style.bottom="500px";

document.querySelector("#fileField").style.left="500px";

document.querySelector("#fileField").style.right="500px";

document.querySelector("#fileField").style.marginBottom="100px";

Uploading a file in a test is easier with Endtest than it is with Selenium:

1. You first need to upload your file in the Drive section:



Make sure to copy the File Download URL.

2. Use the Upload File action in your test:

3. Execute the test on their cross-browser cloud: