Watir webdriver - How to click on dynamically generated last <td> in table? - watir-webdriver

In my application,I've to select the last td (which is an img) in table.Can anyone help me with this ?
HTML
<table>
<tbody>
<tr>
<td>
<td>
<a onclick="return confirm('Delete creative?')" href="delete.page?cid=47">
<a href="edit.page?id=47"><a href="?duplicateId=47">
<img title="Duplicate" src="/tracker/images/skin2/bolean.png">
</a>
</td>
</tr>
</tbody>
</table>
Implemenetd as below :
#browser.img(:src => "/tracker/images/skin2/bolean.png").click
#browser.img(:src => "/tracker/images/skin2/bolean.png").last.click
which is clicking on the first image.

When you do:
#browser.img(:src => "/tracker/images/skin2/bolean.png")
This returns the first matching element.
If you want to get all of the matching elements, you need to pluralize the method:
#browser.imgs(:src => "/tracker/images/skin2/bolean.png")
You will then get a collection of all images that have the specified src. You can then get the last one and click it similar to how Ċ½eljko did it for tds.
#browser.imgs(:src => "/tracker/images/skin2/bolean.png").last.click

Try this:
#browser.tds.last.click

Related

How to find text for multiple elements using find_elements

I'm fairly new to using Selenium Remote Driver and Perl. What I'd like to do is to have Selenium find all elements on a page using a partial match of text. Then store the full text of those elements into an array.
I've tried using:
#elements = $driver->find_elements("//tbody/tr[td[2]/div/span[2][contains(text(),'matching text')]]")->get_text;
However, this doesn't seem to work.
I've also tried:
#elements = $driver->find_elements("//tbody/tr[td[2]/div/span[2][contains(text(),'matching text')]]");
This does populate the array with webelements.
my #elements;
my #elementtext;
my $elementtext;
#elements = $driver->find_elements("//tbody/tr[td[2]/div/span[2][contains(text(),'matching text')]]");
foreach my $currentelement (#elements) {
$elementtext = $driver->find_element($currentelement)->get_text();
push #elementtext, $elementtext;
}
This causes perl to generate an error because webdriver can't find the element. Any ideas on what I'm doing wrong and how to fix it? I suspect that the problem is with the contents of the #elements array not actually being xpath elements.
Here is an example of the html:
<td>
<div class='cellContent'>Atlanta</div>
</td>
<td>
<div class='cellContent'>City</div>
</td>
<td>
<div class='cellContent'>Georgia</div>
</td>
<td class='sort_column'>
<div class='cellContent'>USA</div>
</td>
</tr>
<tr>
<td>
<div class='cellContent'>Joe Passenger</div>
</td>
<td>
<div class='cellContent'> <span>NFL</span>
<span>matching text: Atlanta.Falcons.team</span>
</div>
</td>
I want to get 'matching text: Atlanta.Falcons.team' stored into the array.
you can directly point to span tag using this xpath.
//tbody/tr/td/div/span[contains(text(),'matching text')]

Accordion Bootstrap table with spacebars

I have seen questions pertaining to accordion but not entirely to my specific need. My table is populated using spacebars, more specific a nested each loop like this:
<tbody>
{{#each piece in pieces}}
<tr id="{{piece._id}}" class="itemList table-warning">
<th class="name tText">{{piece.name}} {{piece._id}}</th>
<td class="pdf tText" style="text-align: center"><a class ="pdf" href="{{piece.pdf}}" target="_blank"><i class="fa fa-file-text-o" aria-hidden="true"></i></a></td>
<td class="audio tText" style="text-align: center"><a class="audio" href="{{piece.audio}}" target="_blank"><i class="fa fa-volume-up" aria-hidden="true"></i></a></td>
<td class="format tText">{{piece.instrumentation}}</td>
<th class="price tText" >${{piece.price}}</th>
<td><input class ="qty" type ="number" name ="quantity" value="0" min="0"></td>
</tr>
<!-- Row that is being clicked-->
<tr class="partsList">
<td colspan="3"></td>
<th class="partName tText">{{piece.name}} Parts</th>
<td colspan="2"></td>
</tr>
{{#each part in piece.parts}}
<!-- Rows that should accordion -->
<!-- Currently ALL rows accordion on click. Need to accordion based on _id-->
<tr class="partList">
<td colspan="3"></td>
<td class="pname tText">{{piece.name}}: {{part.pname}}</td>
<td class="price tText">${{part.pprice}}</td>
<td><input class="qty" type="number" name="quantity" value="0" min="0"></td>
</tr>
{{/each}}
{{/each}}
</tbody>
I have a click function like so:
'click .partsList': function(e){
e.preventDefault();
$('.partList').nextUntil('tr.itemList').toggle();
}
The accordion function works, however it works with every instance of the each loop. i.e. every tr class ="partsList" will accordion at the same time on click.
To my understanding of the each loop, I can access the _id of a document using {{piece._id}}. If I set the table row id to equal that however, it only reads the _id of the FIRST document in the collection.
What I need is on click for the <tr class="partList"> to accordion based on _id. Or perhaps you would go about this a different way than bootstrap tables?
Please let me know if my question needs clarification.
You could filter the clicked .partslist using a data-* attribute. This causes jQuery to select only this specific items. Note that you need to attach the data-* attribute to the row that is clicked and to the rows that should collapse:
<tbody>
{{#each piece in pieces}}
...
<!-- Row that is being clicked-->
<!-- use the _id value of the piece context as data attribute -->
<tr class="partsList" data-id="{{piece._id}}">
<td colspan="3"></td>
<th class="partName tText">{{piece.name}} Parts</th>
<td colspan="2"></td>
</tr>
{{#each part in piece.parts}}
<!-- Rows that should accordion -->
<!-- Currently ALL rows accordion on click. Need to accordion based on _id-->
<!-- use the _id value of the piece context as data attribute -->
<tr class="partList" data-target="{{piece._id}}">
...
</tr>
{{/each}}
{{/each}}
</tbody>
'click .partsList': function(e, templateInstance){
e.preventDefault();
// get the data-id attribute of the clicked row
const targetId = templateInstance.$(e.currentTarget).data('id')
// skip if this row is not intended to toggle
if (!targetId) return
// toggle based on data-target attribute
templateInstance.$(`.partList[data-target="${targetId}"]`).nextUntil('tr.itemList').toggle();
}

Q:how to use a specific element to locate anothor equative element by protractor?

im a new bee of protractor .
here is the code:
// fist line
<table class="table">
<tbody class="table-body">
<tr class="table-tree" ng-repeat="items in page">
<td class="checkbox" >
<input type="checkbox">
<td class="node-name">
<span class="node-icon" title="tree">
// second line
<tr class="table-tree" ng-repeat="items in page">
<td class="checkbox" >
<input type="checkbox">
<td class="node-name">
<span class="node-icon" title="flower">
// third line
<tr class="table-tree" ng-repeat="items in page">
<td class="checkbox" >
<input type="checkbox">
<td class="node-name">
<span class="node-icon" title="flower">
</tbody>
</table>
Im want to click the sencond checkbox , and the first line is not always present, so i cant use $$('.checkbox').get(1) to get it, so I trying to locate the first checkbox where has [title = "flower"], then I write this:
var a = $$('[title="flower"]').get(0).getWebElement();
var b = a.getDriver().findElement(by.css('.checkbox'));
b.click();
but when the process finish , the first line checkbox was be click,
whats the wrong? and how can I fix it?
try $$('[title="flower"]').get(0).$('.checkbox').click()
First of all: why do you use .getWebElement() and .getDriver()?
What is you error message?
#Vlad's solution would be ok, but checkbox is not an ancestor of flower.
You need to get tr, check whether it contains title="flower" and if so, click checkbox of tr.
I won't write code for you, but you can check my answer: https://stackoverflow.com/a/48020146/6331748 and adjust code for your needs.
Option 1) Use XPath
element(by.xpath('//tr[td/span[#title="flower"]]/td[1]/input')).click();
Option 2) Use element() chain
// find the `SPAN` which title is flowser <br>
element(by.css('span[title="flower"]')) <br>
// find parent of `SPAN` until `TR` <br>
.element(by.xpath('./../..')) <br>
// find the `input` inside the first `TD` of above `TR` <br>
.element(by.xpath('./td[1]/input'))

How to delete specific table data from a table?

In my application I've a table with 40 rows. How do I delete some specific <td> named as "default", "tags", "city", "organic" in that table? All the deletes links are images with the same src name. Please find the attachment of the table row.
My step def:
Then(/^I click on all the delete rules on the setup page$/) do
words = ["default", "tags","organic","city"]
#current_page.delete_rules(:words => words)
end
In my ruby class I've added delete_rules method as below:
def delete_rules(words)
image_elements(:src => "/tracker/images/skin2/bin.png").click
end
Problem here is its deleting the first row in the table, not the rows which I've mentioned in the array.
My HTML is:
<tr>
<td>
tags
</td>
<td>
<a href="delete.page?did=83">
<img title="Delete" src="/tracker/images/skin2/bin.png">
</a>
<a href="edit.page?id=83">
<a href="activate.page?id=83">
</td>
<td>
</td>
you should use the following code in your delete method:
#check all <tr>
#browser.trs.each do |row|
# the row below will check the first <td> text in order to find "default", "tags", "city","organic"
if row.text.match(/default|tags|organic|city/)!= nil
# the row below will click the 1st link in the 2nd <td>
row.td(:index=>1).link.click
end
end

LIFTWEB: How to render a simple table clicking a button?

I would like to display an HTML table clicking on a button.
This is what I've tried so far:
My SCALA code:
object Snippet {
def render = {
def showTable() = {
val table = <table border="1">
<caption>My Table</caption>
<thead>
<tr>
<td>Entry</td>
<td>Value1</td>
<td>Value2</td>
</tr>
</thead>
<tbody>
<tr>
<td>PREV</td>
<td>1</td>
<td>10</td>
</tr>
<tr>
<td>CURR</td>
<td>2</td>
<td>20</td>
</tr>
<tr>
<td>NEXT</td>
<td>3</td>
<td>30</td>
</tr>
</tbody>
</table>
SetHtml("table_div",table)
}
"#getTable" #> SHtml.button("Get Table", () => null, "onclick" -> "$('#msg_div').html('<span>Getting table...</span>')") &
"name=proc" #> SHtml.hidden(showTable)
}
}
And my HTML:
<div class="lift:Snippet.render">
<form>
<input type="hidden" name="proc"/>
<button id="getTable" value="Get Table" class="btn btn-inverse">Get Table</button>
</form>
<div id="msg_div"></div>
<div id="table_div"></div>
</div>
Nothing is displayed clicking the button.. Do you see what is the problem?
Or someone could tell me another way to do that?
I am not sure what you are looking to accomplish with the hidden input. Why not just do something like:
"#getTable" #> SHtml.ajaxButton("Get Table", showTable)
If you are looking to display a waiting indicator, Lift has a mechanism for setting the ajax loading animation. In Boot.scala:
//Show the spinny image when an Ajax call starts
LiftRules.ajaxStart =
Full(() => LiftRules.jsArtifacts.show("ajax-loader").cmd)
// Make the spinny image go away when it ends
LiftRules.ajaxEnd =
Full(() => LiftRules.jsArtifacts.hide("ajax-loader").cmd)
You can use any JsCmd instead to call your own function. I'd probably opt for that.
Totally agree with jcern. A slightly different way could also be:
"#getTable [onclick]" #> SHtml.ajaxInvoke(showTable)
(this way you won't override the original button name)
Also note that you don't even need to use the <form> tag -- you can delete it.