rspec-path_matchers 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.release-please-manifest.json +1 -1
  3. data/.rubocop.yml +5 -0
  4. data/CHANGELOG.md +21 -0
  5. data/README.md +161 -260
  6. data/design.rb +10 -10
  7. data/lib/rspec/path_matchers/matchers/base.rb +210 -56
  8. data/lib/rspec/path_matchers/matchers/directory_matcher.rb +172 -0
  9. data/lib/rspec/path_matchers/matchers/{have_file.rb → file_matcher.rb} +8 -5
  10. data/lib/rspec/path_matchers/matchers/no_entry_matcher.rb +64 -0
  11. data/lib/rspec/path_matchers/matchers/{have_symlink.rb → symlink_matcher.rb} +9 -6
  12. data/lib/rspec/path_matchers/options/atime.rb +6 -40
  13. data/lib/rspec/path_matchers/options/base.rb +296 -0
  14. data/lib/rspec/path_matchers/options/birthtime.rb +6 -49
  15. data/lib/rspec/path_matchers/options/content.rb +13 -42
  16. data/lib/rspec/path_matchers/options/ctime.rb +6 -40
  17. data/lib/rspec/path_matchers/options/etc_base.rb +42 -0
  18. data/lib/rspec/path_matchers/options/file_stat_base.rb +47 -0
  19. data/lib/rspec/path_matchers/options/group.rb +5 -52
  20. data/lib/rspec/path_matchers/options/json_content.rb +6 -30
  21. data/lib/rspec/path_matchers/options/mode.rb +6 -40
  22. data/lib/rspec/path_matchers/options/mtime.rb +7 -41
  23. data/lib/rspec/path_matchers/options/owner.rb +6 -53
  24. data/lib/rspec/path_matchers/options/parsed_content_base.rb +67 -0
  25. data/lib/rspec/path_matchers/options/size.rb +5 -40
  26. data/lib/rspec/path_matchers/options/symlink_atime.rb +7 -40
  27. data/lib/rspec/path_matchers/options/symlink_birthtime.rb +7 -49
  28. data/lib/rspec/path_matchers/options/symlink_ctime.rb +7 -40
  29. data/lib/rspec/path_matchers/options/symlink_group.rb +6 -52
  30. data/lib/rspec/path_matchers/options/symlink_mtime.rb +7 -40
  31. data/lib/rspec/path_matchers/options/symlink_owner.rb +7 -53
  32. data/lib/rspec/path_matchers/options/symlink_target.rb +6 -43
  33. data/lib/rspec/path_matchers/options/symlink_target_exist.rb +6 -41
  34. data/lib/rspec/path_matchers/options/symlink_target_type.rb +20 -43
  35. data/lib/rspec/path_matchers/options/yaml_content.rb +6 -31
  36. data/lib/rspec/path_matchers/options.rb +1 -0
  37. data/lib/rspec/path_matchers/refinements.rb +79 -0
  38. data/lib/rspec/path_matchers/version.rb +1 -1
  39. data/lib/rspec/path_matchers.rb +185 -16
  40. metadata +12 -8
  41. data/lib/rspec/path_matchers/matchers/directory_contents_inspector.rb +0 -57
  42. data/lib/rspec/path_matchers/matchers/have_directory.rb +0 -126
  43. data/lib/rspec/path_matchers/matchers/have_no_entry.rb +0 -49
@@ -3,31 +3,200 @@
3
3
  require 'rspec'
4
4
 
5
5
  module RSpec
6
- # RSpec::PathMatchers is a collection of matchers for testing directory entries
6
+ # A collection of matchers for testing directory entries
7
+ #
8
+ # This module provides the main DSL methods for use in RSpec tests.
9
+ #
10
+ # @example
11
+ # require 'rspec/path_matchers'
12
+ #
13
+ # RSpec.configure do |config|
14
+ # config.include RSpec::PathMatchers
15
+ # end
16
+ #
17
+ # RSpec.describe '/var/log' do
18
+ # it { is_expected.to be_dir.containing(file('syslog')) }
19
+ # end
20
+ #
7
21
  module PathMatchers
8
22
  # Returns true if object is a matcher
23
+ # @api private
9
24
  def self.matcher?(object)
10
25
  object.respond_to?(:matches?) && object.respond_to?(:description)
11
26
  end
27
+
28
+ # A simple, immutable structure to hold failure data internally.
29
+ # @api private
30
+ Failure = Data.define(:relative_path, :message)
31
+
32
+ # @!group Top-Level Matchers
33
+
34
+ # Creates a matcher that tests if the subject path is a directory
35
+ #
36
+ # @param options_hash [Hash] A hash of attribute matchers (e.g., mode:, owner:).
37
+ #
38
+ # @return [RSpec::PathMatchers::Matchers::DirectoryMatcher] The matcher instance.
39
+ #
40
+ # @example Basic existence check
41
+ # expect('/var/log').to be_dir
42
+ #
43
+ # @example Checking attributes
44
+ # expect('/tmp').to be_dir(mode: '1777')
45
+ #
46
+ def be_dir(**options_hash)
47
+ RSpec::PathMatchers::Matchers::DirectoryMatcher.new('', matcher_name: __method__, **options_hash)
48
+ end
49
+
50
+ # Creates a matcher that tests if the subject path is a file
51
+ #
52
+ # @param options_hash [Hash] A hash of attribute matchers (e.g., content:, size:).
53
+ # @return [RSpec::PathMatchers::Matchers::FileMatcher] The matcher instance.
54
+ #
55
+ # @example
56
+ # expect('/etc/hosts').to be_file(content: include('localhost'))
57
+ #
58
+ def be_file(**options_hash)
59
+ RSpec::PathMatchers::Matchers::FileMatcher.new('', matcher_name: __method__, **options_hash)
60
+ end
61
+
62
+ # Creates a matcher that tests if the subject path is a symbolic link
63
+ #
64
+ # @param options_hash [Hash] A hash of attribute matchers (e.g., target:).
65
+ # @return [RSpec::PathMatchers::Matchers::SymlinkMatcher] The matcher instance.
66
+ #
67
+ # @example
68
+ # expect('/usr/bin/ruby').to be_symlink(target: a_string_ending_with('ruby3.2'))
69
+ #
70
+ def be_symlink(**options_hash)
71
+ RSpec::PathMatchers::Matchers::SymlinkMatcher.new('', matcher_name: __method__, **options_hash)
72
+ end
73
+
74
+ # @!endgroup
75
+
76
+ # @!group Top-Level Child Matchers
77
+
78
+ # A matcher to test if the subject path has a child directory with the given name
79
+ #
80
+ # @param entry_name [String] The name of the expected child directory.
81
+ # @param options_hash [Hash] A hash of attribute matchers.
82
+ # @return [RSpec::PathMatchers::Matchers::DirectoryMatcher]
83
+ #
84
+ # @example
85
+ # expect('/tmp').to have_dir('new_project', owner: 'root')
86
+ #
87
+ def have_dir(entry_name, **options_hash) # rubocop:disable Naming/PredicatePrefix
88
+ RSpec::PathMatchers::Matchers::DirectoryMatcher.new(entry_name, matcher_name: __method__, **options_hash)
89
+ end
90
+
91
+ # A matcher to test if the subject path has a child file with the given name
92
+ #
93
+ # @param entry_name [String] The name of the expected child file.
94
+ # @param options_hash [Hash] A hash of attribute matchers.
95
+ # @return [RSpec::PathMatchers::Matchers::FileMatcher]
96
+ #
97
+ # @example
98
+ # expect('/etc').to have_file('hosts', content: /localhost/)
99
+ #
100
+ def have_file(entry_name, **options_hash) # rubocop:disable Naming/PredicatePrefix
101
+ RSpec::PathMatchers::Matchers::FileMatcher.new(entry_name, matcher_name: __method__, **options_hash)
102
+ end
103
+
104
+ # A matcher to test if the subject path has a child symlink with the given name
105
+ #
106
+ # @param entry_name [String] The name of the expected child symlink.
107
+ # @param options_hash [Hash] A hash of attribute matchers.
108
+ # @return [RSpec::PathMatchers::Matchers::SymlinkMatcher]
109
+ #
110
+ # @example
111
+ # expect('/usr/local/bin').to have_symlink('ruby')
112
+ #
113
+ def have_symlink(entry_name, **options_hash) # rubocop:disable Naming/PredicatePrefix
114
+ RSpec::PathMatchers::Matchers::SymlinkMatcher.new(entry_name, matcher_name: __method__, **options_hash)
115
+ end
116
+
117
+ # @!endgroup
118
+
119
+ # @!group Nested Entry Declarations
120
+
121
+ # Declares an expectation for a file within a directory
122
+ #
123
+ # Intended for use as an argument to #containing or #containing_exactly.
124
+ #
125
+ # @param name [String] The name of the expected file.
126
+ # @param options_hash [Hash] A hash of attribute matchers (e.g., content:, size:).
127
+ # @return [RSpec::PathMatchers::Matchers::FileMatcher] The matcher object.
128
+ #
129
+ def file(name, **options_hash)
130
+ RSpec::PathMatchers::Matchers::FileMatcher.new(name, matcher_name: __method__, **options_hash)
131
+ end
132
+
133
+ # Declares an expectation for a directory within a directory
134
+ #
135
+ # Intended for use as an argument to #containing or #containing_exactly.
136
+ #
137
+ # @param name [String] The name of the expected directory.
138
+ # @param options_hash [Hash] A hash of attribute matchers (e.g., mode:, owner:).
139
+ # @return [RSpec::PathMatchers::Matchers::DirectoryMatcher] The matcher object.
140
+ #
141
+ def dir(name, **options_hash)
142
+ RSpec::PathMatchers::Matchers::DirectoryMatcher.new(name, matcher_name: __method__, **options_hash)
143
+ end
144
+
145
+ # Declares an expectation for a symbolic link within a directory
146
+ #
147
+ # Intended for use as an argument to #containing or #containing_exactly.
148
+ #
149
+ # @param name [String] The name of the expected symlink.
150
+ # @param options_hash [Hash] A hash of attribute matchers (e.g., target:).
151
+ # @return [RSpec::PathMatchers::Matchers::SymlinkMatcher] The matcher object.
152
+ #
153
+ def symlink(name, **options_hash)
154
+ RSpec::PathMatchers::Matchers::SymlinkMatcher.new(name, matcher_name: __method__, **options_hash)
155
+ end
156
+
157
+ # Declares an expectation that a directory with the given name does NOT exist
158
+ #
159
+ # Intended for use as an argument to #containing or #containing_exactly.
160
+ #
161
+ # @param name [String] The name of the directory that should be absent.
162
+ # @return [RSpec::PathMatchers::Matchers::NoEntryMatcher]
163
+ #
164
+ def no_dir_named(name)
165
+ RSpec::PathMatchers::Matchers::NoEntryMatcher.new(name, matcher_name: __method__, entry_type: :directory)
166
+ end
167
+
168
+ # Declares an expectation that a file with the given name does NOT exist
169
+ #
170
+ # Intended for use as an argument to #containing or #containing_exactly.
171
+ #
172
+ # @param name [String] The name of the file that should be absent.
173
+ # @return [RSpec::PathMatchers::Matchers::NoEntryMatcher]
174
+ #
175
+ def no_file_named(name)
176
+ RSpec::PathMatchers::Matchers::NoEntryMatcher.new(name, matcher_name: __method__, entry_type: :file)
177
+ end
178
+
179
+ # Declares an expectation that a symlink with the given name does NOT exist
180
+ #
181
+ # Intended for use as an argument to #containing or #containing_exactly.
182
+ #
183
+ # @param name [String] The name of the symlink that should be absent.
184
+ # @return [RSpec::PathMatchers::Matchers::NoEntryMatcher]
185
+ #
186
+ def no_symlink_named(name)
187
+ RSpec::PathMatchers::Matchers::NoEntryMatcher.new(name, matcher_name: __method__, entry_type: :symlink)
188
+ end
189
+
190
+ # @!endgroup
12
191
  end
13
192
  end
14
193
 
15
194
  require_relative 'path_matchers/version'
16
195
  require_relative 'path_matchers/options'
17
196
 
18
- require_relative 'path_matchers/matchers/have_file'
19
- require_relative 'path_matchers/matchers/have_directory'
20
- require_relative 'path_matchers/matchers/have_symlink'
21
- require_relative 'path_matchers/matchers/have_no_entry'
197
+ require_relative 'path_matchers/matchers/directory_matcher'
198
+ require_relative 'path_matchers/matchers/file_matcher'
199
+ require_relative 'path_matchers/matchers/no_entry_matcher'
200
+ require_relative 'path_matchers/matchers/symlink_matcher'
22
201
 
23
- def have_file(name, **options_hash) # rubocop:disable Naming/PredicatePrefix
24
- RSpec::PathMatchers::Matchers::HaveFile.new(name, **options_hash)
25
- end
26
-
27
- def have_dir(name, **options_hash, &) # rubocop:disable Naming/PredicatePrefix
28
- RSpec::PathMatchers::Matchers::HaveDirectory.new(name, **options_hash, &)
29
- end
30
-
31
- def have_symlink(name, **options_hash) # rubocop:disable Naming/PredicatePrefix
32
- RSpec::PathMatchers::Matchers::HaveSymlink.new(name, **options_hash)
33
- end
202
+ require_relative 'path_matchers/refinements'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-path_matchers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Couball
@@ -221,21 +221,24 @@ files:
221
221
  - design.rb
222
222
  - lib/rspec/path_matchers.rb
223
223
  - lib/rspec/path_matchers/matchers/base.rb
224
- - lib/rspec/path_matchers/matchers/directory_contents_inspector.rb
225
- - lib/rspec/path_matchers/matchers/have_directory.rb
226
- - lib/rspec/path_matchers/matchers/have_file.rb
227
- - lib/rspec/path_matchers/matchers/have_no_entry.rb
228
- - lib/rspec/path_matchers/matchers/have_symlink.rb
224
+ - lib/rspec/path_matchers/matchers/directory_matcher.rb
225
+ - lib/rspec/path_matchers/matchers/file_matcher.rb
226
+ - lib/rspec/path_matchers/matchers/no_entry_matcher.rb
227
+ - lib/rspec/path_matchers/matchers/symlink_matcher.rb
229
228
  - lib/rspec/path_matchers/options.rb
230
229
  - lib/rspec/path_matchers/options/atime.rb
230
+ - lib/rspec/path_matchers/options/base.rb
231
231
  - lib/rspec/path_matchers/options/birthtime.rb
232
232
  - lib/rspec/path_matchers/options/content.rb
233
233
  - lib/rspec/path_matchers/options/ctime.rb
234
+ - lib/rspec/path_matchers/options/etc_base.rb
235
+ - lib/rspec/path_matchers/options/file_stat_base.rb
234
236
  - lib/rspec/path_matchers/options/group.rb
235
237
  - lib/rspec/path_matchers/options/json_content.rb
236
238
  - lib/rspec/path_matchers/options/mode.rb
237
239
  - lib/rspec/path_matchers/options/mtime.rb
238
240
  - lib/rspec/path_matchers/options/owner.rb
241
+ - lib/rspec/path_matchers/options/parsed_content_base.rb
239
242
  - lib/rspec/path_matchers/options/size.rb
240
243
  - lib/rspec/path_matchers/options/symlink_atime.rb
241
244
  - lib/rspec/path_matchers/options/symlink_birthtime.rb
@@ -247,6 +250,7 @@ files:
247
250
  - lib/rspec/path_matchers/options/symlink_target_exist.rb
248
251
  - lib/rspec/path_matchers/options/symlink_target_type.rb
249
252
  - lib/rspec/path_matchers/options/yaml_content.rb
253
+ - lib/rspec/path_matchers/refinements.rb
250
254
  - lib/rspec/path_matchers/version.rb
251
255
  - package.json
252
256
  - release-please-config.json
@@ -256,8 +260,8 @@ licenses:
256
260
  metadata:
257
261
  homepage_uri: https://github.com/main-branch/rspec-path_matchers
258
262
  source_code_uri: https://github.com/main-branch/rspec-path_matchers
259
- documentation_uri: https://rubydoc.info/gems/rspec-path_matchers/0.1.1
260
- changelog_uri: https://rubydoc.info/gems/rspec-path_matchers/0.1.1/file/CHANGELOG.md
263
+ documentation_uri: https://rubydoc.info/gems/rspec-path_matchers/0.2.0
264
+ changelog_uri: https://rubydoc.info/gems/rspec-path_matchers/0.2.0/file/CHANGELOG.md
261
265
  allowed_push_host: https://rubygems.org
262
266
  rubygems_mfa_required: 'true'
263
267
  rdoc_options: []
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RSpec
4
- module PathMatchers
5
- module Matchers
6
- # Provides the DSL for the `have_dir` matcher's block
7
- #
8
- # It is responsible for creating and collecting the nested matchers
9
- # without immediately executing them.
10
- #
11
- # @api private
12
- #
13
- class DirectoryContentsInspector
14
- # By including RSpec::Matchers, we make methods like `be`, `eq`, `include`,
15
- # `an_instance_of`, etc., available within the `have_dir` block
16
- #
17
- include RSpec::Matchers
18
-
19
- def initialize
20
- @nested_matchers = []
21
- end
22
-
23
- attr_reader :nested_matchers
24
-
25
- # Defines an expectation for a file within the directory.
26
- def file(name, **)
27
- nested_matchers << RSpec::PathMatchers::Matchers::HaveFile.new(name, **)
28
- end
29
-
30
- # Defines an expectation for a nested directory.
31
- def dir(name, ...)
32
- nested_matchers << RSpec::PathMatchers::Matchers::HaveDirectory.new(name, ...)
33
- end
34
-
35
- # Defines an expectation for a symlink within the directory.
36
- def symlink(name, **)
37
- nested_matchers << RSpec::PathMatchers::Matchers::HaveSymlink.new(name, **)
38
- end
39
-
40
- # Defines an expectation that a file does NOT exist within the directory.
41
- def no_file(name)
42
- nested_matchers << RSpec::PathMatchers::Matchers::HaveNoEntry.new(name, type: :file)
43
- end
44
-
45
- # Defines an expectation that a directory does NOT exist within the directory.
46
- def no_dir(name)
47
- nested_matchers << RSpec::PathMatchers::Matchers::HaveNoEntry.new(name, type: :directory)
48
- end
49
-
50
- # Defines an expectation that a symlink does NOT exist within the directory.
51
- def no_symlink(name)
52
- nested_matchers << RSpec::PathMatchers::Matchers::HaveNoEntry.new(name, type: :symlink)
53
- end
54
- end
55
- end
56
- end
57
- end
@@ -1,126 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
- require_relative 'directory_contents_inspector'
5
-
6
- module RSpec
7
- module PathMatchers
8
- module Matchers
9
- # An RSpec matcher that checks for the existence and properties of a directory
10
- #
11
- class HaveDirectory < Base
12
- OPTIONS = [
13
- RSpec::PathMatchers::Options::Atime,
14
- RSpec::PathMatchers::Options::Birthtime,
15
- RSpec::PathMatchers::Options::Ctime,
16
- RSpec::PathMatchers::Options::Group,
17
- RSpec::PathMatchers::Options::Mode,
18
- RSpec::PathMatchers::Options::Mtime,
19
- RSpec::PathMatchers::Options::Owner
20
- ].freeze
21
-
22
- attr_reader :nested_matchers, :exact
23
-
24
- # Initializes the matcher with the directory name and options
25
- #
26
- # @param name [String] The name of the directory
27
- #
28
- # @param exact [Boolean] The directory must contain only entries declared in the specification block
29
- #
30
- # @param options_hash [Hash] A hash of attribute matchers (e.g., mode:, owner:)
31
- #
32
- # @param specification_block [Proc] A specification block that defines the expected directory contents
33
- #
34
- def initialize(name, exact: false, **options_hash, &specification_block)
35
- super(name, **options_hash)
36
-
37
- @exact = exact
38
- @nested_matchers = []
39
- return unless specification_block
40
-
41
- inspector = DirectoryContentsInspector.new
42
- inspector.instance_eval(&specification_block)
43
- @nested_matchers = inspector.nested_matchers
44
- end
45
-
46
- def description
47
- desc = super
48
- desc += ' exactly' if exact
49
- return desc if nested_matchers.empty?
50
-
51
- nested_descriptions = nested_matchers.map do |matcher|
52
- matcher.description.lines.map.with_index do |line, i|
53
- i.zero? ? "- #{line.chomp}" : " #{line.chomp}"
54
- end.join("\n")
55
- end
56
-
57
- "#{desc} containing:\n #{nested_descriptions.join("\n ")}"
58
- end
59
-
60
- def collect_negative_validation_errors(errors)
61
- super
62
- return unless nested_matchers.any?
63
-
64
- errors << "The matcher `not_to #{matcher_name}(...)` cannot be given a specification block"
65
- end
66
-
67
- def collect_validation_errors(errors)
68
- super
69
-
70
- errors << "`exact:` must be true or false, but was #{exact.inspect}" unless [true, false].include?(exact)
71
-
72
- # Recursively validate nested matchers.
73
- nested_matchers.each { |matcher| matcher.collect_validation_errors(errors) }
74
- end
75
-
76
- def option_definitions = OPTIONS
77
- def correct_type? = File.directory?(path)
78
- def matcher_name = 'have_dir'
79
-
80
- protected
81
-
82
- # Overrides Base to add the exactness check after other validations.
83
- def validate_options
84
- super # Validate this directory's own options first.
85
-
86
- nested_matchers.each do |matcher|
87
- failure_messages << matcher.failure_message unless matcher.execute_match(path)
88
- end
89
-
90
- # If any of the declared expectations failed, we stop here.
91
- # The user needs to fix those first.
92
- return unless failure_messages.empty?
93
-
94
- check_for_unexpected_entries if exact
95
- end
96
-
97
- def validate_existance(failure_messages)
98
- return if File.directory?(path)
99
-
100
- failure_messages << (File.exist?(path) ? 'expected it to be a directory' : 'expected it to exist')
101
- end
102
-
103
- private
104
-
105
- # Checks for any files/directories on disk that were not declared in the block.
106
- def check_for_unexpected_entries
107
- positively_declared_entries = nested_matchers.reject do |m|
108
- m.is_a?(RSpec::PathMatchers::Matchers::HaveNoEntry)
109
- end.map(&:name)
110
-
111
- actual_entries = Dir.children(path)
112
- unexpected_entries = actual_entries - positively_declared_entries
113
-
114
- return if unexpected_entries.empty?
115
-
116
- message = build_unexpected_entries_message(unexpected_entries)
117
- failure_messages << message
118
- end
119
-
120
- def build_unexpected_entries_message(unexpected_entries)
121
- "did not expect entries #{unexpected_entries.inspect} to be present"
122
- end
123
- end
124
- end
125
- end
126
- end
@@ -1,49 +0,0 @@
1
- # In lib/rspec/path_matchers/matchers/have_no_entry.rb
2
- # frozen_string_literal: true
3
-
4
- module RSpec
5
- module PathMatchers
6
- module Matchers
7
- # Asserts that a directory entry of a specific type does NOT exist.
8
- # This is a simple, internal matcher-like object.
9
- #
10
- # @api private
11
- class HaveNoEntry
12
- attr_reader :name
13
-
14
- def initialize(name, type:)
15
- @name = name
16
- @type = type
17
- @base_path = nil
18
- @path = nil
19
- end
20
-
21
- # The core logic. Returns `true` if the expectation is met (the entry is absent).
22
- def execute_match(base_path) # rubocop:disable Naming/PredicateMethod
23
- @base_path = base_path
24
- @path = File.join(base_path, @name)
25
-
26
- case @type
27
- when :file then !File.file?(@path)
28
- when :directory then !File.directory?(@path)
29
- else !File.symlink?(@path)
30
- end
31
- end
32
-
33
- # The failure message if `execute_match` returns `false`.
34
- def failure_message
35
- "expected #{@type} '#{@name}' not to be found at '#{@base_path}', but it exists"
36
- end
37
-
38
- # Provide a description for the `have_dir` block's output.
39
- def description
40
- "not have #{@type} #{@name.inspect}"
41
- end
42
-
43
- # Provide a stub for this method, which is called by HaveDirectory
44
- # but is not needed for this simple matcher.
45
- def collect_validation_errors(_errors); end
46
- end
47
- end
48
- end
49
- end