I am testing a website form using clj-webdriver. I want to know how to use (input-text) function if the form fields have same class.
From the (input-text) definition it gives "Type the string s into the first form element found with query q". Since every field has same class and when I give,
(input-text ".class")
It only fills the first field. Is there any way to differentiate all fields with the same class?
The fields of the form has only class and type as selectors.
Thank you
input-text only fills the first match.
Use quick-fill to fill them all.
E.g.,:
(quick-fill {".class" "s"})
/edit
You say "for 2 fields of same class I have to enter 2 and 3 as values. and also if the class is "object object-done" can I consider class as ".object". I am not exactly sure what you mean with the latter, but what I understand is that you want to add different values to different elements.
If you want to find specific elements you can use find-elements. These will return a collection of elements:
(find-elements {:class ".class"})
This will find all elements with the class ".class" in order which they appear on the page.
If the collection is stored in a variable text can be added to every element via input-text based on index. So for example if you want to add an increasing index to them you can use map-indexed to add the index of every value to the element as follows (doall is called to walk every element in the lazy sequence - function calls are only made when the elements are accessed and doall makes that happen):
(defn fill!
"Fills all elements with class class with increasing numbers."
[class]
(let [elements (find-elements {:class class})]
(doall
(map-indexed (fn [index element]
(input-text element (str index)))
elements))))
This function is called like (fill! ".class").
Hope this helps.
You should use the (find-elements [webelement by]) function, which returns a list of 'webelementsmatching a givenby`.
From the project documentation, that can be found at https://github.com/semperos/clj-webdriver/wiki/Introduction%3A-Taxi , an example is:
(defn css-finder
"Given a CSS query `q`, return a lazy seq of the elements found by calling `find-elements` with `by-css`. If `q` is an `Element`, it is returned unchanged."
[q]
(if (element? q)
q
(core/find-elements *driver* {:css q})))
Related
I am trying to make a CONTAINER class that maintains an array of CRITTER objects (that I have already created and tested. Note, there are various CRITTER subspecies, that are inheriting from the CRITTER super class). The aim is to add and remove CRITTER objects from this array. This is what the CONTAINER class looks like:
class
CONTAINER
create
make
feature
num: detachable INTEGER
list: ARRAY[CRITTER]
make
local
do
create list.make_empty
num := 0
end
addCritter(critter: CRITTER)
do
list.put(animal, num)
num := num + 1
end
removeCritter(critter: CRITTER)
do
list.put (list.at (num), ???) -- put last element in position of element to be removed
list.remove_tail (num) -- remove tail
num := num - 1
end
end
Two issues:
Firstly, I can instantiate the CONTAINER class inside APPLICATION, but when I call
create container.make
container.addCritter(myCritter)
I get a precondition, invalid index violation error on the second line. This may be because I have not set the upper and lower bounds of the array. However, when I try to do so, I get syntax errors. Which is the way to solve this issue?
Secondly, in order to remove an object from the array, it would help if I could get hold of the index value, but I can't see any function that does this, unless I am missing something.
ARRAYs are usually used for fixed-length containers. In your case, with lots of dynamic changes, it's better to use more dynamic structures, for example, ARRAYED_LIST. Similar to ARRAY it provides features to access items by their index, but there are also more convenient ones. New elements can be added by using feature extend. Old elements can be removed by using feature prune if only one element matching a given one needs to be removed, or prune_all, if all matching elements need to be removed. The word "matching" denotes either reference or object equality, depending on which comparison criteria is required: = or ~. The comparison criteria is changed using feature compare_objects.
Some general observations:
There is no need to track number of elements yourself, usually there is a feature count that provides this number.
Indexes in Eiffel usually start with 1, not 0.
The declaration detachable INTEGER is equivalent to INTEGER because INTEGER is expanded and all expanded types are attached regardless of any attachment marks.
The following discussion might also be useful:
How to initialise an array of objects in Eiffel?
I have a SportsCentre class which contains an array of Employee objects.
Which is the right way to show that an attribute's data type is an array of objects?
I have found two different versions online:
the first one uses the ArrayList<> keyword:
SportsCentre
- listOfRegistered : ArrayList<Employee>
getRegisteredList() : ArrayList<Employee>
the second one uses square brackets []:
SportsCentre
- listOfRegistered : Employee[0..*]
getRegisteredList() : Employee[0..*]
Both are correct, but the second one, when multiplicity is set to more than one, is used more naturally, and it is not necessary to define the collection class as it is shown in the first picture of your example.
Simply said, multiplicity defines how many instances of a specific type can be stored by attribute. This set of instances can be ordered, or duplicates in it may be allowed. Parameters of multiplicity elements have an impact on the type of collection which should be used, Set, Vector, Array, etc.
But, if you need precise info about this issue, read UML Superstructure. Search for Property and Multiplicity Element. here is the UML website
Can I filter by.repeater('object in array') so it returns just objects with a specific value in Protractor?
E.g. something like
var filteredElements = element.all(by.repeater('object in array')).column('object.type').value('car'));
Is something like this possible without creating additional loops (and without creating new promises)?
These elements doesn't have any unique identifier? If they have you can do a cssSelector searching for that specific identifier (id, class or any other attributes..)
If they don't have ny unique identifier, the best way to do that is change you FE application to add the class "car" to each element that you want to have, and then, have a selector that retrieves all the element with class "car".
I'm attempting to write a sort function to use with Array.sort(). I'm a bit stuck on how I can write exactly what I need though.
In my app items are added to this array at different times throughout execution, and each time an item is added, the array is sorted. The items in the Array are all objects and all have a property "weight". If a weight is greater, the item should go first, if it's less the item should go after. That is easy and I have a function that looks like this:
return a.weight - b.weight;
The problem is I have an added requirement that if an item is added later and it has the same weight as another item it MUST be put after that item in the array. It MUST go behind every item in the array that has already been added which has the same weight.
I'm having trouble coming up with a function to make sure that requirement is met every time.
Thanks for the help!
No need for writing a custom sort, the Array's sortOn can handle this case.
You will however need to add a new member to your items, I'll call it 'timestamp'.
arr.sortOn( [ 'weight', 'timestamp' ], [ Array.NUMERIC | Array.DESCENDING, Array.NUMERIC ] );
The first parameter defines which properties will be used for sorting, the second defines the options for each field. See http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#sortOn() for more info.
The |-operator (bitwise OR-operator) is used to pass multiple options for one field.
So, in this case, the first field ('weight') gets sorted numerically and descending.
--EDIT:
For Vectors you need to use a comparison function:
var sortFunc : Function = function (x: <T>, y : <T>):Number{
var dw:Number = y.weight - x.weight
if( dw ==0 ){
//returns negative if y was added later
return x.timestamp - y.timestamp;
}else{
//returns negative if x has a higher weight
return dw;
}
}
vec.sort( sortFunc );
I would suggest to add another property to the object. Something like :
a.index = i; // where, i is the index before sorting
This will allow you to keep track of the order it entered the list before sorting.
Besides this you may also consider keeping another copy of the array itself (with index intact).
I've got a page containing multiple elements of class .block. In Capybara, I want to be able to loop through and refer to each of the elements with this class before completing an action.
However, none of the code I've tried so far has worked. Here's what I've tried:
within('.block:nth-child(1)') do
find('.Button').click
end
page.find('.block').all.first.find('Button').click
page.find('.block').all[1].find('Button').click
Any ideas?
You want to use the all method (see http://rubydoc.info/github/jnicklas/capybara/Capybara/Node/Finders#all-instance_method).
An example of outputting the text of each element (ie iterating) with class 'block' would be:
page.all(:css, '.block').each do |el|
puts el.text
end
page.all returns an array of matching elements. So if you just want the second matching element, you can do:
page.all(:css, '.block')[1] #Note that it is 0-based index