← Back to index

lib/BDD/Behave/Matcher/Type.rakumod

73 / 73 lines covered (100.0%)

1unit module BDD::Behave::Matcher::Type;23use BDD::Behave::Matcher;4use BDD::Behave::TypeName;56class BeAMatcher does Matcher is export {7  has Mu $.type is required;89  method matches($actual --> Bool) {10    ?($actual ~~ $!type);11  }1213  method type-name(--> Str) {14    short-type-name($!type);15  }1617  method failure-message($actual --> Str) {18    "expected " ~ $actual.raku ~ " to be a " ~ self.type-name;19  }2021  method failure-message-negated($actual --> Str) {22    "expected " ~ $actual.raku ~ " not to be a " ~ self.type-name;23  }2425  method expected-value(--> Mu) { $!type }2627  method description(--> Str) { 'be a ' ~ self.type-name }28}2930class BeAnInstanceOfMatcher does Matcher is export {31  has Mu $.type is required;3233  method matches($actual --> Bool) {34    ?($actual.defined && $actual.WHAT === $!type);35  }3637  method type-name(--> Str) {38    short-type-name($!type);39  }4041  method failure-message($actual --> Str) {42    "expected " ~ $actual.raku ~ " to be an instance of " ~ self.type-name;43  }4445  method failure-message-negated($actual --> Str) {46    "expected " ~ $actual.raku ~ " not to be an instance of " ~ self.type-name;47  }4849  method expected-value(--> Mu) { $!type }5051  method description(--> Str) { 'be an instance of ' ~ self.type-name }52}5354class RespondToMatcher does Matcher is export {55  has $.expected;5657  method !missing($actual) {58    $!expected.list.grep({ !$actual.^can($_.Str) });59  }6061  method matches($actual --> Bool) {62    ?(self!missing($actual).elems == 0);63  }6465  method format-expected(--> Str) {66    $!expected.list.map(*.raku).join(', ');67  }6869  method failure-message($actual --> Str) {70    my @missing = self!missing($actual);71    my $head    = "expected " ~ $actual.raku ~ " to respond to "72                ~ self.format-expected;73    @missing.elems74      ?? $head ~ " (missing: " ~ @missing.map(*.raku).join(', ') ~ ")"75      !! $head;76  }7778  method failure-message-negated($actual --> Str) {79    "expected " ~ $actual.raku ~ " not to respond to " ~ self.format-expected;80  }8182  method expected-value(--> Mu) { $!expected }8384  method description(--> Str) { 'respond to ' ~ self.format-expected }85}8687class HaveAttributesMatcher does Matcher is export {88  has %.expected;8990  method !sorted-names() {91    %!expected.keys.sort;92  }9394  method !missing($actual) {95    self!sorted-names.grep({ !$actual.^can($_) });96  }9798  method !mismatches($actual) {99    my @result;100    for self!sorted-names -> $name {101      next unless $actual.^can($name);102      my $expected-value = %!expected{$name};103      my $actual-value   = $actual."$name"();104105      my $passed = $expected-value ~~ Matcher106        ?? $expected-value.matches($actual-value)107        !! ($actual-value eqv $expected-value);108109      unless $passed {110        @result.push: %(111          :name($name),112          :actual($actual-value),113          :expected($expected-value),114        );115      }116    }117    @result;118  }119120  method matches($actual --> Bool) {121    return False unless $actual.defined;122    return False if self!missing($actual).elems;123    self!mismatches($actual).elems == 0;124  }125126  method format-expected(--> Str) {127    self!sorted-names.map({128      my $v = %!expected{$_};129      my $rendered = $v ~~ Matcher ?? $v.description !! $v.raku;130      "$_ => $rendered";131    }).join(', ');132  }133134  method failure-message($actual --> Str) {135    my $head    = "expected " ~ $actual.raku ~ " to have attributes "136                ~ self.format-expected;137    my @parts;138139    my @missing = self!missing($actual);140    if @missing.elems {141      @parts.push: "missing: " ~ @missing.map(*.raku).join(', ');142    }143144    my @mismatched = self!mismatches($actual);145    if @mismatched.elems {146      my $detail = @mismatched.map({147        my $exp = $_<expected>;148        my $rendered = $exp ~~ Matcher ?? $exp.description !! $exp.raku;149        $_<name> ~ ": got " ~ $_<actual>.raku ~ ", wanted " ~ $rendered;150      }).join('; ');151      @parts.push: "mismatched: " ~ $detail;152    }153154    @parts.elems155      ?? $head ~ " (" ~ @parts.join('; ') ~ ")"156      !! $head;157  }158159  method failure-message-negated($actual --> Str) {160    "expected " ~ $actual.raku ~ " not to have attributes "161      ~ self.format-expected;162  }163164  method expected-value(--> Mu) { %!expected }165166  method description(--> Str) {167    'have attributes ' ~ self.format-expected;168  }169}