# has been turned off, they'll just never be sent. class GroupEmail(AutomatedEmail): def __init__(self, subject, template, filter, ident, **kwargs): AutomatedEmail.__init__(self, Group, subject, template, lambda g: not g.is_dealer and filter(g), ident, sender=c.REGDESK_EMAIL, **kwargs) GroupEmail('Reminder to pre-assign {EVENT_NAME} group badges', 'reg_workflow/group_preassign_reminder.txt', lambda g: days_after(30, g.registered)() and c.BEFORE_GROUP_PREREG_TAKEDOWN and g.unregistered_badges, needs_approval=False, ident='group_preassign_badges_reminder') AutomatedEmail(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)), needs_approval=False, ident='group_preassign_badges_reminder_last_chance') # Dealer emails; these are safe to be turned on for all events because even if the event doesn't have dealers, # none of these emails will be sent unless someone has applied to be a dealer, which they cannot do until
'MAGFest Dept Checklist Introduction', 'dept_checklist_intro.txt', lambda a: a.is_checklist_admin and a.admin_account, ident='magprime_dept_checklist_intro') StopsEmailFixture( 'Last Chance to enter your MAGFest staff shirt preferences', 'second_shirt.html', lambda a: not a.shirt_info_marked, when=days_before(21, c.SHIRT_DEADLINE), ident='magprime_second_shirt') AutomatedEmailFixture( 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(
# query=and_( # Attendee.paid == c.PAID_BY_GROUP, # Attendee.amount_extra != 0, # Attendee.amount_paid >= Attendee.amount_extra), needs_approval=False, ident='group_extra_payment_received') # 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)),
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)
# Attendee.amount_paid >= Attendee.amount_extra), needs_approval=False, ident='group_extra_payment_received') # 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',
def test_representation_days_after(self): assert days_after(days=1, deadline=DateBase.now()).active_when == 'after 09/16'
'MAGFest Dept Checklist Introduction', 'dept_checklist_intro.txt', lambda a: a.is_checklist_admin and a.admin_account, ident='magprime_dept_checklist_intro') StopsEmailFixture( 'Last Chance to enter your MAGFest staff shirt preferences', 'second_shirt.html', lambda a: not a.shirt_info_marked, when=days_before(21, c.SHIRT_DEADLINE), ident='magprime_second_shirt') AutomatedEmailFixture( 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(
def test_invalid_days(self): with pytest.raises(ValueError): days_after(days=-1, deadline=DateBase.now())
def test_no_deadline_set(self): assert not days_after(1, 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')
# Attendee.amount_paid >= Attendee.amount_extra), needs_approval=False, ident='group_extra_payment_received') # 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',
# query=and_( # Attendee.paid == c.PAID_BY_GROUP, # Attendee.amount_extra != 0, # Attendee.amount_paid >= Attendee.amount_extra), needs_approval=False, ident='group_extra_payment_received') # 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)),