Skip to content

Support matchers and regexps for the source property (#980)#47

Open
tas50 wants to merge 1 commit into
chef:mainfrom
tas50:fix/source-property-matcher-980
Open

Support matchers and regexps for the source property (#980)#47
tas50 wants to merge 1 commit into
chef:mainfrom
tas50:fix/source-property-matcher-980

Conversation

@tas50

@tas50 tas50 commented Jun 28, 2026

Copy link
Copy Markdown

Summary

Fixes chefspec#980.with(source: <matcher>) never matches.

ResourceMatcher#matches_parameter? special-cases the source property:

if parameter == :source
  # Chef 11+ stores the source parameter internally as an Array
  Array(expected) == Array(value)

The intent is to let a plain string match a source that Chef stored as an Array. But wrapping the expectation in an Array and comparing with == means an RSpec matcher or Regexp can never match. For the reporter's case:

.with(source: end_with('MyFile.pem'))   # value is "C:/MyFile.pem"
# becomes: [#<EndWith ...>] == ["C:/MyFile.pem"]  => always false

Every other property routes through expected === value, which is exactly what makes matchers/Regexps work — source was the one exception.

Fix

Try expected === value first (so RSpec matchers, Regexps, and exact scalar/array values all work), then fall back to the array-normalized Array(expected) == Array(value) so a plain string still matches a single-element array source — preserving the original behavior.

expected === value || Array(expected) == Array(value)

Testing

  • Added unit specs for :source matching (TDD — the matcher and Regexp cases failed first): exact string, plain-string-vs-array, exact array, an RSpec matcher against a scalar source (the issue), a Regexp, and a non-matching matcher (stays false — no over-matching).
  • bundle exec rspec spec/unit/167 examples, 0 failures.
  • Acceptance examples for the real source-using resources (cookbook_file, remote_file, template, render_file) → 116 examples, 0 failures (array-source path unregressed).
  • cookstyle --chefstyle -c .rubocop.yml → no offenses.

Note

Touches spec/unit/matchers/resource_matcher_spec.rb, which is also rewritten by #31 and #42. Whichever merges first, the others need their describe blocks combined into the one file.

`matches_parameter?` special-cases the `source` property as
`Array(expected) == Array(value)` because Chef may store source as an
Array. But wrapping the expectation in an Array and comparing with `==`
means an RSpec matcher or Regexp expectation can never match: e.g.
`.with(source: end_with("MyFile.pem"))` became
`[<EndWith matcher>] == ["C:/MyFile.pem"]`, which is always false.

Try `expected === value` first so matchers, Regexps, and exact values
all work against a scalar source, then keep the array-normalized
comparison as a fallback so a plain string still matches a single-element
array source (the original behavior).

Signed-off-by: Tim Smith <tsmith84@proton.me>
@tas50
tas50 requested review from a team and jaymzh as code owners June 28, 2026 06:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fails to match anything against windows_certificate resource's source property

1 participant