Cucumber generates out some neat webrat regex steps. I encountered a problem when I tried the this.
In feature:
And I fill in "Telephone (Home)" with "61234567"
In webrat steps:
When /^I fill in "([^\"]*)" with "([^\"]*)"$/ do |field, value|
fill_in(field, :with => value)
end
The error encountered:
Could not find field: "Telephone (Home)" (Webrat::NotFoundError)
It seems that the parenthesis between "Home" is giving problem. How do I tweak the regex to account for parenthesis?
UPDATE:
It seems that the regex wasn't the problem as the "field" instance variable did yield "Telephone (Home)". The real problem was the way webrat's "fill_in" method parses the field variable.
If you only want to capture "Telephone" try this:
/^I fill in "(\w+).*?" with "([^\"]*)"$/
If it's "Home" you're after try this:
/^I fill in "(?:.*?\()?(.+?)\)?" with "([^\"]*)"$/;
This encountered me too with the field "(log out)"...
You could call for the id field?
fill_in("user_telephone_home", :with => data)
I had a similar problem with matching labels to fields in webrat, and I came up with this code snippet which loosens the regexp used to match a label to a field. Maybe it will help you out.
I have this in my features/support/env.rb
module Webrat
module Locators
class FieldLabeledLocator < Locator
def matching_label_elements_with_numbering
label_elements.select do |label_element|
text(label_element) =~ /^.*#{Regexp.escape(#value.to_s)}.*$/i
end
end
alias_method_chain :matching_label_elements, :numbering
end
end
end
http://gist.github.com/169215
Related
I'm trying to solve what is most likely a quick problem...
I have this so far
page.check 'Vendor'
page.check 'Partner'
click_button 'Invite'
newUser = User.find_by_email("lemmy#dl.com")
puts "ROLES"
puts newUser.roles
puts "ROLES"
expect(newUser.roles).to have_content("partner")
expect(newUser.roles).to have_content("vendor")
and what this outputs is :
ROLES
admin
vendor
partner
ROLES
and then an error:
expected to find text "partner" in "#"
I was wondering why this is, and although I know that the partner value is there since I printed it, I would like a way to automatically check it so i can get rid of those puts. Thank you for any help!
have_content looks at the web page to see if it has the content but you are inspecting newUser.roles instead. If newUser.roles returns an array use the include matcher instead:
expect(newUser.roles).to include("partner")
expect(newUser.roles).to include("vendor")
I'd like to test the validation of a model's attribute with rspec and factory_girl. The 'special' thing is, that one attribute (the name) isn't allowed to start with Numbers or special signs like %,&,$, ...
For testing this it would be great to write only one example like
it "is invalid with name starting by special character" do
["1","$","%"].each do |i|
name = i + "test"
FactoryGirl.build(:tutu, name: name).should_not be_valid
end
end
This work's for the first case but it won't return the result for the whole list. Is it possible to tell rspec not to stop on the error?
Do this instead:
["1","$","%"].each do |i|
it "is invalid with name starting by '#{i}'" do
FactoryGirl.build(:tutu, name: "#{i}test").should_not be_valid
end
end
After updating capybara to 2.1, It is throwing Ambiguous error
Capybara::Ambiguous:
Ambiguous match, found 2 elements matching css "div.alert"
and after reading some articles and the log here. You can get the default behaviour from 1.0x by passing :match => :prefer_exact
This can be easily done for something like fill, like this
fill ("Password", :match => :prefer_exact'
but how do you do it for a within block like this
within 'div.alert' do
page.should have_content(text)
end
I tried doing this, but it throws an error
within ('div.alert', :match => :prefer_exact) do
page.should have_content(text)
end
any suggestions would be helpful.
If you don't know the order and have no way to select it by CSS, you can try
page.should have_selector('.alert', text: 'foo bar')
There is no need for within, which is designed for larger divs with complex content.
I am just trying to figure out what the below means in Ruby.
"([^"]*)"$/
I have the following code sample in Ruby using cucumber at the moment:
require "watir-webdriver"
require "rspec/expectations"
Given /^I have entered "([^"]*)" into the query$/ do |term|
#browser ||= Watir::Browser.new :firefox
#browser.goto "google.com"
#browser.text_field(:name => "q").set term
end
When /^I click "([^"]*)"$/ do |button_name|
#browser.button.click
end
Then /^I should see some results$/ do
#browser.div(:id => "resultStats").wait_until_present
#browser.div(:id => "resultStats").should exist
#browser.close
end
I understand at the moment that it is doing a logic check that a button has been clicked. I did a bit of research around and found the following for symbal meanings in Ruby (as I am new to Ruby)
? = method returns a boolean value.
$ = global variable
# = instance variable
## = class variable.
^ = bitwise XOR operator.
* = unpack array
I cannot see to find what the command does. I am trying to clarify exactly how functions are linked to variables and I think this is the final clue for me.
Many thanks in advance for any help.
It's a regular expression. The expression is contained between the "/" characters.
By way of an example and using your code:
/^I have entered "([^"]*)" into the query$/
is interpreted as a string that :
Matches the beginning of the line (^)
Matches "I have entered"
Matches a single quote
(") Matches everything that is not a quote ( ([^"]*) )
Matches " into the query"
Matches a single quote (")
Matches the end of the line $
See http://www.tutorialspoint.com/ruby/ruby_regular_expressions.htm for more information on Ruby and Regular expressions.
I am testing validation of my models with rspec and am expecting an error message. However, the exact text of the message is likely to change, so I want to be a bit more forgiving and only check for a partial message.
Since the Spec::Matchers::include method only works for strings and collections, I'm currently using this construct:
#user.errors[:password].any?{|m|m.match(/is too short/)}.should be_true
This works but seems a bit cumbersome to me. Is there a better (i.e., faster or more ruby-like) way to check an array for the inclusion of a string by regex, or perhaps an rspec matcher that does just this?
I would recommend doing
#user.errors[:password].to_s.should =~ /is too short/
Simply because it will give you a more helpful error when it fails. If you use be_any then you get a message like this...
Failure/Error: #user.errors[:password].should be_any{ |m| m =~ /is too short/}
expected any? to return true, got false
However, if you use the to_s method then you will get something like this:
Failure/Error: #user.errors[:password].to_s.should =~ /is too short/
expected: /is to short/
got: "[]" (using =~)
Diff:
## -1,2 +1,2 ##
-/is too short/
+"[]"
So you can see the reason for the failure and don't have to go digging much to figure out why it is failing.
Using RSpec 3 expect syntax with matchers composing:
To match all:
expect(#user.errors[:password]).to all(match /some message/)
To match any:
expect(#user.errors[:password]).to include(match /some message/)
expect(#user.errors[:password]).to include a_string_matching /some message/
You can put the following code in spec/support/custom_matchers.rb
RSpec::Matchers.define :include_regex do |regex|
match do |actual|
actual.find { |str| str =~ regex }
end
end
Now you can use it like this:
#user.errors.should include_regex(/is_too_short/)
and be sure you have something like this in spec/spec_helper.rb
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
I don't think it makes a performance difference, but a more RSpec-like solution would be
#user.errors[:password].should be_any { |m| m =~ /is too short/ }
Both above answer are good. I would, however, use the newer Rspec expect syntax
#user.errors[:password].to_s.should =~ /is too short/
becomes
expect(#user.errors[:password].to_s).to match(/is too short/)
More great info here: http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
My solution to this is similar to #muirbot's. I use a custom matcher. However, I use the real include matcher, but augment it with the custom matcher as an argument. Load this somewhere before your suite runs (e.g. in spec/support/matchers.rb, in turn loaded by spec/spec_helper.rb):
RSpec::Matchers.define(:a_string_matching) do |expected|
match do |actual|
actual =~ expected
end
end
Then your expectation can be written like this:
expect(#user.errors[:password]).to include(a_string_matching(/is too short/))
Just another option
#user.errors[:password].grep /is too short/