Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow count constraint on include matcher #1168

Merged
merged 2 commits into from Aug 28, 2020

Conversation

marcandre
Copy link
Contributor

This allows to specify how many times an element should be included:

expect([1, 2, 1]).to include(1).at_most(3).times
expect('hello').to include(/l/).twice

Note: Not implemented for include(1, 2, 3) nor for hash cases.
Also: This PR build on #1167.

Copy link
Member

@pirj pirj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

features/built_in_matchers/include.feature Show resolved Hide resolved
features/built_in_matchers/include.feature Show resolved Hide resolved
# @api private
# Asbtract class to implement `once`, `at_least` and other
# count constraints.
class CountExpectation < BaseMatcher
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏 I took a stab at this in the past, but your implementation is superior by all means.
My aim was to reuse it in rspec-mocks's recieve, do you think it's doable in theory by making it an includable module? rspec-mocks don't depend on rspec-expectations, and rspec-support doesn't seem to be a good place for CountExpectation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at receive first too and got discouraged as the implementation is more complex, needs to care about block passing, deals with other constraints, etc. and it wasn't in the same gem. When I realized I could use yield's code, that was simple.

I agree, all of that code could be using the same implementation, although in practice it's not clear if there would be that much gain.

I first used a module BTW, but yard seemed to have issues with the module having an initialize method so instead went with a class.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen this code being repeated in custom matchers quite a lot. E.g. https://github.com/zverok/saharspec/blob/master/lib/saharspec/matchers/send_message.rb#L31

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I turn it into a module? Probably should avoid initialize altogether if it's to be made publicly and rely on attr_readers I imagine

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add attr_reader for count_expectation_type/count_expected_count? They would default to nil and that would make it possible to get rid of initialize.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for the reference WIP.

lib/rspec/matchers/built_in/include.rb Outdated Show resolved Hide resolved
@marcandre marcandre force-pushed the include_count_constraint branch 2 times, most recently from ea43fa1 to c9efca0 Compare March 18, 2020 07:42
@marcandre marcandre force-pushed the include_count_constraint branch 2 times, most recently from ab65187 to ac62d6f Compare March 18, 2020 07:49
@pirj
Copy link
Member

pirj commented Mar 18, 2020

Looks good to me. CounterExpectation is private, so we don't have any obligation to keep it as a class, so it can be turned into an includable module in the futute.

@JonRowe
Copy link
Member

JonRowe commented Mar 19, 2020

👋 I've had a brief look over this, but delayed reviewing in depth because I knew I wanted to support combination constraints on the yield matcher that would have knock on effects.

Could you rebase / rejig this so it works with support that combination? If you have the time I'd love to see the logic from yield pulled out into something thats used by the other matchers with composition rather than inheritance...

@marcandre
Copy link
Contributor Author

👋 I've had a brief look over this, but delayed reviewing in depth because I knew I wanted to support combination constraints on the yield matcher that would have knock on effects.

Could you rebase / rejig this so it works with support that combination? If you have the time I'd love to see the logic from yield pulled out into something thats used by the other matchers with composition rather than inheritance...

Sounds good. I'll be busy for the next few days but will ping when I push the updated PR

@pirj
Copy link
Member

pirj commented Mar 26, 2020

Another matcher that might benefit from the extraction https://github.com/rspec/rspec-rails/blob/master/lib/rspec/rails/matchers/active_job.rb#L167

@marcandre marcandre force-pushed the include_count_constraint branch 5 times, most recently from 11584b1 to 2e314ee Compare March 28, 2020 05:41
@marcandre
Copy link
Contributor Author

Refactored a bit & rebased.

Copy link
Member

@pirj pirj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! ⚡️

lib/rspec/matchers/built_in/count_expectation.rb Outdated Show resolved Hide resolved
lib/rspec/matchers/built_in/include.rb Outdated Show resolved Hide resolved
@pirj pirj requested a review from benoittgt May 11, 2020 20:27
@pirj
Copy link
Member

pirj commented May 11, 2020

@JonRowe mind taking another look?

Copy link
Member

@benoittgt benoittgt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I find the code, clean and self documented. Good job @marcandre. 🙌🏻

@pirj
Copy link
Member

pirj commented Jun 11, 2020

@JonRowe ?

@marcandre
Copy link
Contributor Author

Ping @JonRowe

@JonRowe JonRowe changed the base branch from master to main August 2, 2020 02:06
Obsiye added a commit to ministryofjustice/laa-apply-for-legal-aid that referenced this pull request Aug 12, 2020
Add the aria-describedby id to the select_all_that_apply field as it broke WAVE testing of aria tags

Turn the select_all_that_apply field to a hint text to standardise with other pages such as the identify_types_of_outgoings page

Fix duplication of error messages under the select_all_that_apply hint because it's already in the error summary above the title. This is only when checkboxes are checked and nested values cause an error on submission. It still shows an error underneath it for when no checkboxes were selected validation fails

Test the above. However, keep an eye on rspec/rspec-expectations#1168
which is an rspec matcher coming soon that allows to test how many times something has been seen in a response body.
Obsiye added a commit to ministryofjustice/laa-apply-for-legal-aid that referenced this pull request Aug 12, 2020
Add the aria-describedby id to the select_all_that_apply field as it broke WAVE testing of aria tags

Turn the select_all_that_apply field to a hint text to standardise with other pages such as the identify_types_of_outgoings page

Fix duplication of error messages under the select_all_that_apply hint because it's already in the error summary above the title. This is only when checkboxes are checked and nested values cause an error on submission. It still shows an error underneath it for when no checkboxes were selected validation fails

Test the above. However, keep an eye on rspec/rspec-expectations#1168
which is an rspec matcher coming soon that allows to test how many times something has been seen in a response body.
Obsiye added a commit to ministryofjustice/laa-apply-for-legal-aid that referenced this pull request Aug 12, 2020
Add the aria-describedby id to the select_all_that_apply field as it broke WAVE testing of aria tags for the savings and investments page and other assets page.

Fix duplication of error messages under the select_all_that_apply hint because it's already in the error summary above the title. This is only when checkboxes are checked and nested values cause an error on submission. It still shows an error underneath it for when no checkboxes were selected validation fails

Test the above. However, keep an eye on rspec/rspec-expectations#1168
which is an rspec matcher coming soon that allows to test how many times something has been seen in a response body.
Obsiye added a commit to ministryofjustice/laa-apply-for-legal-aid that referenced this pull request Aug 12, 2020
Add the aria-describedby id to the select_all_that_apply field as it broke WAVE testing of aria tags for the savings and investments page and other assets page.

Fix duplication of error messages under the select_all_that_apply hint because it's already in the error summary above the title. This is only when checkboxes are checked and nested values cause an error on submission. It still shows an error underneath it for when no checkboxes were selected validation fails

Test the above. However, keep an eye on rspec/rspec-expectations#1168
which is an rspec matcher coming soon that allows to test how many times something has been seen in a response body.
Obsiye added a commit to ministryofjustice/laa-apply-for-legal-aid that referenced this pull request Aug 14, 2020
Add the aria-describedby id to the select_all_that_apply field as it broke WAVE testing of aria tags for the savings and investments page and other assets page.

Fix duplication of error messages under the select_all_that_apply hint because it's already in the error summary above the title. This is only when checkboxes are checked and nested values cause an error on submission. It still shows an error underneath it for when no checkboxes were selected validation fails

Test the above. However, keep an eye on rspec/rspec-expectations#1168
which is an rspec matcher coming soon that allows to test how many times something has been seen in a response body.
@marcandre
Copy link
Contributor Author

Rebased, just to be sure.

@JonRowe could this be merged please?

Copy link
Member

@JonRowe JonRowe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One outstanding query, but it's not a blocker.

lib/rspec/matchers/built_in/include.rb Show resolved Hide resolved
@JonRowe JonRowe merged commit be9b97c into rspec:main Aug 28, 2020
@pirj
Copy link
Member

pirj commented Aug 29, 2020

Thank you! 👏

I understand that you're scratching your own itch to allow include to accept counts, but from my point of the most valuable part is the extraction of CountExpectation that can be used in a lot more matchers, and become a part of the public API for the benefit of custom matchers. I've seen so many custom matchers using their own incomplete implementations of CountExpectation.

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.

None yet

4 participants