I'm new to Selenium, TestNG and Stackoverflow.
After sendkeys, I want to do some validation. If the validation is true, then the assert is true. I know this is not the right way to write the Assert method.
WebDriver driver;
#DataProvider(name= "testdata")
public static Object[][] loginData(){
return new Object[][]{{"username1", "123"}, {"username2", "4211"}};
}
#BeforeTest
public void configure(){
....
}
#Test(dataProvider = "testdata")
public void testmethod(String uname, String password){
WebElement usernameTextbox = driver.findElement(By.id("username"));
usernameTextbox.sendKeys(uname);
WebElement passwordTextbox = driver.findElement(By.id("username"));
passwordTextbox.sendKeys(uname);
driver.manage().timeouts().implicitlyWait(2, TimeUnit.MICROSECONDS);
Assert.assertTrue(if(usernameTextbox.contains("[a-zA-Z0-9]+") && passwordTextbox.contains("[0-9]+") == true));
PS: Any inputs will be appreciated.
Try implementing explicit wait in Your code. What that mean, is that You wait for some condition to be set, here is example how to manage this:
But my suggestion is that You assert if there are some error messages (labels, span, or whatever that appears saying something is wrong with email or pass)
So here is how I would do it:
WebDriver driver;
#DataProvider(name= "testdata")
public static Object[][] loginData(){
return new Object[][]{{"username1", "123"}, {"username2", "4211"}};
}
#BeforeTest
public void configure(){
driver = new WebDriver();
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS); //this is wait which will wait until driver throws exception (that is not found eg."NoSuchElementException")
}
#Test(dataProvider = "testdata")
public void testmethod(String uname, String password){
WebElement usernameTextbox = driver.findElement(By.id("usernameID"));
usernameTextbox.sendKeys(uname);
WebElement passwordTextbox = driver.findElement(By.id("passwordID"));
passwordTextbox.sendKeys(password); //here is where You've sent wrong param
// if You know You will get error label or something use this
WebDriverWait wait = new WebDriverWait(driver, 10); //wait for max 10 sec, and wait for error element defined bellow
WebElement errorElement = wait.until(ExpectedConditions. presenceOfElementLocated(By.id("someErrorElementId"))); //(or ExpectedConditions.textToBePresentInElement(..)), see what better suites You
// If You're expecting error than use this assert
Assert.assertTrue(errorElement.isDisplayed(),"There should be error message!")
// but If You're expecting that there should not be any error than use this assert
Assert.assertFalse(errorElement.isDisplayed(),"There shouldn't be no error messages!")
}
tweak this code, but basicaly this is the logic.
So to try to answer the original question your code could look like below:
1. Using the getAttribute("value")
2. Building the assertion - you don't need to wrap the condition in an if as the contains() function will return true or false for you:
WebDriver driver;
#DataProvider(name= "testdata")
public static Object[][] loginData(){
return new Object[][]{{"username1", "123"}, {"username2", "4211"}};
}
#BeforeTest
public void configure(){
....
}
#Test(dataProvider = "testdata")
public void testmethod(String uname, String password){
WebElement usernameTextbox = driver.findElement(By.id("username"));
usernameTextbox.sendKeys(uname);
WebElement passwordTextbox = driver.findElement(By.id("username"));
passwordTextbox.sendKeys(uname);
driver.manage().timeouts().implicitlyWait(2, TimeUnit.MICROSECONDS);
Assert.assertTrue(usernameTextbox.getAttribute("value").contains("[a-zA-Z0-9]+") && passwordTextbox.getAttribute("value").contains("[0-9]+"));
HTH
As per your question just after invoking sendKeys() you want to do some assertions.
At this point it is worth to mention that when you invoke sendKeys() on a <input> node/tag/field the HTML DOM is not immediately updated with the value / characters which you have just entered in majority of the cases (of-coarse there are exceptional cases). Moving forward when you invoke click() or submit()on a <button> or similar <input> element, the associated onclick event of this <input> element updates the HTML DOM and the value / characters previously sent through sendKeys() are adjusted within the HTML DOM.
Unless the value / characters are not accommodated within the DOM Tree Selenium won't be able to interact with them.
As per your code block, you have populated the passwordTextbox field with the String value of uname as follows :
passwordTextbox.sendKeys(uname);
This value / characterset is still volatile and editable (can be overwritten/cleared/deleted) as follows :
passwordTextbox.clear();
passwordTextbox.sendKeys("Emma E");
Essentially, Assert methods can be invoked on text those are part of the HTML DOM. As an example you can use the following Assert for a Page Heading, Table Heading, etc :
Assert.assertTrue(if(pageHeaderElement.contains("[a-zA-Z0-9]+") && tableHeaderElement.contains("[0-9]+") == true));
Related
I am trying to find the element of the field First Name on the page https://whitelabel.sandbox.array.io/signup?platform=v3. I tried searching by id, classname, name, cssSelector, etc. but none works. I even added waiter to ensure it is loaded well before I try to find the element. Same issue happens for all fields in the page. So, the issue is not unique to this field.
Tried this in Chrome and Firefox on Mac. The same code works well to find the username field in gmail.com page.
driver.get("https://whitelabel.sandbox.array.io/signup?platform=v3");
driver.manage().window().maximize();
WebDriverWait wait = new WebDriverWait(driver, java.time.Duration.ofSeconds(10));
WebElement selectFirstName = driver.findElement(By.name("firstName"));
//assertNotNull(driver.findElement(By.name("firstName")));
//assertNotNull(driver.findElement(By.xpath("//input[#name='firstName']")));
//driver.findElement(By.cssSelector("input[name='firstName']")).sendKeys("Thomas");
//driver.findElement(By.name("firstName")).sendKeys("Thomas");
//driver.findElement(By.xpath("//input[#name='firstName']")).sendKeys("Thomas");
//page.locator("[name='firstName']").type("Thomas");
//driver.findElement(By.cssSelector("input[name='firstName']")).sendKeys("Thomas");
//driver.locator("[name='firstName']").type("Thomas");
Error that I get is:
Exception in thread "main" org.openqa.selenium.NoSuchElementException:
no such element: Unable to locate element: {"method":"css
selector","selector":"*[name='firstName']"} (Session info:
chrome=103.0.5060.134)
Does anyone know what I need to do differently to be able to get the webElement?
The First Name field within the website https://whitelabel.sandbox.array.io/signup?platform=v3 is within a #shadow-root (open)
ShadowRoot in selenium4
As per the test implementation in ShadowRoot.java:
import static org.openqa.selenium.remote.Dialect.W3C;
import static org.openqa.selenium.remote.DriverCommand.FIND_ELEMENTS_FROM_SHADOW_ROOT;
import static org.openqa.selenium.remote.DriverCommand.FIND_ELEMENT_FROM_SHADOW_ROOT;
// Note: we want people to code against the SearchContext API, so we keep this class package private
class ShadowRoot implements SearchContext, WrapsDriver {
private final RemoteWebDriver parent;
private final String id;
ShadowRoot(RemoteWebDriver parent, String id) {
this.parent = Require.nonNull("Owning remote webdriver", parent);
this.id = Require.nonNull("Shadow root ID", id);
}
#Override
public List<WebElement> findElements(By by) {
return parent.findElements(
this,
(using, value) -> FIND_ELEMENTS_FROM_SHADOW_ROOT(id, using, String.valueOf(value)),
by);
}
#Override
public WebElement findElement(By by) {
return parent.findElement(
this,
(using, value) -> FIND_ELEMENT_FROM_SHADOW_ROOT(id, using, String.valueOf(value)),
by);
}
#Override
public WebDriver getWrappedDriver() {
return parent;
}
public String getId() {
return this.id;
}
private Map<String, Object> toJson() {
return singletonMap(W3C.getShadowRootElementKey(), id);
}
}
#titusfortner explains the same in their comment as:
The actual state is that the return value of that JavaScript changed in v96 of ChromeDriver in order to be w3c compliant. Selenium 3.141.59 can not parse this new return value. You can use getShadowRoot() in Selenium 4, or you'll be able to get a ShadowRoot instance returned from the JS in Selenium 4.1.
And I stand corrected, you need to cast to SearchContext interface.
Solution
To send a character sequence within the First Name you can use the following Locator Strategy:
Code Block:
driver.get("https://whitelabel.sandbox.array.io/signup?platform=v3");
WebElement element = new WebDriverWait(driver, Duration.ofSeconds(10), Duration.ofSeconds(10)).until(ExpectedConditions.visibilityOfElementLocated(By.tagName("array-account-enroll")));
SearchContext context = element.getShadowRoot();
WebElement firstName = context.findElement(By.cssSelector("input[name='firstName'][placeholder='Enter first name']"));
firstName.sendKeys("Supramanian");
Browser snapshot:
how is possible to find the xpath for an angularJs element? for instance i discovered that all links in my page have the same xpath due to the repeated items in angularJs -->
.//*[#id='div_1_1_1_2']/div/div[1]/div[2]/div[2]/div/div[2]/div[1]/div/div[2]/a
but i have 10 of element , they are differente for text, so i tried with `"
so i tried with contains but it never find it
.//[#id='div_1_1_1_2']/div/div[1]/div[2]/div[2]/div/div[2]/div[1]/div/div[2]/a[contains(#aria-label='Creazione Prodotto')]"`
i use selenium, junit4 , firefox webDriver
this is my code
public class PB01_TTT {
private WebDriver driver;
private String baseUrl;
private boolean acceptNextAlert = true;
private StringBuffer verificationErrors = new StringBuffer();
WebElement element;
#Before()
public void setUp() throws Exception {
FirefoxProfile fxProfile = new FirefoxProfile();
fxProfile.setPreference("browser.download.folderList", 2);
fxProfile.setPreference("browser.download.manager.showWhenStarting", false);
fxProfile.setPreference("browser.helperApps.alwaysAsk.force", false);
fxProfile.setPreference("browser.helperApps.neverAsk.saveToDisk",
"application/pdf, application/x-pdf, application/octet-stream");
fxProfile.setPreference("pdfjs.disabled", true);
driver = new FirefoxDriver(fxProfile);
baseUrl = "https://w8aon2bpm.replynet.prv:9443";
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#Test
public void testPBO1TTT() throws Exception {
driver.get(baseUrl + "/ProcessPortal/login.jsp");
// driver.get(baseUrl + "/ProcessPortal/dashboards/SYSRP/RESPONSIVE_WORK");
driver.findElement(By.id("username")).clear();
driver.findElement(By.id("username")).sendKeys("user");
driver.findElement(By.id("password")).clear();
driver.findElement(By.id("password")).sendKeys("password");
String columnToDisplay=driver.findElements(By.xpath(".//*[#id='div_1_1_1_2']/div/div[1]/div[2]/div[2]/div/div[2]/div[1]/div/div[2]/a[contains(#aria-label='Creazione Prodotto')]"));
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
element = (WebElement) driver.findElements(By.xpath(columnToDisplayXpath));
Assert.assertNotNull(element);
it always return me a notFoundElement, any suggestions ?
Thank you
If you have 10 links, then there is a high chance they are different in a way even if the path is the same, in this case you need to construct an path based on the thing that is different.
For example: use href, text or other any part that differs
//a[contains(#href, 'part_of_href')]
//a[contains(text(), 'part_of_text')]
//a[#title='title']
//a[contains(#aria-label='Creazione Prodotto')]
If you need any help in getting the selector please add the html section of the links, you can change the url if needed.
Tip: avoid using absolute xpaths and attributes that do not suggest anything and they can change like: .//*[#id='div_1_1_1_2']/div/div[1]/div[2]/div[2]/div/div[2]/div[1]/div/div[2]/a[contains(#aria-label='Creazione Prodotto')]"
This will give you a lot of work in the future.
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 using Selenium WebDriver and its was working all fine and today i am getting either timeout if i use the below code or getting the error Unable to find element with id == //*[#id='ctl00_ContentPlaceHolder1_AddControl1_txtName']
i try to use this:
public IWebElement GetElementId(string id)
{
//return Driver.FindElement(By.Id(id));
Driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(TimeOut));
return Driver.FindElement(By.Id(id));
}
and tried this:
public IWebElement GetElementId(string id)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement category = wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.Id(el_id));
});
}
I am still couldn't figured how to avoid time-out or element not found error
any help?
Try using the FluentWait class:
public WebElement fluentWait( final By locator ) {
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class, StaleElementReferenceException.class);
// use a "custom" ExpectedCondition
WebElement foo = wait.until( new Function<WebDriver, WebElement>() {
public WebElement apply( WebDriver driver ) {
return driver.findElement( locator );
}
});
// usually use one of the built-in ExpectedCondtions
// WebElement foo = wait.until(
// ExpectedConditions.visibilityOfElementLocated( locator );
return foo;
};
you can read about fluent wait here
Or if not check thoroughly if you found locator properly.
Hope this helps you)
You are using xpath but in the findElement you are using By.Id change it as
By.xpath("//*[#id='ctl00_ContentPlaceHolder1_AddeCardControl1_txtName']")
OR
By.id("ctl00_ContentPlaceHolder1_AddeCardControl1_txtName")
If it still shows timeout error then try by specifying the element name too in the xpath like
//div[#id='element_id']
because specifying like this
//*[#id='ctl00_ContentPlaceHolder1_AddeCardControl1_txtName']
may took time by searching all the elements id attribute so if you specify the particular element then the searching time will be minimized.
If it doesn't works then check whether that your xpath is correct or not.
Is there a way in the latest version of Selenium DotNet Webdriver (2.22.0) to check to see if an element is visible before clicking/interacting with it?
The only way I've found is to try to handle the ElementNotVisible exception that occurs when you try to send keys, or click on it. Unfortunately this only occurs after an attempt to interact with the element has been made. I'm using a recursive function to find elements with a certain value, and some of these elements are only visible in certain scenarios (but their html is still there no matter what, so they can be found).
It's my understanding that the RenderedWebElement class is deprecated as well other variants. So no casting to that.
Thanks.
For Java there is isDisplayed() on the RemoteWebElement - as well is isEnabled()
In C#, there is a Displayed & Enabled property.
Both must be true for an element to be on the page and visible to a user.
In the case of "html is still there no matter what, so they can be found", simply check BOTH isDisplayed (Java) / Displayed (C#) AND isEnabled (Java) / Enabled (C#).
Example, in C#:
public void Test()
{
IWebDriver driver = new FirefoxDriver();
IWebElement element = null;
if (TryFindElement(By.CssSelector("div.logintextbox"), out element)
{
bool visible = IsElementVisible(element);
if (visible)
{
// do something
}
}
}
public bool TryFindElement(By by, out IWebElement element)
{
try
{
element = driver.FindElement(by);
}
catch (NoSuchElementException ex)
{
return false;
}
return true;
}
public bool IsElementVisible(IWebElement element)
{
return element.Displayed && element.Enabled;
}
It seems the current answer to this question is outdated: With WebDriver 3.13 both the Displayed and Enabled properties will return true as long as the element exists on the page, even if it is outside of the viewport. The following C# code works for WebDriver 3.13 (from this StackOverflow answer):
{
return (bool)((IJavaScriptExecutor)Driver).ExecuteScript(#"
var element = arguments[0];
var boundingBox = element.getBoundingClientRect();
var cx = boundingBox.left + boundingBox.width/2, cy = boundingBox.top + boundingBox.height/2;
return !!document.elementFromPoint(cx, cy);
", element);
}
There is a simple way to do that, follow below:
public bool ElementDisplayed(By locator)
{
new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut)).Until(condition: ExpectedConditions.PresenceOfAllElementsLocatedBy(locator));
return driver.FindElement(locator).Displayed ;
}
You can use the following:
WebDriver web = new FirefoxDriver(;
String visibility = web.findElement(By.xpath("//your xpath")).getCssValue("display");