Reputation: 1763
I'd like to click on a button that downloads a file on click, and test whether the expected file has been downloaded.
I've already googled this, but unfortunately didn't find any specific answer on this topic, lots of posts I found, are outdated (2014), I bet Selenium must've changed the API definition by now.
Upvotes: 5
Views: 26743
Reputation: 494
This code verifies if the file is downloaded and then deletes it.
private static bool CheckFileDownloaded(string filename)
{
bool exist = false;
string Path = System.Environment.GetEnvironmentVariable("USERPROFILE") + "\\Downloads";
string[] filePaths = Directory.GetFiles(Path);
foreach (string p in filePaths)
{
if(p.Contains(filename))
{
FileInfo thisFile = new FileInfo(p);
//Check the file that are downloaded in the last 3 minutes
if (thisFile.LastWriteTime.ToShortTimeString() == DateTime.Now.ToShortTimeString() ||
thisFile.LastWriteTime.AddMinutes(1).ToShortTimeString() == DateTime.Now.ToShortTimeString() ||
thisFile.LastWriteTime.AddMinutes(2).ToShortTimeString() == DateTime.Now.ToShortTimeString() ||
thisFile.LastWriteTime.AddMinutes(3).ToShortTimeString() == DateTime.Now.ToShortTimeString())
exist = true;
File.Delete(p);
break;
}
}
return exist;
}
Hope this helps. Code in C#.
Upvotes: 9
Reputation: 107247
FWR, both test runners I tried (Resharper, and MS Test explorer) placed the Selenium files in the following folder.
MySolution\MyProject\bin\Debug\Downloads
In fact Se adds a readme.txt
here containing:
This folder is here for Selenium to download files in
However, I was able to modify @Sudeepthi's answer accordingly:
private static readonly string SeleniumDownloadPath =
AppDomain.CurrentDomain.BaseDirectory + "\\Downloads";
private static bool CheckFileDownloaded(string filename)
{
var firstFile = Directory
.GetFiles(SeleniumDownloadPath)
.FirstOrDefault(fp => fp.Contains(filename));
if (firstFile != default)
{
var fileInfo = new FileInfo(firstFile);
var isFresh = DateTime.Now - fileInfo.LastWriteTime < TimeSpan.FromMinutes(3);
File.Delete(firstFile);
//Check the file that are downloaded in the last 3 minutes
return isFresh;
}
return false;
}
Upvotes: 1
Reputation: 15981
This is my generic C# solution
/// <summary>
/// Start a download and wait for a file to appear
/// https://stackoverflow.com/a/46440261/1141876
/// </summary>
/// <param name="expectedExtension">If we don't know the extension, Chrome creates a temp file in download folder and we think we have the file already</param>
protected List<FileInfo> ActAndWaitForFileDownload(
Action action
, string expectedExtension
, TimeSpan maximumWaitTime)
{
Directory.CreateDirectory(DownloadDirectory);
var fileCountbefore = Directory.GetFiles(DownloadDirectory).Length;
var stopwatch = Stopwatch.StartNew();
action();
var isTimedOut = false;
var extensionFilter = $"*{expectedExtension}";
Func<bool> fileAppearedOrTimedOut = () =>
{
isTimedOut = stopwatch.Elapsed > maximumWaitTime;
var isFilePresent = Directory
.GetFiles(DownloadDirectory, extensionFilter)
.Length == fileCountbefore;
return isFilePresent && !isTimedOut;
};
do
{
Thread.Sleep(500);
Log($"Waited {stopwatch.Elapsed} (max={maximumWaitTime}) for download '{extensionFilter}'...");
}
while (fileAppearedOrTimedOut());
var files = Directory
.GetFiles(DownloadDirectory)
.Select(s => new FileInfo(s))
.ToList();
if (isTimedOut)
{
Log($"Timed out: {filenamesForLog}");
}
else
{
var filenamesForLog = string.Join(",", files.Select(f => f.Name));
Log($"File downloaded: {filenamesForLog}");
}
return files;
}
This is the usage
// Wait for a PDF
var downloadedFiles = ActAndWaitForFileDownload(() => buttonElement.click(), ".pdf", TimeSpan.FromSeconds(30));
Upvotes: 2
Reputation: 42518
One simple solution would be to use a file watcher to detect the creation of the file. It would allow you to wait for the download to start and to finish:
string folder = Environment.GetEnvironmentVariable("USERPROFILE") + "\\Downloads";
using (var watcher = new FileSystemWatcher(folder)) {
// wait for new file to be created
var result = watcher.WaitForChanged(WatcherChangeTypes.Created, 5000);
if (result.TimedOut)
throw new WebDriverTimeoutException("Dowmload failed");
Console.WriteLine("Download started for : " + Path.Combine(folder, result.Name));
// wait for the temporary file to be deleted
var result2 = watcher.WaitForChanged(WatcherChangeTypes.Deleted, 10000);
if (result2.TimedOut)
throw new WebDriverTimeoutException("Dowmload failed");
Console.WriteLine("Download finished for : " + Path.Combine(folder, result.Name));
}
Upvotes: 2
Reputation: 17553
Use below code:-
import org.openqa.selenium.By;
import java.io.File;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class FileDownloadVerify {
private WebDriver driver;
private static String downloadPath = "D:\\siva";
private String URL="http://all-free-download.com/free-photos/download/in_love_cosmos_flower_garden_220378.html";
@BeforeClass
public void testSetup() throws Exception{
driver = new FirefoxDriver(firefoxProfile());
driver.manage().window().maximize();
}
@Test
public void example_VerifyExpectedFileName() throws Exception {
driver.get(URL);
driver.findElement(By.xpath(".//*[@id='detail_content']/div[2]/a")).click();
Thread.sleep(10000);
File getLatestFile = getLatestFilefromDir(downloadPath);
String fileName = getLatestFile.getName();
Assert.assertTrue(fileName.equals("in_love_cosmos_flower_garden_220378.zip"), "Downloaded file name is not matching with expected file name");
}
@AfterClass
public void tearDown() {
driver.quit();
}
public static FirefoxProfile firefoxProfile() throws Exception {
FirefoxProfile firefoxProfile = new FirefoxProfile();
firefoxProfile.setPreference("browser.download.folderList",2);
firefoxProfile.setPreference("browser.download.manager.showWhenStarting",false);
firefoxProfile.setPreference("browser.download.dir",downloadPath);
firefoxProfile.setPreference("browser.helperApps.neverAsk.saveToDisk","application/zip");
return firefoxProfile;
}
public boolean isFileDownloaded(String downloadPath, String fileName) {
boolean flag = false;
File dir = new File(downloadPath);
File[] dir_contents = dir.listFiles();
for (int i = 0; i < dir_contents.length; i++) {
if (dir_contents[i].getName().equals(fileName))
return flag=true;
}
return flag;
}
private boolean isFileDownloaded_Ext(String dirPath, String ext){
boolean flag=false;
File dir = new File(dirPath);
File[] files = dir.listFiles();
if (files == null || files.length == 0) {
flag = false;
}
for (int i = 1; i < files.length; i++) {
if(files[i].getName().contains(ext)) {
flag=true;
}
}
return flag;
}
private File getLatestFilefromDir(String dirPath){
File dir = new File(dirPath);
File[] files = dir.listFiles();
if (files == null || files.length == 0) {
return null;
}
File lastModifiedFile = files[0];
for (int i = 1; i < files.length; i++) {
if (lastModifiedFile.lastModified() < files[i].lastModified()) {
lastModifiedFile = files[i];
}
}
return lastModifiedFile;
}
}
Hope it will help you :)
Upvotes: 5