How to disable SmartScreen (safebrowsing in edge) on C# Selenium Edge Chromium? - selenium

I'm trying to run some selenium C# end-to-end tests on Edge Chromium browser. One of the tests does a download check, basically it downloads a xml file and check whether it exists in the downloaded location.
I'm using Microsoft.Edge.SeleniumTools EdgeOptions to construct options for the EdgeDriver.
But the issue right now is that Edge blocks downloads.
Tried different sorts of things but none of them worked.
Same issue can be solved on Chrome by disabling "safebrowsing" on UserProfilePreferences in ChromeOptions.
I know for a fact that SmartScreen does the blocking, if that is so is there any profile preference that I can use to disable SmartScreen ?
Or any other workaround to force download without the block would be very helpful.

For testing purposes, I suggest you create HashMap objects and try to set Edge preferences like below.
static void Main(string[] args)
{
HashMap<String, Object> edgePrefs = new HashMap<String, Object>();
edgePrefs.put("profile.default_content_settings.popups", 0);
edgePrefs.put("profile.default_content_setting_values.notifications", 2);
edgePrefs.put("profile.default_content_setting_values.automatic_downloads" , 1);
edgePrefs.put("profile.content_settings.pattern_pairs.*,*.multiple-automatic-downloads",1);
var options = new EdgeOptions();
egdeOptions.setExperimentalOption("prefs",edgePrefs);
options.UseChromium = true;
options.BinaryLocation = #"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"; // Here add the Edge browser exe path.
var driver = new EdgeDriver(#"Edge_driver_path_here...", options); // Here modify the selenium web driver path.
driver.Navigate().GoToUrl("http://website_URL_here...");
driver.FindElementById("lnk1").Click();
}
If the issue persists then I suggest you set the default download directory like below.
options.AddUserProfilePreference("download.default_directory", #"D://Folder1");
See whether it help to download the file.

I was trying to find the answer with the usage of W3C WebDriver Protocol, but it seems like the only possible way is to turn off XML Edge SmartScreen policies using Windows Registry:
public void SetEdgeXmlDownloadPolicy()
{
var keyName = #"HKEY_CURRENT_USER\Software\Policies\Microsoft\Edge\ExemptDomainFileTypePairsFromFileTypeDownloadWarnings";
var valueName = "AllowXmlDownload";
var valueData = #"{""domains"": ["" * ""], ""file_extension"": ""xml""}";
var currentValue = Registry.GetValue(keyName, valueName, string.Empty).ToString();
if (currentValue == string.Empty || !currentValue.Contains("xml"))
Registry.SetValue(keyName, valueName, valueData, RegistryValueKind.String);
}
Credits to this workaround goes to IndianCodeMaster

Related

Additional chrome options for headless mode with Kameleo

Been testing the Kameleo.LocalApiClient now whole day. Noticed something strange.
var client = new KameleoLocalApiClient(new Uri(KameleoBaseUrl));
client.SetRetryPolicy(null);
// Search Chrome Base Profiles
var baseProfileList = await client.SearchBaseProfilesAsync("desktop", "windows", "chrome", "ru-ru");
Random rnd = new Random();
var baseId = rnd.Next(1, baseProfileList.Count);
// Create a new profile with recommended settings
// Choose one of the Firefox BaseProfiles
// You can set your proxy up in the setProxy method
var requestBody = BuilderForCreateProfile
.ForBaseProfile(baseProfileList[baseId].Id)
.SetRecommendedDefaults()
.SetProxy("http", new Server("zproxy.lum-superproxy.io", 22225, "lum-customer-joshua901-zone-zone2", "5inhblkgrzxj"))
//.SetProxy("http", new Server("zproxy.lum-superproxy.io", 22225, "lum-customer-joshua901-zone-russiashared-ip-181.214.180.215", "lqoz0ee2hbvb"))
.SetLauncher("chrome")
//.SetScreen("--window-size", 500, 783)
.Build();
var profile = await client.CreateProfileAsync(requestBody);
// Start the browser
await client.StartProfileAsync(profile.Id);
// Connect to the running browser instance using WebDriver
var uri = new Uri($"{KameleoBaseUrl}/webdriver");
var opts = new ChromeOptions();
opts.AddAdditionalOption("kameleo:profileId", profile.Id.ToString());
opts.AddExcludedArgument("enable-automation");
opts.AddArgument("--window-size=500,783");
opts.AddArgument("disable-infobars");
opts.AddArgument("--incongito");
opts.AddArgument("--disable-extensions");
opts.AddArgument("disable-gpu");
opts.AddArgument("headless");
opts.AddArgument("--ignore-certificate-errors");
opts.AddArgument("no-sandbox");
opts.AddArgument("--silent-launch");
opts.AddArgument("--no-startup-window");
//var webdriver = new RemoteWebDriver(uri, opts);
_driver = new RemoteWebDriver(uri, opts)
I want to add my additional ChromeOptions to my driver, especially be able to run things in "headless" mode.
Even if i define the ChromeOptions above and create the RemoteWebDriver with these options, the chrome browser does still popup and not run as headless.
How come and how do i add my additional options?
The browser is started by Kameleo
The RemoteWebDriver is not starting any browser, just connecting to the already started browser
Because of these, you cannot pass any arguments to the browser with the RemoteWebDriver's options.
There is way to provide additional web driver options. There is a POST /profiles/{guid}/start endpoint which can process additional arguments, options, and preferences when Kameleo is starting the browser. See the documentation or see the example code.
await client.StartProfileWithWebDriverSettingsAsync(profile.Id, new WebDriverSettings
{
Arguments = new List<string> { "mute-audio" },
Preferences = new List<Preference>
{
new Preference("profile.managed_default_content_settings.images", 2),
new Preference("profile.password_manager_enabled.images", 2),
},
AdditionalOptions = new List<Preference>
{
new Preference("pageLoadStrategy", "eager"),
}
});
There are arguments that are not supported and that may cause issues so it is better to contact the team about the arguments.
For example:
opts.AddArgument("--disable-extensions");
This cannot be added, since Kameleo's extension is needed in the browser. If you remove it, the spoofing won't work.
I see you want to use this flag as well:
opts.AddArgument("disable-gpu");
You can simply set WebGL to Block. IT will result in the same.
Currently, there is no opportunity to start the browser in headless mode. But there will be a solution soon.

How to run Selenium test using Edge headless

Some time ago, I wrote some Selenium unit tests and these used the Firefox browser (headless). After a few years, I have returned to these (and cannot now remember how they worked) and would like to update them to use the Edge browser (in headless mode). How do I do this ? Specifically, when I ask the IWebDriver to "Navigate", how does it know the root URL - specifically the port ? I presume that my URL would be "http://localhost:nnnn/blah...", but how do I determine the port (which I also presume I need) ?
My code is based upon the following:
protected IWebDriver GetBrowserEdge(bool headless = true)
{
var service = SeleniumTools.EdgeDriverService.CreateChromiumService();
service.UseVerboseLogging = true;
var options = new SeleniumTools.EdgeOptions { PageLoadStrategy = PageLoadStrategy.Normal, UseChromium = true };
if (headless) options.AddArgument("headless");
return new SeleniumTools.EdgeDriver(service, options);
}
I wasn't using "CreateChromiumService" before (and I note it is disposable - which gives me a design issue), but I note that the service it returns has a "port" property. Do I need to leverage that in my "IWebDriver.Navigate" calls ?
I am using Edge v92.0.902.73 and Microsoft.Edge.SeleniumTools v3.141.2

How to understand if credentials are valid or not using selenium

I created an app that lets users login through my app to Wikipedia, and I achieved this goal with selenium, but I can't find a way to verify either credentials are ok or not.
I tried find by id but since failed condition doesn't display an ID it's not helping.
private void button1_Click(object sender, EventArgs e)
{
string BaseUrl = "https://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Main+Page";
int TimeOut = 30;
var driver = new FirefoxDriver();
driver.Navigate().GoToUrl(BaseUrl);
var loginBox = driver.FindElement(By.Id("wpName1"));
loginBox.SendKeys("email.address#gmail.com");
var pwBox = driver.FindElement(By.Id("wpPassword1"));
pwBox.SendKeys("!SuperSecretpassw0rd");
I would like to know if entered credentials are correct or not.
A general approach to this kind of question is to ask yourself, "How can a human see this?" and then replicate this behavior in your test. In your example, how would a human detect that the login is wrong?
A human would see the error message.
Selenium on the other hand only sees the DOM tree. So for Selenium to see the error message, you need to find out where to look in the DOM tree. To do this, open your browser developer tools and find the matching section in the DOM tree:
With this in mind, a very simple solution is to find the error div that is shown when the credentials are invalid.
var error = driver.findElement(By.className("error"));
Then you can check if the element actually exists and you can use additional Selenium methods to inspect the actual contents of the error message, to see what the error is. If the field is not present then you could assume that the login succeeded. In addition you can use driver.getCurrentUrl() to inspect whether you are still located on the login page, to confirm that you are really logged in.
That being said, if you try to do any serious browser testing you should consider using the page object model (see https://www.toolsqa.com/selenium-webdriver/page-object-model/) so you don't end up with an unmaintainable mess of test cases.
As you havn't mentioned the language binding this solution is based on Java.
An elegant approach to validate whether the credentials are valid or not would be to induce a try-catch{} block to look for the element with the error inducing WebDriverWait for the desired visibilityOfElementLocated() and you can use the following Locator Strategies:
Code Block:
public class A_demo
{
public static void main(String[] args) throws Exception
{
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized");
options.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation"));
options.setExperimentalOption("useAutomationExtension", false);
WebDriver driver = new ChromeDriver(options);
driver.get("https://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Main+Page");
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("input[name='wpName']"))).sendKeys("Helios.Lucifer#stackoverflow.com");
driver.findElement(By.cssSelector("input[name='wpPassword']")).sendKeys("!SuperSecretpassw0rd");
driver.findElement(By.cssSelector("button#wpLoginAttempt")).click();
try
{
new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("form[name='userlogin']>div.error>p")));
System.out.println("Unsuccessful login attempt");
}
catch (TimeoutException e)
{
System.out.println("Successful Login.");
}
driver.quit();
}
}
Console Output;
Unsuccessful login attempt

selenium proxy configuration multiple times in same browser

I opened a browser(any) with selenium tool and applying proxy to that browser by this below posted code, below is for Firefox
//LINE 1 FirefoxProfile profile = new FirefoxProfile();
//LINE 2 profile.setPreference("network.proxy.http", configuration
.getProxyConfiguration().getHostname());
//LINE 3 profile.setPreference("network.proxy.http_port", configuration
.getProxyConfiguration().getPort());
//LINE 4 profile.setPreference("network.proxy.type", configuration
.getProxyConfiguration().getType().toInt());
//LINE 5 return new FirefoxDriver(profile);
Now, I want to apply another proxy configuration for the same browser(Because, If I use another browser, session will be get change, So.... I want to apply my changes to that browser itself). How to apply my proxy configuration to the same browser. When I use same code I've to return driver which uses "NEW". I showed in my code(//LINE 5). Please help me to solve this issue.
Thanks:
Ramakrishna K.C
You can create Proxy with Kind = ProxyKind.System
new Proxy { Kind = ProxyKind.System};
Then update the internet settings in the registry
var proxyServer = string.Format("http={0};https={0}", ipAddressAndPort);
var proxyEnable = enableProxy ? 1 : 0;
const string subKeyPath = #"Software\Microsoft\Windows\CurrentVersion\Internet Settings";
using (var subKey = Registry.CurrentUser.CreateSubKey(subKeyPath))
{
if (subKey == null)
{
throw new Exception(string.Format("Failed to create or open subKey. SubKeyPath: {0} ", subKeyPath));
}
subKey.SetValue("ProxyServer", proxyServer, RegistryValueKind.String);
subKey.SetValue("ProxyEnable", proxyEnable, RegistryValueKind.DWord);
}
otherwise use PAC file in firefox profile.
http://findproxyforurl.com/

How can I get the WebDriver version during Testrun?

I am writing on a testframework where the report should include the webdriver version of the test run. When using selenium there is the getEval("Selenium.version") method. But I find no way to read the version when using webdriver. Does anyone know a solution?
It's possible by reading the VERSION.txt properties file. This seems hacky, but it's what the WebDriver developers do in SeleniumServer.java:
final Properties p = new Properties();
p.load(getSeleniumResourceAsStream("/VERSION.txt"));
String rcVersion = p.getProperty("selenium.rc.version");
String rcRevision = p.getProperty("selenium.rc.revision");
String coreVersion = p.getProperty("selenium.core.version");
String coreRevision = p.getProperty("selenium.core.revision");
BuildInfo info = new BuildInfo();
String versionString = String.format("v%s%s, with Core v%s%s. Built from revision %s",
rcVersion, rcRevision, coreVersion, coreRevision, info.getBuildRevision());
Note that this requires a static import:
import static org.openqa.selenium.browserlaunchers.LauncherUtils.getSeleniumResourceAsStream;
Actual path to file with version in selenium is:
/META-INF/maven/org.seleniumhq.selenium/selenium-java/pom.properties
Properties p = new Properties();
p.load(LauncherUtils.class.getResourceAsStream("/META-INF/maven/org.seleniumhq.selenium/selenium-java/pom.properties"));
p.getProperty("version");`