I have an element with a class a
. So, in Selenium code I am getting with this:
WebElement element = driver.findElement(By.cssSelector(".a"));
Afterwards, I am clicking on it with element.click();
. The click event removes the class a
from the element - which exactly is the test case I am trying to execute.
So, now I wanted to ask the element if it already owns this class:
element.getAttribute("class").contains("a");
But this did not work because of the WebElement
tried to find the element again by the given selector which was not clear to me. I thought the WebElement, once found, is internally copied throughout the scope. But obviously, it calls the linked selector every time it is called in the code.
So, how can I retrieve an element more persistently? How can I avoid the WebElement
being refreshed on every call to track the changes of the already selected element?
Of course, I could use a work-around using the DOM, the parents or a list id. But I really want to avoid this, because I do not want to get too much information about the DOM structure into my test code. This is the reason why I added classes and ids.
Edit: Adding the log output:
WebElement element = driver.findElement(By.cssSelector(".a"));
1564042692783 webdriver::server DEBUG -> POST /session/2d7cce7d-bd10-4814-b619-b4c8dc212fac/elements {"value":".a","using":"css selector"}
1564042692787 Marionette TRACE 0 -> [0,10,"WebDriver:FindElements",{"using":"css selector","value":".a"}]
1564042692793 Marionette TRACE 0 <- [1,10,null,[{"element-6066-11e4-a52e-4f735466cecf":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a","ELEMENT":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a"}]]
1564042692794 webdriver::server DEBUG <- 200 OK {"value":[{"element-6066-11e4-a52e-4f735466cecf":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a"}]}
As you can see, the received element is 517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a.
element.click();
1564042703055 webdriver::server DEBUG -> POST /session/2d7cce7d-bd10-4814-b619-b4c8dc212fac/elements {"value":".a","using":"css selector"}
1564042703058 Marionette TRACE 0 -> [0,11,"WebDriver:FindElements",{"using":"css selector","value":".a"}]
1564042703065 Marionette TRACE 0 <- [1,11,null,[{"element-6066-11e4-a52e-4f735466cecf":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a","ELEMENT":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a"}]]
1564042703066 webdriver::server DEBUG <- 200 OK {"value":[{"element-6066-11e4-a52e-4f735466cecf":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a"}]}
1564042703142 webdriver::server DEBUG -> POST /session/2d7cce7d-bd10-4814-b619-b4c8dc212fac/element/517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a/click {"id":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a"}
1564042703145 Marionette TRACE 0 -> [0,12,"WebDriver:ElementClick",{"id":"517f4e9c-5d09-4fe0-8c34-4d8c153a9c4a"}]
1564042703380 Marionette DEBUG Canceled page load listener because no navigation has been detected
1564042703382 Marionette TRACE 0 <- [1,12,null,{}]
1564042703384 webdriver::server DEBUG <- 200 OK {"value":null}
And now the check:
element.getAttribute("class");
1564042714064 webdriver::server DEBUG -> POST /session/2d7cce7d-bd10-4814-b619-b4c8dc212fac/elements {"value":".a","using":"css selector"}
1564042714067 Marionette TRACE 0 -> [0,13,"WebDriver:FindElements",{"using":"css selector","value":".a"}]
1564042714070 Marionette TRACE 0 <- [1,13,null,[]]
1564042714071 webdriver::server DEBUG <- 200 OK {"value":[]}
As you can see, no element has been returned now.
Edit: After evaluating the solution of @RahulL (which seems to work; at the click execution no further WebDriver:FindElements
call is logged - in contrast to my log) I believe that the problem lies somewhere in the Aquillian Graphene implementation which wraps my Selenium. The findElement()
call does not call the Selenium class directly. That's why I added these tags. It could be relevant for finding the problem.
So, the class definition:
import static org.junit.Assert.assertFalse;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.junit.Arquillian;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
@RunWith(Arquillian.class)
@RunAsClient
public class MyTests {
@Drone
WebDriver driver;
@Test
public void test_removeClassFromElement() {
driver.navigate().refresh();
driver.get("my.application");
WebElement element = driver.findElement(By.className("a"))
element.click();
assertFalse(
element .getAttribute("class").contains("a")
);
}
}
and the arquillian.xml:
<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.org/schema/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/schema/arquillian
http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<extension qualifier="webdriver">
<property name="browser">firefox</property>
<property name="firefoxLogLevel">FINEST</property>
</extension>
</arquillian>