Below is the approach I have used in order to select values from a dropdown using nightwatch.As you can see this is not a good approach. We can't select the specific value from dropdown unless we click on the exact element.
this.useXpath();
this.click('(//td[#class="styles_selectDropdownContainer__2Vrns"])[1]')
this.useCss();
this.click('#react-select-6-option-1')
In selenium java there is a very good option like below
Select fruits = new Select(driver.findElement(By.id("fruits")));
fruits.selectByVisibleText("Banana");
I want to know of there is a similar approach can be used in nightwatch as well?
This is not built up using Select and Option tag so inbuilt selenium functions wouldn't work. Work around would be to click first on the parent span and then in list store every div (which is option), iterate the loop and for each web element if text matches with your desired text you can click on it.
Code :
this.useCss();
this.click("span[aria-live='polite']")
Now store options in a list :
var elements = document.querySelectorAll('.elements'); // use
//div[contains(#class,'option')] as element selector.
Now iterate the list :
// Iterate over them.
[].forEach.call(elements, function (element) {
// Manipulate each element.
element.click();
});
});
Related
I am grabbing a copy of some info from a page, but I do not want to include certain <option> elements that appear inside <select> elements on the page.
Therefore, while I grab all the elements I want and am storing them in the variable fields, I check to see if each element is a <select> and if they have the specific <option> that I don't want.
var field = allFields[i].innerHTML; //allFields is the raw HTML I'm iterating through
if ($(field).find("select").length > 0) { //If the element we're looking at contains a select
console.log("Found a select. It is in " + field);
console.log($(field).find(".bad-option");
field = $(field).not(".bad-option").prop("outerHTML"); //Use .not() to remove the elements which have the .bad-option class
// (and .prop("outerHTML") is just there to convert it back to a String instead of a jQuery object)
}
console.log("Adding " + field);
fields[i] = field; //Add the HTML, free of any unwanted options, to the `fields` variable
Based on jQuery's documentation, I would expect the .not() function to remove any elements out of field which have the bad-option class. Yet that is not the case at all. When I log field before and after using .not(), it prints out the same thing. See the console output from the code above:
Found a select. It is in <label>Description: <select><option>thing1</option><option class="bad-option">thing2</option></select></label>
-----------------
[jQuery list object size 1, containing an object called option.bad-option]
-----------------
Adding <label>Description: <select><option>thing1</option><option class="bad-option">thing2</option></select></label>
So what's going on? How do I remove an option with a certain class from from within a jQuery object? Why isn't .not() working?
If I need to clarify anything, please let me know. I tried to make this question as specific as possible and would be happy to elaborate on any details further.
The documentation is perhaps a bit confusing: not removes elements from the selection, not the DOM. If you want to remove the elements, then just filter and remove:
const processed = $(field);
processed.filter(".bad-option").remove();
field = processed.prop("outerHTML");
I am currently writing a Nightwatch test to select a new document from a list. And I will need to be able to select the next in the list. Is there a way to manually override the child number that needs selecting?
For example the current selector being used is :
<ul class="dv-packdocs">
<li class="dv-packdoc"<div class="icon-todo"></li>
<li class="dv-packdoc"<div class="icon-todo"></li>
<li class="dv-packdoc"<div class="icon-todo"></li>
<li class="dv-packdoc"<div class="icon-todo"></li>
</ul>
and the test would be something like :
viewer.selectNewDocument([2])
would this select the second child under the ul?
Or would I have to specify each child element?
If I understand correctly, you are trying to dynamically find the appropriate child element (li) from a dynamical length list (ul, where the list is populated based on user input, or other site actions). Correct?
I see two scenarios with two different approaches:
1. You have a set/fixed condition (way of identifying your target element): for example, in your list, the second li would be targeted by the below command.
viewer.selectNewDocument('ul.dv-packdocs li:nth-child(2)') (considering you are passing a complete selector to the selectNewDocument function)
, or
viewer.selectNewDocument(2), passing a number & form the selector inside the command (if you care for aesthetics):
selectNewDocument: function(index) {
this.api.perform((done) => {
// Click the second document in the list:
let selector = `ul.dv-packdocs li:nth-child(${index})`;
this.api.click(selector);
done();
});
return this;
},
Alternatively, if you would want the last document added, then you would have to issue a elements call on the ul to retrieve the length of the list, then use that in the same way to determine which li you have to click: viewer.selectNewDocument('ul.dv-packdocs li:nth-child('+length+')') (where length is the result of your elements call).
2. You don't have a fixed condition (I'll fill this up if the first part doesn't cover it, or later today, kinda slammed after the holidays)
Hope it's what you were looking for! Cheers!
Lets say I have a table named unitTables with some rows. It is one of many similar tables on the webpage. In those rows is a class called selected, which I want to retrieve for a variable. The other tables on the page also use the selected class, so I need to retrieve this specific instance of selected.
In plain JavaScript, the way to find it is:
var table = document.getElementById('unitTables');
var selected = table.getElementsByClassName("selected");
What's the equivalent to the above two rows in jQuery?
I know I can rewrite the first row like this:
var table = $('#unitTables');
But I know I can't do the exact same thing to the next row, as I need to use to id of unitTables in order to get the specific selected row in that table. Currently I have:
var selected = from.$(".selected");
Which throws an Uncaught TypeError: from.$ is not a function. error, so I know that's not the correct syntax.
What's the best approach?
var table = document.getElementById('unitTables');
var selected = table.getElementsByClassName("selected");
What's the equivalent to the above two rows in jQuery?
var selected = $("#unitTables .selected");
(Except selected will be a jQuery object around the matched set of elements, instead of a collection.)
The jQuery function (jQuery or [usually] $) looks up elements via CSS selectors. So in this case, a descendant selector that looks for .selected within #unitTables.
From the starting point of an element that happens to be a select box (element has a class of: service_category_selection) I want to find another select box (element has a class of: service_selection).
I need to grab specifically the closest element with class: service_selection because I don't want to grab all of the elements with that class.
Snapshot of how far away that first select box is from the second select box:
Assume that $(this) already contains the first select box. Now I just need to draw the route to the closest next select box with the class: service_selection.
I attempted to use .closest but it wasn't working for me.
Example: var el = $(this).closest(".service_selection");
You need to get the overall top parent container - then find the element:
var el = $(this).closest(".row").find(".service_selection");
Doing this kind of navigation is a bit hackish and easy to break since your logic highly rely on your layout. I suggest you to use a unique CSS class on that element and access it directly.
I have a table wherein the first column is a checkbox and the second one has a text.
Whenever, the checkbox is checked, I want to know the corresponding value which is in the next cell.
Please tell me how to do.
If I use the getelementsbytagname function, it returns from the start of the document.
This is quite simple to do without jquery. We have a input inside a td so we can go up a level and get the next sibling:
var nextTd = myInput.parentNode.nextSibling;
Because some browser insert empty text nodes between tds we can do the following to make sure we're on the right node:
if (nextTd.tagName != "TD")
nextTd = nextTd.nextSibling;
Also, FWIW, getElementsByTagName can be called from any Node. Thus, if I have a table, I can call
myTable.getElementsByTagName("tr");
To return all rows inside of myTable.
Assuming you're using jQuery (or some other civilized framework), it's pretty easy:
$('table#yourTableId input:checkbox').click(function(ev) {
if (this.checked) {
// not sure what you mean by "want to know" ...
console.log($(this).closest('tr').find('td:nth-child(2)').html());
}
});
You could do it with the jQuery "live" event facility similarly, which'd be cheaper if there are a lot of checkboxes.
The simplest way would be yo use jQuery or a similar library, that implements CSS3 selectors.
$('table input:checked').parent().parent().find('td.nth-child(2)').text():
You could also bind onto the change events of the checkboxes
$('input:checkbox').change = function(){
val = $(this).parent().parent().find('td.nth-child(2)').text():
}