I want to increase the number of target data by one by sending POST in request spec, but I get Can't verify CSRF token authenticity.

Asked 2 years ago, Updated 2 years ago, 93 views

  • Rails 7.0
  • Docker

I am currently studying Rspec in the Introduction to Rails Testing with Everyday Rails Rspec

"We are testing using requestspec to ""send Post to make sure DB has one more target data"", but the test has failed due to the following error:

error

 expected Project:: ActiveRecord_Associations_CollectionProxy #count to have changed by 1, but was changed by 0

I debugged some of them and put out the error screen, and I was stuck with Rails' CSRF countermeasures such as Can't verify CSRF token authenticity, so this is probably the reason.

Enter a description of the image here

We use Device for user login authentication.
We use Rsepc's FactoryBot for user generation and target data generation (Project).
Also, the version of Rails I am currently using is 7.0, so I am not sure how to pass the CSRF countermeasure, so I would appreciate it if you could let me know if anyone knows.

spec/requests/projects_api_spec.rb

require 'rails_helper'

RSpec.describe "ProjectsApis", type: :request do
# This test is successful.
    it "create one project" do
      user=FactoryBot.create(:user)
      FactoryBot.create(:project, name: "Sample Project")
      FactoryBot.create(:project, name: "Second Sample Project", owner:user)

      get api_projects_path, params: {
        user_email: user.email,
        user_token —user.authentication_token
      }

      expect(response).to have_http_status(:success)
      json=JSON.parse(response.body)
      expect(json.length).to eq1
      project_id=json[0]["id"]

      get api_projects_path(project_id), params: {
        user_email: user.email,
        user_token —user.authentication_token
      }

      expect(response).to have_http_status(:success)
      json=JSON.parse(response.body)
      expect(json[0]["name"]).to eq "Second Sample Project"
    end

    # This test has failed.
        it "Be able to create a project" do
      user=FactoryBot.create(:user)
      project_attributes=FactoryBot.attributes_for(:project)

      expect{
        post api_projects_path, params: {
          user_email: user.email,
          user_token —user.authentication_token,
          project —Project_attributes
        }
      }.to change(user.projects,:count).by(1)

      expect(response).to have_http_status(:success)
    end
end

app/controllers/application_controller.rb

class ApplicationController<ActionController::Base
  before_action —Authenticate_user!

  protected

  default_project
    @project=Project.find(params[:project_id])
  end

  def project_owner ?
    [email protected]==current_user
      redirect_to root_path, alert: "You don't have access to that project."
    end
  end
end

spec/factories/projects.rb

FactoryBot.definedo
  factory —Project do
    sequence(:name) {|n|"Project#{n}"}
    description {"A test project"}
    due_on {1.week.from_now}
    association:owner

    # a project with a note
    trace —with_notes do
      after(:create) { | project | create_list(:note, 5, project:project)}
    end

    # a project due yesterday
    trace —due_yesterday do
      due_on {1.day.ago}
    end

    # project due today
    trace —due_today do
      due_on {Date.current.in_time_zone}
    end

    # a project due tomorrow
    trace —due_tomorrow do
      due_on {1.day.from_now}
    end

    # be disabled
    trace —Invalid do
      name {nil}
    end
  end
end
FactoryBot.definedo
  factory:user, aliases:[:owner] do
    first_name {"Aaron"}
    last_name {"Sumner"}
    sequence(:email) { | n | "tester#{n}@e-xample.com"}
    password {"dottle-nouveau-pavillion-tights-furze"}
  end
end

ruby-on-rails rspec

2022-09-30 17:42

1 Answers

Rails 7.0 defaults to config.action_controller.allow_forgery_protection with false skipped CSRF token validation: in the test environmenthttps://github.com/rails/rails/blob/1a22ebc/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt#L33-L34

If you don't even need to verify the CSRF token during the test, check this setting.

If you want to verify the CSRF token during the test, it would be better to explicitly give the token in the request spec.You should use ActionController::RequestForgeryProtection #form_authenticity_token to generate your own token and pass it as a parameter named authenticity_token.

By the way, the failure of the test may not be due to the CSRF token.The error message that the test failed is that the count has not changed as intended, not that the POST request failed.If the POST request has failed, the error should appear before detecting the change.

So, maybe post api_projects_path is really not creating a new record?Please review the implementation of the controller that handles this request.


2022-09-30 17:42

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.