We have notifications sent out to users when their orders are finished processing. Recently we added "user groups" and so orders (which used to belong to a single user) now belong to groups of users. Which brought about the possibilty that a user could be removed from the group (and therefore could no longer see the order).
It's possible that this could happen between the time they submit their order and the time that the order has finished processing. We determined that, if the user no longer belongs to the group, they shouldn't get the notification - it should go to the next person in the group.
So our original notification code had something along the lines of:
# Prepares an email that will notify the user that his calculation is complete def report_complete_notification(report) setup_common_values(report.user) @subject += 'Your report is complete' body[:report] = report end # Details common to all emails from us def setup_common_values(user) recipients user.email from DEFAULT_FROM_EMAIL subject "Our Funky Service - " sent_on Time.now.utc body :user => user end
So first we needed to update the notifier to call an appropriate 'recipient' if needed:
setup_common_values(report.recipient)
Using the following recipient code in the model object:
def recipient # always belongs to the original owner if no group is specified. return self.user unless self.group # use same recipient if creator still belongs to the request's group return self.user if self.group.users.include?(self.user) # otherwise grab the first person out of the group return self.group.users.first unless self.group.users.blank? # no users left - who do we notify? raise "HELP! The report: #{self.id} belongs to group: #{self.group.id}, but the group has no users so I don't know who should receive my notifications." end
As you can see, we aren't yet sure where to escalate notificaton if the group is completely empty. We have several options, but we're still waiting on the customer to get back to us and tell us what they want. The most likely option is to send an alternative notification to our admins.
How to test?
So now we need to test whether the appropriate person gets the notification. To begin with, testing whether an email went to a recipient, or set of them, isn't a pretty assertion, so I've abstracted it out into its own assertion (below). This also allows me to extend it if we need to check CC: and BCC: lists later. For now we don't use them, so "to" is good enough.
# assert that the given recipients appeared in the recipient list of # the given email. If "want_match" is false - assert that *none* of the # given recipients were in the recipient list def assert_recipients(eml, recipients, want_match = true) recipients = [recips] unless recipients.respond_to?('[]') # arrayify if single item recipients.each do |recip| match = eml.to.any? {|r| r =~ /#{recip}/} match = !match unless want_match msg = want_match ? "email should have been sent to recipient #{recip}, but instead went to: #{eml.to}" : "email should not have been sent to recipient #{recip}" assert match, msg end end # convenience function for asserting an email had recipients def assert_sent_to(eml, recips) assert_recipients eml, recips end # convenience function for asserting an email did not have recipients def assert_not_sent_to(eml, recips) assert_recipients eml, recips, false end
Now we can do various tests such as:
# note - assume mailer.deliveries is instantiated as @emails in setup. def test_should_send_completion_notification order = orders(:completed) UserNotifier.deliver_completion_notification(order) assert_equal 1, @emails.size, "should have received one email to confirm completion" assert_sent_to @emails[0], order.user.email end def test_should_send_completion_notification_to_new_recipient_if_user_moved order = orders(:completed_for_moved_user) # sanity check assert_not_equal order.user, order.recipient, "user has moved group, but they are still showing up as the recipient" UserNotifier.deliver_completion_notification(order) assert_equal 1, @emails.size, "should have received one email to confirm completion" assert_sent_to @emails[0], order.recipient.email assert_not_sent_to @emails[0], order.user.email end
No comments:
Post a Comment