Capybara testing of sinatra app fails - ruby

I am trying to test a sinatra app using minitest and capybara but get several errors on all tests using capybara features like fill_in or visit.
test_index gives:
undefined local variable or method `app' for #
test_create_user gives:
Invalid expression: .////form[#id = 'register']
test_same_email gives:
Unable to find css "#register"
test_login gives:
cannot fill in, no text field, text area or password field with id,
name, or label 'email' found
Any suggestions on what may be wrong?
test.rb
require "test/unit"
require "minitest/autorun"
require "capybara"
require "capybara/dsl"
require "rack/test"
require_relative "../lib/kimsin.rb"
ENV["RACK_ENV"] = "test"
class KimsinTests < Test::Unit::TestCase
include Rack::Test::Methods
include Capybara::DSL
Capybara.app = Sinatra::Application
def test_index
visit "/"
assert stuff..
end
def test_create_user
visit "/user/new"
within "//form#register" do
fill_in :username, :with => "first#company.com"
fill_in :password, :with => "abC123?*"
fill_in :confirm_password, :with => "abC123?*"
click_link "Register"
end
assert stuff..
end
end
I'm using cygwin 1.7.15-1 on windows 7, rvm -v 1.14.1 (stable) and ruby -v 1.9.2p320.
----UPDATE----
Finally I got the tests work by incorporating Steve's suggestions:
within "form#register" do
fill_in "email", :with => "first#company.com"
click_button "Register"
and asserting the response by using capybara_minitest_spec:
page.must_have_content "Password"
page.must_have_button "Register"

I just answered a more recent question you posted about Sintra with Webrat.
Acceptance testing of sinatra app using webrat fails
I think the problem here is the same. Try replacing:
Capybara.app = Sinatra::Application
with:
Capybara.app = Kimsin
Personally I would choose Capybara over Webrat.

Related

Rspec and Capybara uninitialized constant

I am using Rspec 3.2 and Capybara 2.4 in a non RoR project. I am trying to test with feature mode provided by Capybara gem.
$ cat .rspec
--color
--require spec_helper
$ cat spec/features/test_spec.rb
feature 'login' do
username ="rspec#{Time.now.to_i}"
valid_email = "#{username}#gmail.com"
scenario 'with valid email' do
sign_up_with valid_email, 'pwd', 'pwd', username
expect(page).to have_content('LOGOUT')
end
end
$ cat spec/support/session_helper.rb
module SessionHelper
def sign_up_with(email, password, confirm_password, username)
visit '/signup'
fill_in 'email', with: email
fill_in 'password', with: password
fill_in 'passconf', with: confirm_password
fill_in 'username', with: username
click_button 'submit'
end
end
$ cat spec/spec_helper.rb
require 'capybara/rspec'
Capybara.default_driver = :selenium
RSpec.configure do |config|
...
config.include SessionHelper, type: :feature
...
end
This is a non RoR project, when I run the test I have this error:
$ rspec
spec/spec_helper.rb:26:in `block in <top (required)>': uninitialized constant SessionHelper (NameError)
In online documentation there are many examples, I have structured my files like the examples but it not works.
The way I handle this in all of my projects is like this:
Require all the support files:
In spec_helper.rb
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
And then your spec/support/session_helper.rb should look like this:
module SessionHelper
def sign_up_with(email, password, confirm_password, username)
visit '/signup'
fill_in 'email', with: email
fill_in 'password', with: password
fill_in 'passconf', with: confirm_password
fill_in 'username', with: username
click_button 'submit'
end
end
RSpec.configure do |config|
# Remove the equivalent line from spec_helper.rb
config.include(SessionHelper)
end

Why am I getting FactoryGirl wrong number of arguments error?

Having strange behavior from FactoryGirl in non-rails app. getting wrong number of arguments error...don't know why.
gideon#thefonso ~/Sites/testing (master)$ rspec spec
/Users/gideon/.rvm/gems/ruby-1.9.3-p194/gems/factory_girl-4.1.0/lib/factory_girl/syntax/default.rb:6:in `define': wrong number of arguments (1 for 0) (ArgumentError)
from /Users/gideon/Sites/testing/spec/factories.rb:1:in `<top (required)>'
Here are the files involved...
login_user_spec.rb
require_relative '../spec_helper'
require_relative '../lib/login_user'
describe "Existing User Log in Scenario", :type => :request do
before :all do
#user = FactoryGirl(:user)
end
xit "should allow user to select login from top nav" do
visit "/"
within("#main-header")do
click_link 'Log In'
end
page.should have_content('Log in to your account')
end
it "and fill in login form" do
visit "/login"
within("#login-form")do
fill_in 'user-email', :with => #user.email
fill_in 'user-password', :with => #user.password
end
#FIXME - the design crew will make this go away
within("#login-form") do
click_link '#login-link' #this gives false failing test...geek query...why?
end
page.should have_content('Manage courses')
end
end
Factories.rb
FactoryGirl.define :user do |u|
u.email "joe#website.com"
u.password "joe009"
end
user.rb
class User
attr_accessor :email, :password
end
spec_helper.rb
require 'rubygems'
require 'bundler/setup'
require 'capybara'
require 'rspec'
require 'capybara/rspec'
require 'json'
require 'capybara/dsl'
# Capybara configuration
Capybara.default_driver = :selenium
Capybara.app_host = "http://www.website.com"
require 'factory_girl'
# give me ma stuff
FactoryGirl.find_definitions
require "rspec/expectations"
include Capybara::DSL
include RSpec::Matchers
ANSWER: :user is a reserved word..changed it to :stuff...works fine now.
Try to use new syntax from readme
FactoryGirl.define do
factory :user do
email "joe#website.com"
password "joe009"
end
end
If this is a non-rails app you will have to create a Userclass first. I'm not sure if you have to have instance vars with name, password and email but you definitely will have to have that class defined somewhere.
See the Getting Started file on Github for more on that.
Try this
FactoryGirl.define do
factory :user do |u|
u.email "joe#website.com"
u.password "joe009"
end
end

Acceptance testing of sinatra app using webrat fails

I am trying to test a ruby authentication app using minitest and webrat but get errors.
Tests like visit '/' fail with an error Status 200 expected but was 404.
Tests containing code like fill_in :email, :with => "first#company.com" fail with error Could not find field: :email.
I read several sinatra, testing and webrat documents and forums. Some of them were old and suggested stuff like Sinatra::Default, but github.com/brynary/webrat/wiki/sinatra, Building a Sinatra App Driven By Webrat Tests and Learning From the Masters: Sinatra Internals are new, yet they still fail.
Basically, I didn't like sentence-like syntax of rspec, cucumber etc but do want to do behaviour driven development. I really like the minitest syntax, both tests and output and that is why I choose webrat for BDD. If I'm wrong about expecting webrat to fulfill acceptance testing requirements, please simply tell me that I should use this framework or that one.
Apart from that, the first parts of the main file and test file are below. I hope someone can explain me, what I am missing?
test_file
require "test/unit"
require "minitest/autorun"
require "rack/test"
require 'webrat'
require_relative "../lib/kimsin.rb"
Webrat.configure do |config|
config.mode = :rack
end
ENV["RACK_ENV"] = "test"
class KimsinTests < Test::Unit::TestCase
include Rack::Test::Methods
include Webrat::Methods
include Webrat::Matchers
def app
Sinatra::Application.new
end
def test_create_user
visit "/user/new"
fill_in :username, :with => "first#company.com"
fill_in :password, :with => "abC123?*"
fill_in :confirm_password, :with => "abC123?*"
click_link "Register"
assert 201, last_response.status, "Status 201 expected but was #{last_response.status}.\n#{error}"
assert_contain /Logged in as first#company.com./, "No user created"
assert_contain /Logout/, "Logout link not present"
end
main_file
require "sinatra"
require "erb"
require_relative "../lib/kimsin/version"
require_relative "../lib/kimsin/user"
class Kimsin < Sinatra::Application
use Rack::Session::Pool, :expire_after => 2592000
set :session_secret, BCrypt::Engine.generate_salt
configure :development do
DataMapper.auto_migrate!
end
get "/" do
if session[:user_id]
user = User.get session[:user_id]
email = user.email
erb :index, :locals => { :email => email }
else
email = nil
erb :index, :locals => { :email => email }
end
end
Using Sinatra with Webrat should work fine. I think that the errors that you are seeing are caused by the following method (around line 18 in your test file):
def app
Sinatra::Application.new
end
This is setting up the Sinatra::Application base class to run your tests against when you really need to set up your own subclass Kimsin (because you are creating a modular style Sinatra app), i.e.
def app
Kimsin.new
end
The 404 errors and missing fields are happening because Sinatra::Application doesn't define any of the routes you are testing.
You might also like to take a look at Capybara if you are looking for similar alternatives to Webrat.

"No tests." error in ruby unit tests

My original test for user.rb looks like this:
require "test/unit"
require "minitest/autorun"
require "rack/test"
require_relative "../lib/kimsin.rb"
ENV['RACK_ENV'] = 'test'
class UserTests < Test::Unit::TestCase
include Rack::Test::Methods
include Kimsin
def app
Sinatra::Application
end
def test_user
#user = User.create :username => "barerd", :password => "abcdef"
get "/users"
assert_equal #user.username, "barerd"
refute_match #user.password, "abcdef"
end
end
The test ran and obviously failed as there was no User class. When I added the User class like below:
module Kimsin
require "data_mapper"
require "dm-migrations"
DataMapper.setup :default, "sqlite:///users.db"
class User
include DataMapper::Resource
include BCrypt
property :id, Serial
property :username, String, :required => true
property :password, String, :required => true
property :salt, String, :default => "876587349506434245565664566"
property :crypto, String, :default => BCrypt::Password.create password + salt
end
User.auto_migrate!
end
it throws a "No tests." error. Actually, not only this one but all tests throw the same error now. I suspected that this has sth to do with ruby in general, because it happened after I gem installed dm-core and at the beginning it threw an error:
"Error loading RubyGems plugin "/home/barerd/.rvm/gems/ruby-1.9.3-p125/gems/rubygems-bundler-0.2.8/lib/rubygems_plugin.rb": cannot load such file -- rubygems_bundler/rubygems_bundler_installer (LoadError)"
But when I try to run tests of other apps, they all work fine.
I use rvm 1.11.6 (stable) and ruby 1.9.3p125 (2012-02-16 revision 34643) [i386-cygwin] on a windows 7 by the way. Any clue to the error?
To note, the core module file kimsin.rb is as follows:
require "sinatra"
require "erb"
require "bcrypt"
require_relative "../lib/kimsin/version"
require_relative "../lib/kimsin/user"
use Rack::Session::Pool, :expire_after => 2592000
set :session_secret, "n9c0431qt043fcwo4ponm3w5483qprutc3q9pfw3r0swaypedx2qafec2qdomvuj8cy4nawscerf"
module Kimsin
get "/" do
title = "Kimsin?"
erb :index, :locals => {:title => title}
end
end

Load error when trying to include custom module

Same app, different problem. I'm working on an app using the Dan Benjamin "Meet Sinatra" screencast as a reference. I'm trying to include a custom authentication module, which is housed in a lib folder (lib/authentication.rb). I am requiring that line at the top of my code, but when I try to load the page, it claims there is no such file to load.
Any thoughts?
Here's the top of my main Sinatra file:
require 'sinatra'
require 'rubygems'
require 'datamapper'
require 'dm-core'
require 'lib/authorization'
DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/entries.db")
class Entry
include DataMapper::Resource
property :id, Serial
property :first_name, String
property :last_name, String
property :email, String
property :created_at, DateTime
end
# create, upgrade, or migrate tables automatically
DataMapper.auto_upgrade!
helpers do
include Sinatra::Authorization
end
And the actual Module:
module Sinatra
module Authorization
def auth
#auth ||= Rack::Auth::Basic::Request.new(request.env)
end
def unauthorized!(realm="Short URL Generator")
headers 'WWW-Authenticate' => %(Basic realm="#{realm}")
throw :halt, [ 401, 'Authorization Required' ]
end
def bad_request!
throw :halt, [ 400, 'Bad Request' ]
end
def authorized?
request.env['REMOTE_USER']
end
def authorize(username, password)
if (username=='topfunky' && password=='peepcode') then
true
else
false
end
end
def require_admin
return if authorized?
unauthorized! unless auth.provided?
bad_request! unless auth.basic?
unauthorized! unless authorize(*auth.credentials)
request.env['REMOTE_USER'] = auth.username
end
def admin?
authorized?
end
end
end
Then, on any of the handlers I want to protect, I put "require_admin."
Assuming you're using Ruby 1.9, the default $LOAD_PATH no longer includes the current directory. So while statements like require 'sinatra' work just fine (because those gems are in $LOAD_PATH), Ruby doesn't know that your lib/authorization file is located relative to your main Sinatra file.
You can add the Sinatra file's directory to the load path, and then your require statements should work fine:
$LOAD_PATH.unshift(File.dirname(__FILE__))
require 'sinatra'
require 'rubygems' # Not actually needed on Ruby 1.9
require 'datamapper'
require 'dm-core'
require 'lib/authorization'
Personnaly, I use a "relative" path since I work with Ruby 1.9.2 :
require 'sinatra'
require 'rubygems' # Not actually needed on Ruby 1.9
require 'datamapper'
require 'dm-core'
require './lib/authorization'
But I never check what would happen if my code should work on Ruby 1.8.6 again.

Resources