How can I access the selector field of a By object? - selenium-webdriver

I'm using Java, Selenium Webdriver in Eclipse.
I wrote a helper method to wait for an element present, scroll to it, wait for the element to be visible and click it. Here's what I have:
protected void waitScrollWaitClick(By by, String scroll)
{
wait.until(ExpectedConditions.presenceOfElementLocated(by));
getJse().executeScript("$('.mCustomScrollbar#" + scroll + "').mCustomScrollbar('scrollTo',document.querySelector(\"" + by.selector + "\"), {scrollInertia:0})");
wait.until(ExpectedConditions.visibilityOfElementLocated(by));
getDriver().findElement(by).click();
Now the issue I'm having is in that second line in the method. I am passing a By object. This works for the conventional Webdriver methods on lines 1,3,4. But since we are using a custom scrollbar for our web app, I need to use that JavascriptExecutor class (the getJse()) to scroll on the proper div #id (thus passing in the 'scroll' argument). To use that JSE I just need the CSS selector, not the whole By object. If I add a breakpoint and look, the By object contains a 'selector' field that has what I want (in Eclipse there's a red square icon with an 'F' on it), but I can't seem to access it. I tried with the "by.selector" in the code above, but that is a compile error.
How can use that selector field? I'm not Java expert, so maybe I'm missing something obvious. I guess I don't understand why I can stop on a breakpoint, see the By object I created in the Variables tab, expand the By object and see the 'selector' field I want, but just can't access it.

The easy answer is that you cannot get the CSS selector from a By type, or even WebElement type. This is because the WebElements themselves are found by the By class. In case the By specified was a xpath there would be no way to populate the CSS selector.
The long answer specifically for your issue, to get the CSS Selector would be to create it using Javascript. An example would be Florent B.'s answer here. However, I didn't tried myself and I have no idea if it works for all cases.
Now, to address the general issue, instead of using document.querySelector use document.getElementById in case your element has an id.
Or by using document.evaluate to get your element by xpath. You can find an example in the answer posted here.

Related

Cannot get XPath selector to work using Robocorp Selenium library

I am attempting web automation with a platform called Robocorp using the Selenium library.
When I run my program, I have no issues until I encounter this page where I am trying to get the program to click on the icon that says SQL.
I want the <a> element with the #href attribute.
Here are some (of many) XPaths I have tried that have all failed:
xpath://a[contains(#href,'sql_form.jsp')]
xpath://*[text()='SQL']
xpath://a[#target='frame2]
Snapshot of the element:
I circled the element in red ^^^
I cannot get the selector to be recognized on this page. I have tried adding delays, waiting until the element is active, waiting until the element is visible, etc.
Nothing seems to work.
Here is an image of the elements I am trying to select.
(The link in the href element takes me to the page I am trying to access).
I thought that the third one would for sure work but is still failing.
I am using a platform called Robocorp which only needs the raw selector to work (CSS or XPath)
I was unaware that iframe needed to be handled differently or that it even existed
https://robocorp.com/docs/development-guide/browser/how-to-work-with-iframes
I first needed to switch frames.
To identify the element with text as SQL you can use you can use either of the following locator strategies:
Using Wait Until Element Is Visible:
Wait Until Element Is Visible xpath=//a[starts-with(#href, 'sql_form.jsp') and #target='frame2']/font[text()='SQL'] 10 seconds
Using Wait Until Element Is Enabled:
Wait Until Element Is Enabled xpath=//a[starts-with(#href, 'sql_form.jsp') and #target='frame2']/font[text()='SQL'] 10 seconds
References
You can find a couple of relevant detailed discussions in:
How to click a row that has javascript on click event in RIDE
Robot Framework: Wait Until Element Is Visible vs. Element Should Be Visible, which one is better to use?

How to locate element based on text()/contains criteria in Cypress.io

I need to locate an element/ verify presense of an element, based on the Text inside element, using something like:
//div[contains(text(),'<My intended text>')]
As Cypress.io do not support the XPATh yet, then how to locate it using alternate locators.
There seems to be lot of discussions around cssselectors :contains & when tried div:contains('<My intended text>') it failed to locate the element.
Given the fact that both XPATH & CSSLocators have good performance on modern browsers.
Kindly advise. Thanks
so you are looking for the parent which holds 'My intended text'?
You can do so by using:
cy.contains('My intended text')
and that's how you selected the element. Now you can use for example .click() to click on the element which holds 'My intended text'

Is it possible to uniquely identify DOM elements in React code?

I am using React Dev Tools to inspect a React App in Chrome. Here is a screenshot of what I see:
Now I would like to identify the highlighted input object in my React code, in order to modify the event that is called when I type in some input. My problem is that there are several input elements in the DOM. I can easily type in some random number in one of the input fields and then identify which element in the DOM I have modified by my input. But I do not know how to identify that element in the code since there are several input elements of the same type in the code. That makes it hard to identify the specific line or the specific element in the code that I modified in the DOM.
Is there a way to find a specific DOM element in the code? Or to modify my code such that I find out which element in the code has called the event handler?
I have tried to log this in the console in the event handler but this in my case returns a reference to the entire component and not the specific element that called the event handler.
Use React Dev Tools
As the main image of React Dev Tools shows, you can inspect the element on the screen and see the structure of the code. This will be a helpfull tool for you.
If you want to know exactly what field to change, just add so prop to the field like id='123' and you will be able to see it in the Dev Tools.
To learn how to install and use that Chrome plugin, you can do a little search and you will find it ;)
Edit: I said to add a prop field like id='123' but you can add any prop like elementIWantToSee='here'and with the Dev Tools you would easily find the element

Error stating "element is not found in the cache perhaps the page has changed"

I'm trying to click search button on flipkart through Selenium Webdriver using Java, i'm able to click the button by the X-path and i written 'Boolean' to display button was clicked.
Here's the code:
WebElement search = driver.findElement(By.xpath(".//*[#id='fk-header-search-form']/div/div/div[2]/input[1]"));
search.click();
boolean clicked = search.isEnabled();
System.out.println("Serach Button Clicked"+clicked);
If page is change after click on button, it is normal to not find element. You perform a search peocess, after click, new page being loading.
Another point, isEnabled, everytime returns true except disabled. In this situation, it looks already active.
There are a few issues.
.isEnabled() Determines whether the element is enabled. According to the docs, this is pretty much always going to be true except in a case where there's an INPUT that is disabled (which doesn't apply here). So your code is just telling you that the Search button is not disabled, not whether you clicked it or not.
You didn't post enough code to tell why you are getting this error. I can see what you are trying to do and wrote a simple example of how to do this.
Try this
FirefoxDriver driver = new FirefoxDriver();
driver.get("http://www.flipkart.com/");
By searchBoxLocator = By.id("fk-top-search-box");
By searchButtonLocator = By.cssSelector("input[value='Search']");
driver.findElement(searchBoxLocator).sendKeys("watch");
driver.findElement(searchButtonLocator).click();
I would suggest that you use something other than XPaths. They are brittle and slower than other methods. In the code above, I used a CSS Selector. Read some tutorials and use this page as a reference. They are very powerful and are, IMHO, better than XPath. There is some stuff that can only be done with XPath... avoid XPath until you hit one of those cases.

Are there any tools for recording web browser events for seleniumn2?

I am looking for something very simple. It can use the Selenium IDE recording tool, but it does not allow me to pick what kind of locators I get.
I want to use:
driver.findElement(By.className(str))
to locate things. All I need is something which watches which UI elements on a web page get clicked and writes out the class attributes of those tags.
If I use the Selenium IDE recording (and export to the right type of thing), I get:
#Test
public void testNav() throws Exception {
driver.get(baseUrl + "/");
driver.findElement(By.name("3.1.1.5.1.1")).clear();
driver.findElement(By.name("3.1.1.5.1.1")).sendKeys("dan");
driver.findElement(By.name("3.1.1.5.1.5")).click();
driver.findElement(By.linkText("Products")).click();
driver.findElement(By.linkText("Categories")).click();
driver.findElement(By.linkText("Create a Category")).click();
driver.findElement(By.linkText("Cancel")).click();
driver.findElement(By.linkText("Products")).click();
driver.findElement(By.cssSelector("a.DisplayAdminProductsLink")).click();
driver.findElement(By.linkText("Product1")).click();
There are problems with this. First, it is not give me any By.className() calls. Why? Those first 3 calls will not help me. The framework I am using puts arbitrary things into the name. How can I get it to see the class attribute?
There actually are unique words in the class attribute of all of the above tags. I design my apps so that this is so. Yet it will not use them.
Earlier I asked:
Why is it doing a "driver.findElement().click()"? This is fragile and does not
end up working.
What I need is:
elt = driver.waitFor(By.className("c")); elt.click();
This will work reproducibly.....
I am considering to be removed from the question, as the findElement() code does work. You need to set a general time-out on the driver. It is not very obvious that this can be done, but it can.
So, continuing on....
I can go to the "Options" and change the order of the "Locator Builders" in eclipse. I can put "css" at the top. Then I get:
driver.findElement(By.cssSelector("input[name=\"3.1.1.5.1.1\"]")).clear();
driver.findElement(By.cssSelector("input[name=\"3.1.1.5.1.1\"]")).sendKeys("dan");
driver.findElement(By.cssSelector("input[name=\"3.1.1.5.1.5\"]")).click();
The tags are like:
<input class="form-control LoginUsernameField" ... />
But it does not see the class attribute.... Or I can do this manually.
Selenium looks for a unique identifier to identify elements in a webpage. classNames are a very less desired option for this purpose as they are generally not unique. Ids and names on the other hand are generally unique. This might be the reason why Selenium IDE is not selecting classNames and going for other identifiers.
Selenium IDE records user actions. You would have clicked on the element for Selenium IDE to identify it and that is why you are getting driver.findElement().click().
If you want to wait for element to wait you can try implicit wait.
When you want to use driver.findElement(By.className(str)), are you sure that there is one and only one element in the webpage that is associated with a className? If that is the case you can modify the webdriver code manually to use className.

Resources