Unable to handle download file in Chrome using selenium webdriver - selenium

In the AUT when user clicks on the Excel button then a file should be downloaded.
In the past in other web applications I have handled it using the chrome options as:
But in my current application I see that when user clicks on Excel button then a new tab is open which presents the file explorer pop up. The question here is how to handle this. Even if I switch window handles still I will have the pop up which I don't want. How can I handle this situation.
HashMap<String, Object> chromePrefs = new HashMap<String, Object>();
chromePrefs.put("profile.default_content_settings.popups", 0);
chromePrefs.put("download.default_directory", download_dir);
chromeOptions.setExperimentalOption("prefs", chromePrefs);

This is the (python) code that I've used in the past to download files
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_experimental_option("prefs", {
"download.default_directory": r"C:\Users\xxx\downloads\Test",
"download.prompt_for_download": False,
"download.directory_upgrade": True,
"safebrowsing.enabled": True
})
(obviously this is in python, I can take a stab at making a version for Java or you can try if you like)

I developed a library which is dealing more clearly in such case. You can generate a ChromeOptions object with given download folder and use a one line method call to download a file and verify succession:
private SeleniumDownloadKPI seleniumDownloadKPI;
#BeforeEach
void setUpTest() {
seleniumDownloadKPI =
new SeleniumDownloadKPI("/tmp/downloads");
ChromeOptions chromeOptions =
seleniumDownloadKPI.generateDownloadFolderCapability();
driver = new ChromeDriver(chromeOptions);
}
#Test
void downloadAttachTest() throws InterruptedException {
adamInternetPage.navigateToPage(driver);
seleniumDownloadKPI.fileDownloadKPI(
adamInternetPage.getFileDownloadLink(), "SpeedTest_16MB.dat");
waitBeforeClosingBrowser();
}

Related

Accept microphone and camera permissions on Edge using selenium

I am running selenium scripts on Edge browser. one of the functionality requires to initiate a audio or video call between two windows. In chrome, we can use 'use-fake-ui-for-media-stream' in chrome options. Is there anything similar for Edge. If there isn't, is there a way to accept these alerts at runtime. I have tried -
driver.switchTo().alert().accept(),
but this also doesn't work, and throws error saying no such alert present
Edited
I am using Edge chromium and java selenium and have set properties as below in code. Still permission pop up shows when script runs
Map<String, Object> prefs = new HashMap<String, Object>();
prefs.put("profile.default_content_settings.popups", 0);
prefs.put("download.default_directory", fileDownloadLocation);
EdgeOptions options= new EdgeOptions();
options.setCapability("prefs", prefs);
options.setCapability("allow-file-access-from-files", true);
options.setCapability("use-fake-device-for-media-stream", true);
options.setCapability("use-fake-ui-for-media-stream", true);
DesiredCapabilities capabilities = DesiredCapabilities.edge;
capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS,true);
capabilities.setCapability(CapabilityType.ACCEPT_INSECURE_CERTS,true);
System.setProperty("webdriver.edge.driver", getDriverPath("EDGE"));
driver = new EdgeDriver(options);
driver.manage().window().maximize();
I suggest you make a test with the sample code below. I tried to test with the Edge Chromium browser and it looks like it is not asking the permission popup.
JAVA code:
public static void main(String[] args)
{
System.setProperty("webdriver.edge.driver","\\msedgedriver.exe");
EdgeOptions op=new EdgeOptions();
op.addArguments("use-fake-device-for-media-stream");
op.addArguments("use-fake-ui-for-media-stream");
WebDriver browser = new EdgeDriver(op);
browser.get("https://your_URL_here...");
}
In Selenium 3.141 Version we dont have addArguments() method but in Selenium 4.0.0 alpha version we have addArguments() method
EdgeOptions edgeOpts = new EdgeOptions();
edgeOpts.addArguments("allow-file-access-from-files");
edgeOpts.addArguments("use-fake-device-for-media-stream");
edgeOpts.addArguments("use-fake-ui-for-media-stream");
edgeOpts.addArguments("--disable-features=EnableEphemeralFlashPermission");
driver = new EdgeDriver(edgeOpts);

Keep file with Chromedriver in chrome://downloads

I'm trying to automate the download of an XML file with Google Chrome.
I'm using:
Google Chrome v73.0.3683.75 (64 bits)
Chromedriver v73
Selenium WebDriver v3.14.0
C#
The problem comes up when a message of harmful file appears:
As I'm using Chromedriver, I can not interact with this message, so I tried to accept the download from the chrome://downloads page.
Once I open the chrome://downloads page, I click on the Keep button, but an Alert comes up again to confirm the download.
This popup is not a popup Selenium and Chromedriver can Handle with the Dismiss()/Accept()/SendKeys()/... methods. When I try to SwitchTo() it, Chromedriver crashes.
I tried to directly send the keystrokes of {TAB} and {SPACE}/{RIGHT} and {ENTER}, but Chrome seems not to catch them...
The full code is:
String currentWindow = this.Drivers[Navegador].CurrentWindowHandle;
String popupHandle = "";
((IJavaScriptExecutor)this.Drivers[Navegador]).ExecuteScript("window.open('about:blank','_blank')");
ReadOnlyCollection<String> tabs = this.Drivers[Navegador].WindowHandles;
foreach (string handle in tabs){
if (handle != currentWindow){
popupHandle = handle;
break;
}
}
this.Drivers[Navegador].SwitchTo().Window(popupHandle);
this.Drivers[Navegador].Navigate().GoToUrl("chrome://downloads");
String script = "return document.querySelector('body > downloads-manager').shadowRoot.querySelector('#downloadsList > downloads-item').shadowRoot.querySelector('#dangerous > paper-button:nth-child(2)');";
//String script = "return document.querySelector('body > downloads-manager').shadowRoot.querySelector('#downloadsList > downloads-item:nth-child(2)').shadowRoot.querySelector('#url').textContent;";
IWebElement boton = (IWebElement) ((IJavaScriptExecutor) this.Drivers[Navegador]).ExecuteScript(script);
boton.Click();
Thread.Sleep(2000);
SendKeys.Send("{TAB}{SPACE}");
Thread.Sleep(1000);
this.Drivers[Navegador].Close();
this.Drivers[Navegador].SwitchTo().Window(currentWindow);
this.Drivers[Navegador].SwitchTo().DefaultContent();
result = true;
IMPORTANT NOTE:
I tried to launch Chrome with all the flags/options/experimental_options/user_preferences/... possible and it doesn't work. These options/arguments seem to be deprecated in the latest versions of Chrome or Chromedriver.
As discussed with OP, answering the question in Java.
Encountered the same problem few months back, so this is how it worked for me, might work for you as well.
Map<String, Object> chromePreferences = new Hashtable<String, Object>();
// Below preferences will disable popup dialog while downloading the file
chromePreferences.put("profile.default_content_settings.popups", 0);
chromePreferences.put("download.prompt_for_download", "false");
// Set the customised path for downloading the file, if required
chromePreferences.put("download.default_directory", "path");
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setExperimentalOption("prefs", chromePreferences);
DesiredCapabilities cap = DesiredCapabilities.chrome();
cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
cap.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
//Now initiate ChromeDriver with the capabilities set above and continue with your automation
ChromeDriver chromeDriver = new ChromeDriver(cap);
I recently ran into this issue, and due to the deprecation of some of the methods in the ChromeDriver, the above solution didn't work.
After a lot of research I decided to switch to IE and explore an alternate option with the inspiration from this article - https://sqa.stackexchange.com/questions/3169/downloading-a-file-in-internet-explorer-through-selenium/3520 I came up with this solution in JAVA.
It is not as 'clean' but it worked for me.
public static void main(String[] args) throws NoAlertPresentException,InterruptedException {
System.setProperty("webdriver.ie.driver","C:\\selenium-java-3.141.59\\IEDriverServer.exe");
String url ="myfileurl";
WebDriver driver = new InternetExplorerDriver();
driver.get(url);
try {
Robot robot = new Robot();
Thread.sleep(2000);
//press alt+s key to save
robot.keyPress(KeyEvent.VK_ALT);
robot.keyPress(KeyEvent.VK_S);
robot.keyRelease(KeyEvent.VK_S);
robot.keyRelease(KeyEvent.VK_ALT);
Thread.sleep(2000);
}
catch (AWTException e) {
e.printStackTrace();
}
driver.close();
}

Selenium Disable “Disable Developer Mode Extensions” Popup While adding extension

I want to disable the "Disable Developer Mode Extensions" popup while keeping an extension as mentioned in this post keep "Disable developer mode" closed while adding extension
There was no answer and I'm trying to do the same thing. Is there a chrome option like this available for Selenium?
import pywinauto
window_title = "Disable Developer Mode Extensions"
app = pywinauto.Application().connect(name_re=window_title)
win_ext = app.window(name=window_title)
win_ext.close()
Here is the Answer to your Question:
While working with Selenium 3.4.0, chromedriver v2.30, Google Chrome 59.0 through Java bindings, you can use the ChromeOption class to disable the "Disable Developer Mode Extensions" popup as follows:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
public class Q44959944_dev_extn {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized");
options.addArguments("disable-infobars");
options.addArguments("--disable-extensions");
WebDriver driver = new ChromeDriver(options);
driver.navigate().to("https://google.com");
}
}
Let me know if this Answers your Question.
The solution provided by DebanjanB doesn't work with the latest version of Chrome and Chrome Driver.
To get this to work you need to specify the exclude switches and useAutomationExtension in the prefs flag.
System.setProperty("webdriver.chrome.driver", Constant.BROWSER_CHROME_PATH);
Map prefs = new HashMap<String, Object>();
prefs.put("profile.default_content_setting_values.geolocation", 1); // 1:allow 2:block
prefs.put("useAutomationExtension", false);
prefs.put("excludeSwitches", Collections.singletonList("enable-automation"));
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("-incognito");
chromeOptions.addArguments("--disable-gpu"); // applicable to windows os only
chromeOptions.setExperimentalOption("prefs", prefs);
chromeOptions.addArguments("--no-sandbox");
wDriver = new ChromeDriver(chromeOptions);
((LocationContext)wDriver).setLocation(new Location(37.774929, -122.419416, 0));
wDrivers.put("chrome", wDriver);
log.info("New Chrome Browser Instance Created.");

Is there any egde webdriver documentation about preferences?

I am currently trying to create cross-browser automated tests with Geb but I cannot find any documentation about preferences with Edge. What I am trying to do is to set up my Edge environment to automatically download documents and save them in downloads/edge.
I have done this way for chrome and firefox:
customChrome {
driver = {
System.setProperty("webdriver.chrome.driver", new File ("Drivers/chromedriver_win32/chromedriver.exe").getAbsolutePath())
Map<String, Object> chromePrefs = new HashMap<String, Object>()
chromePrefs.put("download.default_directory", new File("downloads/chrome").getAbsolutePath())
chromePrefs.put("download.prompt_for_download", false)
chromePrefs.put("plugins.always_open_pdf_externally", true)
ChromeOptions opt = new ChromeOptions()
opt.setExperimentalOption("prefs", chromePrefs)
new ChromeDriver(opt)
}
}
customFF {
driver = {
FirefoxProfile myProfile = new FirefoxProfile()
myProfile.setPreference("browser.helperApps.alwaysAsk.force", false)
myProfile.setPreference("browser.download.manager.showWhenStarting", false)
myProfile.setPreference("browser.download.folderList", 2)
myProfile.setPreference("browser.download.dir", new File("downloads/firefox").getAbsolutePath()) // my downloading dir
myProfile.setPreference("services.sync.prefs.sync.browser.download.manager.showWhenStarting", false)
myProfile.setPreference("browser.download.useDownloadDir", true)
myProfile.setPreference("browser.helperApps.neverAsk.saveToDisk", "application/pdf, image/jpeg")
myProfile.setPreference("pdfjs.disabled", true)
System.setProperty("webdriver.gecko.driver", new File("Drivers/GeckoDriver/geckodriver.exe").getAbsolutePath())
new FirefoxDriver(myProfile)
}
}
I used this source file to get chrome's prefs and this webpage for getting those of firefox but I cannot find anything similar for Edge. Does Microsoft provides any info about this ?
Please share any info you may have.
I'm not sure if things have changed since, but according to this answer
IE doesn't use profiles and is therefore unable to download files to a specific location.

How do I enable geolocation support in chromedriver?

I need to test a JS geolocation functionality with Selenium and I am using chromedriver to run the test on the latest Chrome.
The problem is now that Chrome prompts me to enable Geolocation during the test and that I don't know how to click that little bar on runtime, so I am desperately looking for a way to start the chromedriver and chrome with some option or trigger to enable this by default. All I could find here was however how I can disable geolocation altogether.
How can I solve this issue?
In the known issues section of the chromedriver wiki they said that you Cannot specify a custom profile
This is why it seems to me that #Sotomajor answer about using profile with Chrome as you would do with firefox will not work.
In one of my integration tests I faced the same issue. But because I was not bothering about the real geolocation values, all I had to do is to mock window.navigator.gelocation
In you java test code put this workaround to avoid Chrome geoloc permission info bar.
chromeDriver.executeScript("window.navigator.geolocation.getCurrentPosition = function(success) {
var position = {
"coords": {
"latitude": "555",
"longitude": "999"
}
};
success(position);
}");
latitude (555) and longitude (999) values here are just test value
Approach which worked for me in Firefox was to visit that site manually first, give those permissions and afterwards copy firefox profile somewhere outside and create selenium firefox instance with that profile.
So:
cp -r ~/Library/Application\ Support/Firefox/Profiles/tp3khne7.default /tmp/ff.profile
Creating FF instance:
FirefoxProfile firefoxProfile = new FirefoxProfile(new File("/tmp/ff.profile"));
FirefoxDriver driver = new FirefoxDriver(firefoxProfile);
I'm pretty sure that something similar should be applicable to Chrome. Although api of profile loading is a bit different. You can check it here: http://code.google.com/p/selenium/wiki/ChromeDriver
Here is how I did it with capybara for cucumber tests
Capybara.register_driver :selenium2 do |app|
profile = Selenium::WebDriver::Chrome::Profile.new
profile['geolocation.default_content_setting'] = 1
config = { :browser => :chrome, :profile => profile }
Capybara::Selenium::Driver.new(app, config)
end
And there is link to other usefull profile settings: pref_names.cc
Take a look at "Tweaking profile preferences" in RubyBindings
As for your initial question:
You should start Firefox manually once - and select the profile you use for Selenium.
Type about:permissions in the address line; find the name of your host - and select share location : "allow".
That's all. Now your Selenium test cases will not see that dreaded browser dialog which is not in the DOM.
I took your method but it can not working. I did not find "BaseUrls.Root.AbsoluteUri" in Chrome's Preferences config. And use a script for test
chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument("proxy-server=http://127.0.0.1:1087")
prefs = {
'profile.default_content_setting_values':
{
'notifications': 1,
'geolocation': 1
},
'devtools.preferences': {
'emulation.geolocationOverride': "\"11.111698#-122.222954:\"",
},
'profile.content_settings.exceptions.geolocation':{
'BaseUrls.Root.AbsoluteUri': {
'last_modified': '13160237885099795',
'setting': '1'
}
},
'profile.geolocation.default_content_setting': 1
}
chromeOptions.add_experimental_option('prefs', prefs)
chromedriver_path = os.path.join(BASE_PATH, 'utils/driver/chromedriver')
log_path = os.path.join(BASE_PATH, 'utils/driver/test.log')
self.driver = webdriver.Chrome(executable_path=chromedriver_path, chrome_options=chromeOptions, service_log_path=log_path)
We just found a different approach that allows us to enable geolocation on chrome (currently 65.0.3325.181 (Build officiel) (64 bits)) without mocking the native javascript function.
The idea is to authorize the current site (represented by BaseUrls.Root.AbsoluteUri) to access to geolocation information.
public static void UseChromeDriver(string lang = null)
{
var options = new ChromeOptions();
options.AddArguments(
"--disable-plugins",
"--no-experiments",
"--disk-cache-dir=null");
var geolocationPref = new JObject(
new JProperty(
BaseUrls.Root.AbsoluteUri,
new JObject(
new JProperty("last_modified", "13160237885099795"),
new JProperty("setting", "1")
)
)
);
options.AddUserProfilePreference(
"content_settings.exceptions.geolocation",
geolocationPref);
WebDriver = UseDriver<ChromeDriver>(options);
}
private static TWebDriver UseDriver<TWebDriver>(DriverOptions aDriverOptions)
where TWebDriver : RemoteWebDriver
{
Guard.RequiresNotNull(aDriverOptions, nameof(UITestsContext), nameof(aDriverOptions));
var webDriver = (TWebDriver)Activator.CreateInstance(typeof(TWebDriver), aDriverOptions);
Guard.EnsuresNotNull(webDriver, nameof(UITestsContext), nameof(WebDriver));
webDriver.Manage().Window.Maximize();
webDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
webDriver.NavigateToHome();
return webDriver;
}
ChromeOptions options = new ChromeOptions();
HashMap<String, Integer> contentSettings = new HashMap<String, Integer>();
HashMap<String, Object> profile = new HashMap<String, Object>();
HashMap<String, Object> prefs = new HashMap<String, Object>();
contentSettings.put("geolocation", 1);
contentSettings.put("notifications", 2);
profile.put("managed_default_content_settings", contentSettings);
prefs.put("profile", profile);
options.setExperimentalOption("prefs", prefs);
The simplest to set geoLocation is to just naviaget on that url and click on allow location by selenium. Here is the code for refrence
driver.navigate().to("chrome://settings/content");
driver.switchTo().frame("settings");
WebElement location= driver.findElement(By.xpath("//*[#name='location' and #value='allow']"));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
((JavascriptExecutor) driver).executeScript("arguments[0].click();", location);
WebElement done= driver.findElement(By.xpath(""));
driver.findElement(By.xpath("//*[#id='content-settings-overlay-confirm']")).click();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
driver.navigate().to("url");
Cypress:
I encountered with same problem but mocking was not worked for me.
My case:
Application use geo location for the login purpose. So with mock it not worked for me.
Solution:
I used below package and followed the steps and its works for me.
https://www.npmjs.com/package/cypress-visit-with-custom-geolocation
Working sample example:
https://github.com/gaikwadamolraj/cypress-visit-with-custom-geolocation