Is it possible to select multiple equal elements in capybara? - cucumber

I'm starting to study automated testing with the following gems capybara,cucumber,SitePrism,webdriver, one thing I see a lot happening in my tests is Input type fields if they repeat.
Some like that:
<input type="text" placeholder="some cool text"/>
<input type="text" placeholder="some cool text"/>
<input type="text" placeholder="some cool text"/>
So I'm wondering, if it is possible to define some value in all fields at the same time, something like:
site.find('[placeholder="some cool text"]').set('A simple string')
I'm having trouble finding an answer to that, there would be no problem making loops to define one at a time, but I have no idea how to select them at the same time.

find is limited to returning one element, if you want multiple you'll want to use all. Using Capybara something like
page.all('input', text: 'some cool text').each do |inp|
inp.set('A simple string')
end
would do what you're asking. If you wanted to make sure it was exactly 3 matching elements that were handled you would use the count option (there arealsominimum, maximum, and between` options available)
page.all('input', text: 'some cool text', count: 3).each do |inp|
inp.set('A simple string')
end
Update: Since you've updated the question you could do
page.all("input[placeholder='some cool text']", count: 3).each do |inp|
inp.set('A simple string')
end
but I would probably use the Capybara provided selector types like
page.all(:fillable_field, placeholder: 'some cool text', count: 3).each do |inp|
inp.set('A simple string')
end

Related

How to use regex inside objectContaining

Essentially trying to test the result of a function that contains 3 irrelevant string properties (irrelevant to this question). But a 4th property that is a ISO 8601 string that gets created when the function gets executed. I have no way of knowing what this exact value will be, so I want to test the property via regex. Usually I'd do something like this (which would work but not as clean):
expect(desiredProperty).toMatch(ISOPattern); // ISOPattern = regex i made that works
But doing it this way would mean i need to write this expect for every single property, whereas something like this is more clean and easier to read:
expect(result).toEqual(
expect.objectContaining({
id: mockEmail,
otpPassword: mockOtpPassword,
expire: 1000 * 60 * 60,
expire_at: expect.toMatch(ISOPattern), // NOT WORKING, FAILS
})
);
So I am wondering, is doing something like the above possible at all? I could just not check that property in my expect.objectContaining function, and add another expect to do what i mentioned above. But again, wondering if I could have the best of both worlds.
Not sure if I formatted my post right but essentially this is what I ended up doing (i mentioned this in the OP):
expect(result).toEqual(
expect.objectContaining({
id: mockEmail,
otpPassword: mockOtpPassword,
expire: 1000 * 60 * 60
})
);
expect(result.expire_at).toMatch(ISOPattern);
So the idea here was to get rid of the extra expect call (if you notice here I am checking against the same object result, but I wont know the value of the date and its not important anyways so I just want to check some regex I wrote (whether this works or not is irrelevant although the regex works for sure), and somehow do the regex check inside the expect.objectContaining function, but I dont think I did a good job at formatting my question right so thats probably on me.
Open to anyones help if they see a way to do what im talking about.
The code in this solution is what I am using now, the question I am trying to ask is if theres a better way to do this. The regex working is not relevant, although I know 100% it does work. I did not provide this regex because its literally not what I am asking or relevant to the solution I am seeking.

Way to find a number at the end of a string in Smalltalk

I have different commands my program is reading in (i.e., print, count, min, max, etc.). These words can also include a number at the end of them (i.e., print3, count1, min2, max6, etc.). I'm trying to figure out a way to extract the command and the number so that I can use both in my code.
I'm struggling to figure out a way to find the last element in the string in order to extract it, in Smalltalk.
You didn't told which incarnation of Smalltalk you use, so I will explain what I would do in Pharo, that is the one I'm familiar with.
As someone that is playing with Pharo a few months at most, I can tell you the sheer amount of classes and methods available can feel overpowering at first, but the environment actually makes easy to find things. For example, when you know the exact input and output you want, but doesn't know if a method already exists somewhere, or its name, the Finder actually allow you to search by giving a example. You can open it in the world menu, as shown bellow:
By default it seeks selectors (method names) matching your input terms:
But this default is not what we need right now, so you must change the option in the upper right box to "Examples", and type in the search field a example of the input, followed by the output you want, both separated by a ".". The input example I used was the string 'max6', followed by the desired result, the number 6. Pharo then gives me a list of methods that match that:
To get what would return us the text part, you can make a new search, changing the example output from number 6 to the string 'max':
Fortunately there is several built-in methods matching the description of your problem.
There are more elegant ways, I suppose, but you can make use of the fact that String>>#asNumber only parses the part it can recognize. So you can do
'print31' reversed asNumber asString reversed asNumber
to give you 31. That only works if there actually is a number at the end.
This is one of those cases where we can presume the input data has a specific form, ie, the only numbers appear at the end of the string, and you want all those numbers. In that case it's not too hard to do, really, just:
numText := 'Kalahari78' select: [ :each | each isDigit ].
num := numText asInteger. "78"
To get the rest of the string without the digits, you can just use this:
'Kalahari78' withoutTrailingDigits. "Kalahari"6
As some of the Pharo "OGs" pointed out, you can take a look at the String class (just type CMD-Return, type in String, hit Return) and you will find an amazing number of methods for all kinds of things. Usually you can get some ideas from those. But then there are times when you really just need an answer!

How to quickly navigate to a certain position using VIM

Below is a code snippet that I get from the internet as an example. Say we are at line 48 (the secong input near the bottom), however, we need to go back to the second of at line 8.Do we just hit :82o?
What if the line number is really large (e.g., 1425) and there are a few of the same word within the line.
In this case, it will take many key strokes, even I have to hit w after I get to the line. How can VIM compete with a mouse in a scenario of random access of a certain word in a large file, in which case you just need to move your pointer with the mouse to achieve this?
Edit: The code is a snippet that I got from the internet in order to demostrate my question. The possible scenario could be I am working on line 1148 and I'd like to go back to line 1108 just to change a word in a comment or I need to fix a bug by making a little bit change within the line 1108. Therefore, the place to go back is hardly predictable and pretty much random.
Edit: I would prefer to know a best practice to achieve this with a vanilla Vim. But you can feel free to provide a solution based on a plugin.
<HTML>
<HEAD><TITLE> Banner</TITLE>
<SCRIPT LANGUAGE= "javascript">
// Puts the text to scroll into variable called sent - SECTION A
// uses length propert to assess its length and put into variable slen
// initalizes a,b,n, and subsent variables
var sent = "This is a demonstration of a banner moving from the left to right. It makes use of the substring property of Javascript to make an interesting display"
var slen = sent.length
var siz = 25
var a = -3, b = 0
var subsent = "x"
// Creates a function to capture substrings of sent - SECTION B
function makeSub(a,b) {
subsent = sent.substring(a,b) ;
return subsent;
}
//Creates a function that increments the indexes of the substring - SECTION C
//each time and calls the makeSub() function to geneate strings
//a indicates start of substring and siz indicates size of string required
function newMake() {
a = a + 3;
b = a + siz
makeSub(a,b);
return subsent
}
//function uses loop to get changing substrings of target - SECTION D
//repeatedly calls newMake to get next substring
//uses setTimeout() command to arrange for substrings to display
// at specified times
function doIt() {
for (var i = 1; i <= slen ; i++) {
setTimeout("document.z.textdisplay.value = newMake()", i*300);
setTimeout("window.status = newMake()", i*300);
}
}
</SCRIPT>
</HEAD>
<BODY >
<HR> <CENTER>
<FORM NAME="z">
<INPUT NAME="textdisplay" TYPE="text" SIZE=25> <P>
<INPUT NAME="doit" Type="button" value = "Run Banner" onClick = "doIt()">
</FORM></CENTER>
<HR>
</BODY></HTML>
Best way to navigate if you know which word you should end up at is to search for it.
I'd do a /of to search for of and I'm there.
I find this easier than moving my mouse pointer.
Now coming to the scenario of really large files, relativenumbers can help you.
set relativenumber
Now to go from 1148 to 1104, you can just do a 40k then use f to get to desired character.
You can prefix f with numbers to move to nth appearance of that character. You can search too.
Again I find this easier than using mouse.
If you have enough command over searching and moving with jk prefixed with motion numbers, you'll be faster than using mouse.
Editing is not something you do at random like in your example. Navigation usually happens from one point of interest to another related point of interest, whether both POIs are part of the same task or parts of related tasks.
Your first example is very unrealistic for two reasons:
because there would be no reason whatsoever to jump from that first POI to that second POI as they are completely unrelated,
because the whole file may not fit wholly in the editing window, which would make the mouse largely irrelevant.
The only potentially useful navigation from your initial state would be to jump to the definition of the event handler, which is only a ?do<CR> away. Note that the function is already under our nose so there's no need to navigate to begin with if all we want is to know what doIt() does.
Your second example is too abstract to work with.
The local navigation tools at your disposal correspond to various zoom levels:
gegEbBwWeE at the word level,
fFtT;,0^$g_g^g$ at the line level,
(){} at the paragraph level,
ggnG at the buffer level,
nHMnL at the window level,
and a bunch of other commands at various levels like hjkl or gm.
But the most powerful of the lot is search, ?/nN (together with set incsearch), which lets you jump directly to wherever you want with minimal effort.
Keyword Search
For random access, keyword search using \{keyword} is normally your best option. Although I have a feeling that this question (with its use of the word of) was geared to sabotage this method, I will point out that you could still run this search by just continuing to type the next word after of. With this approach we are looking at 5-7 keystrokes at most I'd say. That's quite a lot better than using the mouse if you ask me.
EasyMotion
Several others have mentioned the EasyMotion project. I am not too familiar with this project so I will not comment on it any further.
Why to really avoid the mouse?
I do not believe that the added efficiency one acquires by using Vim is the result of avoiding the mouse at all costs; rather, it is the result of training yourself to avoid leaving the home row at all costs. It is not the mechanics of the mouse but the constant task-switching between keyboard to mouse that slows us down the most.

Freemarker - How to prevent Split builtin from breaking prematurely

I'm still fairly new to Freemarker and am currently trying to output a bulleted list using the Split builtin.
My code so far is so:
<#list listingname?split(", ") as x>
• ${x} <br />
</#list>
My issue arises when a value from the 'listingname' field contains a comma-space (, ) - this causes the the outputed code to break prematurely.
So for example, let's say:
listingname = "john's company", "bill, bob's tackle and bait", "john do - attorney at law"
The above code would render it as so:
• "john's company"
• "bill
• bob's tackle and bait"
• "john do - attorney at law"
The issue here is that the 2nd set of double-quoted text breaks instead of displaying "bill, bob's tackle and bait" on one line.
So I guess my question is, is there a way to prevent this from happening?
Can't you just pass that listing to FreeMarker as a Java List or array? I mean, it's like you try to parse the list literals of some language here. That's not something you usually do in templates. And ?split is just for spliting, it's certainly not smart enough for this.
But if you indeed has to do this, parsing in the template, what syntactical rules does this listing string follow? Like, what if a list item value contains a quotation mark? Will it be escaped like \"? If the syntax is compatible with FTL's own syntax, you could do <#list ('[' + listingname + ']')?eval as x>.

How can I find an <acronym> tag with watir-webdriver without taking a huge performance hit?

I am using watir-webdriver (0.5.3) in a Cucumber (1.1.9) test. I am attempting to verify the text value of an <acronym> tag. The code is legacy, and there are plans to change it to a <div> or <span> tag, but in the mean time I have to deal with it. I first attempted:
#browser.acronym(:id => /expense_code(.*)/).text
I received the following error:
NoMethodError: undefined method `acronym' for #<Watir::Browser:0x33e9940>
I poked around in the Watir code to see how tag objects were being created, and found that they seem to be dynamically created based on the HTML5 spec, but then I also found a comment in element.rb stating that they are no longer being created from the spec. At any rate, I couldn't see an easy way to inherit a <span> object and call it an <acronym> object. So, I looked into alternatives, and found the element object.
#browser.element(:id => /expense_code(.*)/).text
This code works, but it takes about a minute to traverse my page. I'm stuck with the regex for now, as the tag id is actually dynamically generated and I don't currently have a way to figure out those values. This is what the tag actually looks like:
<acronym class="editable select fillwith:exp_codes default:E100"
title="Expense Code: Expenses" id="expense_code114_582_10777">
E100 </acronym>
I would appreciate any thoughts on how I can improve the performance of my test.
Is that class name predictable? could you construct that from a set part plus the text you are about to validate (it's the same in your example above) and go that way?
acronym = 'E100'
browser.element(:class, 'editable select fillwith:exp_codes default:#{acronym}'.text.should == acronym
Does using XPath to limit the elements to just acronym tags help performance?
#browser.element(:xpath, "//acronym[contains(#id, 'expense_code')]")
UPDATE: As Chuck mentioned, CSS-Selector is also an option:
#browser.element(:css => "acronym[id^=expense_code]")
I was recently stealing logic from Watir 1.6.5 to make custom locators/collections for my page objects and I noticed in the Watir::TaggedElementLocator, it kind of supports any method that the element supports. Noticing in Watir-Webdriver that elements have a tag_name() method, I thought I would try the same and it looks like it works.
So you can use tag_name as a locator by doing:
#browser.element(:tag_name => 'acronym', :id => /expense_code(.*)/).text
I'm not sure what order the locators get run in, so since the regex is expensive, it might be faster to get all the acronym elements and then find the one with the right ID:
#browser.elements(:tag_name, 'acronym').find{ |acronym|
acronym.id =~ /expense_code(.*)/
}.text
While I think it makes the code look better, unfortunately I'm not sure if its any faster. I am guessing the performance of each will depend on the specific page layout being tested.
I'm not sure what the proper etiquette is here, but this is the answer I came up with using Chuck's reply and feedback from jarib in the #watir IRC chat. With all my examples, expense_code = 'E100'.
#browser.element(:tag_name => "acronym",
:class => "default:#{expense_code}").text
The above code works at a very reasonable speed and doesn't require an xpath. It is a shortening of the following code:
#browser.element(:tag_name => "acronym",
:class => "editable select fillwith:exp_codes default:#{expense_code}").text
I learned that I didn't need to pass the whole string. Anything in a class delimited by a space is dealt with gracefully by watir. I adapted that code from this xpath:
#browser.element(:xpath => "//acronym[contains(#class,
\'editable select fillwith:exp_codes default:#{expense_code}\')]").text
The gotcha in that code above was needing to escape out the ' around the class values so that it would evaluate correctly.
Just searching for the class (code below) did not work. I have no idea why. I did notice that it pounded the database with requests. Whatever it was doing, the page didn't like it. Though the reason it was trying multiple times is I slipped a wait_until_present in there.
#browser.element(:class, "editable select fillwith:exp_codes
default:#{expense_code}").text
Thanks for the help. :)

Resources