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 _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users