Class: RSpec::PathMatchers::Matchers::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/rspec/path_matchers/matchers/base.rb

Overview

The base class for matchers

Implements the RSpec matcher protocol for value expectations including:

  • #matches?(base_path) - checks if the matcher matches the given base_path
  • #failure_message - returns a human-readable failure message
  • #actual - returns the actual value that was matched against
  • #expected - returns the expected value that was matched against
  • #description - returns a human-readable description of the matcher
  • #does_not_match?(base_path) - checks if the matcher does not match the given base_path
  • #failure_message_when_negated - returns a human-readable failure message for negative matches

Direct Known Subclasses

DirectoryMatcher, FileMatcher, SymlinkMatcher

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(entry_name, matcher_name:, **options_hash) ⇒ Base

Create a new matcher instance

Subclasses may override this to provide additional arguments or options. They should call super to ensure the base class is initialized correctly.

Parameters:

  • entry_name (String)

    The name of the entry to match against

    • If entry_name is empty, the matcher will match against the base_path directly (this is the path passed to matches? or does_not_match?).
    • If entry_name is NOT empty, the matcher will match against File.join(base_path, entry_name)
  • matcher_name (Symbol)

    The matcher name (e.g. :have_dir, :have_file, etc.) to use in descriptions and messages

  • options_hash (Hash)

    Options for the matcher passed to the options factory to get an options object



39
40
41
42
43
44
45
# File 'lib/rspec/path_matchers/matchers/base.rb', line 39

def initialize(entry_name, matcher_name:, **options_hash)
  super()
  @entry_name = entry_name.to_s
  @matcher_name = matcher_name
  @options = options_factory(*option_keys, **options_hash)
  @failures = []
end

Instance Attribute Details

#base_pathString (readonly)

The base path against which the matcher is applied

Returns:

  • (String)


61
62
63
# File 'lib/rspec/path_matchers/matchers/base.rb', line 61

def base_path
  @base_path
end

#entry_nameString (readonly)

The name of the entry being matched against or an empty String

If entry_name is empty, the matcher will match against the base_path directly. If entry_name is not empty, the matcher will match against File.join(base_path, entry_name).

Returns:

  • (String)


100
101
102
# File 'lib/rspec/path_matchers/matchers/base.rb', line 100

def entry_name
  @entry_name || base_path.basename
end

#failuresArray<RSpec::PathMatchers::Failure> (readonly)

An array of failures that describe why the matcher did not match the actual value

Only populated after matches? or execute_match is called

Returns:



88
89
90
# File 'lib/rspec/path_matchers/matchers/base.rb', line 88

def failures
  @failures
end

#matcher_nameSymbol (readonly)

The name of this matcher, used for descriptions and messages

Returns:

  • (Symbol)

    The matcher name (e.g. :have_dir, :have_file, etc.)



77
78
79
# File 'lib/rspec/path_matchers/matchers/base.rb', line 77

def matcher_name
  @matcher_name
end

#optionsObject (readonly)

The matcher options loaded from the options_hash passed to the initializer

Returns:

  • (Object)

    A Data object containing the options



53
54
55
# File 'lib/rspec/path_matchers/matchers/base.rb', line 53

def options
  @options
end

#pathString (readonly)

The full path to the entry being matched against

Returns:

  • (String)


69
70
71
# File 'lib/rspec/path_matchers/matchers/base.rb', line 69

def path
  @path
end

Instance Method Details

#descriptionString

A human-readable description of the matcher's expectation

This description is used by RSpec formatters (e.g., --format documentation) to provide output about the specification itself. It is NOT used to build the detailed failure message when an expectation fails.

Subclasses can override this method to add to or provide a more specific description based on the entry type, options, or other factors.

Returns:

  • (String)


115
116
117
118
119
120
# File 'lib/rspec/path_matchers/matchers/base.rb', line 115

def description
  desc = (@entry_name.empty? ? "be a #{entry_type}" : "have #{entry_type} #{entry_name.inspect}")
  options_description = build_options_description
  desc += " with #{options_description}" unless options_description.empty?
  desc
end

#does_not_match?(base_path) ⇒ Boolean

This method is called by RSpec for expect(...).not_to have_...

Returns:

  • (Boolean)

Raises:

  • (ArgumentError)


155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/rspec/path_matchers/matchers/base.rb', line 155

def does_not_match?(base_path) # rubocop:disable Naming/PredicatePrefix
  # Phase 1: Validate all options for syntax errors (in this case options are not allowed)
  validation_errors = []
  collect_negative_validation_errors(validation_errors)
  raise ArgumentError, validation_errors.join(', ') if validation_errors.any?

  @base_path = base_path.to_s
  @path = @entry_name.empty? ? base_path : File.join(base_path, entry_name)

  # Phase 2: Execute the actual match logic
  #
  # A negative match SUCCEEDS if the entry of the specified type does NOT
  # exist. We delegate the type-specific check to the subclass.
  !correct_type?
end

#failure_messageObject



143
144
145
146
147
148
149
150
151
152
# File 'lib/rspec/path_matchers/matchers/base.rb', line 143

def failure_message
  header = "#{path} was not as expected:"
  grouped_failures = failures.group_by(&:relative_path)

  messages = grouped_failures.map do |relative_path, failures_for_path|
    format_failure_group(relative_path, failures_for_path)
  end

  "#{header}\n#{messages.join("\n")}"
end

#failure_message_when_negatedObject

This is the message RSpec will display if does_not_match? returns false.



172
173
174
# File 'lib/rspec/path_matchers/matchers/base.rb', line 172

def failure_message_when_negated
  "expected it not to be a #{entry_type}"
end

#matches?(base_path) ⇒ Boolean

Returns true if the matcher matches the actual value

If false is returned, the failures array will be populated with human-readable error messages that describe why the match failed.

Parameters:

  • base_path (Object)

    The base_path together with entry_name determine the actual value

Returns:

  • (Boolean)

    true if the matcher matches, false otherwise

Raises:

  • (ArgumentError)

    if there are errors in the matcher or its options



133
134
135
136
137
138
139
140
141
# File 'lib/rspec/path_matchers/matchers/base.rb', line 133

def matches?(base_path)
  # Phase 1: Validate all options for syntax errors
  validation_errors = []
  collect_validation_errors(validation_errors)
  raise ArgumentError, validation_errors.join(', ') if validation_errors.any?

  # Phase 2: Execute the actual match logic
  execute_match(base_path)
end