C# Selenium Firefox Driver set navigator.webdriver = false [duplicate] - c#

I'm trying to automate a very basic task in a website using selenium and chrome but somehow the website detects when chrome is driven by selenium and blocks every request. I suspect that the website is relying on an exposed DOM variable like this one https://stackoverflow.com/a/41904453/648236 to detect selenium driven browser.
My question is, is there a way I can make the navigator.webdriver flag false? I am willing to go so far as to try and recompile the selenium source after making modifications, but I cannot seem to find the NavigatorAutomationInformation source anywhere in the repository https://github.com/SeleniumHQ/selenium
Any help is much appreciated
P.S: I also tried the following from https://w3c.github.io/webdriver/#interface
Object.defineProperty(navigator, 'webdriver', {
get: () => false,
});
But it only updates the property after the initial page load. I think the site detects the variable before my script is executed.

First the update 1
execute_cdp_cmd(): With the availability of execute_cdp_cmd(cmd, cmd_args) command now you can easily execute google-chrome-devtools commands using Selenium. Using this feature you can modify the navigator.webdriver easily to prevent Selenium from getting detected.
Preventing Detection 2
To prevent Selenium driven WebDriver getting detected a niche approach would include either / all of the below mentioned steps:
Adding the argument --disable-blink-features=AutomationControlled
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument('--disable-blink-features=AutomationControlled')
driver = webdriver.Chrome(options=options, executable_path=r'C:\WebDrivers\chromedriver.exe')
driver.get("https://www.website.com")
You can find a relevant detailed discussion in Selenium can't open a second page
Rotating the user-agent through execute_cdp_cmd() command as follows:
#Setting up Chrome/83.0.4103.53 as useragent
driver.execute_cdp_cmd('Network.setUserAgentOverride', {"userAgent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.53 Safari/537.36'})
Change the property value of the navigator for webdriver to undefined
driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
Exclude the collection of enable-automation switches
options.add_experimental_option("excludeSwitches", ["enable-automation"])
Turn-off useAutomationExtension
options.add_experimental_option('useAutomationExtension', False)
Sample Code 3
Clubbing up all the steps mentioned above and effective code block will be:
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=options, executable_path=r'C:\WebDrivers\chromedriver.exe')
driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
driver.execute_cdp_cmd('Network.setUserAgentOverride', {"userAgent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.53 Safari/537.36'})
print(driver.execute_script("return navigator.userAgent;"))
driver.get('https://www.httpbin.org/headers')
History
As per the W3C Editor's Draft the current implementation strictly mentions:
The webdriver-active flag is set to true when the user agent is under remote control which is initially set to false.
Further,
Navigator includes NavigatorAutomationInformation;
It is to be noted that:
The NavigatorAutomationInformation interface should not be exposed on WorkerNavigator.
The NavigatorAutomationInformation interface is defined as:
interface mixin NavigatorAutomationInformation {
readonly attribute boolean webdriver;
};
which returns true if webdriver-active flag is set, false otherwise.
Finally, the navigator.webdriver defines a standard way for co-operating user agents to inform the document that it is controlled by WebDriver, so that alternate code paths can be triggered during automation.
Caution: Altering/tweaking the above mentioned parameters may block the navigation and get the WebDriver instance detected.
Update (6-Nov-2019)
As of the current implementation an ideal way to access a web page without getting detected would be to use the ChromeOptions() class to add a couple of arguments to:
Exclude the collection of enable-automation switches
Turn-off useAutomationExtension
through an instance of ChromeOptions as follows:
Java Example:
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation"));
options.setExperimentalOption("useAutomationExtension", false);
WebDriver driver = new ChromeDriver(options);
driver.get("https://www.google.com/");
Python Example
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=options, executable_path=r'C:\path\to\chromedriver.exe')
driver.get("https://www.google.com/")
Ruby Example
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument("--disable-blink-features=AutomationControlled")
driver = Selenium::WebDriver.for :chrome, options: options
Legends
1: Applies to Selenium's Python clients only.
2: Applies to Selenium's Python clients only.
3: Applies to Selenium's Python clients only.

ChromeDriver:
Finally discovered the simple solution for this with a simple flag! :)
--disable-blink-features=AutomationControlled
navigator.webdriver=true will no longer show up with that flag set.
For a list of things you can disable, check them out here

Do not use cdp command to change webdriver value as it will lead to inconsistency which later can be used to detect webdriver. Use the below code, this will remove any traces of webdriver.
options.add_argument("--disable-blink-features")
options.add_argument("--disable-blink-features=AutomationControlled")

Before (in browser console window):
> navigator.webdriver
true
Change (in selenium):
// C#
var options = new ChromeOptions();
options.AddExcludedArguments(new List<string>() { "enable-automation" });
// Python
options.add_experimental_option("excludeSwitches", ['enable-automation'])
After (in browser console window):
> navigator.webdriver
undefined
This will not work for version ChromeDriver 79.0.3945.16 and above. See the release notes here

To exclude the collection of enable-automation switches as mentioned in the 6-Nov-2019 update of the top voted answer doesn't work anymore as of April 2020. Instead I was getting the following error:
ERROR:broker_win.cc(55)] Error reading broker pipe: The pipe has been ended. (0x6D)
Here's what's working as of 6th April 2020 with Chrome 80.
Before (in the Chrome console window):
> navigator.webdriver
true
Python example:
options = webdriver.ChromeOptions()
options.add_argument("--disable-blink-features")
options.add_argument("--disable-blink-features=AutomationControlled")
After (in the Chrome console window):
> navigator.webdriver
undefined

Nowadays you can accomplish this with cdp command:
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
driver.get(some_url)
by the way, you want to return undefined, false is a dead giveaway.

Finally this solved the problem for ChromeDriver, Chrome greater than v79.
ChromeOptions options = new ChromeOptions();
options.addArguments("--disable-blink-features");
options.addArguments("--disable-blink-features=AutomationControlled");
ChromeDriver driver = new ChromeDriver(options);
Map<String, Object> params = new HashMap<String, Object>();
params.put("source", "Object.defineProperty(navigator, 'webdriver', { get: () => undefined })");
driver.executeCdpCommand("Page.addScriptToEvaluateOnNewDocument", params);

Since this question is related to selenium a cross-browser solution to overriding navigator.webdriver is useful. This could be done by patching browser environment before any JS of target page runs, but unfortunately no other browsers except chromium allows one to evaluate arbitrary JavaScript code after document load and before any other JS runs (firefox is close with Remote Protocol).
Before patching we needed to check how the default browser environment looks like. Before changing a property we can see it's default definition with Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor(navigator, 'webdriver');
// undefined
So with this quick test we can see webdriver property is not defined in navigator. It's actually defined in Navigator.prototype:
Object.getOwnPropertyDescriptor(Navigator.prototype, 'webdriver');
// {set: undefined, enumerable: true, configurable: true, get: ƒ}
It's highly important to change the property on the object that owns it, otherwise the following can happen:
navigator.webdriver; // true if webdriver controlled, false otherwise
// this lazy patch is commonly found on the internet, it does not even set the right value
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
navigator.webdriver; // undefined
Object.getOwnPropertyDescriptor(Navigator.prototype, 'webdriver').get.apply(navigator);
// true
A less naive patch would first target the right object and use right property definition, but digging deeper we can find more inconsistences:
const defaultGetter = Object.getOwnPropertyDescriptor(Navigator.prototype, 'webdriver').get;
defaultGetter.toString();
// "function get webdriver() { [native code] }"
Object.defineProperty(Navigator.prototype, 'webdriver', {
set: undefined,
enumerable: true,
configurable: true,
get: () => false
});
const patchedGetter = Object.getOwnPropertyDescriptor(Navigator.prototype, 'webdriver').get;
patchedGetter.toString();
// "() => false"
A perfect patch leaves no traces, instead of replacing getter function it would be good if we could just intercept the call to it and change the returned value. JavaScript has native support for that throught Proxy apply handler:
const defaultGetter = Object.getOwnPropertyDescriptor(Navigator.prototype, 'webdriver').get;
defaultGetter.apply(navigator); // true
defaultGetter.toString();
// "function get webdriver() { [native code] }"
Object.defineProperty(Navigator.prototype, 'webdriver', {
set: undefined,
enumerable: true,
configurable: true,
get: new Proxy(defaultGetter, { apply: (target, thisArg, args) => {
// emulate getter call validation
Reflect.apply(target, thisArg, args);
return false;
}})
});
const patchedGetter = Object.getOwnPropertyDescriptor(Navigator.prototype, 'webdriver').get;
patchedGetter.apply(navigator); // false
patchedGetter.toString();
// "function () { [native code] }"
The only inconsistence now is in the function name, unfortunately there is no way to override the function name shown in native toString() representation. But even so it can pass generic regular expressions that searches for spoofed browser native functions by looking for { [native code] } at the end of its string representation. To remove this inconsistence you can patch Function.prototype.toString and make it return valid native string representations for all native functions you patched.
To sum up, in selenium it could be applied with:
chrome.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': """
Object.defineProperty(Navigator.prototype, 'webdriver', {
set: undefined,
enumerable: true,
configurable: true,
get: new Proxy(
Object.getOwnPropertyDescriptor(Navigator.prototype, 'webdriver').get,
{ apply: (target, thisArg, args) => {
// emulate getter call validation
Reflect.apply(target, thisArg, args);
return false;
}}
)
});
"""})
The playwright project maintains a fork of Firefox and WebKit to add features for browser automation, one of them is equivalent to Page.addScriptToEvaluateOnNewDocument, but there is no implementation for Python of the communication protocol but it could be implemented from scratch.

Simple hack for python:
options = webdriver.ChromeOptions()
options.add_argument("--disable-blink-features=AutomationControlled")

As mentioned in the above comment - https://stackoverflow.com/a/60403652/2923098 the following option totally worked for me (in Java)-
ChromeOptions options = new ChromeOptions();
options.addArguments("--incognito", "--disable-blink-features=AutomationControlled");

I would like to add a Java alternative to the cdp command method mentioned by pguardiario
Map<String, Object> params = new HashMap<String, Object>();
params.put("source", "Object.defineProperty(navigator, 'webdriver', { get: () => undefined })");
driver.executeCdpCommand("Page.addScriptToEvaluateOnNewDocument", params);
In order for this to work you need to use the ChromiumDriver from the org.openqa.selenium.chromium.ChromiumDriver package. From what I can tell that package is not included in Selenium 3.141.59 so I used the Selenium 4 alpha.
Also, the excludeSwitches/useAutomationExtension experimental options do not seem to work for me anymore with ChromeDriver 79 and Chrome 79.

For those of you who've tried these tricks, please make sure to also check that the user-agent that you are using is the user agent that corresponds to the platform (mobile / desktop / tablet) your crawler is meant to emulate. It took me a while to realize that was my Achilles heel ;)

Python
I tried most of the stuff mentioned in this post and i was still facing issues.
What saved me for now is https://pypi.org/project/undetected-chromedriver
pip install undetected-chromedriver
import undetected_chromedriver.v2 as uc
from time import sleep
from random import randint
driver = uc.Chrome()
driver.get('www.your_url.here')
driver.maximize_window()
sleep(randint(3,9))
A bit slow but i will take slow over non working.
I guess if every interested could go over the source code and see what provides the win there.

If you use a Remote Webdriver , the code below will set navigator.webdriver to undefined.
work for ChromeDriver 81.0.4044.122
Python example:
options = webdriver.ChromeOptions()
# options.add_argument("--headless")
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
driver = webdriver.Remote(
'localhost:9515', desired_capabilities=options.to_capabilities())
script = '''
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
'''
driver.execute_script(script)

Use --disable-blink-features=AutomationControlled to disable navigator.webdriver

Related

Selenium geckodriver executes findElement 10 times slower than chromedriver (.Net)

Sorry didn't find a similar question and maybe somebody can help.
Due to additional requirements we have to test our project not only with Chrome but with Firefox as well. When we simply changed a test context to Firefox it turned out that all calls of findElement took 10 times more time than with Chrome. All tests are completely ruined. We tried to use different test machines but the results are the same. The project is on Core .Net. For testing we use MSTest V2, Firefox 63 (64 bit) and Geckodriver 0.22 (64 bit) .
Very appreciate any help.
By referring to the previous answer, my issue was solved by below code.
string geckoDriverDirectory = "Path of geckodriver.exe"
FirefoxDriverService geckoService =
FirefoxDriverService.CreateDefaultService(geckoDriverDirectory);
geckoService.Host = "::1";
var firefoxOptions = new FirefoxOptions();
firefoxOptions.AcceptInsecureCertificates = true;
Driver = new FirefoxDriver(geckoService, firefoxOptions);
Yep. You’re definitely hitting the performance issue that is part of .NET Core. It doesn’t happen on Chrome, IE, or Edge, because the driver executables for each of those browsers (unlike geckodriver) listen on both the IPv4 and IPv6 loopback addresses. If you were to specify “::1” as the host for geckodriver with .NET, the problem would disappear.
Refer to https://github.com/SeleniumHQ/selenium/issues/6597
A complete .Net Core webdriver for Firefox 7/14/2020:
// .Net Core workaround #1: Slow Firefox webdriver
string projectFolder = Directory.GetParent(Directory.GetCurrentDirectory()).FullName;
string geckoDriverDirectory = projectFolder + "\\netcoreapp3.1\\";
FirefoxDriverService geckoService =
FirefoxDriverService.CreateDefaultService(geckoDriverDirectory);
geckoService.Host = "::1";
var ffOptions = new FirefoxOptions();
ffOptions.BrowserExecutableLocation = #"C:\Program Files\Mozilla Firefox\Firefox.exe";
ffOptions.AcceptInsecureCertificates = true;
// This profile will by-pass *ALL* credentials. Note that Chrome uses Internet Explorer settings, so it does not need this.
// You must pre-setup the profile, by launching Firefox and doing phone authentication
// The profile's location is: C:\Users\<windows logon>\AppData\Local\Mozilla\Firefox\Profiles
// Without this, if your AUT uses SSO, you will always get prompted for the PIN or Two factor authentication
FirefoxProfile profile = new FirefoxProfileManager().GetProfile("Selenium");
ffOptions.Profile = profile;
// DotNet Core workaround #2- Code page
// https://stackoverflow.com/questions/56802715/firefoxwebdriver-no-data-is-available-for-encoding-437
// https://stackoverflow.com/questions/50858209/system-notsupportedexception-no-data-is-available-for-encoding-1252
CodePagesEncodingProvider.Instance.GetEncoding(437);
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
_driver = new FirefoxDriver(geckoService, ffOptions);
In case anyone is trying gary.zhang's answer in Javascript, it looks like this:
let driver = new Builder()
.forBrowser('firefox')
.setFirefoxService(new firefox.ServiceBuilder('path_to_driver', host='::1'))
.setFirefoxOptions(new firefox.Options().headless())
.build();
Took me a bit of staring at it to figure out how to convert the syntax.

With DesiredCapabilities deprecated, how will I use SetCapability in selenium webdriver C #?

With DesiredCapabilities deprecated, how will I use SetCapability in selenium webdriver C #?
Can I use it this way?
capacidades = new ChromeOptions();
capacidades.AddAdditionalCapability(#"browserName", #"chrome");
Instead of DesiredCapabilities, you should be using a browser-specific “Options” class, just as shown in your example. However, you can only call AddAdditionalCapability for capability names that do not already have a type-safe property or method to set the capability value. In the case of the browserName capability, there is already a BrowserName property to access the value of that capability. The runtime exception you receive should have the name of the property or method to use in place of manually setting the capability with that name, but I believe there is a bug that does not properly format the exception message.
Note, however, that the BrowserName property is read-only, because since you’re using ChromeOptions, the bindings already know the browser name should be “chrome”.
Adding a simple example to the answer from JimEvans.
Simple Example to disable chrome info bars:
private IWebDriver GetChromeDriver()
{
var outPutDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
//Disable chrome info bar in order to prevent "Chrome is being run by automation software."
var chromeOption = new ChromeOptions();
chromeOption.AddArguments("disable-infobars");
return new ChromeDriver(outPutDirectory, chromeOption);
}

How to get Selenium to operate two browser windows using only one driver selenium (using c# and chromedriver)?

I am attempting to control two browser windows via selenium using c# and a single chromedriver. The reason being that I need to share session details accross browser windows.
The code that I have tried and failed with is below;
var options = new ChromeOptions();
options.AddArguments("chrome.switches", "--disable-extensions --disable-extensions-file-access-check --disable-extensions-http-throttling --disable-infobars --enable-automation ");
options.AddUserProfilePreference("credentials_enable_service", false);
options.AddUserProfilePreference("profile.password_manager_enabled", false);
options.PageLoadStrategy = PageLoadStrategy.Default;
ChromeDriverService service = ChromeDriverService.CreateDefaultService();
service.HideCommandPromptWindow = true;
var Driver = new ChromeDriver(service, options);
//THIS WILL OPEN A NEW WINDOW. BUT BECAUSE IT IS A NEW DRIVER DOES NOT WORK FOR SHARING SESSION DETAILS.
//var TestDriver = new ChromeDriver(service, options);
//TestDriver.Manage().Window.Maximize();
//THIS JUST OPENS UP A NEW TAB. NOT A NEW WINDOW (IT WOULD SEEM MOST DOCUMENTATION SUGGESTS THAT IT SHOULD)
IJavaScriptExecutor jscript = Driver as IJavaScriptExecutor;
jscript.ExecuteScript("window.open();", "google.com.au");
//TRY USING THE SEND KEYS TECHNIQUE. NOTHING HAPPENS
var test = Driver.FindElement(By.TagName("html"));
test.SendKeys(Keys.Control + "n");
test.SendKeys(Keys.Control + "t");
//TRY AGAIN USING THE SEND KEYS TECHNIQUE USING A DIFFERENT TAG. NOTHING HAPPENS
var blah = Driver.FindElements(By.TagName("body"));
blah[0].SendKeys(Keys.Control + "t");
//TRY USING ACTIONS. NOTHING HAPPENS
Actions action = new Actions(Driver);
action.SendKeys(OpenQA.Selenium.Keys.Control + "n");
action.Build().Perform();
I may resort to AutoIt to open a browser if I have to, but one more dependency is not what I need. Documentation everywhere around the web seems to suggest than all the options I tried above should work...I suspect it may be a chromedriver issue of some kind.
Any ideas on how to achieve my goal would be greatly appreciated
UPDATE.
Arnons answer below lead me to the solution. If you are in a similar situation the best thing to do is just open up the browser console (from developers tools) and experiment with javascript until you get what you want. Then just execute that. In the end executing the following code has worked for me.
IJavaScriptExecutor jscript = Driver as IJavaScriptExecutor;
jscript.ExecuteScript("window.open('https://www.bing.com.au','_blank','toolbar = 0, location = 0, menubar = 0')");
The other alternative was to use Autoit, which I also got working, much easier than I did figuring out the javascript. But one less dependency is best :)
UPDATE2.
Further complications arise with trying to control the window as an independent browser window. I believe any new window created from a parent window, has the same process id (at least my testing has indicated so), and for all intense and purpose is treated as a tab in the selinium driver. I therefore conclude that certain things are just not possible (for example relocating the child browser window on the screen).
Your first attempt using ExecuteJavaScript was very close, but In order for it to open a new window instead of new tab, you should add the following arguments: `"_blank", "toolbar=0,location=0,menubar=0" to it.
See this question for more details.
I should have read the question better, here is my solution. Ended up using this for selecting windows that popped up after clicking a button but should work with swapping between windows.
//---- Setup Handles ----
//Create a Handle to come back to window 1
string currentHandle = driver.CurrentWindowHandle;
//Creates a target handle for window 2
string popupWindowHandle = wait.Until<string>((d) =>
{
string foundHandle = null;
// Subtract out the list of known handles. In the case of a single
// popup, the newHandles list will only have one value.
List<string> newHandles = driver.WindowHandles.Except(originalHandles).ToList();
if (newHandles.Count > 0)
{
foundHandle = newHandles[0];
}
return foundHandle;
});
//Now you can use these next 2 lines to continuously swap
//Swaps to window 2
driver.SwitchTo().Window(popupWindowHandle);
// Do stuff here in second window
//Swap back to window 1
driver.SwitchTo().Window(currentHandle);
// Do stuff here in first window
You need to explicitly tell Selenium which tab you wish to interact with, which in this case would be;
driver.SwitchTo().Window(driver.WindowHandles.Last());

How to avoid 'This type of file can harm your computer' pop up in chrome autoamtion using selenium

I am using selenium to automate website filling in chrome. When I download exe or XML files I am getting a popup 'This type of file can harm your computer' with keep and discard options. How to disable this programmatically ?
I am implementing this in c#,
I have tried,
chromeOptions.AddUserProfilePreference("disable-popup-blocking", "true")
But this is not working for me.
How to disable this popup ?
If not possible how to accept the warning ?
Please help me.
To disable the message, you need to set the preference safebrowsing.enabled to true. Here is a working example with CSharp:
var options = new ChromeOptions();
options.AddUserProfilePreference("download.default_directory", "C:\\Downloads");
options.AddUserProfilePreference("download.prompt_for_download", false);
options.AddUserProfilePreference("download.directory_upgrade", true);
options.AddUserProfilePreference("safebrowsing.enabled", true);
var driver = new ChromeDriver(options);
driver.Navigate().GoToUrl("http://www.7-zip.org/a/7z1602.exe");
And for a description of the preferences:
https://chromium.googlesource.com/chromium/src/+/master/chrome/common/pref_names.cc
Probably what you need is change
chromeOptions.AddUserProfilePreference("disable-popup-blocking", "true") // disables blocking the popup
to
chromeOptions.AddUserProfilePreference("disable-popup-blocking", "false") // enables blocking the popup
instead to avoid the popup window.
Edit : In case you are getting stuck with the harmful file contents, you can try and set an experimental chrome options using :
Map<String, Object> prefs = new HashMap<String, Object>();
prefs.put("safebrowsing.enabled", "true");
chromeOptions.setExperimentalOption("prefs", prefs);
Quoting a sample from the doc here :
Set a Chrome preference
ChromeOptions options = new ChromeOptions();
Map<String, Object> prefs = new HashMap<String, Object>();
prefs.put("profile.default_content_settings.popups", 0);
options.setExperimentalOption("prefs", prefs);
Date - 4 June,2016 [C#]
Went through few links and could figure this out that .Net still doesn't have an setExperimentalOption preferences along with the ChromeOptions. So, one of the way to Add Argument to the ChromeOptions using C# with the flags listed here would be :
chromeOptions.AddArgument("--safebrowsing-disable-download-protection");
Disables safebrowsing feature that checks download url and downloads
content's hash to make sure the content are not malicious.
Date - 4 June,2016 [JAVA]
The document here quotes it as :
public void setExperimentalOption(java.lang.String name,
java.lang.Object value)
Sets an experimental option. Useful for new ChromeDriver options not yet
exposed through the ChromeOptions API.

selenium - internetexplorerdriver compatibility mode

Is there any way how to force webdriver/internetexplorerdriver to open a site in compatibility mode. Every time I run my tests by Nunit all the history and compatibility mode list (where was my site listed before) are cleaned.
I can't change the code of the site. Can I add item to compatibility mode list or open site in specifi version of IE (I have 11 and I need open it in 7 with doc type 5).
Unfortunately no, unless you change the source code. As a workaround I use VMS. If you want to use the same route consider using free VMs from Microsoft. See my another answer related to question here
This is better description of my issue: I need to test a site that I can't edit. The site works only in compatibility mode in my IE 11 (it is made for ie 7 doc type 5). I want to run tests and cookies should be cleaned before that. But if I set "EnsureCleanSession = true" it cleans compatibilty list in IE besides cookies. Because of it, it's not possible to test the site.
I have found possible solution, but I have to test it... I've found out that compatibility list is in registry and I can load its value before it is cleaned and set the value again:
const string keyName = #"HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\BrowserEmulation\ClearableListData";
var a = Registry.GetValue(keyName, "UserFilter" , "Return this default if NoSuchName does not exist.");
// value of registry is removed
Registry.SetValue(keyName, "UserFilter", a);
Console.ReadLine();
But as I said, I don't know if it will do the trick...
[UPDATE]
Ok, it works with small work-around (because IE must be restarted after change in registry)
[SetUp]
public void SetUp()
{
//read the compatibility mode list from registry
const string path = #"HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\BrowserEmulation\ClearableListData";
const string key = "UserFilter";
var regValue = Registry.GetValue(path, key, "Return this default if NoSuchName does not exist.");
//run IE driver with cleaning of cookies and history
var options = new InternetExplorerOptions
{
IntroduceInstabilityByIgnoringProtectedModeSettings = true,
EnsureCleanSession = true
};
_driver = new InternetExplorerDriver(IeDriversPath, options);
//cloase IE
_driver.Quit();
_driver.Dispose();
//put the compatibility mode list back into registry
Registry.SetValue(path, key, regValue);
//run IE driver without cleaning of cookies and history
options.EnsureCleanSession = false;
_driver = new InternetExplorerDriver(IeDriversPath, options);
}

Categories

Resources