rspec-be_valid_when_matcher

Gem Version Build Status Code Climate Test Coverage Inline docs Dependency Status

RSpec matcher for testing ActiveRecord models with a fluent and clear language.

expect(person).to be_valid_when(:age).is_numeric

The matcher will check only the specified field for validation errors, so if there's one buggy validator the whole model spec suite won't go red.

Install

First, add to your Gemfile (preferably in the :test group):

gem 'rspec-be_valid_when_matcher'

Then, include RSpec::BeValidWhenMatcher in RSpec configuration:

RSpec.configure do |config|
  config.include RSpec::BeValidWhenMatcher
end

Or, directly in your model spec(s):

describe MyModel do
  include RSpec::BeValidWhenMatcher

  subject { build(:my_model) }

  describe '#header' do
    it { is_expected.not_to be_valid_when :header, nil }
  end
end

Basic usage

Here's an example using be_valid_when matcher:

require 'active_model'

class Person
  include ActiveModel::Validations

  attr_accessor :name
  attr_accessor :age

  validates_presence_of :name
  validates_numericality_of :age, greater_than: 0
end

RSpec.describe Person do
  subject { Person.new }

  it { is_expected.to be_valid_when :name, 'Frank', 'some text' }
  it { is_expected.to be_valid_when :age, 42, 'positive number' }
  it { is_expected.not_to be_valid_when :age, -1, 'negative number' }
end

The :name and :age are names of fields belonging to Person instance. If the matcher will fail, say for negative number check, it'll display the following message:

Failures:

  1) Person should not be valid when #age is negative number (-1)
     Failure/Error: it { is_expected.not_to be_valid_when :age, -1, 'negative number' }

To keep the specs more readable #is(value, message) method can be used to separate field from expected value and optional message declaration like so:

RSpec.describe Person do
  subject { Person.new }

  it { is_expected.to be_valid_when(:name).is('Frank', 'some text') }
  it { is_expected.to be_valid_when(:age).is(42, 'positive number') }
  it { is_expected.not_to be_valid_when(:age).is(-1, 'negative number') }
end

Built-in checks

In addition to standard matcher declaration interface and the #is method, there is also a number of helper methods to test common cases.

Presence

Test field validity with the nil value:

be_valid_when(:field).is_not_present

Type

Test field validity with specific type values (all methods accept field value argument):

be_valid_when(:field).is_numeric    # Defaults to 42
be_valid_when(:field).is_integer    # Defaults to 42
be_valid_when(:field).is_fixnum     # Defaults to 42
be_valid_when(:field).is_bignum     # Defaults to 42**13
be_valid_when(:field).is_float      # Defaults to 3.14
be_valid_when(:field).is_complex    # Defaults to 42+0i
be_valid_when(:field).is_rational   # Defaults to 42/1
be_valid_when(:field).is_bigdecimal # Defaults to 0.42E2
be_valid_when(:field).is_string     # Defaults to 'value'
be_valid_when(:field).is_regexp     # Defaults to /^value$/
be_valid_when(:field).is_array      # Defaults to [42]
be_valid_when(:field).is_hash       # Defaults to { value: 42 }
be_valid_when(:field).is_symbol     # Defaults to :value
be_valid_when(:field).is_range      # Defaults to 2..42

Boolean values

be_valid_when(:field).is_true
be_valid_when(:field).is_false

MIT Licensed

See LICENSE file for full license text.