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

Feature/have enqueued mail matcher #2047

Merged
merged 25 commits into from
Jan 11, 2019

Conversation

jdlubrano
Copy link
Contributor

Work in progress to add a have_enqueued_mail RSpec matcher

Fixes #1901

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.

Great start! Are you going to add some of the other bits of the active job matcher? (Like exactly etc?)

lib/rspec/rails/matchers/have_enqueued_mail.rb Outdated Show resolved Hide resolved
@jdlubrano
Copy link
Contributor Author

@JonRowe After I started poking around the ActiveJob matcher I realized that a lot could be added to the have_enqueued_mail matcher which is admittedly barebones. To answer your question, yes I do plan to mimic as much as I can with regards to the ActiveJob functionality.

@jdlubrano jdlubrano force-pushed the feature/have-enqueued-mail-matcher branch 2 times, most recently from ea4f4b4 to 6330850 Compare December 25, 2018 18:25
@jdlubrano
Copy link
Contributor Author

@JonRowe

How does this look to you now? The only piece of functionality, I think, that I didn't implement for the have_enqueued_mail matcher was the ability to pass a block to .with. Is that missing functionality a necessity? I was kind of scratching my head wondering what the use case for passing a block to .with for ActiveJobs was in the first place. I understand how it works from the documentation and the code.

Nevertheless, it didn't seem as easy to pass along only the mailer arguments to that with block given the implementation of the RSpec::Rails::Matchers::HaveEnqueuedJob#check method. Before I potentially extracted something in the ActiveJob matchers, I wanted to get a better understanding of a real(ish) use case for passing a block .with in order to consider how such a case could apply to a ActionMailer.

@JonRowe
Copy link
Member

JonRowe commented Jan 2, 2019

Very good! The with block allows you to express more complex argument matching than is possible directly, e.g.

expect { ... }.to have_enqueued_mail.with { |a| expect(a).to eq("a").or eq("b") }

I think its desirable, but its not a blocker. Let me know what you think.


def mailer_job
ActionMailer::DeliveryJob
end
Copy link
Member

Choose a reason for hiding this comment

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

Not a blocker, but why not just use the constant name directly in places?

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 had the hardest time keeping the constant straight in my head. I kept wanting to call it ActionDelivery::MailerJob or ActionMailer::DeliverJob. So I guess out of frustration, I just made it a method 😅

message = "expected to enqueue TestMailer.email_with_args exactly 1 time with [1, 2], but enqueued 0" + \
"\nQueued deliveries:" + \
"\n TestMailer.test_email" + \
"\n TestMailer.email_with_args with [3, 4], on queue #{queue}, at #{send_time}"
Copy link
Member

Choose a reason for hiding this comment

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

Not a blocker, but it might be nice to show other jobs are not mentioned here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, that's a good callout; I will add that!

Copy link
Member

Choose a reason for hiding this comment

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

👍

@jdlubrano
Copy link
Contributor Author

@JonRowe I may have a way to replicate the with block capability that would not require too much overhead. I will try that out and if it proves to be straightforward, I will include it. I can probably get to it this weekend.

@benoittgt
Copy link
Member

Thanks a lot @jdlubrano

super(*mailer_args)

super(*mailer_args) do |*job_args|
block.call(*(job_args - base_mailer_args)) if block.present?
Copy link
Member

Choose a reason for hiding this comment

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

This should just call super if block is nil, else pass this block

@jdlubrano jdlubrano force-pushed the feature/have-enqueued-mail-matcher branch from 9048adc to 4dc20ae Compare January 4, 2019 16:06
@jdlubrano
Copy link
Contributor Author

@JonRowe

I believe that I addressed the latest changes that you requested. It looks like the builds are failing on Travis CI due to bundler issues, however. I'm fairly certain those failures are not specific to this branch...

@JonRowe
Copy link
Member

JonRowe commented Jan 4, 2019

Awaiting #2061 probably, will ask you to give it a poke when thats merged!

@jdlubrano jdlubrano changed the title [WIP] Feature/have enqueued mail matcher Feature/have enqueued mail matcher Jan 4, 2019
@JonRowe
Copy link
Member

JonRowe commented Jan 9, 2019

#2061 is merged so a rebase would get this green hopefully.

Joel Lubrano added 12 commits January 9, 2019 15:54
Moving the internals of
https://github.com/jdlubrano/deliver_later_matchers into rspec-rails as
a new RSpec::Rails::Matchers::HaveEnqueuedMail class.
…ing email methods that accept parameters when no specific arguments are expected.
The ActiveJob matcher provides output for each unmatching, enqueued job
in its failure messages.  Those unmatching jobs have certainly helped me
catch typos in the past, so it makes sense to provide similar feedback
in enqueued email failure messages.
deliver_later can be called with `wait`, `wait_until`, and `queue`
keyword arguments, so the have_enqueued_mail matcher should support
matching those types of things.  At this point, I am beginning to
suspect that this code would be better off using inheritance over
composition.  I am going to try and refactor to inherit from the
ActiveJob base matcher now that I have all of the tests in a good state.
@jdlubrano jdlubrano force-pushed the feature/have-enqueued-mail-matcher branch from 4dc20ae to c8cc534 Compare January 9, 2019 20:54
@jdlubrano
Copy link
Contributor Author

@JonRowe

Looks like the build passed!

@JonRowe JonRowe merged commit 1fb6e67 into rspec:master Jan 11, 2019
JonRowe added a commit that referenced this pull request Jan 11, 2019
benoittgt pushed a commit to benoittgt/rspec-rails that referenced this pull request Jan 13, 2019
* Write first test case for calling simple mailer method with deliver_later

* Move deliver_later gem logic into HaveEnqueuedMail matcher

Moving the internals of
https://github.com/jdlubrano/deliver_later_matchers into rspec-rails as
a new RSpec::Rails::Matchers::HaveEnqueuedMail class.

* Add tests for arguments matcher and error messages.  Largely based on existing ActiveJob matcher tests.

* Add exactly, at_least, at_most functionality for have_enqueued_mail matcher.

* Support mailer methods with default/optional arguments; Support matching email methods that accept parameters when no specific arguments are expected.

* Correct private YARD doc on RSpec::Rails::Matchers::HaveEnqueuedJob

* Provide unmatching enqueued email info in failure messages

The ActiveJob matcher provides output for each unmatching, enqueued job
in its failure messages.  Those unmatching jobs have certainly helped me
catch typos in the past, so it makes sense to provide similar feedback
in enqueued email failure messages.

* Add tests for have_enqueued_mail matcher at_least and at_most modifiers

* Add support for `at` and `on_queue`

deliver_later can be called with `wait`, `wait_until`, and `queue`
keyword arguments, so the have_enqueued_mail matcher should support
matching those types of things.  At this point, I am beginning to
suspect that this code would be better off using inheritance over
composition.  I am going to try and refactor to inherit from the
ActiveJob base matcher now that I have all of the tests in a good state.

* Explicitly require rspec/mocks for access to `anything` method

* Ignore Rubocop class length for HaveEnqueuedMail class

* Replace .negative? with < 0 for older ruby versions

* Remove .inspect call from test to see if that works...

* Remove %i array syntax for older ruby versions

* Remove the send_time part of the error message to see if that is causing the failed test

* Replace new Hash key syntax with old => format for Ruby 1.8.7

* Call strftime in test to get some semblance of timestamp verification

* Fix Ruby 1.8.7 syntax errors

* Fix ActiveJob::Base.queue_adapter error

When using the HaveEnqueuedMail matcher, the error message should not complain
about using "ActiveJob" matchers.

* Refactor HaveEnqueuedMail matcher to be a subclass of the HaveEnqueuedJob matcher

Implementing as a subclass resulted in DRYer code IMO.  There was no
longer a need to reimplement once, twice, thrice and other duplicated
methods that were basically just delegating to the job_matcher instance
variable anyways.

* Support with blocks

* Test that non-mailer jobs do not appear in the have_enqueued_mail matcher list of mail jobs

* Make 'deliver_now' a frozen constant

* Only pass a mailer-specific block to super if a block is provided

* Fix hash rocket syntax for Ruby 1.8.7
benoittgt pushed a commit to benoittgt/rspec-rails that referenced this pull request Jan 13, 2019
@benoittgt benoittgt mentioned this pull request Jan 16, 2019
8 tasks
benoittgt pushed a commit to benoittgt/rspec-rails that referenced this pull request Jan 17, 2019
benoittgt pushed a commit to benoittgt/rspec-rails that referenced this pull request Jan 17, 2019
sebjacobs pushed a commit to futurelearn/rspec-rails that referenced this pull request Mar 15, 2019
benoittgt pushed a commit to benoittgt/rspec-rails that referenced this pull request May 1, 2019
* Write first test case for calling simple mailer method with deliver_later

* Move deliver_later gem logic into HaveEnqueuedMail matcher

Moving the internals of
https://github.com/jdlubrano/deliver_later_matchers into rspec-rails as
a new RSpec::Rails::Matchers::HaveEnqueuedMail class.

* Add tests for arguments matcher and error messages.  Largely based on existing ActiveJob matcher tests.

* Add exactly, at_least, at_most functionality for have_enqueued_mail matcher.

* Support mailer methods with default/optional arguments; Support matching email methods that accept parameters when no specific arguments are expected.

* Correct private YARD doc on RSpec::Rails::Matchers::HaveEnqueuedJob

* Provide unmatching enqueued email info in failure messages

The ActiveJob matcher provides output for each unmatching, enqueued job
in its failure messages.  Those unmatching jobs have certainly helped me
catch typos in the past, so it makes sense to provide similar feedback
in enqueued email failure messages.

* Add tests for have_enqueued_mail matcher at_least and at_most modifiers

* Add support for `at` and `on_queue`

deliver_later can be called with `wait`, `wait_until`, and `queue`
keyword arguments, so the have_enqueued_mail matcher should support
matching those types of things.  At this point, I am beginning to
suspect that this code would be better off using inheritance over
composition.  I am going to try and refactor to inherit from the
ActiveJob base matcher now that I have all of the tests in a good state.

* Explicitly require rspec/mocks for access to `anything` method

* Ignore Rubocop class length for HaveEnqueuedMail class

* Replace .negative? with < 0 for older ruby versions

* Remove .inspect call from test to see if that works...

* Remove %i array syntax for older ruby versions

* Remove the send_time part of the error message to see if that is causing the failed test

* Replace new Hash key syntax with old => format for Ruby 1.8.7

* Call strftime in test to get some semblance of timestamp verification

* Fix Ruby 1.8.7 syntax errors

* Fix ActiveJob::Base.queue_adapter error

When using the HaveEnqueuedMail matcher, the error message should not complain
about using "ActiveJob" matchers.

* Refactor HaveEnqueuedMail matcher to be a subclass of the HaveEnqueuedJob matcher

Implementing as a subclass resulted in DRYer code IMO.  There was no
longer a need to reimplement once, twice, thrice and other duplicated
methods that were basically just delegating to the job_matcher instance
variable anyways.

* Support with blocks

* Test that non-mailer jobs do not appear in the have_enqueued_mail matcher list of mail jobs

* Make 'deliver_now' a frozen constant

* Only pass a mailer-specific block to super if a block is provided

* Fix hash rocket syntax for Ruby 1.8.7
benoittgt pushed a commit to benoittgt/rspec-rails that referenced this pull request May 1, 2019
@jdlubrano jdlubrano deleted the feature/have-enqueued-mail-matcher branch February 14, 2020 22:13
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

3 participants