On Jul 26, 2011, at 12:51 AM, Patrick J. Collins wrote:
>> Here''s an example of my first test, but I''m wondering
how I setup the
>> login routine so I can use it in future specs without repeating the
>> method. Some sort of - before.each (:login)
> You can use shared examples...
>
> shared_examples_for "any page requiring authentication" do
> fill_in :login, :with => @user.email
> fill_in :password, :with => @user.password
> click_button "login_button"
> page.has_content?("Logged in successfully")
> end
>
> Then in your specs you can do:
>
> describe User do
> it_behaves_like "any page requiring authentication"
> end
You _can_ use shared content, but what you have here ^^ doesn''t work as
written. The scope in the shared_examples_for block is an example group scope,
not an example scope, so methods like fill_in and click_button are not
available. You''d want to wrap them in a before block. Also,
page.has_content?(...) will return true or false, but will not act like an
expectation (i.e. RSpec won''t care which it returns).
Here are a couple of ways you could do this that will work as Chris expects:
shared_context "logged in" do
let(:user) { Factory(:user) }
before do
fill_in :login, :with => user.email
fill_in :password, :with => user.password
click_button "login_button"
end
end
describe ArticlesController do
include_context "logged in"
describe "GET edit" do
it "does something" do
# here the shared before hook has already run
# and you have access to the `user` generated
# by the `let` declaration.
end
end
end
This assumes you only want one user. It''s simple and clean, without
confusing indirection or parameterization. On the other extreme you could do
this:
shared_context "logged in" do
before do
visit new_session_path
fill_in :login, :with => user.email
fill_in :password, :with => user.password
click_button :submit
end
end
shared_context "admin" do
let(:user) { Factory(:admin_user) }
include_context "logged in"
end
shared_context "staff" do
let(:user) { Factory(:staff_user) }
include_context "logged in"
end
RSpec.configure do |conf|
conf.alias_it_should_behave_like_to :logged_in_as
end
describe "Articles" do
describe "GET index" do
logged_in_as "admin" do
it "does something" do
# ...
end
end
logged_in_as "staff" do
it "does something else" do
# ...
end
end
end
end
The output from this looks like:
ArticlesController
GET index
logged in as admin
does something
logged in as staff
does something else
Both of these approaches keep things explicit. You can also do a more implicit
approach, like this:
RSpec.configure do |c|
c.before(:each, :type => :request) do
@user = Factory(:user)
visit new_session_path
fill_in :login, :with => @user.email
fill_in :password, :with => @user.password
click_button :submit
end
end
describe "Articles" do
describe "GET index" do
it "does something" do
# ...
end
end
end
Here you don''t see any evidence in the example that you''re
logging in. Less typing, but less clarity. I''d avoid this approach
myself, but it is another option for you.
HTH,
David
> Patrick J. Collins
> http://collinatorstudios.com