Skip to content

Commit

Permalink
Merge pull request #357 from dn0000001/header-support-file-download
Browse files Browse the repository at this point in the history
Add support to add header when downloading files
  • Loading branch information
AutomatorGuy123 authored Jun 18, 2021
2 parents ac8853f + a0e8460 commit ce0befb
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.automation.common.ui.app.pageObjects;

import com.lazerycode.selenium.filedownloader.FileDownloader;
import com.taf.automation.ui.support.PageObjectV2;
import com.taf.automation.ui.support.TestContext;
import com.taf.automation.ui.support.util.AssertJUtil;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import org.apache.http.HttpStatus;
import org.openqa.selenium.support.FindBy;
import ui.auto.core.components.WebComponent;

import java.io.File;

/**
* This the Other Files page on the site <a href="https://file-examples.com/">File Examples</a>
*/
@SuppressWarnings("java:S3252")
public class FileExamplesOtherFilesPage extends PageObjectV2 {
private static final String LINK_HTTP_STATUS = "Link HTTP Status";

@XStreamOmitField
@FindBy(css = "[download$='.csv']")
private WebComponent downloadSampleCsvFile;

public FileExamplesOtherFilesPage() {
super();
}

public FileExamplesOtherFilesPage(TestContext context) {
super(context);
}

/**
* Perform download of the CSV file using an element
*
* @return the CSV file that was saved to a temporary file which needs to be deleted after
*/
public File performDownloadOfCsvFileUsingElement() {
FileDownloader downloader = new FileDownloader(getDriver());
downloader.withURISpecifiedInAnchorElement(downloadSampleCsvFile.getCoreElement());

// This is unnecessary and only for testing purposes
int status = downloader.getLinkHTTPStatus();
AssertJUtil.assertThat(status).as(LINK_HTTP_STATUS).isEqualTo(HttpStatus.SC_OK);

// For testing purposes, we are setting the suffix
return downloader.downloadFile(".csv");
}

/**
* Perform download of the CSV file using a URL
*
* @return the CSV file that was saved to a temporary file which needs to be deleted after
*/
public File performDownloadOfCsvFileUsingUri() {
FileDownloader downloader = new FileDownloader(getDriver());
downloader.withURI(downloadSampleCsvFile.getAttribute("href"));

// This is unnecessary and only for testing purposes
int status = downloader.getLinkHTTPStatus();
AssertJUtil.assertThat(status).as(LINK_HTTP_STATUS).isEqualTo(HttpStatus.SC_OK);

// For testing purposes, we are setting the both the prefix & suffix
return downloader.downloadFile("auto-", ".csv");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,8 @@ public void toSeleniumEasyBasicCheckbox(boolean cleanCookies) {
toURL("Selenium Easy - Basic Checkbox", props.getCustom("seleniumeasy-basic-checkbox-url", null), cleanCookies);
}

public void toFileExamplesOtherFiles(boolean cleanCookies) {
toURL("File Examples - Other Files", props.getCustom("file-examples-other-files-url", null), cleanCookies);
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.automation.common.ui.app.tests;

import com.automation.common.ui.app.pageObjects.FileExamplesOtherFilesPage;
import com.automation.common.ui.app.pageObjects.Navigation;
import com.lazerycode.selenium.filedownloader.FileDownloader;
import com.taf.automation.ui.support.csv.CsvUtils;
import com.taf.automation.ui.support.testng.TestNGBase;
import com.taf.automation.ui.support.util.AssertJUtil;
import com.taf.automation.ui.support.util.DomainObjectUtils;
import com.taf.automation.ui.support.util.FilloUtils;
import com.taf.automation.ui.support.util.Utils;
import org.apache.commons.csv.CSVRecord;
import org.apache.http.HttpStatus;
Expand All @@ -30,59 +31,49 @@
*/
@SuppressWarnings("java:S3252")
public class FileDownloaderTest extends TestNGBase {
private static final String LINK_HTTP_STATUS = "Link HTTP Status";

@Features("Framework")
@Stories("FileDownloader")
@Severity(SeverityLevel.CRITICAL)
@Test
public void performTest(ITestContext injectedContext) {
DomainObjectUtils.overwriteTestName(injectedContext);
new Navigation(getContext()).toHerokuappDownloads(Utils.isCleanCookiesSupported());
FileDownloader downloader = new FileDownloader(getContext().getDriver());
downloadImageFromElement(downloader);
downloadImageFromHref(downloader);
downloadFileFromUri(downloader);
downloadImageFromElement();

new Navigation(getContext()).toFileExamplesOtherFiles(Utils.isCleanCookiesSupported());
downloadImageFromHref();
downloadFileFromUri();
}

@Step("Perform Download Image from Element")
private void downloadImageFromElement(FileDownloader downloader) {
private void downloadImageFromElement() {
FileDownloader downloader = new FileDownloader(getContext().getDriver());
WebElement element = getContext().getDriver().findElement(By.cssSelector("[alt='Fork me on GitHub']"));
downloader.withURISpecifiedInImageElement(element);
int status = downloader.getLinkHTTPStatus();
AssertJUtil.assertThat(status).as(LINK_HTTP_STATUS).isEqualTo(HttpStatus.SC_OK);
AssertJUtil.assertThat(status).as("Link HTTP Status").isEqualTo(HttpStatus.SC_OK);

File img = downloader.downloadFile();
img.deleteOnExit();
AssertJUtil.assertThat(img).exists().isFile();
}

@Step("Perform Download Image from HREF")
private void downloadImageFromHref(FileDownloader downloader) {
WebElement element = getContext().getDriver().findElement(By.xpath("//a[@href='download/chow.jpg']"));
downloader.withURISpecifiedInAnchorElement(element);
int status = downloader.getLinkHTTPStatus();
AssertJUtil.assertThat(status).as(LINK_HTTP_STATUS).isEqualTo(HttpStatus.SC_OK);

File img = downloader.downloadFile(".jpg");
@Step("Perform Download CSV from HREF")
private void downloadImageFromHref() {
File img = new FileExamplesOtherFilesPage(getContext()).performDownloadOfCsvFileUsingElement();
img.deleteOnExit();
AssertJUtil.assertThat(img).exists().isFile();
}

@Step("Perform Download File from URI")
private void downloadFileFromUri(FileDownloader downloader) {
WebElement element = getContext().getDriver().findElement(By.xpath("//a[@href='download/people.xlsx']"));
downloader.withURI(element.getAttribute("href"));
int status = downloader.getLinkHTTPStatus();
AssertJUtil.assertThat(status).as(LINK_HTTP_STATUS).isEqualTo(HttpStatus.SC_OK);

File excel = downloader.downloadFile("auto-", ".xlsx");
private void downloadFileFromUri() {
File excel = new FileExamplesOtherFilesPage(getContext()).performDownloadOfCsvFileUsingUri();
excel.deleteOnExit();
AssertJUtil.assertThat(excel).exists().isFile();

List<CSVRecord> records = new ArrayList<>();
Map<String, Integer> headers = new HashMap<>();
FilloUtils.read(excel.getAbsolutePath(), "records", records, headers);
CsvUtils.read(excel.getAbsolutePath(), records, headers);
AssertJUtil.assertThat(records).as("Records").isNotEmpty();
AssertJUtil.assertThat(headers).as("Headers").isNotEmpty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
<prop name="rubywatir-checkboxes-url" value="http://test.rubywatir.com/checkboxes.php"/>
<prop name="seleniumeasy-radio-button-url" value="https://www.seleniumeasy.com/test/input-form-demo.html"/>
<prop name="seleniumeasy-basic-checkbox-url" value="https://www.seleniumeasy.com/test/basic-checkbox-demo.html"/>
<prop name="file-examples-other-files-url" value="https://file-examples.com/index.php/text-files-and-archives-download/"/>

<!-- There is bug in UserProvider class of ui_auto_core 2.5.15 that requires at least 1 user with a role -->
<user role="user" userName="u2" password="xzRZ75G077/YqCsRSAHGMw=="/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package com.lazerycode.selenium.filedownloader;

import com.taf.automation.api.clients.ApiClient;
import com.taf.automation.api.clients.FileDownloaderClient;
import com.taf.automation.ui.support.util.AssertJUtil;
import org.apache.commons.io.FileUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.BasicHttpContext;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriver;
Expand All @@ -20,6 +24,8 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
Expand All @@ -34,7 +40,9 @@ public class FileDownloader {
private boolean followRedirects = true;
private boolean mimicWebDriverCookieState = true;
private RequestMethod httpRequestMethod = RequestMethod.GET;
private final List<Header> headers = new ArrayList<>();
private URI fileURI;
private HttpEntity httpEntity;

public FileDownloader(WebDriver driver) {
this.driver = driver;
Expand Down Expand Up @@ -75,6 +83,28 @@ public FileDownloader withHTTPRequestMethod(RequestMethod requestType) {
return this;
}

/**
* Set the HttpEntity<BR>
* <B>Notes: </B>
* <OL>
* <LI>
* This is only applicable to certain request types such as post.
* There is no logic to prevent use with invalid request types.
* </LI>
* <LI>
* A common HttpEntity that might be used is UrlEncodedFormEntity for forms.
* There exists the method <B>getFormHttpEntity</B> in the class <B>ApiUtils</B> that may be of use
* </LI>
* </OL>
*
* @param httpEntity - Http Entity (Use null to clear a previously set Http Entity.)
* @return FileDownloader
*/
public FileDownloader withHttpEntity(HttpEntity httpEntity) {
this.httpEntity = httpEntity;
return this;
}

/**
* Specify a URL that you want to perform an HTTP Status Check upon/Download a file from
*
Expand Down Expand Up @@ -160,6 +190,39 @@ public FileDownloader withURISpecifiedInImageElement(WebElement imageElement) {
return this;
}

/**
* Add Request Header to be sent
*
* @param header - Request Header
* @return FileDownloader
*/
public FileDownloader withRequestHeader(Header header) {
headers.add(header);
return this;
}

/**
* Add Request Header to be sent
*
* @param name - Header Name
* @param value - Header value
* @return FileDownloader
*/
public FileDownloader withRequestHeader(String name, String value) {
Header header = new BasicHeader(name, value);
return withRequestHeader(header);
}

/**
* Reset the request headers back to the empty list
*
* @return FileDownloader
*/
public FileDownloader resetRequestHeaders() {
headers.clear();
return this;
}

/**
* Load in all the cookies WebDriver currently knows about so that we can mimic the browser cookie state
*
Expand All @@ -183,7 +246,7 @@ private BasicCookieStore mimicCookieState(Set<Cookie> seleniumCookieSet) {
private HttpResponse getHTTPResponse() throws IOException {
AssertJUtil.assertThat(fileURI).as("No file URI specified").isNotNull();

HttpClient client = new ApiClient().getClient();
HttpClient client = new FileDownloaderClient().getClient();
BasicHttpContext localContext = new BasicHttpContext();

// Clear down the local cookie store every time to make sure we don't have any left over cookies influencing the test
Expand All @@ -195,6 +258,10 @@ private HttpResponse getHTTPResponse() throws IOException {
HttpRequestBase requestMethod = httpRequestMethod.getRequestMethod();
requestMethod.setURI(fileURI);
requestMethod.setConfig(RequestConfig.custom().setRedirectsEnabled(followRedirects).build());
headers.forEach(requestMethod::setHeader);
if (requestMethod instanceof HttpEntityEnclosingRequest && httpEntity != null) {
((HttpEntityEnclosingRequest) requestMethod).setEntity(httpEntity);
}

return client.execute(requestMethod, localContext);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,22 @@

import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpOptions;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpTrace;

/**
* This code came from <a href="https://github.com/Ardesco/Powder-Monkey">https://github.com/Ardesco/Powder-Monkey</a>
* which was found on the <a href="https://ardesco.lazerycode.com/testing/webdriver/2012/07/25/how-to-download-files-with-selenium-and-why-you-shouldnt.html">blog by Mark Collin</a>
*/
public enum RequestMethod {
OPTIONS(new HttpOptions()),
GET(new HttpGet()),
HEAD(new HttpHead()),
POST(new HttpPost()),
PUT(new HttpPut()),
DELETE(new HttpDelete()),
TRACE(new HttpTrace());
PATCH(new HttpPatch()),
;

private final HttpRequestBase request;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public ApiClient(
this.returnType = returnType;
}

public CloseableHttpClient getClient() {
CloseableHttpClient getClient() {
return client;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.taf.automation.api.clients;

import com.taf.automation.api.ParametersType;
import com.taf.automation.api.ReturnType;
import com.taf.automation.ui.support.TestProperties;
import org.apache.http.impl.client.CloseableHttpClient;

/**
* Wrapper class to provide a CloseableHttpClient for use in the FileDownloader class without exposing it to all classes
*/
public class FileDownloaderClient {
private static final String URL = "https://www.google.com"; // Any valid url
private static final int TIMEOUT = TestProperties.getInstance().getApiTimeout();
private final ApiClient apiClient;

public FileDownloaderClient() {
apiClient = new ApiClient(ParametersType.GENERAL, ReturnType.GENERAL, URL, null, null, TIMEOUT, TIMEOUT);
}

public CloseableHttpClient getClient() {
return apiClient.getClient();
}

}

0 comments on commit ce0befb

Please sign in to comment.