I'm currently creating a tests with protractor and phantomjs.
What I'm trying to do is pretty simple, here is my html code containing the element I want to click.
<tr class="moo" role="foo">
<td class="bar">
<input class="toto" value="42" type="checkbox"></input>
</td>
<td class="titi">
Test
</td>
</tr>
Here I need to click the checkbox element, quite easy actually with :
element(by.xpath("//input[#type='checkbox']")).click();
But the problem is that there is many checkbox elements and the only difference between them is the "a" line with the text (Test in this example) that changes.
My question is : how can I specify that. I want to click on the checkbox Where the text in "a" line is "Test" ?
Use a CSS selector to find the row and then the cell:
element(by.cssContainingText('tr[role="foo"]', 'Test'))
.element(by.css('input'))
.click();
Or with an XPath to find the cell with a single call:
element(by.xpath('//tr[td/a/text()="Test"]//input'))
.click();
Related
I am trying to enter the number 1 into the MasterPack boxes within this table but get an error telling me it is not interactable.
My code looked like this and produced the element not interactable error
driver.find_element_by_xpath('//*[#id="asnPick_order_0_itemInfo_TABLE"]/div[1]/div/div/div/table/tbody/tr[1]/td[8]')
.send_keys("1")
The HTML for the table is here, I am trying to edit the MasterPack cell, so the line in between 125 and 1. The cell in the table I am trying to edit has no attributes and is blank. The text for the other cells is not listed under an attribute it is just there inbetween the tags.
<tr><td class="">0001</td>
<td class="">1022-0221-00</td>
<td class="">1004850854</td>
<td class="">8809490582667</td>
<td class="">19</td>
<td class="htAutocomplete">Each<div class="htAutocompleteArrow"> </div></td>
<td class="">125</td>
<td class=""></td>
<td class="">1</td>
<td class="htAutocomplete">Each<div class="htAutocompleteArrow"> </div></td>
<td class="">D480 3-STAGE TRUE HEPA AIR PURIFIER</td>
<td class=""><a class="no-border" title="Delete"><i class="fa fa-trash-alt fa-lg" aria-hidden="true"> </i><div class="screen-reader-only">Delete</div></a></td></tr>
I found that I can successfully click on the box using
driver.find_element_by_xpath('//*[#id="asnPick_order_0_itemInfo_TABLE"]/div[1]/div/div/div/table/tbody/tr[1]/td[8]').click()
I believe this is a dynamic table because
When I click on any cell it changes the HTML to show the class = "current highlight" I have a line of code that successfully clicks on the master pack cell. The element not intractable error occurs when I try to send keys
I need to figure out how to edit the numbers without a tag, for example here is the html of another cell that already had text in it.
<td class="">8809490582667</td>
I need to edit those numbers, but in the master pack cell where its blank without getting a element not interactable error.
Here is the html from after I click the master pack box, I don't think clicking it is necessary to enter text but then again, I don't know.
<tr><td class="">0001</td>
<td class="">1022-0221-00</td>
<td class="">1004850854</td>
<td class="">8809490582667</td>
<td class="">19</td>
<td class="htAutocomplete">Each<div class="htAutocompleteArrow"> </div></td>
<td class="">125</td>
<td class="current highlight"></td>
<td class="">1</td>
<td class="htAutocomplete">Each<div class="htAutocompleteArrow"> </div></td><td class="">D480 3-STAGE TRUE HEPA AIR PURIFIER</td><td class=""><a class="no-border" title="Delete"><i class="fa fa-trash-alt fa-lg" aria-hidden="true"> </i><div class="screen-reader-only">Delete</div></a></td></tr>
Any ideas on how to use execute script, setAttribute, or send keys to enter numbers into these td Master Pack boxes?
UPDATE:
I was able to temporarily enter numbers into the box using this code
driver.find_element_by_xpath(
'//*[#id="asnPick_order_0_itemInfo_TABLE"]/div[1]/div/div/div/table/tbody/tr[1]/td[8]').click()
element = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//table[#class='htCore']//tbody/tr//td[contains(#class, 'highlight')]")))
driver.execute_script('arguments[0].innerHTML = "1"', element)
When this code runs, it correctly places the number one into the box. However, that number one disappears after I click the next button to save the page. I seems like I am only changing the appearance of this form not actually editing the box because it disappears. Why would editing the innerHTML only be temporary?
Any ideas on how to keep the 1 from disappearing or permanently edit/send the key to the html? Thanks
Here is the html for after the number 1 is added.
<td class="current highlight">1</td>
To set the value as 1 within the column MasterPack for the first row you can use the following xpath based Locator Strategy:
Using setAttribute():
element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//table[#class='htCore']//tbody/tr//td[contains(#class, 'highlight')]")))
driver.execute_script("arguments[0].setAttribute('value','1')", element)
Using setValue():
element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//table[#class='htCore']//tbody/tr//td[contains(#class, 'highlight')]")))
driver.execute_script("arguments[0].value='1';", element)
Reference
You can find a couple of relevant discussions in:
Selenium Datepicker using JavascriptExecutor
Send keys not working selenium webdriver python
A short question: i use a usually html + twig table which i fill with a lot values. The important part of this table looks like that:
{% if rec.pDsDuplicate =='0'%}
<td class="PFu1Exists">
{{rec.getPFu1Exists()}}
</td>
<td class ="PFu2Exists">
{{rec.getPFu2Exists()}}
</td>
<td class ="PFu3Exists">
{{rec.getPFu3Exists()}}
</td>
<td class= "PFu5Exists">
{{rec.getPFu5Exists()}}
</td>
<td class ="PSdqExists">
{{rec.getPSdqExists()}}
</td>
<td class="PFupExists">
{{rec.getPFupExists()}}
</td>
{% else %}
Now i use this function to select a row:
$("#search_results tr").click(function() {
$(this).addClass("selected").siblings().removeClass("selected");
});
after the selection, the row belongs to the class "selected".
Now my specify question: How i can get the value from the column with using the class/ID Attribut e.g PFu1Exists from the selected row.
of course, i can iterate about the row and compare, but im looking for a quick an short JQuery line.
during reading some posts here, i found the function closest and find, but how i have to write the statement that i can be shure!, that the query is just searching in the selected row.. ? and not will traverse up and down to the next row?
value= $(.selected).closest(.selected).find('.PFu1Exists');
thanks for your time!
with your click function, you already remove other selected classes. that means, within your table, there is only 1 tr that has selected class. So, You can just use it like :
$('.selected').find('.PFu1Exists');
by using find(), you will only search through its child / descendants. it wont find its siblings. you can read more from
You can use following code for this..
$("#search_results tr").click(function(){
$(this).addClass("selected").siblings().removeClass("selected");
alert($(this).find('.PFu1Exists').html());
});
OR you can use -
alert($('tr.selected').find('.PFu1Exists').html());
You don't need to use find() function to search inside <tr>.
you can directly use
$('.selected .PFu1Exists')
which will select the child <td class='PFu1Exists'> inside <tr class='selected'>.
I have a calendar where the day cells are clickable "td" elements. Inside each is an "a" that has a title. I need to use this title in a JavaScript function that is called when any of the "td" elements are clicked. I had to disable the PostBack for all "a" elements
Here is code for one of the cells:
<td align="center" style="width:14%;">15</td>
I just need to access the 15 text technically. I can get the month elsewhere.
Is this possible using JavaScript?
Using jQuery for this would be a pretty good idea since you can select elements pretty conveniently. With jQuery you'd use:
$('td a').attr('title');
If you still want to use pure Javascript, you can select the title of the element by using:
document.querySelectorAll('td a')[0].title;
In the end, they both get the job done but the jQuery code is shorter.
So you'd do something similar to this with jQuery.
$('td a').on('click', function() {
console.log($(this).attr('title'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<th>
<tb>
<tr>
<td>
Hey
</td>
</tr>
<tr>
<td>
Oh
</td>
</tr>
<tr>
<td>
Goodbye
</td>
</tr>
</tb>
</th>
</table>
It's not exactly clear to me what you're after, but if you can control the call, then including this in the call gives you a reference to the element that called the listener, e.g.
<a href="javascript:__doPostBack('ctl00$MainContent$Calendar2','6314', this)"...>
Then in the listener, you have a reference to the element and you can get its title property directly, e.g.
function __doPostBack(arg0, arg1, element) {
var title = element.title;
// title is the value of the element's title property
}
I had to disable the PostBack for all "a" elements
I don't understand what that means. If it means you don't want to use __doPostBack to get the title and want to add a listener to each of the links, then you can do that quite simply too:
window.onload = function(){
[].forEach.call(document.querySelectorAll('td a'), function(a){
a.addEventListener('click', showTitle, false)
});
};
function showTitle(){
console.log(this.title);
}
<table>
<tr><td><a href="#" title="foo">foo
<tr><td><a href="#" title="bar">bar
<tr><td><a href="#" title="fum">fum
</table>
I want to identify an element which is a text "My Portal" from td tag. Below is my HTML
<tbody>
<tr>
<td>
<!-- rendered always true, custom column names are also label -->
My Portal
<!-- rendered always false, this feature is not required -->
</td>
</tr>
</tbody>
I have tried below xpaths as shown below, but none of them works:
1. .//td[text()="My Portal"]
2. .//td[contains(text(),"My Portal")]
After some search in the internet I found normalize-space() method which will remove the trailing and unnecessary white spaces. I have tried the method using the below xpath
.//td[normalize-space()="My Portal"]
Am able to identify the element, but in the firebug it is showing as 2 matching nodes. Please find the attachment for the highlighted elements in the firebug
My questions are:
Why two tags are getting highlighted?
Why .//td[contains(text(),"My Portal")] does not work?
How to identify the "My Portal" uniquely?
Can anyone please help?
There are several solutions. An efficient approach is to specify the exact path from the root node to the td you want. Something like
/html/body/table/tbody/tr/td/table/tbody/tr/td[normalize-space()='My Portal']
If you know that there are no more than two nesting tables, you can shorten this to
//td//td[normalize-space()='My Portal']
If you want the td in the innermost table regardless of table structure, try
//td[not(.//table) and normalize-space()='My Portal']
This isn't very efficient though. If you know that the text "My Portal" appears in an immediate text child of td, try
//td[text()[normalize-space()='My Portal']]
To uniquely identify the second td, what you have to do is add an additional filter. So if you look at the difference between the 2 tags highlighted, the parent has a class and the child doesn't. So if you need the second td, the xpath would be //td[normalize-space()='My Portal' and not(#class='rich-table-cell')]
If you need the parent then: //td[normalize-space()='My Portal' and #class='rich-table-cell']
Instead of using text() try .
.//td[contains(.,"My Portal")]
To Answer your questions:
1- Because you are using a global selector, "//", with this selector XPAth will find all the elements into the tree, so if you want select only one td you should specific the path, something like this
/table/tbody/table/td[contains(text(),"My Portal")]
2- The command that you are using it should work, I already tried, check your path again, maybe you are not selecting his parent or you are starting from the wrong path.
function xpath(){
var input = document.getElementById("xpath").value
var cell = document.evaluate( input, document, null, XPathResult.ANY_TYPE, null );
var cellvalue = cell.iterateNext();
console.log(cellvalue);
alert(cellvalue.data);
};
<html>
<head>
</head>
<body>
<input type="text" id="xpath" value='//body/table/tbody/tr/td/table//td[contains(text(),"My Value")]/text()'/> <input type="button" onclick="xpath()" value="Execute"/>
<table>
<tbody>
<tr>
<td>
<table>
<tbody>
<tr>
<td>
My Value
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</body>
</html>
I have some HTML of the form:-
<table>
<tr>
<td>Text for input 1<br/><div>Lots of textual data</div><input id="field1" class="mandatory"/></td>
<td>Text for input 2<br/><input id="field2" class="mandatory"/></td?
<td>Text for input 3<br/><input id="field3"/></td>
</tr>
</table>
(but with many more fields & rows).
I'm iterating through the mandatory class and, where the input field is empty, I want to display the text preceding the <br/> but not anything else.
Using:-
$(this).parent().text();
only works up to a point because it also displays the text in the <div>
Is there a way that I can limit the text to just that before the <br/>?
I think what you are looking for is .contents()
$(this).parent().contents().eq(0).text();
Demo: Fiddle
You may update your HTML markup to keep your message in a span tag with a special css class which you can use to make your jQuery selection more easier.
<table>
<tr>
<td><span class="msg">Text for input 1</span><br/>
<div>Lots of textual data</div><input id="field1" class="mandatory"/>
</td>
</tr>
</table>
and now use the closest method to get the parent td and use the find method to get the span
$(".mandatory").each(function(index,item){
var msg=$(this).closest("td").find("span.msg").html();
//do something with msg now
});
Here is a working sample http://jsbin.com/oDUPujOl/1/
Time for some plain JS, as jQuery doesn't really play well with textnodes:
var text = this.parentNode.firstChild.nodeValue.trim();
FIDDLE
You can clone your target TD and remove the elements which are with unnecessary text. Now you easily fetch the required text from that TD. For reference please read this : .clone()
Try this one,
$("#field1").keyup(function(){
var xClone = $(this).parent().clone();
xClone.find('div').remove();
alert((xClone).text());
});
DEMO