123456789_123456789_123456789_123456789_123456789_

Module: RSpec::Rails::Matchers

Overview

Container module for ::RSpec::Rails specific matchers.

Class Method Summary

::RSpec::Matchers::DSL - Extended

alias_matcher

Defines a matcher alias.

define

Defines a custom matcher.

define_negated_matcher

Defines a negated matcher.

matcher
warn_about_block_args

:nocov:

Instance Method Summary

Instance Method Details

#be_a_new(model_class)

Passes if actual is an instance of model_class and returns true for new_record?. Typically used to specify instance variables assigned to views by controller actions

Use the with method to specify the specific attributes to match on the new record.

Examples:

get :new
assigns(:thing).should be_a_new(Thing)

post :create, :thing => { :name => "Illegal Value" }
assigns(:thing).should be_a_new(Thing).with(:name => nil)
[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/be_a_new.rb', line 78

def be_a_new(model_class)
  BeANew.new(model_class)
end

#be_new_record

Passes if actual returns true for new_record?.

Examples:

get :new
expect(assigns(:thing)).to be_new_record
[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/be_new_record.rb', line 25

def be_new_record
  BeANewRecord.new
end

#be_valid(*args)

Passes if the given model instance’s valid? method is true, meaning all of the ActiveModel::Validations passed and no errors exist. If a message is not given, a default message is shown listing each error.

Examples:

thing = Thing.new
expect(thing).to be_valid
[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/be_valid.rb', line 44

def be_valid(*args)
  BeValid.new(*args)
end

#check_action_cable_adapter (private)

This method is for internal use only.

Raises:

  • (StandardError)
[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/action_cable.rb', line 63

def check_action_cable_adapter
  return if ::ActionCable::SubscriptionAdapter::Test === ::ActionCable.server.pubsub

  raise StandardError, "To use ActionCable matchers set `adapter: test` in your cable.yml"
end

#check_active_job_adapter (private)

This method is for internal use only.

Raises:

  • (StandardError)
[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/active_job.rb', line 517

def check_active_job_adapter
  return if ::ActiveJob::QueueAdapters::TestAdapter === ::ActiveJob::Base.queue_adapter

  raise StandardError, "To use ActiveJob matchers set `ActiveJob::Base.queue_adapter = :test`"
end

#enqueue_email(mailer_class = nil, mail_method_name = nil)

Alias for #have_enqueued_mail.

[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/have_enqueued_mail.rb', line 255

alias_method :enqueue_email, :have_enqueued_mail

#enqueue_job(job = nil)

Alias for #have_enqueued_job.

[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/active_job.rb', line 405

alias_method :enqueue_job, :have_enqueued_job

#enqueue_mail(mailer_class = nil, mail_method_name = nil)

Alias for #have_enqueued_mail.

[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/have_enqueued_mail.rb', line 254

alias_method :enqueue_mail, :have_enqueued_mail

#have_been_enqueued

Passes if a job has been enqueued. May chain at_least, at_most or exactly to specify a number of times.

Examples:

before { ActiveJob::Base.queue_adapter.enqueued_jobs.clear }

HeavyLiftingJob.perform_later
expect(HeavyLiftingJob).to have_been_enqueued

HelloJob.perform_later
HeavyLiftingJob.perform_later
expect(HeavyLiftingJob).to have_been_enqueued.exactly(:once)

3.times { HelloJob.perform_later }
expect(HelloJob).to have_been_enqueued.at_least(2).times

HelloJob.perform_later
expect(HelloJob).to enqueue_job(HelloJob).at_most(:twice)

HelloJob.perform_later
HeavyLiftingJob.perform_later
expect(HelloJob).to have_been_enqueued
expect(HeavyLiftingJob).to have_been_enqueued

HelloJob.set(wait_until: Date.tomorrow.noon, queue: "low").perform_later(42)
expect(HelloJob).to have_been_enqueued.with(42).on_queue("low").at(Date.tomorrow.noon)

HelloJob.set(queue: "low").perform_later(42)
expect(HelloJob).to have_been_enqueued.with(42).on_queue("low").at(:no_wait)
[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/active_job.rb', line 436

def have_been_enqueued
  check_active_job_adapter
  ActiveJob::HaveBeenEnqueued.new
end

#have_been_performed

Passes if a job has been performed. May chain at_least, at_most or exactly to specify a number of times.

Examples:

before do
  ActiveJob::Base.queue_adapter.performed_jobs.clear
  ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
  ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = true
end

HeavyLiftingJob.perform_later
expect(HeavyLiftingJob).to have_been_performed

HelloJob.perform_later
HeavyLiftingJob.perform_later
expect(HeavyLiftingJob).to have_been_performed.exactly(:once)

3.times { HelloJob.perform_later }
expect(HelloJob).to have_been_performed.at_least(2).times

HelloJob.perform_later
HeavyLiftingJob.perform_later
expect(HelloJob).to have_been_performed
expect(HeavyLiftingJob).to have_been_performed

HelloJob.set(wait_until: Date.tomorrow.noon, queue: "low").perform_later(42)
expect(HelloJob).to have_been_performed.with(42).on_queue("low").at(Date.tomorrow.noon)
[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/active_job.rb', line 509

def have_been_performed
  check_active_job_adapter
  ActiveJob::HaveBeenPerformed.new
end

#have_broadcasted_to(target = nil)

Passes if a message has been sent to a stream/object inside a block. May chain at_least, at_most or exactly to specify a number of times. To specify channel from which message has been broadcasted to object use from_channel.

Examples:

expect {
  ActionCable.server.broadcast "messages", text: 'Hi!'
}.to have_broadcasted_to("messages")

expect {
  SomeChannel.broadcast_to(user)
}.to have_broadcasted_to(user).from_channel(SomeChannel)

# Using alias
expect {
  ActionCable.server.broadcast "messages", text: 'Hi!'
}.to broadcast_to("messages")

expect {
  ActionCable.server.broadcast "messages", text: 'Hi!'
  ActionCable.server.broadcast "all", text: 'Hi!'
}.to have_broadcasted_to("messages").exactly(:once)

expect {
  3.times { ActionCable.server.broadcast "messages", text: 'Hi!' }
}.to have_broadcasted_to("messages").at_least(2).times

expect {
  ActionCable.server.broadcast "messages", text: 'Hi!'
}.to have_broadcasted_to("messages").at_most(:twice)

expect {
  ActionCable.server.broadcast "messages", text: 'Hi!'
}.to have_broadcasted_to("messages").with(text: 'Hi!')
[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/action_cable.rb', line 50

def have_broadcasted_to(target = nil)
  check_action_cable_adapter

  ActionCable::HaveBroadcastedTo.new(target, channel: described_class)
end

#have_enqueued_email(mailer_class = nil, mail_method_name = nil)

Alias for #have_enqueued_mail.

[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/have_enqueued_mail.rb', line 253

alias_method :have_enqueued_email, :have_enqueued_mail

#have_enqueued_job(job = nil) Also known as: #enqueue_job

Passes if a job has been enqueued inside block. May chain at_least, at_most or exactly to specify a number of times.

Examples:

expect {
  HeavyLiftingJob.perform_later
}.to have_enqueued_job

# Using alias
expect {
  HeavyLiftingJob.perform_later
}.to enqueue_job

expect {
  HelloJob.perform_later
  HeavyLiftingJob.perform_later
}.to have_enqueued_job(HelloJob).exactly(:once)

expect {
  3.times { HelloJob.perform_later }
}.to have_enqueued_job(HelloJob).at_least(2).times

expect {
  HelloJob.perform_later
}.to have_enqueued_job(HelloJob).at_most(:twice)

expect {
  HelloJob.perform_later
  HeavyLiftingJob.perform_later
}.to have_enqueued_job(HelloJob).and have_enqueued_job(HeavyLiftingJob)

expect {
  HelloJob.set(wait_until: Date.tomorrow.noon, queue: "low").perform_later(42)
}.to have_enqueued_job.with(42).on_queue("low").at(Date.tomorrow.noon)

expect {
  HelloJob.set(queue: "low").perform_later(42)
}.to have_enqueued_job.with(42).on_queue("low").at(:no_wait)

expect {
  HelloJob.perform_later('rspec_rails', 'rails', 42)
}.to have_enqueued_job.with { |from, to, times|
  # Perform more complex argument matching using dynamic arguments
  expect(from).to include "_#{to}"
}
[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/active_job.rb', line 401

def have_enqueued_job(job = nil)
  check_active_job_adapter
  ActiveJob::HaveEnqueuedJob.new(job)
end

#have_enqueued_mail(mailer_class = nil, mail_method_name = nil) Also known as: #have_enqueued_email, #enqueue_mail, #enqueue_email

Passes if an email has been enqueued inside block. May chain with to specify expected arguments. May chain at_least, at_most or exactly to specify a number of times. May chain at to specify a send time. May chain on_queue to specify a queue.

Examples:

expect {
  MyMailer.welcome(user).deliver_later
}.to have_enqueued_mail

expect {
  MyMailer.welcome(user).deliver_later
}.to have_enqueued_mail(MyMailer)

expect {
  MyMailer.welcome(user).deliver_later
}.to have_enqueued_mail(MyMailer, :welcome)

# Using alias
expect {
  MyMailer.welcome(user).deliver_later
}.to enqueue_mail(MyMailer, :welcome)

expect {
  MyMailer.welcome(user).deliver_later
}.to have_enqueued_mail(MyMailer, :welcome).with(user)

expect {
  MyMailer.welcome(user).deliver_later
  MyMailer.welcome(user).deliver_later
}.to have_enqueued_mail(MyMailer, :welcome).at_least(:once)

expect {
  MyMailer.welcome(user).deliver_later
}.to have_enqueued_mail(MyMailer, :welcome).at_most(:twice)

expect {
  MyMailer.welcome(user).deliver_later(wait_until: Date.tomorrow.noon)
}.to have_enqueued_mail(MyMailer, :welcome).at(Date.tomorrow.noon)

expect {
  MyMailer.welcome(user).deliver_later(queue: :urgent_mail)
}.to have_enqueued_mail(MyMailer, :welcome).on_queue(:urgent_mail)
[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/have_enqueued_mail.rb', line 250

def have_enqueued_mail(mailer_class = nil, mail_method_name = nil)
  HaveEnqueuedMail.new(mailer_class, mail_method_name)
end

#have_http_status(target)

Passes if response has a matching HTTP status code.

The following symbolic status codes are allowed:

  • Rack::Utils::SYMBOL_TO_STATUS_CODE

  • One of the defined ActionDispatch::TestResponse aliases:

    • :error

    • :missing

    • :redirect

    • :success

Examples:

Accepts numeric and symbol statuses

expect(response).to have_http_status(404)
expect(response).to have_http_status(:created)
expect(response).to have_http_status(:success)
expect(response).to have_http_status(:error)
expect(response).to have_http_status(:missing)
expect(response).to have_http_status(:redirect)

Works with standard response objects and Capybara’s page

expect(response).to have_http_status(404)
expect(page).to     have_http_status(:created)

Raises:

  • (ArgumentError)

See Also:

[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/have_http_status.rb', line 374

def have_http_status(target)
  raise ArgumentError, "Invalid HTTP status: nil" unless target

  HaveHttpStatus.matcher_for_status(target)
end

#have_performed_job(job = nil) Also known as: #perform_job

Passes if a job has been performed inside block. May chain at_least, at_most or exactly to specify a number of times.

Examples:

expect {
  perform_enqueued_jobs { HeavyLiftingJob.perform_later }
}.to have_performed_job

expect {
  perform_enqueued_jobs {
    HelloJob.perform_later
    HeavyLiftingJob.perform_later
  }
}.to have_performed_job(HelloJob).exactly(:once)

expect {
  perform_enqueued_jobs { 3.times { HelloJob.perform_later } }
}.to have_performed_job(HelloJob).at_least(2).times

expect {
  perform_enqueued_jobs { HelloJob.perform_later }
}.to have_performed_job(HelloJob).at_most(:twice)

expect {
  perform_enqueued_jobs {
    HelloJob.perform_later
    HeavyLiftingJob.perform_later
  }
}.to have_performed_job(HelloJob).and have_performed_job(HeavyLiftingJob)

expect {
  perform_enqueued_jobs {
    HelloJob.set(wait_until: Date.tomorrow.noon, queue: "low").perform_later(42)
  }
}.to have_performed_job.with(42).on_queue("low").at(Date.tomorrow.noon)
[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/active_job.rb', line 476

def have_performed_job(job = nil)
  check_active_job_adapter
  ActiveJob::HavePerformedJob.new(job)
end

#perform_job(job = nil)

Alias for #have_performed_job.

[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/active_job.rb', line 480

alias_method :perform_job, :have_performed_job

#receive_inbound_email(message)

Passes if the given inbound email would be routed to the subject inbox.

Parameters:

  • message (Hash, Mail::Message)

    a mail message or hash of attributes used to build one

[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/action_mailbox.rb', line 68

def receive_inbound_email(message)
  ActionMailbox::ReceiveInboundEmail.new(message)
end

#send_email(criteria = {})

Check email sending with specific parameters.

Examples:

Positive expectation

expect { action }.to send_email

Negative expectations

expect { action }.not_to send_email

More precise expectation with attributes to match

expect { action }.to send_email(to: 'test@example.com', subject: 'Confirm email')
[ GitHub ]

  
# File 'rspec-rails/lib/rspec/rails/matchers/send_email.rb', line 117

def send_email(criteria = {})
  SendEmail.new(criteria)
end