mirror of
				https://gitea.invidious.io/iv-org/shard-spectator.git
				synced 2024-08-15 00:53:35 +00:00 
			
		
		
		
	Refactor predicate and respond matchers
Add missing match? method to AttributesMatcher.
This commit is contained in:
		
							parent
							
								
									520c738f6a
								
							
						
					
					
						commit
						3ae16c6ec1
					
				
					 4 changed files with 108 additions and 124 deletions
				
			
		| 
						 | 
				
			
			@ -21,7 +21,7 @@ module Spectator::Matchers
 | 
			
		|||
 | 
			
		||||
    def match(actual)
 | 
			
		||||
      snapshot = snapshot_values(actual.value)
 | 
			
		||||
      if matched?(snapshot)
 | 
			
		||||
      if match?(snapshot)
 | 
			
		||||
        SuccessfulMatchData.new
 | 
			
		||||
      else
 | 
			
		||||
        FailedMatchData.new("#{actual.label} does not have attributes #{expected.label}", **values(snapshot))
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ module Spectator::Matchers
 | 
			
		|||
 | 
			
		||||
    def negated_match(actual)
 | 
			
		||||
      snapshot = snapshot_values(actual.value)
 | 
			
		||||
      if matched?(snapshot)
 | 
			
		||||
      if match?(snapshot)
 | 
			
		||||
        FailedMatchData.new("#{actual.label} has attributes #{expected.label}", **values(snapshot))
 | 
			
		||||
      else
 | 
			
		||||
        SuccessfulMatchData.new
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +49,16 @@ module Spectator::Matchers
 | 
			
		|||
      {% end %}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private def match?(snapshot)
 | 
			
		||||
      # Test that every attribute has the expected value.
 | 
			
		||||
      {% for attribute in ExpectedType.keys %}
 | 
			
		||||
      return false unless expected.value[{{attribute.symbolize}}] === snapshot[{{attribute.symbolize}}]
 | 
			
		||||
      {% end %}
 | 
			
		||||
 | 
			
		||||
      # At this point, none of the checks failed, so the match was successful.
 | 
			
		||||
      true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private def values(snapshot)
 | 
			
		||||
      {% begin %}
 | 
			
		||||
      {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,57 +7,53 @@ module Spectator::Matchers
 | 
			
		|||
  # Each key in the tuple is a predicate (without the '?' and 'has_' prefix) to test.
 | 
			
		||||
  # Each value is a a `Tuple` of arguments to pass to the predicate method.
 | 
			
		||||
  struct HavePredicateMatcher(ExpectedType) < ValueMatcher(ExpectedType)
 | 
			
		||||
    # Determines whether the matcher is satisfied with the value given to it.
 | 
			
		||||
    private def match?(values)
 | 
			
		||||
      # Test each predicate and immediately return false if one is false.
 | 
			
		||||
      {% for attribute in ExpectedType.keys %}
 | 
			
		||||
      return false unless values[{{attribute.symbolize}}]
 | 
			
		||||
      {% end %}
 | 
			
		||||
    private getter expected
 | 
			
		||||
 | 
			
		||||
      # All checks passed if this point is reached.
 | 
			
		||||
      true
 | 
			
		||||
    def initialize(@expected : TestValue(ExpectedType))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Determines whether the matcher is satisfied with the partial given to it.
 | 
			
		||||
    def match(partial, negated = false)
 | 
			
		||||
      values = snapshot_values(partial.actual)
 | 
			
		||||
      MatchData.new(match?(values), values, partial.label, label)
 | 
			
		||||
    def description
 | 
			
		||||
      "has #{expected.label}"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def match(actual)
 | 
			
		||||
      snapshot = snapshot_values(actual.value)
 | 
			
		||||
      if match?(snapshot)
 | 
			
		||||
        SuccessfulMatchData.new
 | 
			
		||||
      else
 | 
			
		||||
        FailedMatchData.new("#{actual.label} does not have #{expected.label}", **snapshot)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def negated_match(actual)
 | 
			
		||||
      snapshot = snapshot_values(actual.value)
 | 
			
		||||
      if match?(snapshot)
 | 
			
		||||
        FailedMatchData.new("#{actual.label} has #{expected.label}", **snapshot)
 | 
			
		||||
      else
 | 
			
		||||
        SuccessfulMatchData.new
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Captures all of the actual values.
 | 
			
		||||
    # A `NamedTuple` is returned,
 | 
			
		||||
    # with each key being the attribute.
 | 
			
		||||
    private def snapshot_values(actual)
 | 
			
		||||
    # A `NamedTuple` is returned, with each key being the attribute.
 | 
			
		||||
    private def snapshot_values(object)
 | 
			
		||||
      {% begin %}
 | 
			
		||||
      {
 | 
			
		||||
        {% for attribute in ExpectedType.keys %}
 | 
			
		||||
        {{attribute}}: actual.has_{{attribute}}?(*@expected[{{attribute.symbolize}}]),
 | 
			
		||||
        {{attribute}}: object.has_{{attribute}}?(*@expected[{{attribute.symbolize}}]),
 | 
			
		||||
        {% end %}
 | 
			
		||||
      }
 | 
			
		||||
      {% end %}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Match data specific to this matcher.
 | 
			
		||||
    private struct MatchData(ActualType) < MatchData
 | 
			
		||||
      # Creates the match data.
 | 
			
		||||
      def initialize(matched, @named_tuple : ActualType, @actual_label : String, @expected_label : String)
 | 
			
		||||
        super(matched)
 | 
			
		||||
      end
 | 
			
		||||
    private def match?(snapshot)
 | 
			
		||||
      # Test each predicate and immediately return false if one is false.
 | 
			
		||||
      {% for attribute in ExpectedType.keys %}
 | 
			
		||||
      return false unless snapshot[{{attribute.symbolize}}]
 | 
			
		||||
      {% end %}
 | 
			
		||||
 | 
			
		||||
      # Information about the match.
 | 
			
		||||
      getter named_tuple
 | 
			
		||||
 | 
			
		||||
      # Describes the condition that satisfies the matcher.
 | 
			
		||||
      # This is informational and displayed to the end-user.
 | 
			
		||||
      def message
 | 
			
		||||
        "#{@actual_label} has #{@expected_label}"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Describes the condition that won't satsify the matcher.
 | 
			
		||||
      # This is informational and displayed to the end-user.
 | 
			
		||||
      def negated_message
 | 
			
		||||
        "#{@actual_label} does not have #{@expected_label}"
 | 
			
		||||
      end
 | 
			
		||||
      # All checks passed if this point is reached.
 | 
			
		||||
      true
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,58 +5,54 @@ module Spectator::Matchers
 | 
			
		|||
  # The `ExpectedType` type param should be a `NamedTuple`.
 | 
			
		||||
  # Each key in the tuple is a predicate (without the '?') to test.
 | 
			
		||||
  # Each value is a a `Tuple` of arguments to pass to the predicate method.
 | 
			
		||||
  struct PredicateMatcher(ExpectedType) < ValueMatcher(ExpectedType)
 | 
			
		||||
    # Determines whether the matcher is satisfied with the value given to it.
 | 
			
		||||
    private def match?(values)
 | 
			
		||||
      # Test each predicate and immediately return false if one is false.
 | 
			
		||||
      {% for attribute in ExpectedType.keys %}
 | 
			
		||||
      return false unless values[{{attribute.symbolize}}]
 | 
			
		||||
      {% end %}
 | 
			
		||||
  struct PredicateMatcher(ExpectedType) < Matcher(ExpectedType)
 | 
			
		||||
    private getter expected
 | 
			
		||||
 | 
			
		||||
      # All checks passed if this point is reached.
 | 
			
		||||
      true
 | 
			
		||||
    def initialize(@expected : TestValue(ExpectedType))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Determines whether the matcher is satisfied with the partial given to it.
 | 
			
		||||
    def match(partial, negated = false)
 | 
			
		||||
      values = snapshot_values(partial.actual)
 | 
			
		||||
      MatchData.new(match?(values), values, partial.label, label)
 | 
			
		||||
    def description
 | 
			
		||||
      "is #{expected.label}"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def match(actual)
 | 
			
		||||
      snapshot = snapshot_values(actual.value)
 | 
			
		||||
      if match?(snapshot)
 | 
			
		||||
        SuccessfulMatchData.new
 | 
			
		||||
      else
 | 
			
		||||
        FailedMatchData.new("#{actual.label} is not #{expected.label}", **snapshot)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def negated_match(actual)
 | 
			
		||||
      snapshot = snapshot_values(actual.value)
 | 
			
		||||
      if match?(snapshot)
 | 
			
		||||
        FailedMatchData.new("#{actual.label} is #{expected.label}", **snapshot)
 | 
			
		||||
      else
 | 
			
		||||
        SuccessfulMatchData.new
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Captures all of the actual values.
 | 
			
		||||
    # A `NamedTuple` is returned,
 | 
			
		||||
    # with each key being the attribute.
 | 
			
		||||
    private def snapshot_values(actual)
 | 
			
		||||
    # A `NamedTuple` is returned, with each key being the attribute.
 | 
			
		||||
    private def snapshot_values(object)
 | 
			
		||||
      {% begin %}
 | 
			
		||||
      {
 | 
			
		||||
        {% for attribute in ExpectedType.keys %}
 | 
			
		||||
        {{attribute}}: actual.{{attribute}}?(*@expected[{{attribute.symbolize}}]),
 | 
			
		||||
        {{attribute}}: object.{{attribute}}?(*@expected[{{attribute.symbolize}}]),
 | 
			
		||||
        {% end %}
 | 
			
		||||
      }
 | 
			
		||||
      {% end %}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Match data specific to this matcher.
 | 
			
		||||
    private struct MatchData(ActualType) < MatchData
 | 
			
		||||
      # Creates the match data.
 | 
			
		||||
      def initialize(matched, @named_tuple : ActualType, @actual_label : String, @expected_label : String)
 | 
			
		||||
        super(matched)
 | 
			
		||||
      end
 | 
			
		||||
    private def match?(snapshot)
 | 
			
		||||
      # Test each predicate and immediately return false if one is false.
 | 
			
		||||
      {% for attribute in ExpectedType.keys %}
 | 
			
		||||
      return false unless snapshot[{{attribute.symbolize}}]
 | 
			
		||||
      {% end %}
 | 
			
		||||
 | 
			
		||||
      # Information about the match.
 | 
			
		||||
      getter named_tuple
 | 
			
		||||
 | 
			
		||||
      # Describes the condition that satisfies the matcher.
 | 
			
		||||
      # This is informational and displayed to the end-user.
 | 
			
		||||
      def message
 | 
			
		||||
        "#{@actual_label} is #{@expected_label}"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Describes the condition that won't satsify the matcher.
 | 
			
		||||
      # This is informational and displayed to the end-user.
 | 
			
		||||
      def negated_message
 | 
			
		||||
        "#{@actual_label} is not #{@expected_label}"
 | 
			
		||||
      end
 | 
			
		||||
      # All checks passed if this point is reached.
 | 
			
		||||
      true
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,67 +6,49 @@ module Spectator::Matchers
 | 
			
		|||
  # The `ExpectedType` type param should be a `NamedTuple`,
 | 
			
		||||
  # with each key being the method to check and the value is ignored.
 | 
			
		||||
  struct RespondMatcher(ExpectedType) < Matcher
 | 
			
		||||
    # Determines whether the matcher is satisfied with the value given to it.
 | 
			
		||||
    private def match?(actual)
 | 
			
		||||
      # The snapshot did the hard work.
 | 
			
		||||
      # Here just check if all values are true.
 | 
			
		||||
      actual.values.all?
 | 
			
		||||
    def description
 | 
			
		||||
      "responds to #{label}"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Determines whether the matcher is satisfied with the partial given to it.
 | 
			
		||||
    def match(partial, negated = false)
 | 
			
		||||
      values = snapshot_values(partial.actual)
 | 
			
		||||
      MatchData.new(match?(values), values, partial.label, label)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Captures all of the actual values.
 | 
			
		||||
    # A `NamedTuple` is returned,
 | 
			
		||||
    # with each key being the attribute.
 | 
			
		||||
    private def snapshot_values(actual)
 | 
			
		||||
      {% begin %}
 | 
			
		||||
      {
 | 
			
		||||
        {% for method in ExpectedType.keys %}
 | 
			
		||||
        {{method.stringify}}: actual.responds_to?({{method.symbolize}}),
 | 
			
		||||
        {% end %}
 | 
			
		||||
      }
 | 
			
		||||
      {% end %}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Textual representation of what the matcher expects.
 | 
			
		||||
    def label
 | 
			
		||||
    private def label
 | 
			
		||||
      # Prefix every method name with # and join them with commas.
 | 
			
		||||
      {{ExpectedType.keys.map { |e| "##{e}".id }.splat.stringify}}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Match data specific to this matcher.
 | 
			
		||||
    private struct MatchData(ActualType) < MatchData
 | 
			
		||||
      # Creates the match data.
 | 
			
		||||
      def initialize(matched, @actual : ActualType, @actual_label : String, @expected_label : String)
 | 
			
		||||
        super(matched)
 | 
			
		||||
    def match(actual)
 | 
			
		||||
      snapshot = snapshot_values(actual.value)
 | 
			
		||||
      if match?(snapshot)
 | 
			
		||||
        SuccessfulMatchData.new
 | 
			
		||||
      else
 | 
			
		||||
        FailedMatchData.new("#{actual.label} does not respond to #{label}", **snapshot)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
      # Information about the match.
 | 
			
		||||
      def named_tuple
 | 
			
		||||
    def negated_match(actual)
 | 
			
		||||
      snapshot = snapshot_values(actual.value)
 | 
			
		||||
      if match?(snapshot)
 | 
			
		||||
        FailedMatchData.new("#{actual.label} responds to #{label}", **snapshot)
 | 
			
		||||
      else
 | 
			
		||||
        SuccessfulMatchData.new
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Captures all of the actual values.
 | 
			
		||||
    # A `NamedTuple` is returned, with each key being the attribute.
 | 
			
		||||
    private def snapshot_values(object)
 | 
			
		||||
      {% begin %}
 | 
			
		||||
      {
 | 
			
		||||
          {% for method in ActualType.keys %}
 | 
			
		||||
          {{"responds to #" + method.stringify}}: @actual[{{method.symbolize}}],
 | 
			
		||||
        {% for attribute in ExpectedType.keys %}
 | 
			
		||||
        {{attribute}}: object.responds_to?({{attribute.symbolize}}),
 | 
			
		||||
        {% end %}
 | 
			
		||||
      }
 | 
			
		||||
      {% end %}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
      # Describes the condition that satisfies the matcher.
 | 
			
		||||
      # This is informational and displayed to the end-user.
 | 
			
		||||
      def message
 | 
			
		||||
        "#{@actual_label} responds to #{@expected_label}"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Describes the condition that won't satsify the matcher.
 | 
			
		||||
      # This is informational and displayed to the end-user.
 | 
			
		||||
      def negated_message
 | 
			
		||||
        "#{@actual_label} does not respond to #{@expected_label}"
 | 
			
		||||
      end
 | 
			
		||||
    private def match?(snapshot)
 | 
			
		||||
      # The snapshot did the hard work.
 | 
			
		||||
      # Here just check if all values are true.
 | 
			
		||||
      snapshot.values.all?
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue