RSpec testing a method that uses a form builder element - ruby-on-rails

I was wondering if anyone had an idea on how to implement an Rspec test which can utilize the form builder from rails. Here is what is in my helper:
def render_radio_buttons(answer, label)
check_these = []
field = '<div class="radio">'
label.split(',').each do |option|
if check_these.include?(option.strip)
field += answer.radio_button :body, option.strip, checked = true
else
field += answer.radio_button :body, option.strip
end
field += label_tag option.strip
end
field += '</div>'
end
This method is pulling a label field from the database which contains multiple comma separated labels. The answer in this case is the form builder f. How would I go about testing something like this since it needs the form builder?
If you have a better rails method on how to implement this, I would love to know! Thanks for anyone who can help!

I would just test the form using Capybara.
https://github.com/jnicklas/capybara
Capybara helps you test Rails and Rack applications by simulating how a real user would interact with your app. It is agnostic about the driver running your tests and comes with Rack::Test and Selenium support built in. WebKit is supported through an external gem.
describe "the signup process", :type => :request do
before :each do
User.make(:email => 'user#example.com', :password => 'caplin')
end
it "signs me in" do
within("#session") do
fill_in 'Login', :with => 'user#example.com'
fill_in 'Password', :with => 'password'
end
click_link 'Sign in'
end
end

Related

Rspec fails when it needs to open up a popup on click function in Ruby on Rails

In my application , when i click href(hyperlink), popup should open up and test the features. In all the places where there is on click event for a link, all Rspecs test cases are failing to open the modal window. i am using below gems. i am runnning the Rspecs inside docker -Centos image. It was working early . We made few changes in the application like adding few css. After those changes ,all onclick Rspecs is failing. Can anyone help? Ruby version is 2.3
rspec-expectations 3.4.0
rspec-mocks 3.4.1
rspec 3.4.0
rspec-rails 3.4.2
rspec_junit_formatter 0.2.3
selenium-webdriver 3.9.0
capybara 2.7.1
rails 4.2.6
Sample HTML code for link
<%= link_to 'Contact Us', '/contactus', {:id=> 'submit', :remote => true, 'data-toggle' => "modal", 'data-target' => '#contactusId', :class=>'btn btn-default'}
Sample Rspec
require 'rails_helper'
require 'capybara/rspec'
RSpec.feature 'Contact Us - 'do
scenario 'create a simple contact request after login with logged in users email id and name' do
visit '/signin'
do_login 'test', 'test'
sleep 5
click_link('Contact Us', visible: true)
fill_contact_us_form 'a','b','c','8056286205','From Rspec'
click_on 'Send Email'
expect(page).to have_content("Your request has been submitted")
end
def fill_contact_us_form(name, companyname, emailid,contactNumber,notes)
if(name!=nil)
fill_in 'contact_us_name', :with => name
end
fill_in 'contact_us_company_name', :with => companyname
if(emailid!=nil)
fill_in 'contact_us_email_id', :with => emailid
end
if(contactNumber!=nil)
fill_in 'contact_us_contact_number', :with => contactNumber
end
if(contactNumber!=nil)
fill_in 'contact_us_notes', :with => notes
end
end
Error
Contact Us - create a simple contact request after login with logged in users email id and name
Failure/Error: fill_in 'contact_us_company_name', :with => companyname
Capybara::ElementNotFound:
Unable to find field "contact_us_company_name"
There could be several factors contributing to the failure. You should check the following:
The input you're looking does exist. fill_in will try to match an input with name, id or label contact_us_company_name
The modal has transitions and take longer than Capybara.max_wait_time_out, so you should set the :wait option
The scenario is not running javascript, so the modal is never shown.
fill_in documentation can be found here

Testing signup form with rspec, capybara, and stripe

I'm super new to testing, so I'm not really sure what I should be debugging here.
That said, I have two different user types: Authors and Readers, subclassed on Users.
They can both sign up fine in my app, and the tests for Readers works without any problems.
The signup form for Authors includes a stripe payment form - and makes a remote call to Stripe's API before submitting the form.
Here is what the test looks like:
require 'spec_helper'
feature 'Author sign up' do
scenario 'author can see signup form' do
visit root_path
expect(page).to have_css 'form#new_author'
end
scenario 'user signs up and is logged in' do
visit root_path
fill_in 'author[email]', :with => 'author#example.com'
fill_in 'author[password]', :with => '123456'
fill_in 'author[password_confirmation]', :with => '123456'
fill_in 'author[name]', :with => 'joe shmoe'
fill_in 'author[zipcode]', :with => '02021'
fill_in 'card_number', :with => '4242424242424242'
fill_in 'card_code', :with => '123'
select "1 - January", :from => 'card_month'
select "2014", :from => 'card_year'
find('.author_signup_button').click
expect(page).to have_css '.author_menu'
end
end
The only difference between this test and the Reader test are the credit card forms.
The controller which handles this account creation looks like this:
def create
#author = Author.new(params[:author])
if #author.save_with_payment
sign_in #author, :event => :authentication
redirect_to root_path, :notice => "Thanks for signing up!"
else
render :nothing => true
end
end
If I don't have the else in here, the test fails sooner, saying its missing templates. Which means its not passing the "save_with_payment" method, which supports the idea that the form never hits stripe.
The error simply says:
**Failure/Error: expect(page).to have_css '.author_menu'
expected css ".author_menu' to return something**
This worked before I integrated with stripe - so I'm convinced it has to do with the ajax call.
Is there something I should be doing to support ajax?
The answer, was to use :js => true in the test:
scenario 'user signs up and is logged in', :js => true do
This forces the test to run with selenium, and uses the browser.

Rails Integration Test With Capybara is Filling In Form with Values from Previous Test

I am running my tests for a rails application using test/unit and capybara. I am fairly new to rails, so I'm hoping that I'm missing something obvious. I have the following integration test to fill out a single field and submit a form. This works as expected and the test passes:
test "create post with title only should add post" do
assert_difference('Post.count') do
visit '/posts/new'
fill_in :title, :with => "Sample Post"
click_button 'create Post'
end
assert current_path == post_path(Post.last)
assert page.has_content?("Sample Post")
end
I added a second test, that pretty much copies the previous test but also fills out a second field and checks for the additional input (this fails).
test "create post with title and body should add post" do
assert_difference('Post.count') do
visit '/posts/new'
fill_in :title, :with => "Testing"
fill_in :body, :with => "This is a sample post"
save_and_open_page
click_button 'create Post'
end
save_and_open_page
assert current_path == post_path(Post.last)
assert page.has_content?("Testing")
assert page.has_content?("This is a sample post")
end
When this failed, I added the call to:
save_and_open_page
and found that the form was being filled out with the title value from the previous test and no body value was supplied at all. The name of the test and the assertions match the second test, so this isn't a case of mistaken identity. It seems that Capybara isn't getting the updated values. I also have this code in my test_helper.rb file:
DatabaseCleaner.strategy = :truncation
module ActionController
class IntegrationTest
include Capybara::DSL
self.use_transactional_fixtures = false
teardown do
DatabaseCleaner.clean
Capybara.reset_sessions!
Capybara.use_default_driver
end
end
end
I'm assuming this should clear out values in between tests. Since that clearly wasn't happening, I also tried adding a call to Capybara.rest_sessions! at the end of the first test and that didn't help.
Any advice or help would be greatly appreciated.
I figured it out. I was calling the fill in method with the symbol :title instead of a string for the field id. I needed to be using 'post_title'. I started that way, but was not prefixing the name with the model name so it wasn't found and it started working when I changed to the symbol that I was using in my erb code.
So use:
fill_in 'post_title', :with => "whatever"
instead of
fill_in :title, :with => "whatever"

Rspec test on Simple Form Associations

I am trying to run a request spec on a form (built with Simple Form). The form includes some select boxes that are generated using the association method and therefore database values for the model.
When running save_and_open_page it doesn't look like the select the values in the drop downs.
I have looked at Mocking and Stubbing but this is new to me and I'm still a little confused on the concept beyond basic usage.
Is there any way to generate the collection for the select box so Capybara can pick it up?
I'm using Rails 3.1, Simple Form, Capybara and FactoryGirl.
My code is...
challenge_spec
describe "New Challenges" do
before(:all) do
%w["Under 13", "13 - 16"].each do |item|
FactoryGirl.create(:age, :name => item)
end
end
it "should redirect to resources after submission" do
login_valid_user
visit new_challenge_path
#challenge = Factory.build(:challenge)
fill_in "challenge_name", :with => #challenge.name
fill_in "challenge_description", :with => #challenge.description
fill_in "challenge_description", :with => #challenge.description
select "30 mins", :from => "challenge_timescale"
save_and_open_page
select 1, :from => "challenge_age_id"
select #challenge.category, :from => "challenge_category_id"
click_button "save_button"
end
end
Controller
def new
#challenge = Challenge.new
respond_to do |format|
format.html # new.html.haml
format.json { render json: #challenge }
end
end
Form item
<%= f.association :age, :prompt => "Please select..." %>
Models
Challenge
class Challenge < ActiveRecord::Base
belongs_to :age
end
Age
class Age < ActiveRecord::Base
has_many :challenges
end
I strongly recommend creating fixtures for your tests.
This way you can manually create and manipulate the records needed for tests. It's not as efficient or elegant as using mocks, stubs and doubles but it reinforces understanding of the application and tests.

Testing Sessions in Rails 3 with Rspec & Capybara

I'm trying to write integration tests with rspec, factory_girl & capybara. I also have cucumber installed, but I'm not using it (to my knowledge).
I basically want to prepopulate the db with my user, then go to my home page and try to log in. It should redirect to user_path(#user).
However, sessions don't seem to be persisted in my /rspec/requests/ integration tests.
My spec: /rspec/requests/users_spec.rb
require 'spec_helper'
describe "User flow" do
before(:each) do
#user = Factory(:user)
end
it "should login user" do
visit("/index")
fill_in :email, :with => #user.email
fill_in :password, :with => #user.password
click_button "Login"
assert current_path == user_path(#user)
end
end
Returns:
Failures:
1) User flow should login user
Failure/Error: assert current_path == user_path(#user)
<false> is not true.
# (eval):2:in `send'
# (eval):2:in `assert'
# ./spec/requests/users_spec.rb:16
Instead, it redirects to my please_login_path - which should happen if the login fails for any reason (or if session[:user_id] is not set).
If I try to put session.inspect, it fails as a nil object.
If I try to do this in the controller tests (/rspec/controllers/sessions_spec.rb), I can access the session with no problem, and I can call session[:user_id]
If you are using Devise, you'll need to include Warden::Test::Helpers (right after the require of spec_helper is a good place) as outlined in the warden wiki.
The call to session is returning nil because capybara doesn't provide access to it when running as an integration test.
I have the same problems and although filling out a form might be an option for some, I had to roll my own authentication ruby because I was using a third party auth system (Janrain to be exact).... in my tests I ended up using something like this:
Here is what I have in my spec/support/test_helpers_and_stuff.rb
module AuthTestHelper
class SessionBackdoorController < ::ApplicationController
def create
sign_in User.find(params[:user_id])
head :ok
end
end
begin
_routes = Rails.application.routes
_routes.disable_clear_and_finalize = true
_routes.clear!
Rails.application.routes_reloader.paths.each{ |path| load(path) }
_routes.draw do
# here you can add any route you want
match "/test_login_backdoor", to: "session_backdoor#create"
end
ActiveSupport.on_load(:action_controller) { _routes.finalize! }
ensure
_routes.disable_clear_and_finalize = false
end
def request_signin_as(user)
visit "/test_login_backdoor?user_id=#{user.id}"
end
def signin_as(user)
session[:session_user] = user.id
end
end
Then in my request spec, with capybara and selenium, I did the following:
describe "Giveaway Promotion" do
context "Story: A fan participates in a giveaway", js: :selenium do
context "as a signed in user" do
before :each do
#user = Factory(:user)
request_signin_as #user
end
it "should be able to participate as an already signed in user" do
visit giveaway_path
....
end
end
end
end
BTW, I came up with solutions after trying the proposed solutions to this post and this post and neither of them worked for me. (but they certainly inspired my solution)
Good luck!
You've probably moved on from this, but I was just struggling with the same question. Turns out it was a matter of syntax. I was using symbols for :email and :password and I should've been using strings instead ("email" and "password").
In other words, try changing this:
fill_in :email, :with => #user.email
fill_in :password, :with => #user.password
to this:
fill_in "email", :with => #user.email
fill_in "password", :with => #user.password

Resources