Module: DuckTyper::RSpec

Defined in:
lib/duck_typer/rspec.rb

Class Method Summary collapse

Class Method Details

.define_shared_example(name = "an interface") ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/duck_typer/rspec.rb', line 43

def self.define_shared_example(name = "an interface")
  ::RSpec.shared_examples name do |*args, namespace: nil, name: nil, type: :instance_methods, methods: nil, strict: false|
    objects = namespace ? nil : args.first

    # We intentionally avoid reusing the have_matching_interfaces matcher
    # here. Since this shared example is defined in gem code, RSpec filters
    # it from its backtrace, causing the Failure/Error: line to show an
    # internal RSpec constant instead of useful context.
    it "has compatible interfaces" do
      checker = DuckTyper::BulkInterfaceChecker
        .new(objects, namespace:, type:, methods:, strict:, name:)

      failures = checker.call.reject(&:match?)

      if failures.any?
        message = failures.map(&:failure_message).join("\n")
        raise ::RSpec::Expectations::ExpectationNotMetError, message
      end
    end
  end
end