This XPath expression is not working with Selenium WebDriver - xpath

I am using Google Chrome as webdriver.
The Sign Up button code is:
<button type="submit" class="signupbtn btn_full btn btn-action btn-block btn-lg">
<span class="ink animate" style="height: 488px; width: 488px; top: -215px; left: -118px;"></span>
<i class="fa fa-check-square-o"></i>
Sign Up
</button>
The error code is:
Exception in thread "main" org.openqa.selenium.WebDriverException:
unknown error: Element is not clickable at point (681, 658)
My XPath code for execution is:
driver.findElement(By.xpath("//*#id='headersignupform']/div[9]/button")).click();
However, it is not executing the script and is throwing the above error. As you can see, in the console it is locating the button with my code in the console.

You need to use focus or scroll to that element.
You also might have to use an explicit wait.
WebElement element = driver.findElement(By.xpath("//*#id='headersignupform']/div[9]/button"));
Actions actions = new Actions(driver);
actions.moveToElement(element);
actions.perform();
If it still does not work, use JavascriptExecutor:
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", element);

It seems the Sign Up button has an overlay. So to interact directly with the Sign Up button, we need to use the help of JavascriptExecutor as follows:
WebElement button = driver.findElement(By.xpath("//button[#class='signupbtn btn_full btn btn-action btn-block btn-lg']"));
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("arguments[0].click();", button);

You could use an action class for the same:
WebElement element = driver.findElement(By.xpath("//*[#id='headersignupform']/div[9]/button"));
Actions actions = new Actions(driver);
actions.moveToElement(element).click().perform();
The second thing is it's always advisable to use an exact tag instead of *[#id =""].

Related

Laravel Livewire/AlpineJS: Disable a button while loading data from an API and then enabling it again

This should be really simple, but I don't get it. I want to replicate the functionality of a button that when pressed goes to an API (which could take about a minute to get the data and process it), it gets diabled, and after loading the data it gets enabled.
I'm using Laravel/Livewire/Alpine
So, in my livewire component I have:
public $loading = false;
In my blade file, I have the declaration for the div where the button is:
<div
class="grid grid-cols-3 gap-4"
x-data="{
loading: #entangle('loading')
}"
>
Then the button x-binds the disabled property to the loading value, when the button is clicked, it changes the property of the loading variable, and calls the loader function
<button
type="button"
class="btn btn-sm btn-jbn"
x-on:click="loading = true"
x-bind:disabled="loading"
wire:click="loader"
>
Load API
</button>
And it does what it is supposed to do... the button is grayed, it becomes unusable, the cursor change, etc., it executes the loader function in my livewire component, but it never return to the normal state after loading the API. In my livewiere componente I have:
public function loader() {
// API call and logic goes here, this works
$this->loading = false;
}
So I would imagine that at the end of the API process the entangled variable loading would return the button to its normal state, but it doesn't
What am I missing?
Livewire already has incorporated functionality to handle loading-states. Instead of implementing your own, you can use this.
Get rid of all your current loading-logic, and simply use wire:loading with wire:target on your button.
wire:loading can toggle the disabled attribute directly by doing wire:loading.attr="disabled", and wire:target is to set the target for that loading-state to the method you are calling, so in your case that's wire:target="loader".
This means your button looks like this,
<button
type="button"
class="btn btn-sm btn-jbn"
wire:click="loader"
wire:loading.attr="disabled"
wire:target="loader"
>
Load API
</button>

How to capture current set of classes used on an element

I have two elements on the page: button1 and button2. One of them has class active set on an initial load.
I want to grab button1 and check if active is set. If set, then for my tests I want to use button2, if not I stick with button1.
For my test, I need to test the switch action between two buttons, hence why I need to use the button which is not an active one.
Each button does have a text, i.e. <div class="active" data-cy="button1">Button 1</div>, so I was also thinking that maybe a different option would be to grab a button1 with class active set and check if it exists? Not sure if that is possible...
How can the above be achieved?
You want to avoid conditional processing in the test, try to use a selector that targets what you want.
Given
<button class="active">Button 1</button>
<button>Button 2</button>
use a :not() selector
cy.get('button:not(.active)')
.should('have.text', 'Button 2')
If there's other button, also not active but not wanted,
<button class="active">Button 1</button>
<button>Button 2</button>
<button>Ignore me</button>
you can add a filter
cy.get('button:not(.active)')
.filter((index, button) => ['Button 1', 'Button 2'].includes(button.innerText))
.should('have.text', 'Button 2')
If you really meant the active attribute,
<button active>Button 1</button>
<button>Button 2</button>
cy.get('button:not([active])')
.should('have.text', 'Button 2')

Unable to click on 'Cancel' button

I'm writing automated script using Selenium WebDriver with Ruby. In the case, I've to click on 'Cancel' button and following is the html code for it:
<div class="ui-dialog-buttonset">
<button class="otherButtonClass" type="button" role="button" aria-disabled="false">
<span class="ui-button-text">Rename</span>
</button>
<button class="cancelButtonClass" type="button" role="button" aria-disabled="false">
<span class="ui-button-text">Cancel</span>
</button>
</div>
For clicking on 'Cancel' button, I wrote following:
driver.find_element(:xpath, "//button[#class='cancelButtonClass']").click
here click action doesn't happen. I tried sleep, wait.until { element.displayed? } still issue wasn't resolved. The error thrown is 'Element is not visible and hence may not be interacted with'
However, if I perform click action on 'Rename' button, it works:
driver.find_element(:xpath, "//button[#class='otherButtonClass']").click
Please help me to understand why this is happening. I'm confused, 'Rename' and 'Cancel' have similar html code and still clicking on 'Rename' passes and clicking on 'Cancel' fails. Why like this?
You can try the below :
script = <<-end
element = arguments[0];
element.setAttribute('aria-disabled','true');
return element;
end
# select the 'Cancel' button element
elem = driver.find_element(:css,'div.ui-dialog-buttonset>button')[1]
# setting the 'aria-disabled' to true
elem = driver.execute_script(script,elem)
#after enabling the css attribute 'aria-disabled' click on the
#cancel button
elem.click
Using CSS selection will not be a perfect solution in case if the Button CSS are dynamic for any hover actions. Also the Simple way of selecting given element is using the following xpath.
driver.find_element(:xpath, "//span[text()='Cancel']").click

Mouse Hover in selenium Ruby using capybara

Searching from many forums i got the code to hover the mouse over an element
.I want to hover the mouse over a thumbnail image.
i put html element ".thumbnail" as class inside find_element method .I dont know which parameter should i place inside find_element method?
My html element is given below.
<a class="thumbnail">
<span class="badgeFeatured">featured</span>
<img alt="" src="https://do3dm75n3e02m.cloudfront.net/arts/preview_3ds/14/original/open-uri20121128-5897-wh90rf_1354148717.png20121128-5897-194vld7-0?1354148717">
<p>Flourish Happy Birthday</p>
</a>
el = driver.find_element(:class => "thumbnail")
driver.move_to.(el).perform
Due to this problem it does not move mouse over the thumbnail image.
In Webdriver(java), we can perform mouse over action like this:
Actions actions = new Actions(driver);
WebElement imageSpan = driver.findElement(By.className("badgeFeatured"));
actions.moveToElement(imageSpan);

Selenium href blank New Window test

So, using Selenium, I want to test links on a page and see if they open a new window. They are NOT javascript links, just a basic href "target=_blank".
I want to make sure the newly opened window actually loaded a page.
I can do all the scripting to get the link clicked, but when i test for page Title, I get the page I'm testing on, not the new window that is on top.
How do I target that new window and check to see if THAT page loaded?
thanks
The following worked for me with a form with attribute target="_blank" that sends a POST request on a new window:
// Open the action in a new empty window
selenium.getEval("this.page().findElement(\"//form[#id='myForm']\").target='my_window'");
selenium.getEval("selenium.browserbot.getCurrentWindow().open('', 'my_window')");
//The contents load in the previously opened window
selenium.click("//form[#id='myForm']//input[#value='Submit']");
Thread.sleep(2000);
//Focus in the new window
selenium.selectWindow("my_window");
selenium.windowFocus();
/* .. Do something - i.e.: assertTrue(.........); */
//Close the window and back to the main one
selenium.close();
selenium.selectWindow(null);
selenium.windowFocus();
The html code would be similar to:
<form id="myForm" action="/myAction.do" target="_blank">
<input type="text" name="myText" value="some text"/>
<input type="submit" value="Save"/>
</form>
You've tagged the question RC so I assume it's not Selenium IDE.
You can use something like selenium.selectWindow or selenium.selectPopUp or selenium.windowFocus to target the new window.
A technique I find quite useful is to use Selenium IDE to capture the script and then select Options and then the programming format you require (Java, C# etc.) and then use that snippet as the basis of the RC test.
Based on the name randomization, I guess I can loop through the window names and pick th unknown one.
This works, but not tested fully...
public function testMyTestCase() {
$this->open("/");
$this->click("link=Sign in");
$this->waitForPageToLoad("30000");
$this->type("email", "xxx#gmail.com");
$this->type("password", "xxx");
$this->click("login");
$this->waitForPageToLoad("30000");
$this->click("link=Resources");
$this->waitForPageToLoad("30000");
$this->click("link=exact:http://100pages.org/");
$cc = $this->getAllWindowNames();
foreach($cc as $v ) {
if (strpos($v, "blank")) {
$this->selectWindow($v);
$this->waitForPageToLoad("30000");
$this->assertRegExp("/100/", $this->getTitle());
}
}
}

Resources