Module: RSpec::Matchers

Defined in:
lib/saharspec/matchers/ret.rb,
lib/saharspec/matchers/dont.rb,
lib/saharspec/matchers/be_json.rb,
lib/saharspec/matchers/eq_multiline.rb,
lib/saharspec/matchers/send_message.rb

Instance Method Summary collapse

Instance Method Details

#be_json(expected = Saharspec::Matchers::BeJson::ANY) ⇒ Object

be_json checks if provided value is JSON, and optionally checks it contents.

If you need to check against some hashes, it is more convenient to use be_json_sym, which parses JSON with symbolize_names: true.

Examples:


expect('{}').to be_json # ok
expect('garbage').to be_json
# expected value to be a valid JSON string but failed: 765: unexpected token at 'garbage'

expect('{"foo": "bar"}').to be_json('foo' => 'bar') # ok
expect('{"foo": "bar"}').to be_json_sym(foo: 'bar') # more convenient

expect('{"foo": [1, 2, 3]').to be_json_sym(foo: array_including(3)) # nested matchers work
expect(something_large).to be_json_sym(include(meta: include(next_page: Integer)))

Parameters:

  • expected (defaults to: Saharspec::Matchers::BeJson::ANY)

    Value or matcher to check JSON against. It should implement #=== method, so all standard and custom RSpec matchers work.



90
91
92
# File 'lib/saharspec/matchers/be_json.rb', line 90

def be_json(expected = Saharspec::Matchers::BeJson::ANY)
  Saharspec::Matchers::BeJson.new(expected)
end

#be_json_sym(expected = Saharspec::Matchers::BeJson::ANY) ⇒ Object

be_json_sym checks if value is a valid JSON and parses it with symbolize_names: true. This way, it is convenient to check hashes content with Ruby's short symbolic keys syntax.

See #be_json_sym for examples.

Parameters:

  • expected (defaults to: Saharspec::Matchers::BeJson::ANY)

    Value or matcher to check JSON against. It should implement #=== method, so all standard and custom RSpec matchers work.



101
102
103
# File 'lib/saharspec/matchers/be_json.rb', line 101

def be_json_sym(expected = Saharspec::Matchers::BeJson::ANY)
  Saharspec::Matchers::BeJson.new(expected, symbolize_names: true)
end

#dontObject

Negates attached matcher, allowing creating negated matchers on the fly.

While not being 100% grammatically correct, seems to be readable enough.

Examples:

# before
RSpec.define_negated_matcher :not_change, :change
it { expect { code }.to do_stuff.and not_change(obj, :attr) }

# after: no `define_negated_matcher` needed
it { expect { code }.to do_stuff.and dont.change(obj, :attr) }


78
79
80
# File 'lib/saharspec/matchers/dont.rb', line 78

def dont
  Saharspec::Matchers::Not.new
end

#eq_multiline(expected) ⇒ Object

Allows to pretty test multiline strings with complex indentation (for example, results of code generation).

In provided string, removes first and last empty line, trailing spaces and leading spaces up to | character.

If you need to preserve trailing spaces, end them with another |.

Examples:

require 'saharspec/matchers/eq_multiline'

expect(some_code_gen).to eq_multiline(%{
  |def something
  |  a = 5
  |  a**2
  |end
})

Parameters:

  • expected (String)


38
39
40
# File 'lib/saharspec/matchers/eq_multiline.rb', line 38

def eq_multiline(expected)
  Saharspec::Matchers::EqMultiline.new(expected)
end

#ret(expected) ⇒ Object

Note:

There is a case when ret fails: when it is not the first in a chain of matchers joined by .and. That's not exactly the matchers bug, that's how RSpec works (loses block's return value passing the block between matchers)

ret (short for return) checks if provided block returns value specified.

It should be considered instead of simple value matchers (like eq) in the situations:

  1. Several block behaviors tested in the same test, joined with .and, or in separate tests
  2. You test what some block or method returns with arguments, using #its_call

Values are tested with ===, which allows chaining other matchers and patterns to the check.

Examples:

# case 1: block is a subject
subject { -> { do_something } }

it { is_expected.not_to raise_error }
it { is_expected.to change(some, :value).by(1) }
it { is_expected.to ret 8 }

# or, joined:
specify {
  expect { do_something }.to ret(8).and change(some, :value).by(1)
}

# case 2: with arguments
subject { %i[a b c].method(:[]) }

its_call(1) { is_expected.to ret :b }
its_call(1..-1) { is_expected.to ret %i[b c] }
its_call('foo') { is_expected.to raise_error TypeError }

# Note, that values are tested with ===, which means all other matchers could be chained:
its_call(1) { is_expected.to ret instance_of(Symbol) }
its_call(1..-1) { is_expected.to ret instance_of(Array).and have_attributes(length: 2) }


99
100
101
# File 'lib/saharspec/matchers/ret.rb', line 99

def ret(expected)
  Saharspec::Matchers::Ret.new(expected)
end

#send_message(target, method) ⇒ Object

Checks if the (block) subject sends specified message to specified object.

Examples:

# before:
specify {
   allow(double).to receive(:fetch)
   code_being_tested
   expect(double).to have_received(:fetch).with(something)
}

# after:
require 'saharspec/matchers/send_message'

it { expect { code_being_tested }.to send_message(double, :fetch).with(something) }

# after + its_block
require 'saharspec/its/block'

subject { code_being_tested }
its_block { is_expected.to send_message(double, :fetch).with(something) }

Parameters:

  • target

    Object which expects message, double or real object

  • method (Symbol)

    Message being expected

Returns:

  • Instance of a matcher, allowing the following additional methods:

    • once, twice, exactly(n).times;
    • with(arguments);
    • calling_original;
    • returning(response).


146
147
148
# File 'lib/saharspec/matchers/send_message.rb', line 146

def send_message(target, method)
  Saharspec::Matchers::SendMessage.new(target, method)
end