collect all xpath results into an array in ruby - ruby

I have a very poorly coded JSP that I am trying to run automation on. There are a series of checkboxes with names (no IDs) of "delete[x]" where X is the item number of the item populated. I am trying to select all the checkboxes so I can delete every entry. Here is what I have
check_boxes = []
check_boxes.push(#browser.checkbox(:xpath, "//input[contains(#name,'delete')]"))
puts check_boxes.size
check_boxes.each do |check_box|
check_box.set
The problem with this is it only selects the first instance (node) that matches the xpath to dump into the array. I know I can iterate through the xpath adding an index to the node, and then put a rescue in that drops me out when the index goes out of bounds, but that seems like the dirty way to do it.
I know there is an "as" tag that gets a set of anchors and i was wondering if there was a method like that for taking the whole selection of checkboxes

I don't think the problem is the xpath itself. It is the #browser.checkbox that is causing only the first checkbox to be returned.
If you want all matching checkboxes, you should use (notice the plural):
#browser.checkboxes
Note that checkboxes returns a collection of checkboxes. Unless you are doing something really fancy, you usually do not need to convert it to an array.
You can simply do:
#browser.checkboxes(:name => /delete/).each do |checkbox|
checkbox.set
end

Related

Using selectAll in d3.js

I would like to selectAll X that have the properties Y and Z. For instance, I would specifically like to select all lines with an ID of d.id AND a target of d.target. It's the 'and' part that I can't figure out; I assumed from the documentation that it should be something like this:
selectedLine = d3.selectAll("line[id="+d.id+"]").selectAll(line[target="+d.target+"]");
But calling selectAll on a selection always returns an empty selection to me, regardless of the contents (In this case, I'm certain that exists one line with an ID of d.id and a target of d.target).
I suspect that target is not an attribute that the line element but a data property instead. Besides that, calling selectAll on a selection does not return an empty selection: you probably have some other problem. Finally, pay attention to the fact that you are using selectAll with an ID, which makes little sense: IDs have to be unique.
Anyway, whatever you are using in those attribute selectors, you can simply use multiple attribute selectors:
selectedLine = d3.selectAll("line[id='foo'][target='bar']")
According to the documentation:
Multiple attribute selectors can be used to refer to several attributes of an element, or even several times to the same attribute.
Here, the selector matches all SPAN elements whose "hello" attribute has exactly the value "Cleveland" and whose "goodbye" attribute has exactly the value "Columbus":
span[hello="Cleveland"][goodbye="Columbus"]

How can an Xpath be written for search results that change

I have a scenario where i am filling a search field with text 'A' and it returns a bunch of results. These results are always changing and i simply want to select the first 5 options. How is it possible to write an Xpath for this. I am trying to write an acceptance test using codecption
.//*[#id='js_search_table_filter'] - is the search table filter. I enter A with this below
$this->fillField($_sSelectSearchXPath,"A");
The xpath element when i click on the tick box option for the search results are like
.//*[#id='assign-9488'].
<label class="checkbox checked" for="assign-9488">
Note that the numbers vary and they are not in any chronological order.
I'm not sure if this is what you're after, but if you need the first 5 elements of a nodeset, you can suffix it with:
[position() <= 5]
Example:
<a>
<b>1</b>
<c>2</c>
<d>3</d>
<e>4</e>
<f>5</f>
<g>6</g>
</a>
If you want to get elements from b to f, you can run /a/*[position() <= 5].
I am not sure how codeception/php version works but in ruby (watir or pageobjectgem) you can identify all elements with a reqular expression or a partial match
the element would look like:
checkboxes(:your_element_name, :id => /assign/)
Notice the difference between checkbox and checkboxes which returns all checkboxes which have id containing assign.
In Java Webdriver, you have
driver.findElements(By.xpath("//checkbox[contains(#id,'assign')]"));
Both representatinos (ruby and java) return an array of elements where the Java solution is using xpath. The element you mentioned is a label, if you are looking for the checkbox, it is possibly a child element of this label and the xpath will be
//label[contains(#for,'assign')]/checkbox
Basically, you can use "contains" method in xpath to identify your element. You can then take the first five elements of the array.
I used this guys and tried to select all the tickboxes in the dropdown
(.//*[#type='checkbox'])[1]

App Inventor TinyWebDB List Problems

I got a problem using the TinyWebDB in App Inventor 2. Here's a Screenshot of the blockcode.
The goal of this Screen is to store a list(array) of images and later query them with a button but my problem starts already earlier. First there is a variable initialized called fotoList and declared as an empty list.
When this Screen initializes (left block) I store the empty fotoList under the tag FotoListTag. Then if the image under the tag "SteckbriefFoto" is not in this list -> getValue with tag "FotoListTag". Then he jumps into the block on the right and adds the photo .. other stuff not important .. at the end I store the list again in the TinyWebDB (and also in the TinyDB) with the tag "FotoListTag". Then it goes back to the block on the left where at the end I want to set an image.picture to the photo I stored in variable fotoList.
When I compile the code there is an error opening the page that says
Select list item: List index too large
Select list item: Attempt to get item number 1 of a list of length 0:()
I just don't get the problem with this code and i hope someone can help me.
For lists, valueIfTagNotThere should be create empty list instead of an empty string
On first run of your app, TinyDB is empty, which means, for tag = FotoListTag you get no value back, therefore this should be an empty list in the beginning.
Later you are trying to select the first item from the list (zahl is 1). As you know, the list is empty in the beginning, so probably you should add an if statement to check, if the list is not empty and only then select the first item... same for tag = Schriftlist.
You also have a timing issue. in Screen.Initialize you are trying to get a value from TinyWebDB. This is an asynchronous call, you get the result back in TinyWebDB.GotResult event and this takes a little bit (let's say 500 milliseconds), but meanwhile the complete blocks of the Screen.Initialize event will be executed. Probably you are expecting, that meanwhile tag = FotolistTag is not empty anymore, but this is not the case.

Selenium find element which have no attributes but have parents with same attributes

I am trying to find XPath of an element which has no attribute. It can only be identified by its parent's attribute. However, the parent also does not have unique attribute.
Eg: //*[#id="btn"][1]/ul/li[2]/a/span
Here there are 2 elements with id=btn. How do i get the 2nd element. The above syntax gives me 1st element.. However if i use:
//*[#id="btn"][2]/ul/li[2]/a/span
I get an error message
"The xpath expression '//*[#id="btn"][2]/ul/li[2]/a/span' cannot be evaluated or does not result in a WebElement "
Try this, you select those two first, then use brackets around and index them.
(//*[#id="btn"]/ul/li[2]/a/span)[2]
By the way, it's not a good practice to have multiple elements sharing same ids, if you are the developer, may consider change them.

Prototype $$ returns array, should return one element like $

When using the dollar-dollar-function in prototype I alway get an array of elements back, instead of just one element with the dollar-function. How can I combine the power of CSS-selectors of $$ but still get only one element back?
Changing the structure of the source is not possible, so I can't just select it with the id. It needs to get selected with CSS, but should just return one element.
You can also do
$$('.foo').first()
It looks cleaner than $$('.foo')[0] for my taste :)
It does not make sense to return a single element when selecting by class name because potentially there could be many elements in the DOM that have this class. So you could always use the first element of the returned array if you are sure that it will be unique.
$$('.foo')[0]

Resources