Skip to main content

_java

TL;DR - Show Me The Code

2-download-a-file/code/java/src/test/java/com/elemental/selenium/DownloadTest.java
package com.elemental.selenium;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.io.File;
import java.util.UUID;
import java.time.Duration;

public class DownloadTest {
WebDriver driver;
File folder;

@BeforeEach
public void beforeEach() {
folder = new File(UUID.randomUUID().toString());
folder.mkdir();
FirefoxOptions options = new FirefoxOptions();
options.addPreference("browser.download.dir", folder.getAbsolutePath());
options.addPreference("browser.download.folderList", 2);
options.addPreference("browser.helperApps.neverAsk.saveToDisk",
"image/jpeg, application/pdf, application/octet-stream");
options.addPreference("pdfjs.disabled", true);
driver = new FirefoxDriver(options);
}

@AfterEach
public void afterEach() {
if (driver != null) {
driver.quit();
}
for (File file: folder.listFiles()) {
file.delete();
}
folder.delete();
}

@Test
public void downloadFile() throws Exception {
driver.get("https://the-internet.herokuapp.com/download");
driver.findElement(By.cssSelector(".example a")).click();

// Wait for the file to be downloaded up to 5 seconds
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
wait.until((WebDriver d) -> folder.listFiles().length > 0 && folder.listFiles()[0].length() > 0);

File[] listOfFiles = folder.listFiles();
// Make sure the directory is not empty
Assertions.assertTrue(listOfFiles.length > 0);
for (File file : listOfFiles) {
// Make sure the downloaded file(s) is(are) not empty
Assertions.assertTrue(file.length() > 0);
}
}

}

Code Walkthrough

Importing Libraries

Lines 3 to 14 are pulling in our requisite classes for annotations (e.g., org.junit.jupiter.api.BeforeEach, etc.), driving the browser with Selenium (e.g., org.openqa.selenium.WebDriver, etc.), matchers for assertions (e.g., org.junit.jupiter.api.Assertions;, etc. ), something to handle local files (e.g., java.io.File), and a means to create a uniquely named folder to place downloaded files in (e.g., java.util.UUID)

Setup and Teardown

Lines 21 to 42 are setting up and tearing down the browser instance. The beforeEach method, will execute before each test. In it we're creating a uniquely named temp directory (e.g., UUID.randomUUID().toString();), configuring a browser options object (for Firefox in this case), and plying it with the necessary configuration parameters to make it automatically download the file where we want (e.g., in the newly created temp directory).

Here's a breakdown of each of the browser preferences being set:

  • browser.download.dir accepts a string. This is how we set the custom download path. It needs to be an absolute path.
  • browser.download.folderList takes a number. It tells Firefox which download directory to use. 2 tells it to use a custom download path, wheras 1 would use the browser's default path, and 0 would place them on the Desktop.
  • browser.helperApps.neverAsk.saveToDisk tells Firefox when not to prompt for a file download. It accepts a string of the file's MIME type. If you want to specify more than one, you do it with a comma-separated string.
  • pdfjs.disabled is for when downloading PDFs. This overrides the sensible default in Firefox that previews PDFs in the browser. It accepts a boolean.

This options object is then passed into our instance of Selenium (e.g., driver = new FirefoxDriver(options);).

After our test executes the second method, afterEach, will execute. In it, we close the browser instance and then clean up the temp directory by deleting the files in the temp folder and then the temp folder.

The Test

Lines 45 to 60 are the test itself.

After visiting the page we find the first download link and click it. The click triggers an automatic download to the temp directory created in setUp(). We need to wait for the download to finish, so we use Selenium's WebDriverWait to wait up to 5 seconds. After the file downloads, we perform some rudimentary checks to make sure the temp directory isn't empty and then check the file (or files) that they aren't empty either.

Executing the Test

Before executing the test, we need to make sure the required dependencies are declared on the pom.xml file.

Toggle to see the pom.xml file.
2-download-a-file/code/java/pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.elemental.selenium</groupId>
<artifactId>tips</artifactId>
<version>1.0.0</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.24.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

Finally, we can run the test by executing mvn test from the command-line.