Setting path in Cucumber - ruby-on-rails

I am setting up a cucumber scenario for setting up a valid user where my last step is:
"Then I should be taken to the show user page"
which I define as:
Then /I should be taken to the show user page/ do
#user = User.last
if current_path.respond_to? :should
current_path.should == path_to(user_path(#user))
else
assert_equal path_to(user_path(#user)), current_path
end
visit(user_path(#user))
end
After getting an error "Can't find mapping from "/users/49" to a path." I attempted to define the path as:
when /^users\/(.+)$/ do |user|
user_path(user.to_i)
end
But this yields the error:
syntax error, unexpected keyword_do, expecting keyword_then or ',' or ';' or '\n'
when /^landlords/(.+)$/ do |landlord|
I am relatively new to rails and web development and completely new to cucumber and TDD. Also new to regex. Any help would be appreciated!
Thanks,
John

It looks like user_path(#user) is giving you the path you need, so wrapping that in path_to is causing the error as it tries to do the same thing.
I think getting rid of the path_to call might help:
current_path.should == user_path(#user)

The reason for the "unexpected keyword_do" error is because you have when instead of When, i.e. Ruby is interpreting it as a case-style statement. But as Jon M points, you don't need that anyway.

Related

If and Page.Should have_css in Ruby

I am a newbie in Ruby and I have a problem with if condition and page.should have when I programmed the A/B Test for log in function.
This is my code:
if (page.should have_css("body.bg-b")) || (page.should have_css("body.bg-c"))
#do something
else
#do something
end
It works fine in the if condition. My problem is in the case the page doesn't have bg-b or bg-c, it should go to else condition, right, but it stopped running and said
Capybara::ExpectationNotMet:
expected to find css "body.bg-b" but there were no matches
Is there something wrong with this code?
Thanks
The keyword "should" seems you're asserting something.
If you simply want to make a IF, you should write something like this :
if (page.has_css?("body.bg-b")) || (page.has_css?("body.bg-c"))
# Check something with should
else
# Check something else with should
end
It you want to check the page have a css or the other one, you should write
(page.has_css?("body.bg-b")) || (page.has_css?("body.bg-c")).should == true
Or
if !page.has_css?("body.bg-b")
page.should have_css("body.bg-c")
end

How to use shared_examples_for in rsepc-mock?I have try many times but failed.who can help ,please? Wait online

I am a freshman on Rspec
it "should not ask the database" do
#sqlite_database.should_not_receive(:findISBN)
#result = #cache.findISBN('1234')
#result.should eql(#book)
end
it "should not ask the database" do
#sqlite_database.should_not_receive(:authorSearch)
#result = #cache.authorSearch('author')
#result.should eql(#book)
end
Here are two different part 1,:findISBN and :authorSearch 2 findISBN('1234') and authorSearch('author')
I try to use let but it doesn't work ,who can help ?
#sqlite_database = double()
#cache = SQLiteDataBaseWithCache.new(#sqlite_database)
That's ture ,I'm coming from java background .You coding showed some warning: syntax error, unexpected ':', expecting keyword_end (SyntaxError).I have no ideal about it
without more details on the variables like #sqlite_database, #cache etc its hard to tell whats happening, but following should work
probably a stack trace would help
following is the idea of shared examples :)
shared_examples "it should not ask database" do |symbol, params|
it "should not ask the database" do
#sqlite_database.should_not_receive(symbol)
#result = #cache.send symbol, params
#result.should eql(#book)
end
end
it_behaves_like "it should not ask the database", :findISBN, '1234'
it_behaves_like "it should not ask the database", :authorSearch, 'author'
and on a side note, your method signatures are not ruby kind of... in ruby we normally dont use camel case
so in ruby/rails its should be author_search, probably you are coming from java background :)

Check if attribute contains 2 letters in RSpec

What is the right way to test if the field contains 2 letter string with RSpec ? I am following an old example that I guess worked in rails 2. It creates new Address instance, sets invalid value on it, and then trigger valid? on that instance and finally checks if the errors report something wrong.
it 'requires state to be of length 2' do
subject = Address.new
subject.state = 'Cal'
should_not be_valid
subject.errors.on(:state).should_not be_nil
end
Now, Rails 3 doesn't have errors.on, so I tried with
subject.errors[:state].should_not be_nil
But the problem here is that errors[:attribute] is empty Array instead of nil.
You can still say
subject.errors[:state].should_not be_empty
Validation errors are now in errors.messages
errors.messages.should be_present

Rails - why does one work and not the other?

I have a seeds.rb file and for some reason, this doesn't work:
#doesn't work
u=User.new
u['email']=h['email']
u['password']=h['password']
puts u['email']
puts u['password']
if u.save
puts "that saved"
else
puts "that did not save"
end
but this does:
#does work
User.create({:email => h['email'], :password => h['password']})
Is there any reason one works and one doesn't? From rails console, the first does work? Would there be any differences in validations? I run 'rake db:seed' so would think validations would be in effect in both.
thx
edit #1
sorry for lack of info. each one errors with "password can't be blank" but it then echoes out the password. Hmm...
Find out what's happening by looking at the validation errors:
else
puts "that did not save because " + u.errors.join(' ')
end
Edit: Now that you've added that validation errors contain 'password cant be blank' and it still fails to save, it becomes clear that User.create() does a number of things which User.save() omits.
What's missing is the generation of your password hash - hence the blank password error.
Try it this way:
u = User.new
u.email = h['email']
u.password = h['password']
puts u.inspect
if u.save!
puts "that saved"
else
puts "that did not save"
end
I believe the approach of accessing the attribute on the u object as u['password'] is steering you wrong.
Also, doing a u.inspect prints the entire state of the model and that should provide a cleaner way of seeing what's happening. Finally, adding a bang ! at the end of the save will cause it to 'fail fast' and give you the error immediately.

Cucumber: selecting an element from a table for deletion or addition

I have the following table in an application I am developing using ruby on rails:
I want to create a test in cucumber where I select a user from the table and delete it or edit it.
I don't know what is the step definition for that.
I'd like to be able to do something like:
Feature: User Manegement
In order to manage users
As an admin
I want to see a users list and change user properties
Background:
Given the following activated users exists
| name | email |
| Alice Hunter | alice.hunter#example.com |
| Bob Hunter | bob.hunter#example.com |
And the following user records
| name | email |
| Jonh Doe | jonh.doe#example.com |
Scenario: I delete a user from the table
Given I am logged in as admin
When I follow "Administration"
And I follow "User Management"
And I delete "Alice Hunter"
Then I should not see "Alice Hunter"`
Can anyone help?
Thank you.
#brad
The error returned:
wrong number of arguments (2 for 1) (ArgumentError)
./features/step_definitions/table_steps.rb:26:in `within'
./features/step_definitions/table_steps.rb:26:in `/^I delete "(.*)"$/'
After some extensive searching and minor refactoring, I managed to solve the problem.
I have used the following step:
When /^as admin I (press|follow|check|uncheck|choose) "([^\"]*)" for (.*) whose (.*) is "([^\"]*)"$/ do |action, whatyouclick, class_name, var_name, value|
unless var_name == "id" then
id = eval("\"#{class_name}\".classify.constantize.find_by_#{var_name}(\"#{value}\").id.to_s")
else
id = value
end
within("tr[id=as_admin__#{class_name}-list-#{id}-row]") do
case action
when "press"
click_button(whatyouclick)
when "follow"
click_link(whatyouclick)
when "check"
check(whatyouclick)
when "uncheck"
uncheck(whatyouclick)
when "choose"
uncheck(whatyouclick)
end
end
end
I am also insterested in webrat's RDoc, but everything I find seems out of order.
I have a bit of a legacy app that isn't being nice with regard to useful link ids or even classes (i.e. class="deleteLink"). I have to find the link that has 'delete' in the href. Obviously this is error prone but it's working for now. Here's the code for that.
When /^I delete "([^"]*)"$/i do |value|
page.evaluate_script('window.confirm = function() { return true; }')
within(:xpath, "//tr[.//*[contains(text(), '#{value}')]]") do
find(:xpath, ".//a[contains(#href,'delete')]").click
end
end
It's a little messy in the xpath, but it's what i could finally get to work. I'm using Cucumber/Rspec/Capybara/Selenium to test a Java app BTW.
I'm going to assume it's the deleting part that is messing you up as the other stuff is fairly standard (setting up givens and following links etc...)
So, what are you using as your browser abstraction? Webrat? Capybara? It appears as if you have a 'delete' link, is it sufficient to do something like this?
And /I delete "(.*)"/ do |person|
# Use webrat or capybara to find row based on 'person' text... then find 'delete' link in row and click it
# example (untested, pseudo code)
within(:xpath, "//table/tr[contains(#{person})") do
find('.deleteLink').click
end
end
And I believe something like "should not see" is probably supported out of the box with generated webrat/capybara steps.
Is this what you're looking for?
I had the same problem, and looking into the translation of 'I follow "abcd"' to click_link(), I found there's an optional :method. So I defined this:
When /^(?:|I )follow "([^"]*)" as delete$/ do |link|
click_link(link, :method => :delete)
end
and that worked... Then I decided to make it more general, not just "as delete":
When /^(?:|I )follow "([^"]*)" as ([a-z]+)$/ do |link,method|
click_link(link, :method => method.to_sym)
end
Works great. I tried it with 'I follow "mylink" as get' too, and that worked, so the method part seems to be suitably flexible.
Following on Brad's answer below I went with:
When /^I follow "([^"]*)" for "([^"]*)"$/ do |link, person|
# Use capybara to find row based on 'person' text... no need for the additional 'find'
# the '.,' sets the scope to the current node, that is the tr in question
within(:xpath, "//table/tr[contains(.,'#{person}')]") do
click_link(link)
end
end

Resources