Project

matchi

0.01
Low commit activity in last 3 years
A long-lived project that still receives updates
Collection of expectation matchers for Rubyists 🤹
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

Matchi

Version Yard documentation Ruby RuboCop License

Collection of expectation matchers for Rubyists 🤹

A Rubyist juggling between Matchi letters

Project goals

  • Adding matchers should be as simple as possible.
  • Being framework agnostic and easy to integrate.
  • Avoid false positives/negatives due to malicious actual values.

Installation

Add this line to your application's Gemfile:

gem "matchi"

And then execute:

bundle install

Or install it yourself as:

gem install matchi

Overview

Matchi provides a collection of damn simple expectation matchers.

Usage

To make Matchi available:

require "matchi"

All examples here assume that this has been done.

Anatomy of a matcher

A Matchi matcher is an object that must respond to the matches? method with a block as argument, and return a boolean.

To facilitate the integration of the matchers in other tools, Matchi matchers may expose expected values via the expected method.

Built-in matchers

Here is the collection of useful generic matchers.

Equivalence matcher:

matcher = Matchi::Eq.new("foo")

matcher.expected           # => "foo"
matcher.matches? { "foo" } # => true

Identity matcher:

matcher = Matchi::Be.new(:foo)

matcher.expected          # => :foo
matcher.matches? { :foo } # => true

Comparisons matcher:

matcher = Matchi::BeWithin.new(8).of(37)

matcher.expected        # => 37
matcher.matches? { 42 } # => true

Regular expressions matcher:

matcher = Matchi::Match.new(/^foo$/)

matcher.expected           # => /^foo$/
matcher.matches? { "foo" } # => true

Expecting errors matcher:

matcher = Matchi::RaiseException.new(:NameError)

matcher.expected          # => "NameError"
matcher.matches? { Boom } # => true

Type/class matcher:

matcher = Matchi::BeAnInstanceOf.new(:String)

matcher.expected           # => "String"
matcher.matches? { "foo" } # => true

Predicate matcher:

matcher = Matchi::Predicate.new(:be_empty)

matcher.expected        # => [:empty?, [], {}, nil]
matcher.matches? { [] } # => true

matcher = Matchi::Predicate.new(:have_key, :foo)

matcher.expected                 # => [:has_key?, [:foo], {}, nil]
matcher.matches? { { foo: 42 } } # => true

Change matcher:

object = []
matcher = Matchi::Change.new(object, :length).by(1)

matcher.expected                 # => 1
matcher.matches? { object << 1 } # => true

object = []
matcher = Matchi::Change.new(object, :length).by_at_least(1)

matcher.expected                 # => 1
matcher.matches? { object << 1 } # => true

object = []
matcher = Matchi::Change.new(object, :length).by_at_most(1)

matcher.expected                 # => 1
matcher.matches? { object << 1 } # => true

object = "foo"
matcher = Matchi::Change.new(object, :to_s).from("foo").to("FOO")

matcher.expected                    # => "FOO"
matcher.matches? { object.upcase! } # => true

object = "foo"
matcher = Matchi::Change.new(object, :to_s).to("FOO")

matcher.expected                    # => "FOO"
matcher.matches? { object.upcase! } # => true

Satisfy matcher:

matcher = Matchi::Satisfy.new { |value| value == 42 }

matcher.expected        # => #<Proc:0x00007fbaafc65540>
matcher.matches? { 42 } # => true

Custom matchers

Custom matchers can easily be added to express more specific expectations.

A Be the answer matcher:

module Matchi
  class BeTheAnswer
    def expected
      42
    end

    def matches?
      expected.equal?(yield)
    end
  end
end

matcher = Matchi::BeTheAnswer.new

matcher.expected        # => 42
matcher.matches? { 42 } # => true

A Be prime matcher:

require "prime"

module Matchi
  class BePrime
    def matches?
      Prime.prime?(yield)
    end
  end
end

matcher = Matchi::BePrime.new

matcher.matches? { 42 } # => false

A Start with matcher:

module Matchi
  class StartWith
    attr_reader :expected

    def initialize(expected)
      @expected = expected
    end

    def matches?
      /\A#{expected}/.match?(yield)
    end
  end
end

matcher = Matchi::StartWith.new("foo")

matcher.expected              # => "foo"
matcher.matches? { "foobar" } # => true

Contact

Versioning

Matchi follows Semantic Versioning 2.0.

License

The gem is available as open source under the terms of the MIT License.


This project is sponsored by:
Sashité