What's the difference between ImplicitlyWait and RetryingElementLocator regarding PageObject? - selenium

When I use PageObject and I want to set a time to wait for elements on the page then I use ImplicitlyWait:
Driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(3));
This means that when my page object is initializing:
PageFactory.InitElements(Driver, this);
Then it will wait for elements not less then 3 seconds.
Also there is another feature of Selenium that I discovered recently: RetryingElementLocator class
Code of this class: https://seleniumhq.github.io/selenium/docs/api/dotnet/html/T_OpenQA_Selenium_Support_PageObjects_RetryingElementLocator.htm
As I understand it allows to set time to wait elements on a page for PageObject.
The example of usage is the next:
IWebDriver driver = new ChromeDriver();
RetryingElementLocator retry = new RetryingElementLocator(driver, TimeSpan.FromSeconds(5));
IPageObjectMemberDecorator decor = new DefaultPageObjectMemberDecorator();
PageFactory.InitElements(retry.SearchContext, this, decor);
So the question is: if there is any difference between 2 methods and if so when it's better to use the second one?

Related

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

Using Selenium, is it possible to create a mock WebElement to use in a unit test?

Using Selenium, is it possible to create a virtual WebElement to use in a unit test?
#Test
public void testIt() {
JavascriptExecutor js = (JavascriptExecutor) driver;
WebElement we = (WebElement)js.executeScript("code to create and return a input element");
assertTrue("default value", we.getText());
}
I thought about using a Spy or Mock object, but WebElement doesn't have any "setter" methods and so once I create a WebElement instance, I don't know how I would give it values.
For example, would it be possible to convert a HtmlUnit web element to a Selenium WebElement (that contains attributes)?
final String html = "<html><head></head><body id='tag'><b>text</b></body></html>";
final HtmlPage page = loadPage(html);
final HtmlUnitWebElement node = page.getHtmlElementById("tag");
WebElement we = node.findElement(By.xpath(".//b"));
You can write a proxy class with own implementation. I dont know about Java Selenium, but .Net Selenium has proxy WebDriver that used by PageObjectFactory and this proxy WebDriver returns proxy WebElement class that works in lazy way - it does initialization on the first access to that object.
This may help you as example - https://github.com/SeleniumHQ/selenium/tree/master/java/client/src/org/openqa/selenium/support/events . You can check EventFiringWebDriver that works like a proxy too and creates proxy EventFiringWebElement object.
So you can write own implementation for WebElement that will have setters and you can use them with test data.

Selenium Explicit Waits

I am trying to automate a sharepoint-based application, which can be slow at times. In the example below, I am trying to wrap the password input into an explicit wait. Currently, Selenium runs the test to fast and it results in failure to perform the actions.
How can I wrap the password portion into a selenium explicit way?
// Enter username
var input_Username = Driver.Instance.FindElement(By.Id("username_input"));
input_Username.SendKeys("admin");
WebDriverWait wait = new WebDriverWait(Driver.Instance, TimeSpan.FromSeconds(3000));
// Enter pasword
var input_Password = Driver.Instance.FindElement(By.Id("pw_input"));
input_Password.SendKeys("password");
Yes, you are on the right track.
WebDriverWait instance has been created, now you just need to call it like this:
WebDriverWait wait = new WebDriverWait(Driver.Instance, TimeSpan.FromSeconds(3000));
var input_Password = wait.Until(d=> d.FindElement(By.Id("pw_input")));
input_Password.SendKeys("password");
Please refer to C# API doc for more details. Relevant classes are under OpenQA.Selenium.Support.UI Namespace, in which there is an ExpectedConditions class that would be handy.
var input_Password = wait.Until(ExpectedConditions.ElementExists(By.Id("pw_input")));
Also note that your code sets the timeout to 3000 seconds, seems way too long.

How to use "isTrue" method of "Text" class?

I am unable to use "isTrue" method of text class
Here is the "Text" class detail
http://selenium.googlecode.com/git/docs/api/java/index.html
// Code i have written
public void researchSelenium(){
driver.get(baseUrl);
ConditionRunner.Context cont = new Research();
Text obj = new Text("Why implement a customer referral program?");
System.out.println(obj.isTrue(cont));
driver.close();
driver.quit();
I dont know what to do here
ConditionRunner.Context cont = new Research(); //After "new" what should i write?
object of ConditionRunner.Context will pass to "isTrue" method
I'm going to make a few presumptions here:
driver is a selenium web driver instance
You are trying to find if a text field is present in your web page
You know what the text is, but not its xpath (or at least do not care "where" it is).
In this case, you just have a minor syntaxical error
public void researchSelenium()
{
driver.get(baseUrl);
//Not sure what this is doing.
ConditionRunner.Context cont = new Research();
//Small chgange here
string obj = "Why implement a customer referral program?";
System.out.println(driver.isTextPresent(obj));
driver.close();
driver.quit();
}
NB. the above is "free coded" and I've not tested/complied it. Feel free to edit if there's a minor problem.
APPEND:
Personally I'd use NUnit to handle tests, so in that case I'd use:
Assert.isTrue(driver.isTextPresent(obj));
To test if that text was actually present, but how you're running your tests is not something that's stated in your question.

how would I run Selenium test through the GRID using C#

i have just set-up the selenium grid on my local machine and everything seems to be up and running.
my question is, is there a way I can run the test case from selenium grid node (command prompt)?
I am using WebDriver for creating my testcase using .Net
Sample code from here
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
// Requires reference to WebDriver.Support.dll
using OpenQA.Selenium.Support.UI;
class GoogleSuggest
{
static void Main(string[] args)
{
// Create a new instance of the Firefox driver.
// Notice that the remainder of the code relies on the interface,
// not the implementation.
// Further note that other drivers (InternetExplorerDriver,
// ChromeDriver, etc.) will require further configuration
// before this example will work. See the wiki pages for the
// individual drivers at http://code.google.com/p/selenium/wiki
// for further information.
WebDriver driver = new RemoteWebDriver(new Uri("http://127.0.0.1:4444/wd/hub"),
DesiredCapabilities.FirefoxDriver());
//Notice navigation is slightly different than the Java version
//This is because 'get' is a keyword in C#
driver.Navigate().GoToUrl("http://www.google.com/");
// Find the text input element by its name
IWebElement query = driver.FindElement(By.Name("q"));
// Enter something to search for
query.SendKeys("Cheese");
// Now submit the form. WebDriver will find the form for us from the element
query.Submit();
// Google's search is rendered dynamically with JavaScript.
// Wait for the page to load, timeout after 10 seconds
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until((d) => { return d.Title.ToLower().StartsWith("cheese"); });
// Should see: "Cheese - Google Search"
System.Console.WriteLine("Page title is: " + driver.Title);
//Close the browser
driver.Quit();
}
}
WebDriver driver = new RemoteWebDriver(new Uri("http://127.0.0.1:4444/wd/hub"),
DesiredCapabilities.FirefoxDriver());
OR in c#
IWebDriver driver;
DesiredCapabilities capability = new DesiredCapabilities();
driver = new RemoteWebDriver(
new Uri("http://hub-cloud.com/wd/hub/"), capability);
driver.Navigate().GoToUrl("http://www.google.com");