I'm looking to have users only be able to delete the jobs that they've created themselves (not the jobs of others). I've verified that my app does do this through "rails server". However, the tests are coming out weird.
Here are the tests in question:
require 'spec_helper'
describe "Authentication" do
subject { page }
describe "signin" do
[...]
describe "authorization" do
[...]
describe "correct user control" do
let(:user) { FactoryGirl.create(:user) }
let(:job) { FactoryGirl.create(:job, user: user) }
let(:wrong_user) { FactoryGirl.create(:user, email: "[email protected]") }
let(:wrong_job) { FactoryGirl.create(:job, user: wrong_user) }
before { sign_in user }
[...]
describe "users can only delete their own jobs" do
it "should not change job count" do
expect do
delete job_path(wrong_job)
end.to_not change(Job, :count)
end
end
describe "users can delete their own jobs" do
it "should decrease job count" do
expect do
delete job_path(job)
end.to change(Job, :count).by(-1)
end
end
end
end
end
end
Except, I'm getting this weird output:
Failures:
1) Authentication signin authorization correct user control users can only delete their own jobs should not decrease job count
Failure/Error: expect do
count should not have changed, but did change from 0 to 1
# ./spec/requests/authentication_pages_spec.rb:68:in `block (6 levels) in <top (required)>'
2) Authentication signin authorization correct user control users can delete their own jobs should decrease job count
Failure/Error: expect do
count should have been changed by -1, but was changed by 1
# ./spec/requests/authentication_pages_spec.rb:75:in `block (6 levels) in <top (required)>'
Why does the job count increase? Why does the test not work as intended?
Other information:
jobs_controller.rb
class JobsController < ApplicationController
skip_before_action :require_signin, only: [:index, :show]
skip_before_action :correct_user, only: [:index, :show, :new, :create]
before_action :set_job, only: [:show, :edit, :update, :destroy]
[...]
def destroy
@job.destroy
respond_to do |format|
format.html { redirect_to jobs_url }
format.json { head :no_content }
end
end
private
def set_job
@job = Job.find(params[:id])
end
def job_params
params.require(:job).permit(:title, :org, :internship, :postdate, :filldate, :location, :link, :description)
end
end
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_filter :require_signin
before_filter :correct_user
include SessionsHelper
private
def require_signin
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
end
def correct_user
@job = current_user.jobs.find_by(id: params[:id])
redirect_to root_url if @job.nil?
end
end
rake routes
Prefix Verb URI Pattern Controller#Action
jobs GET /jobs(.:format) jobs#index
POST /jobs(.:format) jobs#create
new_job GET /jobs/new(.:format) jobs#new
edit_job GET /jobs/:id/edit(.:format) jobs#edit
job GET /jobs/:id(.:format) jobs#show
PATCH /jobs/:id(.:format) jobs#update
PUT /jobs/:id(.:format) jobs#update
DELETE /jobs/:id(.:format) jobs#destroy
[...]
There are two problems:
As Jacek mentioned, let is evaluated lazily. That means that the code inside the block isn't run until the variable is used. Since the job variable is used for the first time within the expect blocks, the job count increases. If you want the code inside the let blocks to be run immediately, use the let! method.
get, put, patch, and delete should be used in controller tests, not integration tests:
# jobs_controller_spec.rb delete :destroy, id: job
In integration tests, you should use Capybara to simulate user input:
# users_messing_around_with_jobs_spec.rb
click_button("Delete")
In your tests, delete doesn't do what you'd expect: for some reason it's mapped to jobs#index.
Try let! instead of let because simple "let" is lazy-evaluated. I mean especially this two lines:
let!(:job) { FactoryGirl.create(:job, user: user) }
let!(:wrong_job) { FactoryGirl.create(:job, user: wrong_user) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With