Cant insert text - a msg that the element is not visible is displayed - selenium

I run automation on a site that after I click on a button and a screen of PayPal is opened for inserting details. The PayPal is opened in another tab. I added a syntax that move the testing to the relevant tab and then I insert a syntax that checks that the "email input" field exists (to check that it is really goes to the correct tab) - and the result of this test :- field exists.
Then - I add a syntax for the same field to insert the email and the test is failed - the text is not inserted and there is a msg that the field is not visible.
No need to do scroll because the filed is in the top of the screen.
What can I do in this case?
This is the relevant code:
String oldTab = driver.getWindowHandle();
comOps.clickOrChose(PLS.buyButton);
Thread.sleep(4000);
ArrayList<String> newTab = new ArrayList<String> (driver.getWindowHandles());
newTab.remove(oldTab);
driver.switchTo().window(newTab.get(0));
comOps.verifyElementExist(PLP.payPalEmail);
comOps.insertText(PLP.payPalEmail, "paypal-buyer#makeitleo.com");

The reason you get this error message is that the element apparently exists but is not visible when you try to enter text to it. There are a lot of possible reasons why the element is not visible.
Given that a new tab is opended a probable reason is that the page (and its elements) is still loading. If this is the case, you need to wait for the visiblity of the element, e.g. using this piece of code (before inserting text):
WebDriverWait wait = new WebDriverWait(driver, 300); //waiting up to 5 minutes
ExpectedCondition<WebElement> condition =
ExpectedConditions.visibilityOf(PLP.payPalEmail);
wait.until(condition);
Note: that this solution assumes that PLP.payPalEmail is of type org.openqa.selenium.WebElement. If it is of type org.openqa.selenium.By use visibilityOfElementLocated(By locator).
Telling from your code snippet, I assume that comOps is an object of a class wrapping all Selenium actions. So, it is a good idea to place the above code in some method inside that class which could look like this:
public void verifyElementVisible(WebElement element) {
WebDriverWait wait = new WebDriverWait(driver, 300); //ToDo: use configurable timeout
ExpectedCondition<WebElement> condition =
ExpectedConditions.visibilityOf(element);
wait.until(condition);
}
and call it like this
comOps.verifyElementVisible(PLP.payPalEmail);

Related

selenium element.click() not working (doesn't click)

String selector = ".rmcAlertDialog .buttons :first-child";
RemoteWebElement selection = (RemoteWebElement) driver.findElement(By.cssSelector(selector));
WebDriverWait wait = new WebDriverWait(driver, 60);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(selection));
if (element == selection) selection.click();
But the element in question (a button) is not responding to the click.
If I click the button manually it works so its not the web page at fault, but the automation.
I have verified the button is there by comparing it's text content.
updated for clarification
This code works (or worked) for most buttons. The code is from a script interpreter which is parsing:-
select ".rmcAlertDialog .buttons :first-child" click
This code was working prior to more recent versions of chrome/selenium/chromedriver.
The code now doesn't work for some buttons.
selection.click() IS being called (verified in a debugger), as element will always equal selection, it just is not working.
.buttons is the class name of the container div for the button(s)
The selector is not directing to the element with button class. You have a space between .button and :first-child in the selector. Remove the space. The given selector is searching for a child element of the tag with button class. But I'm assuming you are trying to click on the first element with button class not the child node of the button class element.
Use this:
String selector = ".rmcAlertDialog .buttons:first-child";
I think the main reason it's failing is because your if statement will never be true. I've never done any comparisons like this but you can simplify your code significantly and still get the desired effect.
A few suggestions:
Don't define locators as Strings, define them as Bys. The By class is defined for just such a task and makes using and passing them around MUCH easier.
String selector = ".rmcAlertDialog .buttons:first-child";
would turn into
By locator = By.cssSelector(".rmcAlertDialog .buttons:first-child");
Note the correction that S Ahmed pointed out in his answer.
You don't need to find the element to wait for it to be clickable. There is an overload that takes a By locator, use that instead.
RemoteWebElement selection = (RemoteWebElement) driver.findElement(By.cssSelector(selector));
WebDriverWait wait = new WebDriverWait(driver, 60);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(selection));
becomes
WebElement element = new WebDriverWait(driver, 60).until(ExpectedConditions.elementToBeClickable(locator));
Skip the RemoteWebElement and WebElement comparison. I don't think this will work and there's no need for it anyway. Your locator will locate the same element consistently.
So your final code should look something like
By locator = By.cssSelector(".rmcAlertDialog .buttons:first-child");
new WebDriverWait(driver, 60).until(ExpectedConditions.elementToBeClickable(locator)).click();

<Select> Tag is not working for selecting value in dropdown

I am facing an issue where dropdown has tag. but still I am unable to select value in dropdown and it is throwing exception. I am able to get dropdown values but unable to select
Here is complete details
URL : https://semantic-ui.com/modules/dropdown.html
Testcase: Select multiple values in Skill dropdown.( Find attachment for exact field on web page.
WebDriver driver = new FirefoxDriver();
driver.get("https://semantic-ui.com/modules/dropdown.html");
driver.manage().timeouts().implicitlyWait(10L, TimeUnit.SECONDS);
WebElement Dropdown = driver.findElement(By.name("skills"));
Select sel = new Select(driver.findElement(By.name("skills")));
List<WebElement> Options = sel.getOptions();
System.out.println(Options.size());
for(int i=0;i<Options.size()-1;i++) {
driver.findElement(By.xpath("//*[#id=\"example\"]/div[4]/div[1]/div[2]/div[4]/div[1]/div[8]/div")).click();
System.out.println(Options.get(i).getAttribute("value"));
if(Options.get(i).getAttribute("value").equalsIgnoreCase("angular")||Options.get(i).getAttribute("value").equalsIgnoreCase("Graphic Design")||Options.get(i).getAttribute("value").equalsIgnoreCase("HTML")) {
Thread.sleep(6000);
sel.selectByIndex(i);
}
}
}
Exception:
Exception in thread "main" org.openqa.selenium.ElementNotInteractableException:
Please help to suggest for this.
Your drop down is a simulated drop down by css, not a HTML native drop down: Select. So you can not operate it as native drop down.
After look into the HTML code of your dropdown, there is an embed native drop down, but it's always invisible no matter you expand options or not. Selenium can't operate on invisible element(But you can read value/attribute from it), that's why the exception you met.
Actually all options come from the div class="menu", so you should click the option from div class="menu" as below screenshot show:
Code to resolve your problem:
// click arrow down to expand options
driver.findElement(By.cssSelector("select[name='skills'] + i")).click();
// choose option: Angular
driver.findElement(By.xpath("//div[contains(#class, 'multiple')][select[#name='skills']]//div[.='Angular']"));

how can I validate whether values entered in a new form is reflected correctly in edit form

I am trying to automate a website which is mainly dealing with Forms. I have entered values in new form and I need to validate whether it is reflected back correctly in edit form.
In New form I have tried like :
WebElement FN = driver.findElement(By.id("ctl00_ctl41_g_1fc852c8_32cb_4220_80ee_2af21b671f9e_ff21_ctl00_ctl00_TextField"));
FN.click();
FN.sendKeys("abc");
In the edit form code:
if(FN.getAttribute("value").equals("abc"))
System.out.println("First Name is matching with new form");
else
System.out.println("First Name is not matching with new form");
and I am getting error like
Exception in thread "main" org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document(Session info: chrome=57.0.2987.110)
Thanks in advance .
You need to reinitialize the FN Webelement once you are at edit form, as the previous FN Webelement will become stale as soon as you move away from new form. Hence, try following:
FN = driver.findElement(By.id("ctl00_ctl41_g_1fc852c8_32cb_4220_80ee_2af21b671f9e_ff21_ctl00_ctl00_TextField"));
if(FN.getAttribute("value").equals("abc"))
System.out.println("First Name is matching with new form");
else
System.out.println("First Name is not matching with new form");
Let me know, if you have any further queries.
Possibly, you are having exception at FN.sendKeys("abc");. When you click on the element before going to edit mode, the element is also changing. That's why you are having that exception.
I suggest, after clicking on the FN element have locator for textfield afresh and use sendkeys() method on it.
To know about this type of exception this might help you:
http://darrellgrainger.blogspot.com/2012/06/staleelementexception.html

How to edit element in table with selenium?

I'm trying to edit value of element that placed it the table on
this page.
I'm using this code:
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://samples.gwtproject.org/samples/Showcase/Showcase.html#!CwCellTable");
WebElement firstName = driver.findElement(By.xpath("//*[#id=\"gwt-debug-contentPanel\"]/div[2]/div/div[2]/div/div[3]/div/div/div/table/tbody/tr[1]/td/table/tbody[1]/tr[1]/td[2]/div"));
firstName.click();
firstName.clear();
firstName.sendKeys("test");
It says:
"Element must be user-editable in order to clear it."
How i can edit this element?
Also i have troubles with "Category" field on this page. I'm trying to select each of them successively. Doing this with:
WebElement category = driver.findElement(By.xpath("//*[#id=\"gwt-debug-contentPanel\"]/div[2]/div/div[2]/div/div[3]/div/div/div/table/tbody/tr[1]/td/table/tbody[1]/tr[1]/td[4]/div/select"));
category.sendKeys("Businesses");
category.sendKeys("Friends");
category.sendKeys("Coworkers");
category.sendKeys("Businesses");
category.sendKeys("Family");
I tried to make category.sendKeys(""); once and it works well.
But throws this: "stale element reference: element is not attached to the page document" when i get a lot. How i can change this elements one by one?
This is kinda a strange one. The DOM keeps changing which makes it harder to see what's going on so that you can do the right thing to make it work. You have to click one element which changes the DOM and inserts an INPUT which is what you need to .sendKeys() to. I have tested the code below and it works.
I like to create functions for things like this so that they are reusable. This function changes the first name. rowIndex is the row of the table you want to change and firstName is the desired first name. You have to wait for the table to finish loading because it loads dynamically after the page is loaded.
public static void setFirstName(int rowIndex, String firstName)
{
WebElement firstNameElement = new WebDriverWait(driver, 10)
.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("tr[__gwt_row='" + rowIndex + "'] > td > div")))
.get(1);
firstNameElement.click();
firstNameElement.findElement(By.tagName("input")).sendKeys(firstName + "\n");
}
To change the first name of the first row to "FirstName" you would call it like,
setFirstName(0, "FirstName");

Waiting for elements with Selenium WebDriver

I am automating a web page that essentially has a button which, each time it is pressed, creates a new text field.
I am using the FindBy annotation with PageFactory to find the list of text fields.
I have a synchronization problem when I press the button several times, thus creating several text fields, and then try to write into one of them. Stepping through the debugger it works fine, but out of the debugger there is a delay before the FindBy finds all the text fields.
My current workaround performs sleeps until the required number of text fields are found but I find this quite unsatisfactory. Any suggestions how the synchronization could best be done?
#FindBy(how= How.XPATH, using="//*[contains(#id, 'TextField')]")
private List<WebElement> textFields;
:
:
public void enterText(Integer index, String text){
int attempts = 0;
// Check every 10th of a second for 10 seconds if all the textFields have been found
while ((textFields.size() <= index) && attempts < 100){
Thread.sleep(100);
}
textFields.get(index).sendKeys("blah blah");
}
First of all use Implicit wait for all element present in script.
This wait is wait for all element present in the script
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
Initiate above just after get.("URL");
Now for specific element which need additional time you can use below code:-
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));
Refer below:-
http://toolsqa.com/selenium-webdriver/wait-commands/
Hope it will help you :)