Can't click on submit button. Behat/Mink - behat

I have a form with submit button
<input id="myid" type="submit" value="My button"></input>
I tried a lot different ways to click on it, but it doesn't work. Why? I use Selenium Driver with PhantomJS browser.
What I tried:
$page = $this->getSession()->getPage();
$page->find('xpath', '//*[#id="myid"]')->click();
$page->find('xpath', '//*[#id="myid"]')->doubleClick();
$page->find('xpath', '//*[#id="myid"]')->press();
$page->find('css', '#myid')->click();
$page->find('css', '#myid')->doubleClick();
$page->find('css', '#myid')->press();
$this->getMinkContext()->pressButton('myid');

We use a function like this:
/**
* #Then /^(?:|I )click (?:on |)(?:|the )"([^"]*)"(?:|.*)$/
*/
public
function iClickOn($arg1)
{
$findName = $this->getSession()->getPage()->find("css", $arg1);
if (!$findName) {
throw new Exception($arg1 . " could not be found");
} else {
$findName->click();
}
}
Usage 1:
Scenario: Test Click
Given I go to "<url>"
And I click the "#myId" button - to reveal a hidden element
Then I should see an "<url2>" element
Usage 2:
Scenario: Test Click
Given I go to "<url>"
And I click the "#myId" link
Then I should be on "<url2>"
If this doesn't work for you, then it may be because there is an element in the way? Is the button that you want to click on genuinely there?
If it isn't, then perhaps this will help you too:
/**
* #When I scroll :elementId into view
*/
public function scrollIntoView($elementId) {
$function = <<<JS
(function(){
var elem = document.getElementById("$elementId");
elem.scrollIntoView(false);
})()
JS;
try {
$this->getSession()->executeScript($function);
}
catch(Exception $e) {
throw new \Exception("ScrollIntoView failed");
}
}
Personally, I haven't used the final function, however the same function helped a person in one of the posts I was viewing before this.

Related

Find a div with the class using mink and behat

I have a button in the page :
<div class="button wide green attached connectyourself" >Conect</div>
I want tu push on this div, so I create the methode :
/**
* #When I open the connection popup
*/
public function iOpenTheConnectionPopup()
{
$page = $this->getSession()->getPage();
$findName = $page->find("css", '.connectyourself');
if (!$findName) {
throw new Exception('connectyourself' . " could not be found");
} else {
$findName->click();
}
}
Every time I get the exception 'connectyourself could not be found'.
Can you help me please ?
I think this css is not unique. Might be there are more elements with the class name containing "connectyourself". You should try finding it by giving a full class nam.
$findName = $page->find("css", '.button.wide.green.attached.connectyourself');

Click Next link until pagination Next action is disabled in selenium webdriver

I want to verify elements in a row inside a table in by navigating each page through pagination.I am able to navigate to each page and assert element but the probelm is at last page the loop still continues even though the Next link is grayed out.
When Next link is disabled
<span>
<a class="next_btn inactive">NEXT ></a>
</span>
When Next link is enabled
<span>
<a class="next_btn" href="home.do?action=Next&start=10&end=20&sort=&
type=00&status=&fromDate=04/02/2017&toDate=05/02/2017&school=&
district=0009">NEXT ></a>
</span>
Actual Code
public void submissionType() throws Exception {
driver.findElement(By.linkText("NEXT >"));
while(true) {
processPage();
if (pagination.isDisplayed() && pagination.isEnabled()){
pagination.click();
Thread.sleep(100L);
} else
break;
}
}
private void processPage() {
String statusColumn="//td[#class='gridDetail'][2]";
List<WebElement> list = table.findElements(By.xpath(statusColumn));
for (WebElement checkbox : list) {
String columnName=checkbox.getText();
Asserts.assertThat(columnName,"File");
}
}
Instead of identifying the element with By.linkText("NEXT >"), try identifying it with By.cssSelector("a.next_btn").
When you use this approach, then when the object becomes disabled, its class name would change, and hence your object would no longer get identified and your loop would break.
Edit: Add try block and Catch NoSuchElement exception to avoid exceptions.
I know you already accepted an answer but one of the statements is not correct. The locator, By.cssSelector("a.next_btn"), will find both the enabled and disabled button so it will not cause the loop to break.
Looking at your code, I would offer a few suggestions/corrections.
.isEnabled() only really works on INPUT tags so testing for that doesn't really accomplish anything here.
Using Thread.sleep() is not a good practice. You can google some explanations but basically the problem is that it's an inflexible wait. If the element you are waiting for becomes available in 15ms, you are still going to wait 10s or whatever your sleep is set to. Using an explicit wait (WebDriverWait) is a best practice.
I would clean up your functions and write them like
public void submissionType()
{
WebDriverWait wait = new WebDriverWait(driver, 10);
By nextButtonLocator = By.cssSelector("a.next_btn:not(.inactive)");
List<WebElement> nextButton = driver.findElements(nextButtonLocator);
while (!nextButton.isEmpty())
{
processPage();
nextButton.get(0).click();
wait.until(ExpectedConditions.stalenessOf(nextButton.get(0))); // wait until the page transitions
nextButton = driver.findElements(nextButtonLocator);
}
}
private void processPage()
{
for (WebElement checkbox : table.findElements(By.xpath("//td[#class='gridDetail'][2]")))
{
Asserts.assertThat(checkbox.getText(), "File");
}
}

wait for "loading" icon to disappear from the page

we are doing automation for web application and most of the scenario getting loading icon will appear at center of the page .. we need to wait for dis appear to loading icon
<div id="loading" style="display: none; visibility: hidden;">
<div></div>
<div></div>
Example : we are having search functionality their in most of scenario we are getting this loading icon.
selenium webdriver we are using: id we are getting for loading to complete is id= "loading"..please any give the solutions for the above issues am facing.
we have different functionality like click & sendkeys
Explicit Wait should help:
public static String waitForElementNotVisible(int timeOutInSeconds, WebDriver driver, String elementXPath) {
if ((driver == null) || (elementXPath == null) || elementXPath.isEmpty()) {
return "Wrong usage of WaitforElementNotVisible()";
}
try {
(new WebDriverWait(driver, timeOutInSeconds)).until(ExpectedConditions.invisibilityOfElementLocated(By
.xpath(elementXPath)));
return null;
} catch (TimeoutException e) {
return "Build your own errormessage...";
}
}
I have recently faced this issue. My solution might sound hacky but it worked pretty well in my case:
public static void loadingWait(WebDriver driver, WebElement loader) {
WebDriverWait wait = new WebDriverWait(driver, 5000L);
wait.until(ExpectedConditions.visibilityOf(loader)); // wait for loader to appear
wait.until(ExpectedConditions.invisibilityOf(loader)); // wait for loader to disappear
}
you can call this method after clicking on submit button. You have to pass driver, and loader web element to this method.
You can also wait till the ajax calls have been completed. Loading wheel disappears when all the ajax calls have completed (in most of the scenarios):
WebDriverWait wait = new WebDriverWait(d, timeOutSeconds);
wait.until(waitForAjaxCalls());
public static ExpectedCondition<Boolean> waitForAjaxCalls() {
return new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driver) {
return Boolean.valueOf(((JavascriptExecutor) driver).executeScript("return (window.angular !== undefined) && (angular.element(document).injector() !== undefined) && (angular.element(document).injector().get('$http').pendingRequests.length === 0)").toString());
}
};
}
I faced this issue and the solution is really simple :
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until( ExpectedConditions.invisibilityOfElementLocated(By.xpath("path_of_loader")));
Generally, you must have something like on your website :Image
so use path_of_loader = //div[#id='circular3dG'] .. You can also try searching using keywords like loader, spinner or use a page to inspect loader/spinner where it takes long to load the page.

Testing a negative flow in Selenium webdriver

Issue:- webelement (Button) isdisplayed() doesn't works for negative scenarios
Requirement:- I need to fail a test flow in case a button is not displayed on the screen and if its present, then proceed with the flow
Code:-
if (driver.findElement(By.id("button")).isDisplayed() == false) {
System.out.println("The Button isn't present. Exiting!!");
driver.findElement(By.linkText("Logout")).click();
}
else
{
//Proceed with the positive flow
}
In above code, if the button is not present at all on the screen, the test should fail (if statement should be executed, but it's not)
As TestAutomationEngr has mentioned, make sure there is only one type of such button on the page...
one more way you could test for negative flow in webdriver is by using a try and catch..
In your case,
boolean buttonFound=false;
try
{
new WebDriverWait(driver,10).until(ExpectedConditions.visibilityOfElementLocated(By.id("button")));
buttonFound=true;
}catch(Exception e)
{
System.out.println("The Button isn't present. Exiting!!");
driver.findElement(By.linkText("Logout")).click();
}
if(buttonFound)
{
//positive flow
}
here it'l wait for 10 secs for visibility of element,
if found, buttonFound is set to true,hence positive flow is executed
if not found, the message in catch clause will be displayed and logout link will be clicked
In fact it is not required to logout in case an exception is thrown because when the driver is closed this session will be lost. The following code will fail the test in case the element is not present or it is not enabled.
WebElement elem = driver.findElement(By.id("button"));
Assert.assertTrue(elem.isEnabled());
At the end you just need to close the driver in the test teardown the
driver.close()
You can use the FindElements.Count approach.
Like this:
public bool IsElementDisplayed(IWebDriver driver, By element)
{
if (driver.FindElements(element).Count > 0)
{
if (driver.FindElement(element).Displayed)
return true;
else
return false;
}
else
{
return false;
}
}
Hope it helps.

Can I make Behat/ZombieJS/Mink simulate a click on a "non-link" element, to fire JS listeners?

I am using Behat for testing, with the ZombieJS driver, and everything is working very well so far, but there is one thing that bothers me, I can't seem to figure out how to get Behat to simulate a click on a non-link element. I guess this comes from Mink being a "cross-browser" driver, and it doesn't really make sense to click on non-link elements. For my use case though, I need it, because there are several elements on the page that have javascript event listeners attached to them, and I want to test these functionalities.
I tried using
Then I follow "div.sa"
But it fails with the expected error:
01. Link with id|title|alt|text "div.sa" not found.
Since it's not a link element. There is a similar step in Behat:
I press "button.class"
But this one is only for buttons.
Is there a way I could get Behat click on elements that are not tags?
With some error handling:
/** Click on the element with the provided xpath query
*
* #When /^(?:|I )click on the element "([^"]*)"$/
*/
public function iClickOnTheElement($locator)
{
$session = $this->getSession(); // get the mink session
$element = $session->getPage()->find('css', $locator); // runs the actual query and returns the element
// errors must not pass silently
if (null === $element) {
throw new \InvalidArgumentException(sprintf('Could not evaluate CSS selector: "%s"', $locator));
}
// ok, let's click on it
$element->click();
}
Yes I believe so, but you'll need to write a custom step, something along these lines (if you're using a subclass of MinkContext.
/**
* #When /^I click the something$/
*/
public function iClickTheSomething()
{
$something = $this->getSession()
->getPage()
->find("css", "div.sa")
->click();
}
This is my adaptation of the answer by Comstar. The same functionality is achieved, however, it seems simpler to me to do it this way.
/**
* #Then /^I click on "([^"]*)"$/
*/
public function iClickOn($arg1)
{
$page = $this->getSession()->getPage();
$findName = $page->find("css", $arg1);
if (!$findName){
throw new Exception($arg1." could not be found");
}
else {
$findName->click();
}
}
When I execute a click event, so that the current URL be equal to javascript:
$this->iClickOnTheElementWithXPath(‘//div[#class="'.$arg2.'"]/div/div[#class="edit"]/a[text()="'.$arg1.'"]‘);
In the page html:
<a onclick="editForm('Avatar')" href="javascript:;">Modifier</a>