Uploading a file through a form without touching the operating system’s file dialog, and why downloading through the browser is not the right way to test a download.
Clicking a file input opens the operating system’s file chooser, which is outside the browser
and invisible to WebDriver. Clicking a download link starts a download the API cannot watch:
there is no event for “finished”, no progress, and no portable way to find the file afterwards.
Recommended approach
Uploads. Do not click the input. Send the absolute path of the file to the
<input type="file"> element with sendKeys, then submit the form as usual. The browser
attaches the file exactly as if it had been chosen through the dialog. The path must exist on
the machine where the browser is running; when the browser is remote, on a Grid, set a local
file detector so the client uploads the file to the node first.
Downloads. Testing a download through the browser is discouraged. The browser’s download
behaviour is configurable per browser and per platform, the file lands in a directory you then
have to poll, and none of this is what a user actually cares about. Instead, use Selenium to
get to the point where the download link exists, read its href (and any cookies the request
needs), and fetch it with an HTTP client in your test language. That gives you the bytes
directly, with a proper status code, and no polling.
If you are running on Selenium Grid and really need the browser to perform the download, Grid
can be configured to collect downloaded files from the node and the client can retrieve them;
see the remote WebDriver page below.
const{Browser,By,until,Builder}=require("selenium-webdriver");constpath=require("path");constassert=require('node:assert');describe('File Upload Test',function(){letdriver;before(asyncfunction(){driver=newBuilder().forBrowser(Browser.CHROME).build();});after(async()=>awaitdriver.quit());it('Should be able to upload a file successfully',asyncfunction(){constimage=path.resolve('./test/resources/selenium-snapshot.png')awaitdriver.manage().setTimeouts({implicit:5000});// Navigate to URL
awaitdriver.get('https://the-internet.herokuapp.com/upload');// Upload snapshot
awaitdriver.findElement(By.id("file-upload")).sendKeys(image);awaitdriver.findElement(By.id("file-submit")).submit();constrevealed=awaitdriver.findElement(By.id('uploaded-files'))awaitdriver.wait(until.elementIsVisible(revealed),2000);constdata=awaitdriver.findElement(By.css('h3'));assert.equal(awaitdata.getText(),`File Uploaded!`);});});
Common errors
InvalidArgumentException:
the path does not exist on the machine running the browser. Use an absolute path, and a file
detector when the browser is remote.
ElementNotInteractableException:
the file input is hidden behind a styled button. Sending keys to a hidden file input is
allowed in most browsers; if it is refused, check the strictFileInteractability capability.