Traverse the tree with Capybara - cucumber

I want to do something that I think should be quite simple but can't work it out.
Using Cucumber and Capybara
In a table I want to click a button in the same row, but a different cell.
i.e. I want to find the button 'Change Role' that is in the same row as the name "Bob Perkins"
click_button "Change Role" within
I want to do something like
within find("td", text:"Bob Perkins").parent #where this would be the "tr" row
click_link_or_button("Change Role")
But that's giving me an ambigous match on "Change Role". Sure, there are more on the page, but only one of them is in the parent node of where it should be...

I'm not sure how many people are fluent in xpath, but if you find it as confusing as I do, you can chain finds to utilize xpath only as necessary. So for instance:
find("td", text:"Bob Perkins").find(:xpath, '..') # Gives you the TR

After having a bit of a play with capybara it looks as if the parent method returns the whole html document
e = find "table > thead"
=> #<Capybara::Element tag="thead">
e.parent
=> #<Capybara::Document>
The default selector type for capybara is CSS and that does not support the parent selector
It may be worth looking at XPath as with XPath you can perform a contains
e = find :xpath, "//table[thead]"
=> #<Capybara::Element tag="table">
e = find :xpath, "//table[thead]", text: "TOTAL"
=> #<Capybara::Element tag="table">
So looking at your code you could try this:
e = find :xpath, "//tr[td[contains(text(),'Bob Perkins')]]"
=> #<Capybara::Element tag="tr">
OR
e = find :xpath, "//tr[td]", text: 'Bob Perkins'
=> #<Capybara::Element tag="tr">
So you should get something like this
within find(:xpath, "//tr[td[contains(text(),'Bob Perkins')]]") do
click_link_or_button("Change Role")
end
Best of luck.

You are almost close the answer.
Corrected one is the:
within(find("td", text:"Bob Perkins").parent){ click_link_or_button("Change Role") }

Related

Can't acess dynamic element on webpage

I can't acess a textbox on a webpage box , it's a dynamic element. I've tried to filter it by many attributes on the xpath but it seems that the number that changes on the id and name is the only unique part of the element's xpath. All the filters I try show at least 3 element. I've been trying for 2 days, really need some help here.
from selenium import webdriver
def click_btn(submit_xpath): #clicks on button
submit_box = driver.find_element_by_xpath(submit_xpath)
submit_box.click()
driver.implicitly_wait(7)
return
#sends text to text box
def send_text_to_box(box_xpath, text):
box = driver.find_element_by_xpath(box_xpath)
box.send_keys(text)
driver.implicitly_wait(3)
return
descr = 'Can't send this text'
send_text_to_box('//*[#id="textfield-1285-inputEl"]', descr)' #the number
#here is the changeable part on the xpath
:
edit: it worked now with the following xpath //input[contains(#id, 'textfield') and contains(#aria-readonly, 'false') and contains (#class, 'x-form-invalid-field-default')] . Hopefully I found something specific on this element:
You can use partial string to find the element instead of an exact match. That is, in place of
send_text_to_box('//*[#id="textfield-1285-inputEl"]', descr)' please try send_text_to_box('//*[contains(#id,"inputEl")]', descr)'
In case if there are multiple elements that have string 'inputE1' in id, you should look for something else that remains constant(some other property may be). Else, try finding some other element and then traverse to the required input.

Is it possible to find elements in SitePrism fields with case insensitive values?

I've got the following element texts in two labels of an object I need to find with SitePrism:
'Correct date'
'correct date'
Is it possible to find such an element by using a case insensitive expression in SitePrism? I was trying the following but I'm getting an error:
element :correct_date, :field, "/correct date/i"
ERROR: Unable to find field "/correct date/i" (Capybara::ElementNotFound)
The expression above even fails when it's an exact match, for whatever reason :S
Any idea what I could try?
Short answer : No
Longer answer: The Capybara locators (which is what the string associated with the selector type of :field is) are strings and do not accept regexps. This is because they are implemented via XPath and most (if not all) browsers only support XPath 1.0 so there is no regex support there. Most selector types do support the :text option but that is applied to the result element, not to any other elements that may be used to find the result element (in this case it would apply to the field element not the label). So if you were looking for the actual label elements you could do
element :correct_date_label, :label, nil, text: /correct_date/i
One potential way to get what you want is to just use an xpath selector, either using the current Capybara selectors to help or writing your own custom XPath that would match both case versions, something along the lines of
element :correct_date, :xpath, (Capybara::Selector.all[:field].call('Correct date') + Capybara::Selector.all[:field].call('correct date')).to_s # might need to be | instead of +
or
element :correct_date, :xpath, ".//*[self::input | self::textarea | self::select][not(./#type = 'submit' or ./#type = 'image' or ./#type = 'hidden')][./#id = //label[(contains(normalize-space(string(.)), 'Correct date') or contains(normalize-space(string(.)), 'correct date'))]/#for] | .//label[(contains(normalize-space(string(.)), 'Correct date') or contains(normalize-space(string(.)), 'correct date'))]//.//*[self::input | self::textarea | self::select][not(./#type = 'submit' or ./#type = 'image' or ./#type = 'hidden')]"
but that's starting to get a bit complicated

Watir cycle through class elements

How can I cycle through all the elements?
I'm looking for something like:
brower.text_field[0](:name, "asdf").click # get the first element
brower.text_field[1](:name, "asdf").click # get the second element
Is there a good documentation for more advanced stuff?
I haven't found anything useful all I got is simple stuff but I'm looking for something where I can chain elements like:
browser.tr(:id, "asdf").td.click
Thank you for your time.
For what you have described you can simply use the :index attribute:
brower.text_field(:name => "asdf", :index => 0).click # get the first element
brower.text_field(:name => "asdf", :index => 1).click # get the second element
Or loop over all text_fields with attribute :name => "asdf":
browser.text_fields(:name => "asdf").each { |elem| elem.click }
To cycle through all matching elements, you are looking for "element collections".
Basically you need to pluralize the method used to get elements and then you can use the [] to get a specific index:
brower.text_fields(:name, "asdf")[0].click # get the first element
brower.text_fields(:name, "asdf")[1].click # get the second element
The element collection includes Enumerable, so there are also a variety of methods for iterating.
In terms of documentation, you can look into:
The Ruby Docs - http://rubydoc.info/gems/watir-webdriver
There are also a couple of in progress books on Leanpub if you search for Watir - https://leanpub.com/book_search?search=watir

modx how to filter out all resources with pagetitle starting on a spesific letter?

I have this resources with pagetitles:
Resource-tree at svalbardflora.net http://svalbardflora.net/modxrev/svalbardflora_net_modxrev_manager_index_php.png
How can I, in getResources, filter out only the documents with pagetitle starting on p or a to b or e to g (and not a container, but I know how to do that part)?
Xpdo query example:
$c = $modx->newQuery('modResource');
$c->where(array(
'pagetitle:REGEXP' => '^([a-b]|[e-g]|p){1}(.*)$'
,'isfolder' => 0
));
$d = $modx->getCollection('modResource',$c);
If you'd like to use this in getResources snippet just add pagetitle and isfolder condition to "where" property like this has been done there
Thanks to #proxyfabio for great help and to guide me in the right direction.
I got the easiest way thanks to #sottwell in the modx forums:
&where=`{"pagetitle:LIKE":"p%"}`
and
&where=`{"pagetitle:LIKE":"l%","OR:pagetitle:LIKE":"m%","OR:pagetitle:LIKE":"n%","OR:pagetitleon:LIKE":"o%"}`
As easy as that.

In Watir, how to get the full text, from a portion of text?

I have a portion of HTML that looks similar to:
<table><tbody><tr>
<td><div> Text Goes Here </div></td>
<td> ... rest of table
There are no IDs, no Titles, no descriptors of any kind to easily identify the div that contains the text.
When an error occurs on the page, the error is inserted into the location where "Text Goes Here" is at (no text is present unless an error occurs). Each error contains the word "valid".
Examples: "The form must contain a valid name" or "Invalid date range selected"
I currently have the Watir code looking like this:
if browser.frame(:index => 0).text.includes? "valid"
msg = # need to get full text of message
return msg
else
return true
end
Is there any way to get the full text in a situation like this?
Basically: return the full text of the element that contains the text "valid" ?
Using: Watir 2.0.4 , Webdriver 0.4.1
Given the structure you provided, since divs are so often used I would be inclined to look for the table cell using a regular expression as Dave shows in his answer. Unless you have a lot of nested tables, it is more likely to return just the text you want.
Also if 'valid' may appear elsewhere then you might want to provide a slightly larger sample of the text to look for
. browser(:cell => /valid/).text
Try this
return browser.div(:text => /valid/).text
or
return browser.table.div(:text => /valid/).text
if the valid is not found, it should return nil.

Resources