Capybara - usage of applying has_xpath? on an apath with variable - capybara

There is the structure like:
<div class="parent">
<div>
<div class="fieldRow">...</div>
</div>
<div>
<div class="fieldRow">
<div class="CheckBox">
</div>
</div>
<div>
<div class="fieldRow">...</div>
</div>
<div>
<div class="fieldRow">...</div>
</div>
</div>
In my script I am writing a loop for each of the 4 div's under div[#class='parent'] and aiming to click the checkbox if there is, i.e.
members = page.all(:xpath, '//div[#class='parent'])
members.each do |a|
if **page.has_xpath?(a).find(:xpath, "div[#class='fieldRow']/div[#class='CheckBox']")**
a.find(:xpath, "div[#class='fieldRow']/div[#class='CheckBox']").click
end
end
However I can't look for the correct usage of has_xpath? with xpath including variable.
Please advice? Thank you!

has_xpath? takes an XPath expression (not an element) and returns a boolean (true/false) based on whether there are any elements that match that expression within the current scope - http://www.rubydoc.info/gems/capybara/Capybara/Node/Matchers#has_xpath%3F-instance_method. Since it returns true/false you can't then call find on it. For the example you posted there's no need for XPath or checking for the existence of the elements, just find all the matching elements and call click on them. Something like
page.all('div.parent div.fieldRow div.Checkbox').each { |cb| cb.click }
or
page.all('div.parent div.Checkbox').each { |cb| cb.click }
if the fieldRow class isn't something you really need to check.
Note: this assumes clicking the elements doesn't invalidate any of the other matched elements/change the page.
If you REALLY need to do it with the whole members and looping on them , using XPath, and checking for presence then it would be something like
members = page.all(:xpath, './/div[#class='parent'])
members.each do |a|
if a.has_xpath?(:xpath, ".//div[#class='fieldRow']/div[#class='CheckBox']")
a.find(:xpath, ".//div[#class='fieldRow']/div[#class='CheckBox']").click
end
end
Note: the .// at the beginning of the XPath expressions is needed for scoping to work correctly - see https://github.com/teamcapybara/capybara#beware-the-xpath--trap - which is an issue using CSS selectors doesn't have, so you should really prefer CSS selectors whenever possible.

Related

Cannot pass model attribute in thymeleaf th:each

I'm trying to iterate over a list and pass the current iteration and another model variable to a fragment, but the "other" model variable is always null.
<div th:each="place : ${results.placeResults}" class="col-sm-6 col-xl-4 mb-5">
<div th:replace="fragments/placecard :: placecard" th:with="place=${place},res=${results}"/>
</div> <!-- end for each-->
In the fragment ${res} is always blank.
I figured it out, the th:replace basically makes the th:with have no effect. I changed the code to use th:include and things look better.

Angular 2 Dart: Template syntax - how to concatenate strings?

Feels like a dumb question but I do not get it. How can I do fast string concatenation in Angular 2 Dart templates?
I have a seperate html file for my component lets say my_component.html:
Works:
....
<div id="abc">
{{order.pickupPlace.email}}
</div>
...
Works:
....
<div id="abc">
{{ ((order.pickupPlace.state) ? order.pickupPlace.state+" ":'')}}
</div>
...
Does not work:
....
<div id="abc">
{{"<br/>"+order.pickupPlace.email}}
</div>
...
Does not work:
....
<div id="abc">
{{order.pickupPlace.name+" "+order.pickupPlace.email}}
</div>
...
Have tried to find an answer in the docs here (https://webdev.dartlang.org/angular/guide/template-syntax#!#expression-operators) but no luck.
Of course I could use *ngIf on every element which I output conditionally but is there a way for simple string concatenation?
The best way is to declare a getter inside your Component controller that does the concatenation for you, you will get dart syntax support and the html template will looks cleaner.
String get myConcatenation => "${order.pickupPlace.name}${order.pickupPlace.email}";
<div id="abc">
{{myConcatenation}}
</div>
The last two examples can be made to work easily:
<div id="abc">
<br/>{{order.pickupPlace.email}}
</div>
And:
<div id="abc">
{{order.pickupPlace.name}} {{order.pickupPlace.email}}
</div>
Angular handles this pretty well. If you need some more complicated logic you can move it to the Dart code (but you cannot use HTML there easily).
If you find creating lot of weird logic consider creating more smaller components that can handle this for you.

Get a value of element in ruby cucumber

i am making my first steps in writing cucumber features in Ruby On Rails application and am struggling with getting a value of an element.
The structure is something like this:
<div class="selectize-dropdown-content">
<div data-value="test1" data-selectable="" class="option">TEST 1</div>
<div data-value="test2" data-selectable="" class="option">TEST 2</div>
</div>
I would like to get the value of the div element when the data-value is "test1" ... so, TEST 1
Currently I am doing it this way:
within(:xpath, '//div[#class="selectize-dropdown-content"]') do
find(:xpath, '//div[#data-value="' + value + '"]')
end
But it fails for not finding the "within" div.
So, I guess I am doing it wrong.
How does one go about it?
Thx
You need to call text method on the desired element
within('.selectize-dropdown-content') do
find(:xpath, "//div[#data-value='#{value}']").native.text
end
if there's a parent element for your block of code with ID you can do it like:
text = page.find('#parentID div:nth-child(1) div:first-child', visible: true).text
if you don't try it with javascript
text=page.evaluate_script('document.getElementsByClassName("selectize-dropdown-content")[0].getElementsByTagNam("div")[0].value')

Select unique set of nodes with XPath?

I want to select a set of elements as nodes (the content of div[#class="Adres"]):
<div class="KolumnaStyl">
<div class="Nazwa">ABCD</div>
<div class="Adres">
12-345 Warszawa
<br/>
ul. Krasnobrodzka 5
<br/>
Mazowieckie
This can be done with:
//div[#class="KolumnaStyl"]/div[#class="Adres"]/node()
As it happens, there are two identical div[#class="Adres"] on the page, which means that node() currently selects the content of both of them. I can't, however, call //div[#class="KolumnaStyl"][1] - that doesn't select the first occurrence.
How can I select a unique set of nodes if the parent directory exists multiple times?
Take a look at "XPath Get first element of subset".
Basically, predicates have higher precedence than the / and // operators.
So, (//div[#class="KolumnaStyl"]//(div[#class="Adres"]))[1] should return your desired result.
Also check out the spec for more background info.
If you want the first matched one, then do :
(//div[#class="KolumnaStyl"]//div[#class="Adres"])[1]/node()
In XPATH first means 1, not 0.
Here is a sample HTML :
<body>
<div class="foo">
<p> 12 </p>
</div>
<div class="foo">
<p> 112 </p>
</div>
</body>
XPATH expression:
(//div[#class = 'foo'])[1]
output
<div class="foo">
<p>12</p>
</div>

Inserting HTML elements on rails view

I have a view with a bunch of elements in it.One of them (a div) is shown depending of a value that changes inside a select_tag (also within the same page).
I'm getting the selected ID from the select_tag element
$('#some_id').on('change',function(){
//$(this).val()
})
but then just don't know how to fetch the object and check for one of its properties and that way know if I should show the div or not?.
I thought of sending that id to the server...do whatever I need over there and then come back to the view and try something like this
<% if some_condition %>
<div>
...
</div>
<% end %>
This (of course) might not be the way.I'd be glad to understand how this happens
You way of doing it after getting some data from the server onChange of the select would work. You might also consider this approach.
But if you could pre-populate the divs and add a class or some other attribute it with which you could relate to the chosen option in the select field, then you can prevent the server call entirely.
<div class="opt1Val selectOptsDiv"> </div>
<div class="opt2Val selectOptsDiv"> </div>
<div class="opt3Val selectOptsDiv"> </div>
hide all these divs initially with css display: none;.
$('#some_id').on('change',function(){
var selectedOptionVal = $(this).find("option:selected).val();
$("." + selectedOptionVal).show();
})
But I guess you would be able to do this if the showing and hiding of the div's depend only on the selected option value and do not have to go through some other processing at the server end.

Resources