Created
September 25, 2019 22:50
-
-
Save jaimerson/6a538d361276101c01add6c171c1bd1b to your computer and use it in GitHub Desktop.
RSpec custom matchers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'bundler/inline' | |
gemfile do | |
source 'https://rubygems.org' | |
gem 'rspec' | |
end | |
require 'rspec/autorun' | |
class Car | |
attr_reader :make, :model, :year, :doors | |
def initialize(make: 'Chevrolet', model: 'Impala', year: 1967, doors: 2) | |
@make = make | |
@model = model | |
@year = year | |
@doors = doors | |
end | |
end | |
RSpec.configure do |config| | |
config.expect_with :rspec do |c| | |
c.include_chain_clauses_in_custom_matcher_descriptions = true | |
end | |
end | |
RSpec.describe Car do | |
specify do | |
expect(Car.new).to be_made_by('Chevrolet') | |
.and have_model('Impala') | |
.and have_been_made_in(1967) | |
.and have_two_doors | |
end | |
specify do | |
expect(Car.new(doors: 4)).to not_be_made_by('Nissan') | |
.and not_have_model('Skyline') | |
.and not_have_been_made_in(2010) | |
.and not_have_two_doors | |
end | |
specify do | |
car = Car.new(year: 1980) | |
expect(car).to have_been_made_after(1970) | |
.and_before(1990) | |
end | |
context 'when using information from the context' do | |
let(:today) do | |
require 'date' | |
Date.ordinal(2019, -1) # 31/12/2019 | |
end | |
specify do | |
car = Car.new(year: 1960) | |
expect(car).to be_older_than(1980) | |
.and be_older_than(40).years | |
end | |
end | |
matcher :be_older_than do | |
match do |actual| | |
if @older_than_year | |
today - actual.year > expected | |
else | |
have_been_made_before(expected) | |
end | |
end | |
chain :years do | |
@older_than_year = true | |
end | |
end | |
matcher :have_been_made_before do | |
match do |actual| | |
actual.year < expected | |
end | |
end | |
matcher :have_been_made_after do | |
match do |actual| | |
made_after = actual.year > expected | |
if @before_year | |
made_after && actual.year < @before_year | |
else | |
made_after | |
end | |
end | |
match_when_negated do |actual| | |
if @before_year | |
fail ArgumentError, "You can't chain `and_before` when using negated version" | |
end | |
actual.year <= expected | |
end | |
chain :and_before do |before_year| | |
@before_year = before_year | |
end | |
description do | |
desc = "be manufactured after #{expected}" | |
desc << " and before #{@before_year}" if @before_year | |
end | |
failure_message do |actual| | |
message = "Expected #{actual} to have been made after #{expected}" | |
message << " and before #{@before_year}" if @before_year | |
message << " but it was made in #{actual.year}." | |
end | |
RSpec::Matchers.define_negated_matcher :not_have_been_made_after, :have_been_made_after | |
end | |
matcher :be_made_by do | |
match do |actual| | |
actual.make == expected | |
end | |
RSpec::Matchers.define_negated_matcher :not_be_made_by, :be_made_by | |
end | |
matcher :have_model do | |
match do |actual| | |
actual.model == expected | |
end | |
RSpec::Matchers.define_negated_matcher :not_have_model, :have_model | |
end | |
matcher :have_been_made_in do | |
match do |actual| | |
actual.year == expected | |
end | |
RSpec::Matchers.define_negated_matcher :not_have_been_made_in, :have_been_made_in | |
end | |
matcher :have_two_doors do | |
match do |actual| | |
actual.doors == 2 | |
end | |
RSpec::Matchers.define_negated_matcher :not_have_two_doors, :have_two_doors | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment