- Read Tutorial
- Watch Guide Video
In this guide we are going to refactor our post_spec.rb
because it's starting to get a bit unwieldy.
Let's start off by creating some let
statements. Essentially, this will give us access to users
, but a new one won't be run with each block. Instead, it will run just once. This will allow us to use the local variable user
throughout the program.
# spec/features/post_spec.rb let(:user) { FactoryGirl.create(:user) }
Next, we are going to force our post to have the same user id
every time. Here is how we can integrate our let
statement.
# spec/features/post_spec.rb let(:post) do Post.create(date: Date.today, rationale: "Rationale", user_id: user.id) end
Now we can update our before
block to only log the user in (notice how I changed the login argument to use the user
variable).
# spec/features/post_spec.rb before do login_as(user, :scope => :user) end
Now, move down to the test case that says "has a scope so that only post creators can see their posts"
. Let's remove post1
and post2
completely. Now if you run rspec
you'll see that we have a failure in the "Delete"
block. We'll fix that later.
Next, go to the "edit"
block and remove all the code where we create a user and log them in. We can do this because we now have access to the post
variable from our let
, so we don't need any of this duplicate code.
Also, let's change all of the @post
variables in the edit
block to post
since the instance variable doesn't exist anymore. If you run rspec
now, this test passes.
Now, let's fix our "delete"
test case. Remove the code where you create a new post since that is no longer needed. Also, change @post
to post
as we did in the edit
block. If you run rspec
, it still fails.
This failure is due to the permission structure. If we logout our test user and then create a new user, log in that user and create a post with the new user id it will work.
If you run rspec
, all of the tests should now pass.
Overall I'm happy with this refactor. It's cleaned up a number of the duplicate code items and takes advantage of FactoryGirl
factories. The update post_spec
file is shown below:
# spec/features/post_spec.rb require 'rails_helper' describe 'navigate' do let(:user) { FactoryGirl.create(:user) } let(:post) do Post.create(date: Date.today, rationale: "Rationale", user_id: user.id) end before do login_as(user, :scope => :user) end describe 'index' do before do visit posts_path end it 'can be reached successfully' do expect(page.status_code).to eq(200) end it 'has a title of Posts' do expect(page).to have_content(/Posts/) end it 'has a list of posts' do post1 = FactoryGirl.build_stubbed(:post) post2 = FactoryGirl.build_stubbed(:second_post) visit posts_path expect(page).to have_content(/Rationale|content/) end it 'has a scope so that only post creators can see their posts' do other_user = User.create(first_name: 'Non', last_name: 'Authorized', email: "nonauth@example.com", password: "asdfasdf", password_confirmation: "asdfasdf") post_from_other_user = Post.create(date: Date.today, rationale: "This post shouldn't be seen", user_id: other_user.id) visit posts_path expect(page).to_not have_content(/This post shouldn't be seen/) end end describe 'new' do it 'has a link from the homepage' do visit root_path click_link("new_post_from_nav") expect(page.status_code).to eq(200) end end describe 'delete' do it 'can be deleted' do logout(:user) delete_user = FactoryGirl.create(:user) login_as(delete_user, :scope => :user) post_to_delete = Post.create(date: Date.today, rationale: 'asdf', user_id: delete_user.id) visit posts_path click_link("delete_post_#{post_to_delete.id}_from_index") expect(page.status_code).to eq(200) end end describe 'creation' do before do visit new_post_path end it 'has a new form that can be reached' do expect(page.status_code).to eq(200) end it 'can be created from new form page' do fill_in 'post[date]', with: Date.today fill_in 'post[rationale]', with: "Some rationale" click_on "Save" expect(page).to have_content("Some rationale") end it 'will have a user associated it' do fill_in 'post[date]', with: Date.today fill_in 'post[rationale]', with: "User Association" click_on "Save" expect(User.last.posts.last.rationale).to eq("User Association") end end describe 'edit' do it 'can be edited' do visit edit_post_path(post) fill_in 'post[date]', with: Date.today fill_in 'post[rationale]', with: "Edited content" click_on "Save" expect(page).to have_content("Edited content") end it 'cannot be edited by a non authorized user' do logout(:user) non_authorized_user = FactoryGirl.create(:non_authorized_user) login_as(non_authorized_user, :scope => :user) visit edit_post_path(post) expect(current_path).to eq(root_path) end end end