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