Not able to download .csv file through Google Chrome in headless mode - selenium

I have been trying to download a csv file using selenium in Chrome headless mode but it is not working for my scenario. I tried to run the same script without headless and it works. I tried the same headless configuration with https://www.mockaroo.com/ site and it worked. Below is the chrome headless configuration that I'm using
System.setProperty("webdriver.chrome.driver", Constants.CHROME_DRIVER);
ChromeOptions options = new ChromeOptions();
options.addArguments("--test-type");
options.addArguments("--headless");
options.addArguments("--disable-extensions"); //to disable browser extension popup
options.addArguments("window-size=1980,1080");
options.addArguments("--disable-web-security");
options.addArguments("--no-sandbox");
options.addArguments("--disable-gpu");
options.addArguments("--disable-popup-blocking");
options.addArguments("--start-maximized");
options.addArguments("--allow-running-insecure-content");
options.setExperimentalOption("w3c", false);
options.addArguments("--ignore-certificate-errors");
options.addArguments("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36");
DesiredCapabilities cap = DesiredCapabilities.chrome();
cap.setCapability(ChromeOptions.CAPABILITY, options);
// set performance logger
// this sends Network.enable to chromedriver
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
cap.setCapability("goog:loggingPrefs", logPrefs);
ChromeDriverService driverService = ChromeDriverService.createDefaultService();
driver = new ChromeDriver(driverService, cap);
String downloadFilepath = "C:\\Users\\User\\Downloads";
System.out.println(downloadFilepath);
Map < String, Object > commandParams = new HashMap<String, Object>();
commandParams.put("cmd", "Page.setDownloadBehavior");
Map < String, Object > params = new HashMap<String, Object>();
params.put("behavior", "allow");
params.put("download.prompt_for_download", false);
params.put("downloadPath", downloadFilepath);
commandParams.put("params", params);
ObjectMapper objectMapper = new ObjectMapper();
HttpClient httpClient = HttpClientBuilder.create().build();
try {
String command = objectMapper.writeValueAsString(commandParams);
String u = driverService.getUrl().toString() + "/session/" + ((ChromeDriver)driver).getSessionId() + "/chromium/send_command";
System.out.println("U: " + u.toString());
HttpPost request = new HttpPost(u);
request.addHeader("content-type", "application/json");
request.setEntity(new StringEntity(command));
httpClient.execute(request);
} catch (Exception e) { }
driver.get(prop.getProperty("url"));
With the above driver configuration (after authenticating the user), I'm clicking a button which submits the form data and in response, I am getting:
Content-Disposition: attachment;filename=WIS_mop_mis3.csv
which downloads the file.
Please find the logs below where you can see the highlighted part where it says that net::ERR_ABORTED but I am getting this error for both headless & without headless;
Performance logs for headless mode
Anyone have any idea, where I am doing wrong.
Edit: The application flow is when user clicks on the export button a new window gets opened where user fills the data and clicks on a button which calls a function for some sort of validation. After validation, it submits the form using document.formName.submit().

I am able to figure out the solution. Below is the working code
System.setProperty("webdriver.chrome.driver", Constants.CHROME_DRIVER);
ChromeOptions options = new ChromeOptions();
options.addArguments("--test-type");
options.addArguments("--headless");
options.addArguments("--disable-extensions"); //to disable browser extension popup
options.addArguments("window-size=1980,1080");
options.addArguments("--disable-web-security");
options.addArguments("--no-sandbox");
options.addArguments("--disable-gpu");
options.addArguments("--disable-popup-blocking");
options.addArguments("--start-maximized");
options.addArguments("--allow-running-insecure-content");
options.setExperimentalOption("w3c", false);
options.addArguments("--ignore-certificate-errors");
options.addArguments("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36");
HashMap<String, Object> chromePreferences = new HashMap<String, Object>();
// This part was missing in my old code.
chromePreferences.put("download.prompt_for_download", false);
chromePreferences.put("download.directory_upgrade", true);
chromePreferences.put("safebrowsing.enabled", false);
chromePreferences.put("profile.default_content_settings.popups", 0);
chromePreferences.put("safebrowsing.disable_download_protection", true);
chromePreferences.put("download.default_directory", downloadFilepath);
options.setExperimentalOption("prefs", chromePreferences);
DesiredCapabilities cap = DesiredCapabilities.chrome();
cap.setCapability(ChromeOptions.CAPABILITY, options);
// set performance logger
// this sends Network.enable to chromedriver
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
cap.setCapability("goog:loggingPrefs", logPrefs);
ChromeDriverService driverService = ChromeDriverService.createDefaultService();
driver = new ChromeDriver(driverService, cap);
String downloadFilepath = "C:\\Users\\User\\Downloads";
System.out.println(downloadFilepath);
Map < String, Object > commandParams = new HashMap<String, Object>();
commandParams.put("cmd", "Page.setDownloadBehavior");
Map < String, Object > params = new HashMap<String, Object>();
params.put("behavior", "allow");
params.put("downloadPath", downloadFilepath);
commandParams.put("params", params);
ObjectMapper objectMapper = new ObjectMapper();
HttpClient httpClient = HttpClientBuilder.create().build();
try {
String command = objectMapper.writeValueAsString(commandParams);
String u = driverService.getUrl().toString() + "/session/" + ((ChromeDriver)driver).getSessionId() + "/chromium/send_command";
System.out.println("U: " + u.toString());
HttpPost request = new HttpPost(u);
request.addHeader("content-type", "application/json");
request.setEntity(new StringEntity(command));
httpClient.execute(request);
} catch (Exception e) { }
This post helped me to fix this issue https://stackoverflow.com/a/52384942/6017332

Related

SeleniumGrid: org.openqa.selenium.WebDriverException: Unable to parse remote response: <html> <head> <title>

I'm trying to write test cases using selenium. I wrote this code. And i got this error
org.openqa.selenium.WebDriverException: Unable to parse remote response:
but I don't understand what is wrong
public static WebDriver driver=null;
ATUTestRecorder recorder;
#Parameters({"browsername"})
#BeforeTest
public void setUpBrowser(String browsername) throws ATUTestRecorderException, MalformedURLException
{
String timeStamp = new SimpleDateFormat("yy-MM-dd_HH-mm-ss").format(new Date());
recorder = new ATUTestRecorder("./ScreenRecorder/","Test_"+timeStamp+".mp4",false);
DesiredCapabilities cap =null;
if(driver==null)
{
if(browsername.equalsIgnoreCase("Firefox"))
{
// Set the path for geckodriver.exe
//System.setProperty("webdriver.gecko.driver", "./Drivers/geckodriver.exe");
//WebDriverManager.firefoxdriver().setup();
cap = DesiredCapabilities.firefox();
cap.setBrowserName("firefox");
cap.setPlatform(Platform.ANY);
driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"),cap);
}
// If the browser is Chrome
else if(browsername.equalsIgnoreCase("Chrome"))
{
// Set the path for chromedriver.exe
System.setProperty("webdriver.chrome.driver", "./Drivers/chromedriver.exe");
//WebDriverManager.chromedriver().setup();
cap = DesiredCapabilities.chrome();
cap.setBrowserName("chrome");
cap.setPlatform(Platform.ANY);
System.out.println(driver);
driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"),cap);
}
// If the browser is IE
else if(browsername.equalsIgnoreCase("IE"))
{
// Set the path for IEdriver.exe
//System.setProperty("webdriver.ie.driver", "./Drivers/IEDriverServer.exe");
//WebDriverManager.iedriver().setup();
cap = DesiredCapabilities.internetExplorer();
cap.setBrowserName("internetExplorer");
cap.setPlatform(Platform.ANY);
driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"),cap);
}
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().window().maximize();
driver.get(DataConfig.baseURL);
}
recorder.start();
}
How can I resolve this issue?
Remove /wd/hub from your driver URL.
See example at https://www.selenium.dev/documentation/webdriver/remote_webdriver/

language translation in Selenium java

I am Trying to translate the webpage with following code but it did not work.
WebDriverManager.chromedriver().setup();
ChromeOptions option = new ChromeOptions();
option.addArguments("start-maximized");
option.addArguments("test-type");
option.addArguments("--lang=en-US");
option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation"));
option.setExperimentalOption("useAutomationExtension", false);
WebDriver driver = new ChromeDriver(option);
driver.manage().timeouts().implicitlyWait(45, TimeUnit.SECONDS);
driver.get("https://www.staffers.no/jobbsoker");
You can try with below code :
ChromeOptions option = new ChromeOptions();
option.addArguments("start-maximized");
option.addArguments("test-type");
option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation"));
option.setExperimentalOption("useAutomationExtension", true);
Map<String, Object> prefs = new HashMap<String, Object>();
Map<String, Object> langs = new HashMap<String, Object>();
langs.put("no", "en");
prefs.put("translate", "{'enabled' : true}");
prefs.put("translate_whitelists", langs);
option.setExperimentalOption("prefs", prefs);
WebDriver driver = new ChromeDriver(option);
driver.get("https://www.staffers.no/jobbsoker");

How to handle 'Keep' and 'Discard' option while download files in chrome in selenium without AutoIt?

I am using selenium ver. 2.47 and Chrome Ver. 70
I have tried with below code but it didn't worked.
Map<String, Object> prefs = new HashMap<String, Object>();
ChromeOptions options = new ChromeOptions();
options.addArguments("--disable-extensions");
options.addArguments("--safebrowsing-disable-download-protection");
prefs.put("safebrowsing.enabled", "false");
Thanks
Seems you were pretty close. You need to pass the HashMap containing the required configurations to the instance of the ChromeOptions Class as follows:
System.setProperty("webdriver.chrome.driver", "C:/chromedriver/chromedriver.exe");
HashMap<String, Object> chromePrefs = new HashMap<String, Object>();
chromePrefs.put("profile.default_content_settings.popups", 0);
chromePrefs.put("safebrowsing.enabled", "true"); //this is the needed configuration
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("prefs", chromePrefs);
WebDriver driver = new ChromeDriver(options);

With Selenium 3.8.1, Firefox, Chrome, and IE driver capabilities are deprecated.

Can anybody advise how to remove warnings from FirefoxDriver (capabilities) and
ChromeDriver (capabilities)?
FIREFOX
{
#Override
public DesiredCapabilities getDesiredCapabilities ()
{
DesiredCapabilities capabilities = DesiredCapabilities.firefox ();
return capabilities;
}
#Override
public WebDriver getWebDriverObject (DesiredCapabilities capabilities)
{
return new FirefoxDriver (capabilities);
}
},
CHROME_Original
{
#Override
public DesiredCapabilities getDesiredCapabilities ()
{
DesiredCapabilities capabilities = DesiredCapabilities.chrome ();
capabilities.setCapability ("chrome.switches", Arrays.asList ("--no-default-browser-check"));
HashMap<String, String> chromePreferences = new HashMap<String, String> ();
chromePreferences.put ("profile.password_manager_enabled", "false");
capabilities.setCapability ("chrome.prefs", chromePreferences);
return capabilities;
}
#Override
public WebDriver getWebDriverObject (DesiredCapabilities capabilities)
{
return new ChromeDriver (capabilities);
}
},
Try to use the following code:
ChromeOptions options = new ChromeOptions();
options.setCapability("chrome.switches",Arrays.asList("--no-default-browser-check"));
HashMap<String, Boolean>chromePreferences = new HashMap<>();
chromePreferences.put("profile.password_manager_enabled", false);
options.setCapability("chrome.prefs", chromePreferences);
ChromeDriver driver = new ChromeDriver(options);
The ChromeDriver constructor now takes in ChromeOptions object as a parameter
Manipulating DesiredCapabilities directly has been deprecated in favor of type-safe “Options” classes (FirefoxOptions InternetExplorerOptions, etc). This has the advantage of helping you avoid setting incorrect or invalid values for the driver. You get rid of the deprecation warnings by changing your code to use the newer, safer construct.

Chromium/Chrome headless - file download not working?

I downloaded the latest version of chromium, to test out the headless feature.
When I run (as root, because I'm still testing things):
./chrome --no-sandbox http://cp7.awardspace.com/speed-test/awardspace-data1mb.zip
In the GUI terminal, it opens Chromium and downloads the file.
If I'm trying to run it headless, I enter the following:
./chrome --no-sandbox --headless http://cp7.awardspace.com/speed-test/awardspace-data1mb.zip
The terminal outputs some information, no window gets opened, but also: I don't have the file downloaded anywhere.
I have been scouting the internet and discussion groups for more information, but cannot find anything.
Is file downloading not working in headless mode for Chromium?
That's a reported bug in headless implementation:
https://bugs.chromium.org/p/chromium/issues/detail?id=696481
Use ChromeDriverService and POST session/{sessionId}/chromium/send_command
JSON for POST:
{
"cmd": "Page.setDownloadBehavior",
"params": {
"behavior": "allow",
"downloadPath": "C:\\Download\\Path"
}
}
C# Solution
Add reference to System.Net.Http and use NuGet to install Newtonsoft.JSON.
public static IWebDriver Driver { get; private set; }
public void SetDriver()
{
var chromeOptions = new ChromeOptions();
chromeOptions.AddArguments("--headless", "--window-size=1920,1080");
var driverService = ChromeDriverService.CreateDefaultService();
Driver = new ChromeDriver(driverService, chromeOptions);
Task.Run(() => AllowHeadlessDownload(driverService));
}
static async Task AllowHeadlessDownload(ChromeDriverService driverService )
{
var jsonContent = new JObject(
new JProperty("cmd", "Page.setDownloadBehavior"),
new JProperty("params",
new JObject(new JObject(
new JProperty("behavior", "allow"),
new JProperty("downloadPath", #"C:\Download\Path")))));
var content = new StringContent(jsonContent.ToString(), Encoding.UTF8, "application/json");
var sessionIdProperty = typeof(ChromeDriver).GetProperty("SessionId");
var sessionId = sessionIdProperty.GetValue(Driver, null) as SessionId;
using (var client = new HttpClient())
{
client.BaseAddress = driverService.ServiceUrl;
var result = await client.PostAsync("session/" + sessionId.ToString() + "/chromium/send_command", content);
var resultContent = await result.Content.ReadAsStringAsync();
}
}
In Java use following code :
System.setProperty("webdriver.chrome.driver", "/usr/local/bin/chromedriver");
ChromeOptions options = new ChromeOptions();
options.addArguments("--test-type");
options.addArguments("--headless");
options.addArguments("--disable-extensions"); //to disable browser extension popup
ChromeDriverService driverService = ChromeDriverService.createDefaultService();
ChromeDriver driver = new ChromeDriver(driverService, options);
Map<String, Object> commandParams = new HashMap<>();
commandParams.put("cmd", "Page.setDownloadBehavior");
Map<String, String> params = new HashMap<>();
params.put("behavior", "allow");
params.put("downloadPath", "//home//vaibhav//Desktop");
commandParams.put("params", params);
ObjectMapper objectMapper = new ObjectMapper();
HttpClient httpClient = HttpClientBuilder.create().build();
String command = objectMapper.writeValueAsString(commandParams);
String u = driverService.getUrl().toString() + "/session/" + driver.getSessionId() + "/chromium/send_command";
HttpPost request = new HttpPost(u);
request.addHeader("content-type", "application/json");
request.setEntity(new StringEntity(command));
httpClient.execute(request);
driver.get("http://www.seleniumhq.org/download/");
driver.findElement(By.linkText("32 bit Windows IE")).click();
The following code works in C# using ChromeDriver 2.46
private ChromeDriver GetDriver()
{
var options = new ChromeOptions();
options.AddArguments("headless");
options.AddUserProfilePreference("download.prompt_for_download", "false");
options.AddUserProfilePreference("download.directory_upgrade", "true");
options.AddUserProfilePreference("download.prompt_for_download", "false");
options.AddUserProfilePreference("safebrowsing.enabled", "false");
options.AddUserProfilePreference("safebrowsing.disable_download_protection", "true");
options.AddArguments("--disable-web-security");
var curr = Directory.GetCurrentDirectory();
options.AddUserProfilePreference("download.default_directory", curr);
var driver = new ChromeDriver(options);
Log.Info($"Started Chrome Driver with options: {options.ToJsonNoTypes()}");
var param = new Dictionary<string, object>();
param.Add("behavior", "allow");
param.Add("downloadPath", curr);
driver.ExecuteChromeCommand("Page.setDownloadBehavior", param);
return driver;
}
Note: Not exactly answer to the question, but solves the problem
I researched a lot on making headless chrome download with different parameters/options/preferences, but nothing worked. Then I used standard Java way of downloading file using Apache Commons's FileUtils
FileUtils.copyURLToFile(URI, FILE);
I was able to download files with chrome headless thanks to Chrome Remote Interface
public void TryEnableFileDownloading(string downloadPath)
{
TrySendCommand("Page.setDownloadBehavior", new Dictionary<string, object>()
{
["behavior"] = "allow",
["downloadPath"] = downloadPath
});
}
Full code for integration with selenium could be found here
https://github.com/cezarypiatek/Tellurium/blob/master/Src/MvcPages/SeleniumUtils/ChromeRemoteInterface/ChromeRemoteInterface.cs
More info about setDownloadBehavior and Chrome Remote interface
https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-setDownloadBehavior
I tried today in IdeaJ editor, Java and Maven on Windows 10, and it's working fine:
ChromeOptions ds = getDesiredCapabilities(browserName);
ChromeDriverService driverService = ChromeDriverService.createDefaultService();
ChromeDriver driver = new ChromeDriver(driverService, ds);
Map<String, Object> commandParams = new HashMap<>();
commandParams.put("cmd", "Page.setDownloadBehavior");
Map<String, String> params = new HashMap<>();
params.put("behavior", "allow");
params.put("downloadPath", System.getProperty("user.home") + File.separator + "Downloads");
commandParams.put("params", params);
ObjectMapper objectMapper = new ObjectMapper();
HttpClient httpClient = HttpClientBuilder.create().build();
String command = objectMapper.writeValueAsString(commandParams);
String u = driverService.getUrl().toString() + "/session/" + driver.getSessionId() + "/chromium/send_command";
HttpPost request = new HttpPost(u);
request.addHeader("content-type", "application/json");
request.setEntity(new StringEntity(command));
httpClient.execute(request);
User this configured "driver" instance to navigate to download file either by URL or by Json/AngularJs download action.
Also it sometimes behaved to corrupt file while downloading due to internet slowness.
More on this, same configuration will work for both Google Chrome UI or Headless execution in latest chrome driver 77~