module RSpec::Matchers

Public Instance Methods

be_json(expected = Saharspec::Matchers::BeJson::ANY) click to toggle source

`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`.

@example

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)))

@param expected Value or matcher to check JSON against. It should implement `#===` method,

so all standard and custom RSpec matchers work.
# 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) click to toggle source

`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.

@param expected Value or matcher to check JSON against. It should implement `#===` method,

so all standard and custom RSpec matchers work.
# 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
dont() click to toggle source

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

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

@example

# 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) }
# File lib/saharspec/matchers/dont.rb, line 78
def dont
  Saharspec::Matchers::Not.new
end
eq_multiline(expected) click to toggle source

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 `|`.

@example

require 'saharspec/matchers/eq_multiline'

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

@param expected [String]

# File lib/saharspec/matchers/eq_multiline.rb, line 38
def eq_multiline(expected)
  Saharspec::Matchers::EqMultiline.new(expected)
end
ret(expected) click to toggle source

`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

{Saharspec::Its::Call#its_call #its_call}

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

@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)

@example

# 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) }
# File lib/saharspec/matchers/ret.rb, line 99
def ret(expected)
  Saharspec::Matchers::Ret.new(expected)
end
send_message(target, method) click to toggle source

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

@example

# 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) }

@param target Object which expects message, double or real object @param method [Symbol] Message being expected

@return Instance of a matcher, allowing the following additional methods:

* `once`, `twice`, `exactly(n).times`;
* `with(arguments)`;
* `calling_original`;
* `returning(response)`.
# File lib/saharspec/matchers/send_message.rb, line 146
def send_message(target, method)
  Saharspec::Matchers::SendMessage.new(target, method)
end