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))()
Exemple #2
0
 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})
Exemple #3
0
 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})
Exemple #4
0
    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
]
Exemple #6
0
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)
Exemple #7
0
    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')
Exemple #8
0
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)()
Exemple #12
0
                      '{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')
Exemple #13
0
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)),
Exemple #15
0
# 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,
Exemple #16
0
# 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)