I have created a session in Selenium, re-use it by getting the session id, local_url and put into a different session. That means the new session will continue the original session. Function getAttribute() does not work on the continued session but if I put it in the original session, it works fine. I only face the problem with getAttribute() while other selenium functions such as getText(), getCss() worked well.
This is the re-use code:
RemoteWebDriver driver = createDriverFromSession(session_id, local_url);
System.out.println(driver.findElement(By.xpath(xpath)).getAttribute(attribute));
Output:
{message=unknown error: a.getAttributeNode is not a function
(Session info: chrome=67.0.3396.99)
(Driver info: chromedriver=2.40.565498 (ea082db3280dd6843ebfb08a625e3eb905c4f5ab),platform=Windows NT 10.0.14393 x86_64)}
Somebody please help me. Thanks!
I did face some issue --> message=unknown error: a.getAttributeNode is not a function
As i started debugging more - I figured out - Chrome is not using W3C Codec. So i changed code to reflect accordingly. Changed capabilities as well.
new W3CHttpCommandCodec to new JsonHttpCommandCodec()
new W3CHttpResponseCodec to new JsonHttpResponseCodec()
new RemoteWebDriver(executor, new DesiredCapabilities()) to return
new RemoteWebDriver(url, DesiredCapabilities.chrome())
This worked for my sample. Using selenium version 3.14.0 But believe it shouldn't matter.
The answer above worked for me, but I wanted to provide a little more context.
I originally looked for a way to re-attach to an existing Selenium session instead of opening a new one. I found the createDriverFromSession method (below) from another article on the web (I can't find it to link it). That article contained the code below. I commented out the lines that needed changed from the answer above.
public static RemoteWebDriver createDriverFromSession(final SessionId sessionId, URL command_executor){
CommandExecutor executor = new HttpCommandExecutor(command_executor) {
#Override
public Response execute(Command command) throws IOException {
Response response = null;
if (command.getName() == "newSession") {
response = new Response();
response.setSessionId(sessionId.toString());
response.setStatus(0);
response.setValue(Collections.<String, String>emptyMap());
try {
Field commandCodec = null;
commandCodec = this.getClass().getSuperclass().getDeclaredField("commandCodec");
commandCodec.setAccessible(true);
// commandCodec.set(this, new W3CHttpCommandCodec());
commandCodec.set(this, new JsonHttpCommandCodec());
Field responseCodec = null;
responseCodec = this.getClass().getSuperclass().getDeclaredField("responseCodec");
responseCodec.setAccessible(true);
// responseCodec.set(this, new W3CHttpResponseCodec());
responseCodec.set(this, new JsonHttpResponseCodec());
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
response = super.execute(command);
}
return response;
}
};
// return new RemoteWebDriver(executor, new DesiredCapabilities());
return new RemoteWebDriver(executor, DesiredCapabilities.chrome());
}
I have also finally resolved this issue. It was something to do with W3C like mentioned above.
I was doing this:
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setExperimentalOption("w3c", false);
capabilities.setCapability("chromeOptions", chromeOptions);
I simply removed these caps and it worked as intended.
Related
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
To test some of the legacy pages I need to execute few test cases against IE8. These same testcases run efficiently against IE10/11, FF, Chrome without any issue.
public void TypePassword(string password)
{
var element = new WebDriverWait(Driver, TimeSpan.FromSeconds(10)).Until(
ExpectedConditions.ElementIsVisible(By.XPath("//input[#id='txtPassword']")));
//I also tried with just id and cssselector
element.Clear();
element.SendKeys(password);
}
I also tried
public void TypePassword(string password)
{
Password.Clear();
Password.SendKeys(password);
}
Interestingly,
public void TypeUsername(string username)
{
Username.Clear();
Username.SendKeys(username);
}
always work without any issue.
The IE driver configuration
var options = new InternetExplorerOptions { EnableNativeEvents = false};
options.AddAdditionalCapability("EnsureCleanSession", true);
Driver = new InternetExplorerDriver(options);
Seems like I am missing some configuration which is specific to IE8.
Also, confirmed zoom level and protected mode set up
Have you tried JavascriptExecutor ?
var element = new WebDriverWait(Driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.ElementIsVisible(By.XPath("//input[#id='txtPassword']")));
((JavascriptExecutor)Driver).executeScript("arguments[0].value='"+password+"'", element);
It is difficult to find the element exists,
so u can go for the element count >1 using do while loop,
do
{
Thread.Sleep(500);
}while(driver.FindElements(By.Id("IDNAME")).Count>0);
Unless until, the count of the element gets, this do loop will execute and wait for the element to visible also
I am researching how to set an individual profile using RemoteWebDriver. I have been reading about it on the following thread.
http://stackoverflow.com/questions/12961037/parallel-execution-of-firefoxdriver-tests-with-profile-share-same-profile-copy
I am trying to tackle it as following:
public static RemoteWebDriver getDriver(String methodName) throws MalformedURLException {
String SELENIUM_HUB_URL = "http://localhost:4444/wd/hub";
ThreadLocal<RemoteWebDriver> remoteWebDriver = null;
File currentProfileFile = new File(methodName);
//This is where it gives the error
FirefoxProfile currentFireFoxProfile = new FirefoxProfile(currentProfileFile);
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
capabilities.setCapability(FirefoxDriver.PROFILE, currentFireFoxProfile);
String proxy = System.getProperty("proxy");
try {
remoteWebDriver = new ThreadLocal<RemoteWebDriver>();
remoteWebDriver.set(new RemoteWebDriver(new URL(SELENIUM_HUB_URL),
capabilities));
} catch (MalformedURLException e) {
System.out.println("Please fix the RemoteDriverSetup.class");
}
remoteWebDriver.get().manage().window()
.setSize(new Dimension(2880, 1524));
remoteWebDriver.get().manage().timeouts()
.pageLoadTimeout(10, TimeUnit.SECONDS);
remoteWebDriver.get().manage().timeouts()
.implicitlyWait(10, TimeUnit.SECONDS);
return remoteWebDriver.get(); // Will return a thread-safe instance of the WebDriver
}
I am getting the following error :
Time elapsed: 1.044 sec <<< FAILURE!
org.openqa.selenium.firefox.UnableToCreateProfileException: Given model profile directory does
not exist: TEST001
Update : I am injecting method name in the BaseTest class below
#BeforeMethod
public void startTest(Method testMethod) {
LOG.info("Starting test: " + testMethod.getName());
this.driver = WebDriverSetup.getDriver(testMethod.getName());
}
If you don't want to customize anything on your Firefox profile, better to create Firefox webdriver instance by NOT providing any profile details (as mentioned by Nguyen).
If you really want to create separate profiles (may be required to install some plug-ins like Firebug), in that case, you can do that by without passing any file name as below:
FirefoxProfile currentFireFoxProfile = new FirefoxProfile();
//Do some customization - add extension
currentFireFoxProfile.addExtension(pathOfextensionToInstall);
//or Setup some Firefox config. switch values
currentFireFoxProfile.setPreference("browser.download.manager.showWhenStarting", false);
same code is running in firefox but it is not executing in IE9 and displaying the String message "This is the initial start page for the WebDriver server." while no error found on others
public void setUp() throws Exception {
File file = new File("C:/Users/Sunil.Wali/Desktop/Softwares/IEDriverServer_Win32_2.37.0/IEDriverServer.exe");
System.setProperty("webdriver.ie.driver", file.getAbsolutePath());
driver = new InternetExplorerDriver();
// driver = new FirefoxDriver();
baseUrl = "https://tssstrpms501.corp.trelleborg.com:12001";
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#Test
public void testLogin() throws Exception {
driver.get(baseUrl + "/ProcessPortal/login.jsp");
driver.findElement(By.id("username")).clear();
driver.findElement(By.id("username")).sendKeys("sunil.wali");
driver.findElement(By.id("password")).clear();
driver.findElement(By.id("password")).sendKeys("Trelleborg#123");
driver.findElement(By.id("log_in")).click();
driver.findElement(By.id("processPortalUserDropdown")).click();
driver.findElement(By.id("dijit_MenuItem_56_text")).click();
}
#After
public void tearDown() throws Exception {
driver.quit();
String verificationErrorString = verificationErrors.toString();
if (!"".equals(verificationErrorString)) {
fail(verificationErrorString);
}
}
Output:-
Started InternetExplorerDriver server (32-bit)
2.37.0.0
Listening on port 31651
Make sure you have same value of Protected Mode settings for each zone. Refere Required Configuration for IE.
UPDATE: setting ignoreZoomSetting and ignoreProtectedModeSettings capabilities to true helps when you don't have access to change settings.
If you are using qaf you can set capabilities as below:
driver.name=iexplorerDriver
iexplorer.additional.capabilities={'ignoreProtectedModeSettings':true,'ignoreZoomSetting':true,'nativeEvents':false,'acceptSslCerts':true}
On IE 7 or higher on Windows Vista or Windows 7, you must set the
Protected Mode settings for each zone to be the same value. The value
can be on or off, as long as it is the same for every zone. To set
the Protected Mode settings, choose "Internet Options..." from the
Tools menu, and click on the Security tab. For each zone, there will
be a check box at the bottom of the tab labeled "Enable Protected
Mode".
Additionally, "Enhanced Protected Mode" must be disabled for IE 10
and higher. This option is found in the Advanced tab of the Internet
Options dialog.
http://code.google.com/p/selenium/wiki/InternetExplorerDriver#Required_Configuration
Also make sure that your zoom is set up to 100%.
Try using an older version of IEDriverServer. I tried to everything like enabling protection mode and zoom on 100% but was still stuck on localhost page. So i downloaded and used an older version of iedriver 3.4 and Voila it worked.
Solution:
Modify the file ..\node_modules\protractor\lib\driverProviders\local.js
/*
* This is an implementation of the Local Driver Provider.
* It is responsible for setting up the account object, tearing
* it down, and setting up the driver correctly.
*
* TODO - it would be nice to do this in the launcher phase,
* so that we only start the local selenium once per entire launch.
* ------Modified by Jonathan Arias mail: jab504#gmail.com-----------
*/
var util = require('util'),
log = require('../logger.js'),
path = require('path'),
remote = require('selenium-webdriver/remote'),
fs = require('fs'),
q = require('q'),
DriverProvider = require('./driverProvider');
var LocalDriverProvider = function(config) {
DriverProvider.call(this, config);
this.server_ = null;
};
util.inherits(LocalDriverProvider, DriverProvider);
/**
* Helper to locate the default jar path if none is provided by the user.
* #private
*/
LocalDriverProvider.prototype.addDefaultBinaryLocs_ = function() {
if (!this.config_.seleniumServerJar) {
log.debug('Attempting to find the SeleniumServerJar in the default ' +
'location used by webdriver-manager');
this.config_.seleniumServerJar = path.resolve(__dirname,
'../../selenium/selenium-server-standalone-' +
require('../../config.json').webdriverVersions.selenium + '.jar');
}
if (!fs.existsSync(this.config_.seleniumServerJar)) {
throw new Error('No selenium server jar found at the specified ' +
'location (' + this.config_.seleniumServerJar +
'). Check that the version number is up to date.');
}
if (this.config_.capabilities.browserName === 'chrome') {
if (!this.config_.chromeDriver) {
log.debug('Attempting to find the chromedriver binary in the default ' +
'location used by webdriver-manager');
this.config_.chromeDriver =
path.resolve(__dirname, '../../selenium/chromedriver');
}
// Check if file exists, if not try .exe or fail accordingly
if (!fs.existsSync(this.config_.chromeDriver)) {
if (fs.existsSync(this.config_.chromeDriver + '.exe')) {
this.config_.chromeDriver += '.exe';
} else {
throw new Error('Could not find chromedriver at ' +
this.config_.chromeDriver);
}
}
}
if (this.config_.capabilities.browserName === 'internet explorer') {
if (!this.config_.IEDriverServer) {
log.debug('Attempting to find the Internet explorer binary in the default ' +
'location used by webdriver-manager');
this.config_.IEDriverServer =
path.resolve(__dirname, '../../selenium/IEDriverServer');
}
// Check if file exists, if not try .exe or fail accordingly
if (!fs.existsSync(this.config_.IEDriverServer)) {
if (fs.existsSync(this.config_.IEDriverServer + '.exe')) {
this.config_.IEDriverServer += '.exe';
} else {
throw new Error('Could not find IEDriverServer at ' +
this.config_.IEDriverServer);
}
}
}
};
/**
* Configure and launch (if applicable) the object's environment.
* #public
* #return {q.promise} A promise which will resolve when the environment is
* ready to test.
*/
LocalDriverProvider.prototype.setupEnv = function() {
var deferred = q.defer(),
self = this;
this.addDefaultBinaryLocs_();
log.puts('Starting selenium standalone server...');
// configure server
if (this.config_.chromeDriver) {
this.config_.seleniumArgs.push('-Dwebdriver.chrome.driver=' +
this.config_.chromeDriver);
}
if (this.config_.IEDriverServer) {
this.config_.seleniumArgs.push('-Dwebdriver.ie.driver=' +
this.config_.IEDriverServer);
}
this.server_ = new remote.SeleniumServer(this.config_.seleniumServerJar, {
args: this.config_.seleniumArgs,
port: this.config_.seleniumPort
});
//start local server, grab hosted address, and resolve promise
this.server_.start().then(function(url) {
log.puts('Selenium standalone server started at ' + url);
self.server_.address().then(function(address) {
self.config_.seleniumAddress = address;
deferred.resolve();
});
});
return deferred.promise;
};
/**
* Teardown and destroy the environment and do any associated cleanup.
* Shuts down the drivers and server.
*
* #public
* #override
* #return {q.promise} A promise which will resolve when the environment
* is down.
*/
LocalDriverProvider.prototype.teardownEnv = function() {
var self = this;
var deferred = q.defer();
DriverProvider.prototype.teardownEnv.call(this).then(function() {
log.puts('Shutting down selenium standalone server.');
self.server_.stop().then(function() {
deferred.resolve();
});
});
return deferred.promise;
};
// new instance w/ each include
module.exports = function(config) {
return new LocalDriverProvider(config);
};
Even I had the same issue . And it started working when I made sure that the two comments over here done properly
Make sure you have same value of Protected Mode settings for each zone
make sure that your zoom is set up to 100%.
Thanks A lot for the above two comments.
usage of 64 bit IEDriverServer fixed this issue for me.
I tried all the capabilities, still failed and at last 64 bit IE server fixed.
Use this below code to resolve the issue of type "This is the initial start page for the WebDriver server". In my machine its working fine.
System.setProperty("webdriver.ie.driver", "\\IEDriverServer.exe path");
DesiredCapabilities capabilities = DesiredCapabilities.internetExplorer();
// this line of code is to resolve protected mode issue capabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
driver=new InternetExplorerDriver();
The below code fixed the issue for me.
DesiredCapabilities capability = DesiredCapabilities.internetExplorer();
capability.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
capability.setCapability(InternetExplorerDriver.IGNORE_ZOOM_SETTING, true);
How to get the HTTP status code in Selenium?
E.g. so I can test that if the browser requests /user/27 and no user with ID=27 exists, an HTTP 404 is returned?
My primary interest is Selenium RC, but if someone knows the answer for "normal" selenium, I can probably easily translate it into RC.
/Pete
This might not be the best use of Selenium for this type of test. There is unnecessary need to load a browser when you could do and have a faster running test
[Test]
[ExpectedException(typeof(WebException), UserMessage = "The remote server returned an error: (404) Not Found")]
public void ShouldThrowA404()
{
HttpWebRequest task; //For Calling the page
HttpWebResponse taskresponse = null; //Response returned
task = (HttpWebRequest)WebRequest.Create("http://foo.bar/thiswontexistevenifiwishedonedayitwould.html");
taskresponse = (HttpWebResponse)task.GetResponse();
}
If your test is redirecting to another page during a 404 Selenium could check the final page has what you expect.
I know this is a shocking hack, but this is what I've done:
protected void AssertNotYellowScreen()
{
var selenium = Selenium;
if (selenium.GetBodyText().Contains("Server Error in '/' Application."))
{
string errorTitle = selenium.GetTitle();
Assert.Fail("Yellow Screen of Death: {0}", errorTitle);
}
}
It gets the job done in the situation I needed it for, although I accept it's not ideal...
Since Selenium 2 includes HtmlUnit, you can utilize it in order to get access to the response directly.
public static int getStatusCode(long appUserId) throws IOException {
WebClient webClient = new WebClient();
int code = webClient.getPage(
"http://your.url/123/"
).getWebResponse().getStatusCode();
webClient.closeAllWindows();
return code;
}
You probably want to check out the captureNetworkTraffic() call. Right now it only works reliably with Firefox, unless you manually set up IE/Safari/etc to proxy traffic through port 4444.
To use it, just call selenium.start("captureNetworkTraffic=true"), and then later on in your script you can call selenium.captureNetworkTraffic("...") where "..." is "plain", "xml", or "json".
I haven't tried it, but if you don't mind limiting yourself to Firefox, and installing Firebug and Netexport, then Selenium can get access to the page status code (and everything else in Firebug's Net panel): http://selenium.polteq.com/en/using-netexport-to-export-firebugs-net-panel/
Try this, people
WebClient wc = new WebClient();
int countRepeats = 120; // one wait = 0.5 sec, total 1 minute after this code
boolean haveResult = false;
try {
HtmlPage pageHndl = wc.getPage(Urls);
for(int iter=0; iter<countRepeats; iter++){
int pageCode = pageHndl.getWebResponse().getStatusCode();
System.out.println("Page status "+pageCode);
if(pageCode == 200){
haveResult = true;
break;
}
else{
Thread.sleep(500);
}
}
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
If all else fails you could adapt your server side code, during testing, to output the HTTP status in the page as an element:
For example, on my 403 Permission Denied page, I have:
<h1 id="web_403">403 Access Denied</h1>
which can be easily checked via the WebDriver API:
public boolean is403(WebDriver driver) {
try {
driver.findElement(By.id("web_403"));
return true;
} catch (NoSuchElementException e) {
return false;
}
}
https://rogerkeays.com/how-to-get-the-http-status-code-in-selenium-webdriver