Selenium WebDriver: clicking a visible button inside a row of a table - javascript

My apology as this question is quite long.
To be more specific, I am trying to click on the Pencil icon (Edit button) that is shown on the 4th row
Here's the code I tried to execute:
WebElement ele = driver.findElement(By.xpath("//a[contains(#title, 'Edit Row')]"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
Executor1.executeScript("arguments[0].click();", ele);
And here's the HTML code
After I ran the selenium code, the driver actually clicked on the Edit button of the 1st row (Administration | NA) instead of the 4th. I found out that not only the 1st but other rows also have the same HTML code, only difference was that the Pencil/Edit button is hidden because I wasn't the one that created the values of that row.
I did try with the following code as well:
driver.findElement(By.xpath("//a[contains(#title, 'Edit Row')]")).click();
I then received the error
element is not currently visible and so may not be interacted with
It seems the driver was still looking at the hidden Edit button in the first row, instead of the obvious visible one in 4th.
Is there anyway that I could click on the Edit button based on the value instead of the row number? The reason is that in the future, the value I enter for testing may not end up in 4th but 1st or 10th row.
Last but not least, my Safari can't seem to run the JS Executor code, everytime I gave it a go, the following error returned:
org.openqa.selenium.WebDriverException: 'undefined' is not a function (WARNING: The server did not provide any stacktrace information)
Can someone shed some light on this for me as well?
Cheers

Since there is only one edit icon displayed, the code below should work.
driver.findElement(By.cssSelector("a[title='Edit Row']")).click();
I think the reason you were running into the hidden element issue is that you were using JSE to click on it. Selenium is designed to only interact with elements that are visible... the way a user would. JSE allows you to interact with elements that are NOT visible. There are reasons to use JSE but I don't believe this is one of them. Using JSE you were finding an element that matched your XPath that was not visible and then trying to click on it... thus the error.

I suggest you to go once in firefox and then try same xpath in firebug with firepath add-on.
Try to inspect xpath of the pencil icon. Only one maching element with no dynamic values in that, then you can and use it. Else evaluate this xapth
//a[contains(#title, 'Edit Row')]
You can find one or more matching elements. Then try to find difference in one of attribute for required element. If you are able to create xpath by using that odd attribute then its on else go for List and in loop cross theck for that, then work on it.

Thanks murali and JeffC for the suggestions, I have managed to get the driver to click on the displayed Pencil with this:
List<WebElement> EditButtons = driver.findElements(By.cssSelector("a[title='Edit Row']"));
for(WebElement button : EditButtons) {
if(button.isDisplayed()) {
button.click();
}
}
Although it only solved half of the issue, I am trying to click on the displayed Edit button based on the value next to it. If I create another row with the value of 'Test234' and if the row is placed under the 4th row, the Edit button of 'Test234' won't be clicked. Any suggestion? I tried this but it doesn't seem to work, driver still clicked on the first visible edit button it saw:
List<WebElement> EditButtons = driver.findElements(By.cssSelector("a[title='Edit Row']"));
String textvalue = driver.findElement(By.xpath("//span[contains(text(),'test456')]")).getText();
for(WebElement button : EditButtons) {
if(button.isDisplayed() && textvalue.equalsIgnoreCase("test456")) {
button.click();
}
}
UPDATE: Alright, issue resolved, I switched back to use xpath instead of cssSelector, then modified Vagnesh's suggestion (Thanks Vagnesh !!) a bit and now the driver is clicking on the visible edit button next to the text I search for without going through the loop
driver.findElement(By.xpath("//span[contains(text(), 'Enter my desired Text here')]/following::div//a[contains(#title,'Edit Row')]")).click();

You should find the element based on the field text, so that it can find its corresponding edit link.
functional_area = "Business Development / Innovation"
WebElement ele = driver.findElement(By.xpath("//span[#class='xspTextComputedField'][contains(#text, '" + functional_area + "')]/following-sibling::div/a[contains(#title, 'Edit Row')]"));
You can make it more dynamic by parameterizing the text ex. Financial.

Related

Trying to programatically click a button on a web page with cefsharp

I'm using cefsharp and vb.net to put some code together to move to the next page of this site:
https://www.recommendedagencies.com/search#{}
The idea is to read the list of company names on each page and store to a csv file. This part I can do.
The problem I have is that I can't find the name of the 'Next' button - presumably if I had that I could execute some javascript on the browser to press the button.
I've inspected the page in Firefox, but can't see any name I can use - I'm not really familiar enough with html/page design to know why not or how it works.
Could anyone tell me a good method to get button names from a web page? - I've done some searching and even asked a similar question myself before, but I can't find anything which helps, given my patchy knowledge.
Thanks
Inspect the DOM for the 'Next' button.
Look for id's or classes that you can use to identify it.
use document.querySelector() to find the element by the css selector
call the element.click() function to programatically press next
const nextButton = document.querySelector('.sp-pages-nav_next')
nextButton.addEventListener('click', (event) => {
console.log('something clicked next')
})
nextButton.click()
<div class="sp-pages-nav sp-pages-nav_next" data-reactid=".1.3.4.1">Next</div>
In the above snippet on load you can see the code nextButton.click() invokes the console log. You can click the word Next manually to the same effect.
in cefsharp perhaps something like:
browser.ExecuteJavaScriptAsync("(function(){ document.querySelector('.sp-pages-nav_next').click(); })();");
A very similar example can be found here :
https://github.com/cefsharp/CefSharp/wiki/General-Usage#1-how-do-you-call-a-javascript-method-from-net
// When executing multiple statements, group them together in an IIFE
// https://developer.mozilla.org/en-US/docs/Glossary/IIFE
// For Google.com pre-populate the search text box and click the search button
browser.ExecuteJavaScriptAsync("(function(){ document.getElementsByName('q')[0].value = 'CefSharp Was Here!'; document.getElementsByName('btnK')[0].click(); })();");

Preventing Apex Button Double click

Hi I have a button that inserts empty records into an interactive grid. I want to prevent the user from being able to double click that button because it populates duplicate rows. I have a server side argument that says if there are rows the button does not appear however they are still able to double click the Populate_tables button before it vanishes. If there are any other solutions to this please sound off. I've tried everything from javascript to server-side but they are still able to double click no matter what. Here are the before and after pictures of the table.
$('#btnPopulateTbl').dblclick(function(e){
e.preventDefault();
});
The above code prevents the double click for a button. This is in jQuery.
Oracle Apex does not offer this functionality as a setting or etc.
However you can use
$('#button').click(function(event) {
if(!event.detail || event.detail == 1){
// This will be executed once even user clicks multiple times
}
});
Note that your selector must be the id or the class you provide to this button.
By default 'add row' button's classes are:
class="a-Button a-Toolbar-item js-actionButton"
Another solution would be to have apex handle this. Suppose this is on page 1.
Create a page item P1_POPULATE_ROWS_CLICKED with a default value of 'N'
In the page process that populates the table, add the following line before the actual load:
:P1_POPULATE_ROWS_CLICKED := 'Y';
Add a condition to the page process that populates the table of "Item not equal to value", P1_POPULATE_ROWS_CLICKED , Y
Yet another solution is to only execute the insert statement if no rows exist with that condition yet. I can't show you how to do it because you didn't show how the table is populated but happy to do so if you edit your question. This last option is propably the most suitable.

WebDriver Dropdown Menu Won't Stay Open

I'm working with Selenium / Java and having an interesting issue with a DropDown Box that fires an event... I can't use Select because the dropdown is using an organized list, not select and option (when the box is closed):
<section id="..." class="ember-view">
<ol id="...">
<li id="...">
I successfully click on the dropdown box: element.click();
and the dropdown box opens! But then it closes right back up again when the next line executes (which is just a System.out.println("...");).
I'm baffled. I've tried
JavascriptExecutor jse = (JavascriptExecutor)driver
jse.executeScript("$(arguments[0]).change()", element);
and
jse.executeScript("$(arguments[0]).focus()", element);
and even
jse.executeScript("$(arguments[0]).blur()", element);
both before and after I click on the dropdown box, but that little sucker just won't stay open! When I print the value of arguments to the console System.out.println(jse.executeScript("$(arguments[0]));, arguments is null... I'm not sure what that means.
If you're not changing the classes when you click the dropdown then you're going to click it and it's going to just disappear after you click it pretty much. Try making it so the dropdown always shows and add a class that disappears on click called "hide" or "removeDisplay" like so
hide { display:none }
and then put it in the html element.
<htmlElement class="alwaysShowThis hide"></htmlElement>
make sure that on clicking it you remove the hide class, then you can just put a timer on it or just detect for when you are hovered over it.
the javascript might look like this:
display(event) {
if(/*checkfor hide class existing*/){
//remove hide class
}
}
hide() {
if(alwaysShowThis or its id is not being hovered over){
//add hide class to its classes
}
}
I mean these are just some 5 min suggestions, obviously there is a way to write these better but I don't have them off the top of my head, but you can find how to do all of these things quite easily.
I do appreciate everyone for contributing, but I never actually found the reason this was happening. So, I tried a cheat instead...
I put it all in a try / catch block, and that seems to slow it down enough to process the event. Of course, the catch is useless because it will never be reached but it works.
It's a total hack, I know. I'd still be interested in finding a reason for this behavior, but until then, we carry on!
Had similar problem and solved it with moving the cursor to the dropdown.
public void hover(WebElement element) {
Actions builder = new Actions(driver());
builder.moveToElement(element).perform();
}
After that it stayed open and I could click my selection.

Selenium, pop up form (Python)

I am trying to fill forms on certain webpages. I am having success with most
pages however certain ones are giving me trouble.
Some pages have a format where the form is not initially visible on the page itself, instead you need to click a button which then opens a (what seems to be JavaScript) pop up within the page which then needs to be filled.
I have looked around and have seen examples which address how to fill forms which get created in a new pop up window and which get created in alert windows. However I can not seem to find any examples which can solve this particular case.
This is the code I have so far.
driver = webdriver.Chrome()
driver.implicitly_wait(10)
mouse = webdriver.ActionChains(driver)
driver.get(url)
driver.maximize_window()
value = 'fill form'
span_xpath = '//span[contains(text(), "' + value + '")]'
span_element = driver.find_element_by_xpath(span_xpath)
mouse.move_to_element(span_element).click().perform()
time.sleep(5)
Everything works till here, the fill form button gets clicked which opens the form in the browser page.
But when the following is execute an error always arises: "no such element: unable to locate element"
n =driver.find_element_by_id('name')
n.send_keys('john smith')
I have tried to locate the element by, name, id, xpath and so on but no matter what try, it can not locate any of the form elements.
I would greatly appreciate any help on this matter.
First switch using driver.switch_to_frame(0) (parent iFrame)
then switch using driver.switch_to_frame(1) (chiled iFrame)
and then find the element.
Note: instead of using index you can identify the frame using id, name, xpath etc. like any other Web Element and pass that element to switch_to_frame as an argument. This gives more consistency.

Selenium find button

Hy. I have a problem with selenium IDE. I have a button in a table that I must click on.
Command: click
Target: xpath=//table[#id='mainForm:dataTable']//tr[contains(., 'test1')]/td[9]/div/table/tbody/tr/td[contains(., 'Edit')]/a
When I click the button 'Find' of selenium it show's me the button 'Edit' for the person 'test1' in my table. So selenium finds the button, that means what I write in target must be correctly.
The problem is, if I wanna run the test, selenium says :
[error] Element //table[#id='mainForm:dataTable']//tr[contains(., 'test1')]/td[9]/div/table/tbody/tr/td[contains(., 'Löschen')]/a not found
and I don#t know why.
Please help me with this problem :)
Maybe row where this text has to be present is another than 9 ? maybe try/td[contains(., 'Löschen')]/a if you don't have another td like this on page. Good practice will be sign in some way that element in your server script (for example add rel= or title= or just specific id=) and find that by this parameter.
Try to run test growing this xpath from none, thet you should catch a situation where exactly requested element not exists, like:
//table
//table[#id='mainForm:dataTable']
//table[#id='mainForm:dataTable']//tr
//table[#id='mainForm:dataTable']//tr[contains(., 'test1')]
//table[#id='mainForm:dataTable']//tr[contains(., 'test1')]/td
//table[#id='mainForm:dataTable']//tr[contains(., 'test1')]/td[9]
And so on, until error will appear
Maybe you have some javascripts on page that do modifications in DOM tree

Categories

Resources