- 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