VBA how use Selectquery to get next match - vba

The following line will the selected first CSS selector matched, but how do I select next match
ie.Document.getElementsByTagName("iframe")(0).contentDocument.querySelector("option[value='2']").Selected = True
Html code
<div class="col-xs-10 col-sm-9 col-md-6 col-lg-5 form-field input_controls"><input name="sys_original.incident.impact" id="sys_original.incident.impact" type="hidden" value=""><select name="incident.impact" class="form-control" id="incident.impact" style="direction: ltr;" onchange="onChange('incident.impact');" mandatory="true" ng-non-bindable="true"><option value="">-- None --</option><option value="1">1 - High</option><option value="2">2 - Medium</option><option value="3">3 - Low</option></select></div>
The other one
<div class="form-group is-required" id="element.incident.urgency"><div id="label.incident.urgency" nowrap="true" type="choice" data-type="label" choice="1"><label class=" col-xs-12 col-md-3 col-lg-4 control-label" dir="ltr" onclick="return labelClicked(this);" for="incident.urgency"><span title="" class="required-marker label_description" id="status.incident.urgency" aria-label="Mandatory - must be populated before Submit" data-original-title="Mandatory - must be populated before Submit" oclass="" mandatory="true"></span><span title="" class="label-text" data-original-title="Measure of the business criticality based on the impact and on the business needs of the Customer" data-html="false">Urgency</span></label></div><div class="col-xs-10 col-sm-9 col-md-6 col-lg-5 form-field input_controls"><input name="sys_original.incident.urgency" id="sys_original.incident.urgency" type="hidden" value=""><select name="incident.urgency" class="form-control" id="incident.urgency" style="direction: ltr;" onchange="onChange('incident.urgency');" mandatory="true" ng-non-bindable="true"><option value="">-- None --</option><option value="1">1 - High</option><option value="2">2 - Medium</option><option value="3">3 - Low</option></select></div><div class="col-xs-2 col-sm-3 col-lg-2 form-field-addons"></div></div>

Getting aNodeList of all elements with option tags in the frame:
You should be able to get a nodeList with using the querySelectorAll method of document, rather than just querySelector. The CSS pattern would switch from specifying the exact value for the attribute value e.g. value='2', to a more general, elements with option tag having attribute value i.e.
ie.Document.getElementsByTagName("iframe")(0).contentDocument.querySelectorAll("option[value]")
But it looks like this will bring back more nodes than you may require due to multiple dropdowns with option tags. It is hard to say without more HTML to test with.
Being more selective:
Ideally, you want to add in an additional selector to the CSS selector query that narrows this down with an id or className etc that limits to just nodes of interest. Then index into that list, from 0, to set various options.
E.g. for the first of the two selection lists you shown you can isolate with the following CSS selector, to get a nodeList of the possible options:
select[id=incident.impact] option
N.B. The second list can be obtained with select[id=incident.urgency] option.
CSS query:
So, when you apply the CSS selector with the .querySelectorAll method you should get a nodeList matching the above elements. You can then access by index:
Dim aNodeList As Object, i As Long
Set aNodeLIst = ie.Document.getElementsByTagName("iframe")(0).contentDocument.querySelectorAll("select[id=incident.impact] option")
For i = 0 to aNodeList.Length - 1
Debug.Print aNodeList.item(i).outerHTML
Next i
Select a specific node:
aNodeList.item(2).Selected = True '<== Medium, as shown in query results image above
tl;dr
If you literally want the next option on from your current, provided you aren't at the end of the list, you can use an adjacent sibling selector of:
select[id=incident.urgency] option[value=2] + option
Where the + option specifies to select the next element with option tag after the element with id incident.urgency and option tag with attribute value=2.
In this case, it would select option 3 = Low.
If you were at option 1, not 2, it would be select[id=incident.urgency] option[value=1] + option etc.

Related

How to write xpath for a field and validate the fields

I have a requirement to verify field name and values. My code looks like
<div class="line info">
<div class="unit labelInfo TextMdB">
Reference #:
</div>
<div class="unit lastUnit">
701
</div>
</div>
</div>
<div class="line info">
<div class="unit labelInfo TextMdB">
Registered Date:
</div>
<div class="unit lastUnit">
05/05/2020
</div>
</div>
I gave my xpath as
"//div[#class='unit lastUnit']//preceding-sibling::div[#class='unit labelInfo TextMdB' and contains(text(),'Reference #:')]".
With this xpath I am able to reach "reference#" field . But how to verify reference # field is displaying the value (in this case 701) .
Appreciate your response.
Thanks
You can first reach the Reference # text by using its text in the xpath and then you can use following-sibling to fetch the div tag and then use getText()(java) / text (python) method to get 701.
(Edited answer after OP's comment)
If you want to check if the element is displayed on the page or not then you can fetch its list and check if the size of that list is greater than 0 or not.
You can do it like:
In Java:
List<WebElement> elementList = driver.findElements(By.xpath("//div[#class='line info']//div[contains(text(),'Reference #')]//following-sibling::div"));
if(elementList.size()>0){
// Element is present on the UI
// Finding its text
String text = elementList.get(0).getText();
}
In python:
elementList = driver.find_elements_by_xpath("//div[#class='line info']//div[contains(text(),'Reference #')]//following-sibling::div")
if (elementList.len>0):
# Element is present
# Printing its text
print(elementList[0].text)

Any suggesstions to locate the below elements in Selenium

Example HTML below. I want to locate the elements which contains the text Person Attributes and Age.
<div id="ext-gen210" class="x-tool x-tool-toggle"></div>
<span id="ext-gen214" class="x-panel-header-text">Person Attributes</span>
</div>
<div id="ext-comp-1071" class=" DDView ListView" style="height: auto;">
<p class="dragItem "><i class="icon-Gen"></i>Age</p>
</div>
Note: I am looking for a solution without using xpath or id or className as they might change with every new release of my website.
I tried to locate them using
'name' --> By.name("Person Attributes") and By.name("Age") but both failed.
By.name would check for the name attribute. What you need is to check the text of an element using By.xpath:
By.xpath('//div[span/text() = "Person Attributes"]')
Or, you can also check that an id element starts with ext-gen:
By.xpath('//div[starts-with(#id, "ext-gen")]')

WebDriver - finding sibling elements

I have a html markup like this:
<html>
...
<body>
....
<fieldset>
<legend>Other Details</legend>
<div>
<input type='text' id='txt1' title='Detail 01'/>
</div>
<div>
<input type='text' id='txt2' title=''/>
</div>
<div>
<input type='text' id='txt3' title=''/>
</div>
<div>
<input type='text' id='txt4' title='Detail 04'/>
</div>
</fieldset>
.....
<body>
</html>
This is what I want to do.
I need to rapidly traverse the screen, pick up all the textboxes and their titles. When I encounter a textbox that has no title (like two of them in my above example), I need to check if they occur under a fieldset, which they do. Now, for these textboxes without a title, all I have to do is to take the legend value of the fieldset and assign it to the textbox.
For example, the second and third textboxes in the above example do not have a title. In this case I want to do the following:
Take the legend value of the containig fieldset (in this case, "Other Details")
Derive the position of the textbox in the fieldset and append it to the fielset legend like Other Details 2
Do the same thing for the third textbox.
I achieved step 1. When I am in step 2, I need to find out the position of the textbox in the parent fieldset. I have my selenium webdriver code below:
WebElement textbox = driver.findElement(By.id("txt2"));
List<WebElement> precedingSiblings =
textbox.findElement(By.xpath("preceding-sibling::input[#type='text' or #type='Text' or #type='TEXT']"));
String myTitle =
fieldSetLegend + " " + Integer.toString(precedingSiblings.size()+1);
I expect this code to give me the value of myTitle to be Other Details 2 and Other Details 3 for my second and third textboxes.
But the problem is, everytime I hit precedingSiblings.size(), it always returns 0. That is because each input is contained within a div and hence has no siblings.
Now, I want to know of a way through which I can find at what position my current element is within the containing fieldset.
Please help.!!!
What about navigating to the parent div finding it's preceding sibling & then finding the relevant input from there.
Roughly:
parent::div/preceding-sibling::div/input[#type='text' or #type='Text' or #type='TEXT']

Click checkbox with Nested Elements in Watir

I'll try to keep it simple.
I have a list of similar rows like this:
HTML code:
<li ...>
<div ... >
<some elements here>
</div>
<input id="121099" class="containerMultiSelect" type="checkbox" value="121099" name="NodeIds">
<a ...>
<div ... />
<div ... >
<h2>Identified Text</h2>
<h3>...</h3>
</div>
</a>
</li>
I want to click the checkbox with a certain text, but I can't use any of its elements, because they are the same for all the list, and id is generated automatically. The only thing can be differentiated is the h2 text. I tried :
browser.h2(:text => /Identified/).checkbox(:name => "NodeIds").set
and I got UnknownException which is obvious because checkbox is not nested with a tag.
What can I do in this case?
Thanks
The h2 and checkbox are related by the li, which is a common ancestor. Therefore, to find the checkbox, you can look for the li that contains the h2 element. I find the most readable approach to doing this is by using the find method of the element collection. The find method basically allows you to make custom locators.
The code would be:
parent_li = browser.lis.find do |li|
li.h2(:text => 'Identified Text').present?
end
parent_li.checkbox.set
Notes:
browser.lis creates a collection of all li elements.
find iterates through the lis and returns the first element that has the block evaluate as true - ie the first li where an h2 with the specified text is present.
First have a look at this explanation
http://jkotests.wordpress.com/2012/12/20/finding-a-parent-element-that-matches-a-specific-criteria/
Now following a similar approach,
First locate the element that has a unique identifier
parent=#browser.h2(:text=>"Identified Text")
Now we have to iterate over to the parent element which contains both the checkbox and text against it.
parent=parent.parent until parent.tag_name=="li"
Once the control is on the li element, simple click on the checkbox using.
parent.checkbox.click

How do i set the id in WinJS.Binding.Template in a Win8 App

The following html is not working for me.
<div id="weightListViewTemplate" data-win-control="WinJS.Binding.Template">
<span data-win-bind="innerText: name; id: id"></span>
</div>
<div id="basicListView" style="width:420px;height:600px" data-win-options="{ itemTemplate: select('#weightListViewTemplate') }"
data-win-control="WinJS.UI.ListView">
</div>
The list appears but the ID property is not set on the span objects.
How to a set the id of the span dynamically in the template based on the corresponding value in the datasource/array?
I wouldn't recommend using the actual ID property. I believe you can't set it through data binding -- I believe WinJS uses ID's on elements under the covers to allow for weak-references to the DOM elements. Because of this it doesn't let you set the ID.
I would suggest using another property or attribute instead.