← Back to index

lib/BDD/Behave/Mock/ArgMatcher.rakumod

31 / 35 lines covered (88.6%)

1unit module BDD::Behave::Mock::ArgMatcher;23our sub user-callframe() is export {4  my $i = 1;5  loop {6    my $cf = callframe($i++);7    last without $cf;8    last if $i > 32;9    my $file = ~($cf.file // '');10    next if $file eq ''11            || $file.contains('Metamodel')12            || $file.contains('NQP::')13            || $file.contains('/nqp')14            || $file.contains('BDD/Behave/Mock');15    return $cf;16  }17  Nil;18}1920class Call is export {21  has Str $.method is required;22  has @.args;23  has %.named;24  has IO::Path $.file;25  has Int $.line;26}2728role ArgMatcher is export {29  method matches(Mu \value --> Bool) { ... }30  method describe(--> Str) { ... }31}3233class AnyArg does ArgMatcher is export {34  method matches(Mu \value --> Bool) { True }35  method describe(--> Str) { 'anything' }36}3738class InstanceOf does ArgMatcher is export {39  has Mu $.type;40  submethod BUILD(Mu :$type is raw) { $!type := $type }41  method matches(Mu \value --> Bool) { value ~~ $!type }42  method describe(--> Str) { "instance-of({$!type.^name})" }43}4445class HashIncluding does ArgMatcher is export {46  has %.expected;47  submethod BUILD(:%expected) { %!expected = %expected }48  method matches(Mu \value --> Bool) {49    return False unless value ~~ Associative;50    for %!expected.kv -> $k, $exp {51      return False unless value{$k}:exists;52      my $actual = value{$k};53      if $exp ~~ ArgMatcher {54        return False unless $exp.matches($actual);55      } else {56        return False unless $actual ~~ $exp;57      }58    }59    True;60  }61  method describe(--> Str) { "hash-including({%!expected.raku})" }62}6364class ArrayIncluding does ArgMatcher is export {65  has @.items;66  submethod BUILD(:@items) { @!items = @items }67  method matches(Mu \value --> Bool) {68    return False unless value ~~ Positional;69    my @actual = value.list;70    for @!items -> $exp {71      my $found;72      if $exp ~~ ArgMatcher {73        $found = @actual.first({ $exp.matches($_) }).defined;74      } else {75        $found = @actual.first({ $_ ~~ $exp }).defined;76      }77      return False unless $found;78    }79    True;80  }81  method describe(--> Str) { "array-including({@!items.raku})" }82}8384our sub anything()                 is export { AnyArg.new }85our sub instance-of(Mu \type)      is export { InstanceOf.new(:type(type)) }86our sub hash-including(*%pairs)    is export { HashIncluding.new(:expected(%pairs)) }87our sub array-including(*@items)   is export { ArrayIncluding.new(:items(@items)) }