def test_localized_now(fixed_localized_now): """ Asserts that our localized_now monkeypatch is working as expected. """ assert fixed_localized_now == utils.localized_now() assert not before(fixed_localized_now)() assert before(fixed_localized_now + timedelta(microseconds=1))() assert not before(fixed_localized_now - timedelta(microseconds=1))()
def __init__(self, event): AutomatedEmailFixture.__init__( self, SeasonPassTicket, subject='Claim your {} badges with your MAGFest Season Pass'.format(event.name), ident='magprime_season_supporter_{}_invite'.format(event.slug), template='season_supporter_event_invite.txt', when=before(event.deadline), extra_data={'event': event})
Attendee, 'Last Chance for MAGFest ' + c.EVENT_YEAR + ' bonus swag!', 'attendee_swag_promo.html', lambda a: ( a.can_spam and (a.paid == c.HAS_PAID or a.paid == c.NEED_NOT_PAY or (a.group and a.group.amount_paid)) and days_after(3, a.registered)()), when=days_before(14, c.SUPPORTER_DEADLINE), sender='MAGFest Merch Team <*****@*****.**>', ident='magprime_bonus_swag_reminder_last_chance') # Send to any attendee who will be receiving a t-shirt (staff, volunteers, anyone # who kicked in at the shirt level or above). Should not be sent after the t-shirt # size deadline. AutomatedEmailFixture( Attendee, 'MAGFest ' + c.EVENT_YEAR + ' t-shirt size confirmation', 'confirm_shirt_size.html', lambda a: days_after(3, a.registered)() and a.gets_any_kind_of_shirt, when=before(c.SHIRT_DEADLINE), sender='MAGFest Merch Team <*****@*****.**>', ident='magprime_shirt_size_confirmation') AutomatedEmailFixture( Attendee, 'MAGFest ' + c.EVENT_YEAR + ' sweatpants size confirmation', 'confirm_sweatpants_size.html', lambda a: a.amount_extra >= c.SUPPORTER_LEVEL and (a.sweatpants == c.NO_SWEATPANTS or not a.sweatpants), when=before(c.SHIRT_DEADLINE), sender='MAGFest Merch Team <*****@*****.**>', ident='magprime_sweatpants_size_confirmation') AutomatedEmailFixture( Attendee, 'MAGFest Dealer waitlist has been exhausted', 'dealer_waitlist_exhausted.txt', lambda a: 'automatically converted to unpaid discounted badge from a dealer application' in a.admin_notes, sender=c.MARKETPLACE_EMAIL, ident='magprime_marketplace_waitlist_exhausted')
from uber.amazon_ses import AmazonSES from uber.automated_emails import AutomatedEmailFixture from uber.config import c from uber.models import Attendee, AutomatedEmail, Session from uber.utils import after, before NOW = datetime(year=2016, month=8, day=10, hour=12, tzinfo=c.EVENT_TIMEZONE) TWO_DAYS_FROM_NOW = NOW + timedelta(days=2) TOMORROW = NOW + timedelta(days=1) YESTERDAY = NOW - timedelta(days=1) TWO_DAYS_AGO = NOW - timedelta(days=2) ACTIVE_WHEN = [ # ==== ACTIVE ==== [], # Always active [before(TOMORROW)], # Will expire tomorrow [after(YESTERDAY)], # Became active yesterday [after(YESTERDAY), before(TOMORROW)], # Became active yesterday, will expire tomorrow # ==== INACTIVE BUT APPROVABLE ==== [after(TOMORROW)], # Will become active tomorrow [after(TOMORROW), before(TWO_DAYS_FROM_NOW) ], # Will become active tomorrow, will expire in 2 days # ==== INACTIVE ==== [before(YESTERDAY)], # Expired yesterday [after(TWO_DAYS_AGO), before(YESTERDAY)], # Became active 2 days ago, expired yesterday ]
class TestAutomatedEmailCategory: def test_testing_environment(self, get_test_email_category): assert len(AutomatedEmail.instances) == 1 assert len(AutomatedEmail.queries[Attendee](None)) == 3 assert not get_test_email_category.unapproved_emails_not_sent def test_event_name(self, get_test_email_category): assert get_test_email_category.subject == E.SUBJECT_TO_FIND assert get_test_email_category.ident == E.IDENT_TO_FIND def test_approval_needed_and_we_have_it(self, monkeypatch, set_test_approved_idents, get_test_email_category, log_unsent_because_unapproved): job = SendAllAutomatedEmailsJob() assert get_test_email_category.approved assert job.log_unsent_because_unapproved.call_count == 0 def test_approval_needed_and_we_dont_have_it( self, monkeypatch, get_test_email_category, log_unsent_because_unapproved): job = SendAllAutomatedEmailsJob() assert not get_test_email_category.approved assert job.log_unsent_because_unapproved.call_count == 1 # attempt to send the same email and we should see the unapproved count go up because it's still unapproved assert not get_test_email_category.approved assert job.log_unsent_because_unapproved.call_count == 2 def test_approval_not_needed(self, monkeypatch, get_test_email_category): assert not get_test_email_category.approved monkeypatch.setattr(get_test_email_category, 'needs_approval', False) assert get_test_email_category.approved # -------------- test should_send() ------------------- def test_should_send_goes_through(self, get_test_email_category, set_test_approved_idents, attendee1): assert get_test_email_category._should_send(model_inst=attendee1) def test_should_send_incorrect_model_used(self, monkeypatch, get_test_email_category, attendee1): wrong_model = FakeModel() assert not get_test_email_category._should_send(model_inst=wrong_model) def test_should_send_no_email_present(self, monkeypatch, get_test_email_category, attendee1): delattr(attendee1, 'email') assert not get_test_email_category._should_send(model_inst=attendee1) def test_should_send_blank_email_present(self, monkeypatch, get_test_email_category, attendee1): attendee1.email = '' assert not get_test_email_category._should_send(model_inst=attendee1) def test_should_send_already_sent_this_email( self, get_test_email_category, set_test_approved_idents, set_previously_sent_emails_to_attendee1, attendee1): assert not get_test_email_category._should_send(model_inst=attendee1) def test_should_send_wrong_filter(self, get_test_email_category, set_test_approved_idents, attendee1): get_test_email_category.filter = lambda a: a.paid == c.HAS_PAID assert not get_test_email_category._should_send(model_inst=attendee1) def test_should_send_not_approved(self, get_test_email_category, attendee1): assert not get_test_email_category._should_send(model_inst=attendee1) def test_should_send_at_con(self, at_con, get_test_email_category, set_test_approved_idents, attendee1): assert not get_test_email_category._should_send(model_inst=attendee1) get_test_email_category.allow_during_con = True assert get_test_email_category._should_send(model_inst=attendee1) # ----------- def test_send_doesnt_throw_exception(self, monkeypatch, get_test_email_category): get_test_email_category.send_if_should(None, raise_errors=False) def test_send_throws_exception(self, monkeypatch, get_test_email_category): monkeypatch.setattr(get_test_email_category, '_should_send', Mock(side_effect=Exception('Boom!'))) with pytest.raises(Exception): get_test_email_category.send_if_should(None, raise_errors=True) def test_really_send_throws_exception(self, monkeypatch, get_test_email_category): monkeypatch.setattr(get_test_email_category, 'computed_subject', Mock(side_effect=Exception('Boom!'))) with pytest.raises(Exception): get_test_email_category.really_send(None) valid_when = days_after(3, sept_15th - timedelta(days=5)) invalid_when = days_after(3, sept_15th) @pytest.mark.parametrize("when, expected_result", [([invalid_when], False), ([valid_when], True), ([invalid_when, valid_when], False), ([valid_when, invalid_when], False), ([invalid_when, invalid_when], False), ([valid_when, valid_when], True), ((), True)]) def test_when_function(self, monkeypatch, get_test_email_category, set_datebase_now_to_sept_15th, attendee1, when, expected_result): monkeypatch.setattr(get_test_email_category, 'when', when) monkeypatch.setattr(AutomatedEmail, 'approved', True) assert get_test_email_category.filters_run( attendee1) == expected_result assert get_test_email_category._run_date_filters() == expected_result assert get_test_email_category._should_send( model_inst=attendee1) == expected_result @pytest.mark.parametrize("when, expected_text", [ ([ days_after(3, sept_15th - timedelta(days=5)), before(sept_15th - timedelta(days=3)), days_before(3, sept_15th + timedelta(days=5), 1), ], ['after 09/13', 'before 09/12', 'between 09/17 and 09/19']), ([days_after(3, sept_15th - timedelta(days=5))], ['after 09/13']), ]) def test_when_txt(self, monkeypatch, get_test_email_category, set_datebase_now_to_sept_15th, attendee1, when, expected_text): monkeypatch.setattr(get_test_email_category, 'when', when) assert get_test_email_category.when_txt == '\n'.join(expected_text) @pytest.mark.parametrize("filter, expected_result", [ (lambda a: False, False), (lambda a: True, True), (lambda a: a.paid == c.NEED_NOT_PAY, True), (lambda a: a.paid != c.NEED_NOT_PAY, False), ]) def test_filters(self, monkeypatch, get_test_email_category, attendee1, filter, expected_result): monkeypatch.setattr(get_test_email_category, 'filter', filter) monkeypatch.setattr(AutomatedEmail, 'approved', True) assert get_test_email_category.filters_run( attendee1) == expected_result assert get_test_email_category._should_send( model_inst=attendee1) == expected_result def test_none_filter(self): with pytest.raises(AssertionError): AutomatedEmail(Attendee, '', '', None, ident='test_none_filter') def test_no_filter(self): # this is slightly silly but, if this ever changes, we should be explicit about what the expected result is with pytest.raises(TypeError): AutomatedEmail(Attendee, '', '', ident='test_no_filter') def test_missing_ident_arg(self): with pytest.raises(TypeError): AutomatedEmail(Attendee, '', '', lambda a: False) def test_empty_ident_arg(self): with pytest.raises(AssertionError): AutomatedEmail(Attendee, '', '', lambda a: False, ident='') with pytest.raises(AssertionError): AutomatedEmail(Attendee, '', '', lambda a: False, ident=None)
from uber.automated_emails import AutomatedEmailFixture from uber.config import c from uber.models import Attendee, AutomatedEmail, Session from uber.utils import after, before NOW = c.EVENT_TIMEZONE.localize(datetime(year=2016, month=8, day=10, hour=12, tzinfo=None)) TWO_DAYS_FROM_NOW = NOW + timedelta(days=2) TOMORROW = NOW + timedelta(days=1) YESTERDAY = NOW - timedelta(days=1) TWO_DAYS_AGO = NOW - timedelta(days=2) ACTIVE_WHEN = [ # ==== ACTIVE ==== [], # Always active [before(TOMORROW)], # Will expire tomorrow [after(YESTERDAY)], # Became active yesterday [after(YESTERDAY), before(TOMORROW)], # Became active yesterday, will expire tomorrow # ==== INACTIVE BUT APPROVABLE ==== [after(TOMORROW)], # Will become active tomorrow [after(TOMORROW), before(TWO_DAYS_FROM_NOW)], # Will become active tomorrow, will expire in 2 days # ==== INACTIVE ==== [before(YESTERDAY)], # Expired yesterday [after(TWO_DAYS_AGO), before(YESTERDAY)], # Became active 2 days ago, expired yesterday ] ACTIVE_WHEN_LABELS = [ '', 'before Aug 11',
def test_representation_before_empty(self): assert before(deadline=None).active_when == ''
def test_representation_before(self): assert before(deadline=DateBase.now()).active_when == 'before 09/15'
def test_no_deadline_set(self): assert not days_before(1, None)() assert not before(None)()
'{EVENT_NAME} FAQ', 'prefest_faq.html', lambda a: a.badge_status == c.COMPLETED_STATUS and days_before(7, c.FINAL_EMAIL_DEADLINE), ident='magwest_prefest_faq') AutomatedEmailFixture(Attendee, '{EVENT_NAME} PC Gaming Survey', 'pc_gaming_survey.html', lambda a: c.LAN in a.interests_ints, ident='pc_gaming_survey', needs_approval=True, sender="MAGWest LAN Staff <*****@*****.**>") StopsEmailFixture( 'CORRECTION to the {EVENT_NAME} ({EVENT_DATE}) Shift Schedule Email', 'shifts/schedule_correction.html', lambda a: c.SHIFTS_CREATED and a.weighted_hours, when=days_before(1, c.FINAL_EMAIL_DEADLINE), ident='volunteer_shift_schedule_correction') AutomatedEmailFixture( Attendee, 'Last Chance for MAGWest {EVENT_YEAR} bonus swag!', 'attendee_swag_promo.html', lambda a: a.can_spam and a.badge_status == c.COMPLETED_STATUS and a. amount_extra < c.SEASON_LEVEL and days_after(1, a.registered)(), when=before(c.EPOCH - timedelta(days=2)), sender='MAGWest Merch Team <*****@*****.**>', ident='magwest_bonus_swag_reminder_last_chance')
from uber.config import c from uber.automated_emails import MarketplaceEmailFixture from uber.utils import before, days_before MarketplaceEmailFixture( 'Your {EVENT_NAME} ({EVENT_DATE}) Dealer registration is due in one week', 'dealers/payment_reminder.txt', lambda g: g.status == c.APPROVED and days_before(7, g.dealer_payment_due, 2 )() and g.is_unpaid, needs_approval=False, ident='dealer_reg_payment_reminder_due_soon_mff') MarketplaceEmailFixture( 'Last chance to pay for your {EVENT_NAME} ({EVENT_DATE}) Dealer registration', 'dealers/payment_reminder.txt', lambda g: g.status == c.APPROVED and days_before(2, g.dealer_payment_due) () and g.is_unpaid, needs_approval=False, ident='dealer_reg_payment_reminder_last_chance_mff') MarketplaceEmailFixture( 'Your {EVENT_NAME} ({EVENT_DATE}) dealer application has been waitlisted', 'dealers/pending_waitlisted.txt', lambda g: g.status == c.WAITLISTED and g.registered < c. DEALER_REG_DEADLINE, when=before(c.DEALER_WAITLIST_CLOSED), ident='dealer_pending_now_waitlisted_mff')
# has been turned off, they'll just never be sent. AutomatedEmailFixture( Group, 'Reminder to pre-assign {EVENT_NAME} group badges', 'reg_workflow/group_preassign_reminder.txt', lambda g: ( c.BEFORE_GROUP_PREREG_TAKEDOWN and days_after(30, g.registered)() and g.unregistered_badges and not g.is_dealer), # query=and_( # Group.unregistered_badges == True, # Group.is_dealer == False, # Group.registered < (func.now() - timedelta(days=30))), when=before(c.GROUP_PREREG_TAKEDOWN), needs_approval=False, ident='group_preassign_badges_reminder', sender=c.REGDESK_EMAIL) AutomatedEmailFixture( Group, 'Last chance to pre-assign {EVENT_NAME} group badges', 'reg_workflow/group_preassign_reminder.txt', lambda g: ( c.AFTER_GROUP_PREREG_TAKEDOWN and g.unregistered_badges and (not g.is_dealer or g.status == c.APPROVED)), # query=and_( # Group.unregistered_badges == True, # or_(Group.is_dealer == False, Group.status == c.APPROVED)),
# Reminder emails for groups to allocated their unassigned badges. These emails are safe to be turned on for # all events, because they will only be sent for groups with unregistered badges, so if group preregistration # has been turned off, they'll just never be sent. AutomatedEmailFixture( Group, 'Reminder to pre-assign {EVENT_NAME} group badges', 'reg_workflow/group_preassign_reminder.txt', lambda g: (c.BEFORE_GROUP_PREREG_TAKEDOWN and days_after(30, g.registered) () and g.unregistered_badges and not g.is_dealer), # query=and_( # Group.unregistered_badges == True, # Group.is_dealer == False, # Group.registered < (func.now() - timedelta(days=30))), when=before(c.GROUP_PREREG_TAKEDOWN), needs_approval=False, ident='group_preassign_badges_reminder', sender=c.REGDESK_EMAIL) AutomatedEmailFixture( Group, 'Last chance to pre-assign {EVENT_NAME} group badges', 'reg_workflow/group_preassign_reminder.txt', lambda g: (c.AFTER_GROUP_PREREG_TAKEDOWN and g.unregistered_badges and (not g.is_dealer or g.status == c.APPROVED)), # query=and_( # Group.unregistered_badges == True, # or_(Group.is_dealer == False, Group.status == c.APPROVED)), when=after(c.GROUP_PREREG_TAKEDOWN), needs_approval=False,
# Volunteer emails; none of these will be sent unless SHIFTS_CREATED is set. StopsEmail('Please complete your {EVENT_NAME} Staff/Volunteer Checklist', 'shifts/created.txt', lambda a: a.takes_shifts, when=days_after(0, c.SHIFTS_CREATED), ident='volunteer_checklist_completion_request') StopsEmail('Reminder to sign up for {EVENT_NAME} {EVENT_DATE} shifts', 'shifts/reminder.txt', lambda a: ( c.AFTER_SHIFTS_CREATED and days_after(30, max(a.registered_local, c.SHIFTS_CREATED))() and a.takes_shifts and not a.hours), when=before(c.PREREG_TAKEDOWN), ident='volunteer_shift_signup_reminder') StopsEmail('Last chance to sign up for {EVENT_NAME} {EVENT_DATE} shifts', 'shifts/reminder.txt', lambda a: c.AFTER_SHIFTS_CREATED and c.BEFORE_PREREG_TAKEDOWN and a.takes_shifts and not a.hours, when=days_before(10, c.EPOCH), ident='volunteer_shift_signup_reminder_last_chance') StopsEmail('Still want to volunteer at {EVENT_NAME} {EVENT_DATE}?', 'shifts/volunteer_check.txt', lambda a: ( c.SHIFTS_CREATED and c.VOLUNTEER_RIBBON in a.ribbon_ints and a.takes_shifts and a.weighted_hours == 0),
AutomatedEmailFixture(Attendee, '{EVENT_NAME} FAQ', 'prefest_faq.html', lambda a: a.badge_status == c.COMPLETED_STATUS and days_before(7, c.FINAL_EMAIL_DEADLINE), ident='magwest_prefest_faq') AutomatedEmailFixture(Attendee, '{EVENT_NAME} PC Gaming Survey', 'pc_gaming_survey.html', lambda a: c.LAN in a.interests_ints, ident='pc_gaming_survey', needs_approval=True, sender="MAGWest LAN Staff <*****@*****.**>") StopsEmailFixture( 'CORRECTION to the {EVENT_NAME} ({EVENT_DATE}) Shift Schedule Email', 'shifts/schedule_correction.html', lambda a: c.SHIFTS_CREATED and a.weighted_hours, when=days_before(1, c.FINAL_EMAIL_DEADLINE), ident='volunteer_shift_schedule_correction') BandEmailFixture('Important {EVENT_NAME} performer deadlines have changed!', 'band_deadline_updates.html', lambda g: True, when=before( max(c.BAND_BIO_DEADLINE, c.BAND_STAGE_PLOT_DEADLINE) - timedelta(days=1)), ident='band_deadline_updates', needs_approval=True)