Created
February 23, 2012 20:36
-
-
Save justinko/1894922 to your computer and use it in GitHub Desktop.
Help for rspec-users mailing list question
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
shared_examples_for 'employee signin' do | |
it { should have_selector('title', text: employee.emp_full_name) } | |
it { should have_link('Sign out', href: signout_path) } | |
it { should_not have_link('Sign in', href: signin_path) } | |
end | |
describe "Authentication" do | |
subject { page } | |
describe "signin" do | |
before { visit signin_path } | |
it { should have_selector('h2', text: 'Sign in') } | |
it { should have_selector('title', text: 'Sign in') } | |
describe "with an employee" do | |
let(:employee) { FactoryGirl.create(:employee) } | |
before { valid_signin(employee) } | |
include_examples 'employee signin' | |
it { should_not have_link('Employees', href: employees_path) } | |
it { should_not have_link('Profile', href: employee_path(employee)) } | |
it { should_not have_link('Settings', href: edit_employee_path(employee)) } | |
it { should_not have_link('New Employee', href: new_employee_path) } | |
end | |
describe "with an admin employee" do | |
let(:employee) { FactoryGirl.create(:admin_employee) } | |
before { valid_signin(employee) } | |
include_examples 'employee signin' | |
it { should have_link('Employees', href: employees_path) } | |
it { should have_link('Profile', href: employee_path(employee)) } | |
it { should have_link('Settings', href: edit_employee_path(employee)) } | |
it { should have_link('New Employee', href: new_employee_path) } | |
end | |
end | |
end | |
# If you *really* want to get DRY | |
require 'spec_helper' | |
shared_context 'employee signin' do |employee_type| | |
let(:employee) { FactoryGirl.create(employee_type) } | |
before { valid_signin(employee) } | |
it { should have_selector('title', text: employee.emp_full_name) } | |
it { should have_link('Sign out', href: signout_path) } | |
it { should_not have_link('Sign in', href: signin_path) } | |
case employee_type | |
when :employee | |
it { should_not have_link('Employees', href: employees_path) } | |
it { should_not have_link('Profile', href: employee_path(employee)) } | |
it { should_not have_link('Settings', href: edit_employee_path(employee)) } | |
it { should_not have_link('New Employee', href: new_employee_path) } | |
when :admin_employee | |
it { should have_link('Employees', href: employees_path) } | |
it { should have_link('Profile', href: employee_path(employee)) } | |
it { should have_link('Settings', href: edit_employee_path(employee)) } | |
it { should have_link('New Employee', href: new_employee_path) } | |
end | |
end | |
describe "Authentication" do | |
subject { page } | |
describe "signin" do | |
before { visit signin_path } | |
it { should have_selector('h2', text: 'Sign in') } | |
it { should have_selector('title', text: 'Sign in') } | |
describe "with an employee" do | |
include_context 'employee signin', :employee | |
end | |
describe "with an admin employee" do | |
include_context 'employee signin', :admin_employee | |
end | |
end | |
end |
I really dislike the second version
Same here. Didn't really think about what I was doing.
I really dislike the second version
Same here. Didn't really think about what I was doing.
No problem. It helped get us here.
Out of all of the ones listed I like @justinko's 1st version. It's the simplest, clearest, and easiest to understand and change without having to study the code. If you wanted your top-level "authentication" spec to be more declarative then I'd extract the different examples out into two shared contexts. This is similar to @justinko's 2nd version, but avoids the unnecessary case statement.
Here's a take on that:
require 'spec_helper'
shared_context "a user signs in" do
it { should have_link('Sign out', href: signout_path) }
it { should_not have_link('Sign in', href: signin_path) }
it { should have_selector('title', text: employee.emp_full_name) }
end
shared_context 'an employee signs in' do
let(:employee) { FactoryGirl.create(:employee) }
before { valid_signin(employee) }
include_examples "a user signs in"
it { should_not have_link('Employees', href: employees_path) }
it { should_not have_link('Profile', href: employee_path(employee)) }
it { should_not have_link('Settings', href: edit_employee_path(employee)) }
it { should_not have_link('New Employee', href: new_employee_path) }
end
shared_context 'an admin employee signs in' do
let(:employee) { FactoryGirl.create(:admin_employee) }
before { valid_signin(employee) }
include_examples "a user signs in"
it { should have_link('Employees', href: employees_path) }
it { should have_link('Profile', href: employee_path(employee)) }
it { should have_link('Settings', href: edit_employee_path(employee)) }
it { should have_link('New Employee', href: new_employee_path) }
end
And then in your authentication_spec something like:
describe "Authentication" do
subject { page }
describe "signin" do
before { visit signin_path }
it { should have_selector('h2', text: 'Sign in') }
it { should have_selector('title', text: 'Sign in') }
include_examples 'an employee signs in'
include_examples 'an admin employee signs in'
end
end
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I really dislike the second version, because it's like looping, but executing a different branch during each iteration of the loop.
If you really want to be DRY, then describe each set of expectations as data:
This requires a custom matcher, so perhaps this is easier:
I left the empty dictionaries in there just for clarity. You might remove them.