RSpecRails

RSpecRails/AvoidSetupHook

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

Yes

Always

2.4

-

Checks that tests use RSpec before instead of Rails setup.

Examples

# bad
setup do
  allow(foo).to receive(:bar)
end

# good
before do
  allow(foo).to receive(:bar)
end

RSpecRails/FileFixture

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

No

No

2.33

-

Prefer file_fixture over hardcoded paths into spec/fixtures.

Safety

file_fixture uses the configured file_fixture_path, which defaults to spec/fixtures/files. A file under spec/fixtures may need to be moved or file_fixture_path configured before replacing the path.

Examples

# bad
Rails.root.join('spec', 'fixtures', 'files', 'example.pdf')

# good
file_fixture('example.pdf')

RSpecRails/HaveHttpStatus

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

Yes

Always (Unsafe)

2.12

2.27

Checks that tests use have_http_status instead of equality matchers.

Safety

The autocorrection is marked as unsafe because response.status response is not always an HTTP response status.

Examples

ResponseMethods: ['response', 'last_response'] (default)

# bad
expect(response.status).to be(200)
expect(last_response.code).to eq("200")

# good
expect(response).to have_http_status(200)
expect(last_response).to have_http_status(200)

ResponseMethods: ['foo_response']

# bad
expect(foo_response.status).to be(200)

# good
expect(foo_response).to have_http_status(200)

# also good
expect(response).to have_http_status(200)
expect(last_response).to have_http_status(200)

Configurable attributes

Name Default value Configurable values

ResponseMethods

response, last_response

Array

RSpecRails/HttpStatus

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Always

1.23

2.20

Enforces use of symbolic or numeric value to describe HTTP status.

This cop inspects only have_http_status calls. So, this cop does not check if a method starting with be_* is used when setting for EnforcedStyle: symbolic or EnforcedStyle: numeric. This cop is also capable of detecting unknown HTTP status codes.

Examples

EnforcedStyle: symbolic (default)

# bad
it { is_expected.to have_http_status 200 }
it { is_expected.to have_http_status 404 }
it { is_expected.to have_http_status "403" }

# good
it { is_expected.to have_http_status :ok }
it { is_expected.to have_http_status :not_found }
it { is_expected.to have_http_status :forbidden }
it { is_expected.to have_http_status :success }
it { is_expected.to have_http_status :error }

EnforcedStyle: numeric

# bad
it { is_expected.to have_http_status :ok }
it { is_expected.to have_http_status :not_found }
it { is_expected.to have_http_status "forbidden" }

# good
it { is_expected.to have_http_status 200 }
it { is_expected.to have_http_status 404 }
it { is_expected.to have_http_status 403 }
it { is_expected.to have_http_status :success }
it { is_expected.to have_http_status :error }

EnforcedStyle: be_status

# bad
it { is_expected.to have_http_status :ok }
it { is_expected.to have_http_status :not_found }
it { is_expected.to have_http_status "forbidden" }
it { is_expected.to have_http_status 200 }
it { is_expected.to have_http_status 404 }
it { is_expected.to have_http_status "403" }

# good
it { is_expected.to be_ok }
it { is_expected.to be_not_found }
it { is_expected.to have_http_status :success }
it { is_expected.to have_http_status :error }
# bad
it { is_expected.to have_http_status :oki_doki }

# good
it { is_expected.to have_http_status :ok }

Configurable attributes

Name Default value Configurable values

EnforcedStyle

symbolic

numeric, symbolic, be_status

RSpecRails/HttpStatusNameConsistency

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

Yes

Always

2.32

-

Enforces consistency by using the current HTTP status names.

Examples

# bad
it { is_expected.to have_http_status :unprocessable_entity }

# good
it { is_expected.to have_http_status :unprocessable_content }

RSpecRails/InferredSpecType

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

No

Always (Unsafe)

2.14

-

Identifies redundant spec type.

After setting up rspec-rails, you will have enabled config.infer_spec_type_from_file_location! by default in spec/rails_helper.rb. This cop works in conjunction with this config. If you disable this config, disable this cop as well.

Safety

This cop is marked as unsafe because config.infer_spec_type_from_file_location! may not be enabled.

Examples

# bad
# spec/models/user_spec.rb
RSpec.describe User, type: :model do
end

# good
# spec/models/user_spec.rb
RSpec.describe User do
end

# good
# spec/models/user_spec.rb
RSpec.describe User, type: :common do
end

Inferences: {services: service}

# bad
# spec/services/user_spec.rb
RSpec.describe User, type: :service do
end

# good
# spec/services/user_spec.rb
RSpec.describe User do
end

# good
# spec/services/user_spec.rb
RSpec.describe User, type: :common do
end

Configurable attributes

Name Default value Configurable values

Inferences

{"channels" ⇒ "channel", "controllers" ⇒ "controller", "features" ⇒ "feature", "generator" ⇒ "generator", "helpers" ⇒ "helper", "jobs" ⇒ "job", "mailboxes" ⇒ "mailbox", "mailers" ⇒ "mailer", "models" ⇒ "model", "requests" ⇒ "request", "integration" ⇒ "request", "api" ⇒ "request", "routing" ⇒ "routing", "system" ⇒ "system", "views" ⇒ "view"}

RSpecRails/MinitestAssertions

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

Yes

Always

2.17

-

Detects Minitest-like matchers.

Detects the use of Minitest-like matchers (those starting with assert_ or refute_).

Examples

# bad
assert_equal(a, b)
assert_equal a, b, "must be equal"
assert_not_includes a, b
refute_equal(a, b)
assert_nil a
refute_empty(b)
assert_true(a)
assert_false(a)
assert_response :ok
assert_redirected_to '/users'

# good
expect(b).to eq(a)
expect(b).to(eq(a), "must be equal")
expect(a).not_to include(b)
expect(b).not_to eq(a)
expect(a).to eq(nil)
expect(a).not_to be_empty
expect(a).to be(true)
expect(a).to be(false)
expect(response).to have_http_status(:ok)
expect(response).to redirect_to('/users')

RSpecRails/NegationBeValid

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

No

Command-line only (Unsafe)

2.23

2.29

Enforces use of be_invalid or not_to for negated be_valid.

Safety

This cop is unsafe because it cannot guarantee that the test target is an instance of ActiveModel::Validations`.

Examples

EnforcedStyle: not_to (default)

# bad
expect(foo).to be_invalid

# good
expect(foo).not_to be_valid

# good (with method chain)
expect(foo).to be_invalid.and be_odd

EnforcedStyle: be_invalid

# bad
expect(foo).not_to be_valid

# good
expect(foo).to be_invalid

# good (with method chain)
expect(foo).to be_invalid.or be_even

Configurable attributes

Name Default value Configurable values

EnforcedStyle

not_to

not_to, be_invalid

RSpecRails/ReceivePerformLater

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

Yes

No

2.33

-

Prefer have_enqueued_job over receive(:perform_later).

The have_enqueued_job matcher is preferred for testing ActiveJob enqueuing. It is more explicit and provides better clarity than using receive(:perform_later).

Examples

# bad
expect(MyJob).to receive(:perform_later)
do_something

# bad
allow(MyJob).to receive(:perform_later)
do_something
expect(MyJob).to have_received(:perform_later)

# bad
expect(MyJob).to receive(:perform_later).with(user, order)

# good
expect { do_something }.to have_enqueued_job(MyJob)

# good
expect { do_something }.to have_enqueued_job(MyJob).with(user, order)

# good
expect { do_something }
  .to have_enqueued_job(MyJob)
  .on_queue('mailers')
  .at(Date.tomorrow.noon)

RSpecRails/TravelAround

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

No

Always (Unsafe)

2.19

-

Checks for time travel helpers in around hooks.

In Rails example groups, freeze_time in a before hook does not need a block: Rails' after_teardown calls travel_back after each example. This also allows an example to use block-form time travel, which Rails does not allow inside another time travel block. See https://api.rubyonrails.org/classes/ActiveSupport/Testing/TimeHelpers.html

Safety

The automatic travel_back requires both ActiveSupport::Testing::TimeHelpers and RSpec Rails' lifecycle hooks. RSpec Rails applies those hooks to example groups with Rails type: metadata. File paths set that metadata only when infer_spec_type_from_file_location! is enabled. In a plain RSpec group that only includes TimeHelpers, use a block or call travel_back explicitly. See https://rspec.info/features/7-1/rspec-rails/directory-structure/

Autocorrection can change execution order: around starts before all before hooks, while before runs in normal hook order.

Examples

# bad
around do |example|
  freeze_time do
    example.run
  end
end

# bad
around do |example|
  freeze_time(&example)
end

# good
before { freeze_time }