Why isn't my tests working for this form? - ruby-on-rails-3

In Firefox, if I try to submit a post without a title, I get: 1 error prohibited this post from being saved.
But when I run my test. It's a different story.
My Post model has validates_presence_of :title. My test looks like:
require 'spec_helper'
describe 'Users' do
it 'registered users should not be able to post without a title', :js => true do
user = Factory(:user)
visit new_post_path
current_path.should eq(new_post_path)
fill_in 'post[markdown_description]', :with => 'Bar'
click_on 'Submit your post'
page.should have_content('error')
end
end
By the way, I am using Selenium (:js => true), because my submit button is actually an anchor link with some JS. Basically, when the link is clicked, JS triggers the form to be submitted.
Rspec returns:
Running: spec/requests/users_spec.rb
F
Failures:
1) Users registered users should be able to post
Failure/Error: page.should have_content('error')
expected there to be content "error" in ""
# ./spec/requests/users_spec.rb:13:in `block (2 levels) in <top (required)>'
Finished in 7.9 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/requests/users_spec.rb:4 # Users registered users should be able to post

The request may not make it to the controller action if you have before_filters. Check the log to make sure that the correct parameters are posting and that the action is not redirecting.
Another option is to include this in your spec:
click_on 'Submit your post'
save_and_open_page
which opens the current page in the browser so you can see what is actually being rendered.

Related

Rspec Helper Method Not Accessible to Features

I'm learning TDD and running some Feature tests and am having issues with a helper method.
I've pulled out the following method from the feature test:
todo_helper.rb
module Features
def create_todo(todo_title)
click_on "Add a new todo"
fill_in "Title", with: todo_title
click_on "Submit"
end
end
However, I'm getting the following error when I run the Feature Test.
Failures:
1) User creates todo successfully
Failure/Error: create_todo 'Buy Milk'
NoMethodError:
undefined method `create_todo' for # <RSpec::ExampleGroups::UserCreatesTodo:0x007fb1f351b150>
# ./spec/features/user_creates_todo_spec.rb:8:in `block (2 levels) in <top (required)>'
Finished in 0.34992 seconds (files took 2.01 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/features/user_creates_todo_spec.rb:5 # User creates todo successfully
I have two tests that are pulling this method and they are both failing. Here is the one above:
user_creates_todo_spec.rb
require "rails_helper"
feature "User creates todo" do
scenario "successfully" do
sign_in
create_todo 'Buy Milk'
expect(page).to have_css '.todos li', text: 'Buy Milk'
end
end
This is strange because I created another helper that I'm using for the sign_in method above and that is working fine, but can't figure out why the second one is not working. I isolated the create_todo method within the original feature and it passes within each Feature but not as a helper. Any help is appreciated.
Make sure you require and include the module containing your helper method in the RSpec config (spec_helper.rb or rails_helper.rb):
require "todo_helper"
Within RSpec.configure:
config.include Features

Cucumber + Capybara - Difficulty filling a form - Element not found

I am doing my hello world test application in an already completed project and am experiencing some scenarios and am puzzled by what I am seen is happening.
I am using:
Capybara
Cucumber
And selinium web driver for when we need Javascript
All of this on a Sinatra app
RSpec separately, but that is not the interest.
Problem:
When running cucumber tests as cucumber features/#{feature_name}.feature, and given that I am on a specific page. I can find elements by CSS ID but can't click on them.
When(/^I log in with email "(.*?)" and password "(.*?)"$/) do |email, password|
step %{I am on login page}
expect(page).to have_css('#login-form')
expect(page).to have_css('#login-button')
within("#login-form") do
fill_in '#username', with: email
fill_in '#password', with: password
click_button 'dfalkjsdfalsdkfja dflkjasdf alkdsjfasd lfkjsf s' # Which should fail, but odesn't :'(
end
click_button 'Sign In'
# click_button '#login-button' # This fails
end
The following test will pass even if I use a completely random non existent ID for #login-form. And as you see I have a button with some silly text. Also if I give it as an ID, no difference. The test passes.
But when I use them alone without the within block, the the elements are not found.
But above you see expect(page).to statements find them.
The above is some what similar to the example I see in the Capybara repo.
My Questions:
Can I use CSS selectors to target ex: #login-form
Should using a non existing selector in the within block fail? My case it doesn't.
Why is some thing like fill_in '#password', with: 'password' fail saying element not found while the above assertion seems to find it?
I am a newby, so a suggestion where things might have gone wrong in terms of setting up. Example link would also be great.
PS:
Forgot to ask, considering the example in the repo, what is 'Email' in the following fill_in block. Doesn't seem to be a id of the element.
fill_in 'Email', :with => 'user#example.com'
Update
After some playing around, I find the following working (finding the element and filling/clicking it). But the within block doesn't fill in the form. Can any config effect the within block as I explain.
When(/^I log in with email "(.*?)" and password "(.*?)"$/) do |email, password|
step %{I am on login page}
find('form#login-form').find('input#username').set email
find('form#login-form').find('input#password').set password
find('form#login-form').find('#login').click
within("form#login-form") do
fill_in 'input#username', with: email
fill_in 'input#password', with: password
click_button '#login'
end
end

How can I click_link a specific row with Capybara

I'm trying to write all my Capybara code to not use any CSS or funny matchers. For acceptance test purposes, I'm using Capybara to navigate only by button and link text that is visible to the user.
So I have a really simple test that asserts that an administrator can edit any user:
it 'allows an administrator to edit any user' do
user = login_admin_user
user1 = FactoryGirl.create(:user)
click_link "Users"
current_path.should eq(users_path)
click_link "Edit" # This is the problem
current_path.should eq(edit_user_path(user1))
fill_in "Last name", with: "Myxzptlk"
click_button "Update User"
page.should have_content("Myxzptlk")
end
Of course the problem line above is not specific enough; there will be 2 lines in the table (user and user1). I'm pretty new to TDD, so how do I use Capybara to select the correct link using only visible text?
I'm not sure why you're avoiding 'CSS or funny matchers'. If you don't want to put them in your test, abstract them away into helper methods.
In my specs I have a helper method like this:
module FeatureHelper
def within_row(text, &block)
within :xpath, "//table//tr[td[contains(.,\"#{text}\")]]" do
yield
end
end
end
And then in my specs I can call it like:
within_row(user1.name) do
click_link 'Edit'
end
The helper module goes inside the spec/support folder, and then gets loaded into my specs by doing:
config.include FeatureHelper, type: :feature
in my spec_helper.rb.

Few questions about capybara

I've got a few questions about Capybara. And I might as well ask here since the RDOC in the github page for Capybara is great to get it set up and running. But where is the API or list of available methods??
First. Per *_spec.rb file, should scenario only exist once? Or is it fine to have multiple scenario's in one file?
For example, in spec/request/user_spec.rb:
require 'spec_helper'
feature 'User actions' do
background do
data = {
:first_name => 'foo',
:last_name => 'bar',
...
}
user = User.new(data, :as => :user)
user.save
end
scenario 'User can browse home page' do
visit root_path
page.should have_content('Homepage')
end
scenario 'User should not be able to visit the dashboard' do
visit dashboard_root_path
page.should have_content('You are not authorized to access this page.')
end
end
If there is anything wrong with the code structure above, or if there is room for improvement. I am open feedback.
Second. I notice with the code above. If I have config.use_transactional_fixtures = false in spec/spec_helper.rb, it saves the user twice. This means, in my test database / user table, I would have 2 users named 'foo bar'. Is this normal?
Third. I have a form that has an HTML button. When user clicks on this button, jQuery submits the form. How would I test this with Capybara? I don't think click_button "Add" will do the trick.
Fourth. How would I sign in users in Capybara? I am using Devise. Would sign_in User.first do the trick? And would I be able to access current_user in Capybara?
Lastly, if anyone knows any "Getting Started" guides / tutorials on Rspec + Capybara. Please do mention.
I've also switched over to writing request specs ever since i decided that I was no longer liking Cucumber.
ONE) Having multiple scenarios is indeed fine. You get to use all the other great features of rspec, so I would suggest also using contexts as in the code at the bottom.
TWO) This can probably be solved by using the Rspec Set Gem And the Database Cleaner Gem. Also: The Original Rationale for Set
Warning: make sure you set up DatabaseCleaner correctly when you use set. My own setup (which may be a little overkill but is working for me):
config.before(:suite) do
DatabaseCleaner.clean_with :truncation
end
config.before(:all) do
DatabaseCleaner.clean_with :truncation
end
config.after(:all) do
DatabaseCleaner.clean_with :truncation
end
config.after(:suite) do
DatabaseCleaner.clean_with :truncation
end
THREE) yep! click_button "Add" should work! The complete capybara API is useful but took me a while to grok. Of most relevant importance are the actions and rspec matchers.
example:
click_button "Add"
page.should have_content("Successfully Added")
you can narrow the scope with element finders.
FOURTH) Devise provides helpers. there is a sign_in helper. read the dox :). Here's a demo:
feature 'User actions' do
background do
data = {
:first_name => 'foo',
:last_name => 'bar',
...
}
#user = User.new(data, :as => :user)
#user.save
end
context "no user is signed in" do
scenario 'User can browse home page' do
visit root_path
page.should have_content('Homepage')
end
scenario 'User should not be able to visit the dashboard' do
visit dashboard_root_path
page.should have_content('You are not authorized to access this page.')
end
end
context "user is signed in" do
before :each do
sign_in #user
end
[more scenarios]
end
end
ultimately of course, you'd prolly want to split this up into more specific features. Probably have a "Public Navigation" Feature for all the tests that are about guests seeing content, and then a separate feature for a user signing in, etc.
I am not aware of capybara, but a full list of available methods can be found here:
http://rubydoc.info/github/jnicklas/capybara/master#
hope, that helps

"No route matches" error?

I am new Rspec and just started by generating a new controller on Rails 3. It generates some Rspec tests by default. I have a question about how to make them pass though. As it stands, I see this test in my terminal"
1) BuildingsController GET 'show'
should be successful
Failure/Error: get 'show'
No route matches {:controller=>"buildings", :action=>"show"}
# ./spec/controllers/buildings_controller_spec.rb:17:in `block (3 levels) in <top (required)>'
However, I don't understand why it's coming up because I already have this route created ("resources :buildings"), and I ran rake routes and made sure it's there.
building GET /buildings/:id(.:format) {:action=>"show", :controller=>"buildings"}
What is necessary to make this pass? Here is the test by the way:
describe "GET 'show'" do
it "should be successful" do
get 'show'
response.should be_success
end
end
You need to pass id of existing building: get :show, :id => #building.id
Routes complain about it because :id isn't optional.