Esempio n. 1
0
def test_send_comment_notifications(post_id, comment_id):
    """Tests that send_comment_notifications works correctly"""
    comment_users = UserFactory.create_batch(5)
    for user in comment_users:
        NotificationSettingsFactory.create(user=user, comments_type=True)
        # create both so we cover the notifiication deduplication
        SubscriptionFactory.create(user=user,
                                   post_id=post_id,
                                   comment_id=comment_id)
        SubscriptionFactory.create(user=user, post_id=post_id, comment_id=None)

    post_users = UserFactory.create_batch(5)
    for user in post_users:
        NotificationSettingsFactory.create(user=user, comments_type=True)
        SubscriptionFactory.create(user=user, post_id=post_id, comment_id=None)

    # create just a subscription for a user so we can test no settings scenario
    SubscriptionFactory.create(post_id=post_id, comment_id=comment_id)

    # create a bunch on other subscriptions
    SubscriptionFactory.create_batch(10)

    api.send_comment_notifications(post_id, comment_id, "abc")

    users = post_users + comment_users

    assert CommentEvent.objects.count() == len(users)
    for event in CommentEvent.objects.all():
        assert event.post_id == post_id
        assert event.comment_id == "abc"
        assert event.user in users
def test_can_notify_invalid_frequency():
    """Verify it raises an error for an invalid frequency"""
    notification_settings = NotificationSettingsFactory.create(immediate=True,
                                                               via_email=True)
    notifier = frontpage.FrontpageDigestNotifier(notification_settings)
    with pytest.raises(InvalidTriggerFrequencyError):
        notifier.can_notify(None)
def test_send_notification(
    mocker, is_parent_comment, reddit_factories, private_channel_and_contributor
):
    """Tests send_notification"""
    channel, user = private_channel_and_contributor
    ns = NotificationSettingsFactory.create(
        user=user, comments_type=True, via_email=True, immediate=True
    )
    notifier = comments.CommentNotifier(ns)
    send_messages_mock = mocker.patch("mail.api.send_messages")
    post = reddit_factories.text_post("just a post", user, channel=channel)
    comment = reddit_factories.comment("just a comment", user, post_id=post.id)
    if is_parent_comment:
        subscription = Subscription.objects.create(
            user=user, comment_id=comment.id, post_id=post.id
        )
        comment = reddit_factories.comment("reply comment", user, comment_id=comment.id)
    else:
        subscription = Subscription.objects.create(user=user, post_id=post.id)

    event = notifier.create_comment_event(subscription, comment.id)
    note = event.email_notification
    note.state = EmailNotification.STATE_SENDING
    note.save()

    notifier.send_notification(note)

    send_messages_mock.assert_called_once_with([any_instance_of(EmailMessage)])
Esempio n. 4
0
def test_notification_settings_serializer(user):
    """Tests that the correct fields are serialized"""
    settings = NotificationSettingsFactory.create(user=user)
    assert NotificationSettingsSerializer(settings).data == {
        "trigger_frequency": settings.trigger_frequency,
        "notification_type": settings.notification_type,
    }
def test_send_notification(mocker, user):
    """Tests send_notification"""
    ns = NotificationSettingsFactory.create(via_email=True, weekly=True)
    notifier = frontpage.FrontpageDigestNotifier(ns)
    post = PostFactory.create()
    send_messages_mock = mocker.patch("mail.api.send_messages")
    serializer_mock = mocker.patch("channels.serializers.posts.PostSerializer")
    serializer_mock.return_value.data = {
        "id": post.post_id,
        "title": "post's title",
        "slug": "a_slug",
        "channel_name": "micromasters",
        "channel_title": "MicroMasters",
        "created": now_in_utc().isoformat(),
        "author_id": user.username,
    }
    submission = mocker.Mock(id=post.post_id,
                             created=int(now_in_utc().timestamp()),
                             stickied=False)
    api_mock = mocker.patch("channels.api.Api")
    api_mock.return_value.front_page.return_value = [submission]
    note = EmailNotificationFactory.create(
        user=ns.user, notification_type=ns.notification_type, sending=True)

    notifier.send_notification(note)

    serializer_mock.assert_called_once_with(
        PostProxy(submission, post), context={"current_user": note.user})

    send_messages_mock.assert_called_once_with([any_instance_of(EmailMessage)])
Esempio n. 6
0
def test_get_weekly_frontpage_settings_ids():
    """Tests that get_weekly_frontpage_settings_ids only returns weekly settings"""
    notification_settings = NotificationSettingsFactory.create_batch(
        5, weekly=True, frontpage_type=True)
    # these shouldn't show up
    NotificationSettingsFactory.create_batch(5,
                                             weekly=True,
                                             frontpage_type=True,
                                             user__is_active=False)
    NotificationSettingsFactory.create_batch(5,
                                             daily=True,
                                             frontpage_type=True)

    assert set(api.get_weekly_frontpage_settings_ids()) == {
        ns.id
        for ns in notification_settings
    }
Esempio n. 7
0
def test_can_notify_invalid_frequency(notifier, mocker):
    """Tests that this raises an error if an unsupported trigger_frequency is used"""
    notifier.notification_settings = NotificationSettingsFactory.create(
        trigger_frequency="bananas"
    )
    notification = mocker.Mock()
    notification.created_on = now_in_utc()
    with pytest.raises(InvalidTriggerFrequencyError):
        notifier.can_notify(notification)
def test_triggered_properties(trigger_frequency):
    """Test that the is_triggered_X properties return correct values"""
    ns = NotificationSettingsFactory.create(
        trigger_frequency=trigger_frequency)

    assert ns.is_triggered_immediate is (trigger_frequency
                                         == FREQUENCY_IMMEDIATE)
    assert ns.is_triggered_never is (trigger_frequency == FREQUENCY_NEVER)
    assert ns.is_triggered_weekly is (trigger_frequency == FREQUENCY_WEEKLY)
    assert ns.is_triggered_daily is (trigger_frequency == FREQUENCY_DAILY)
Esempio n. 9
0
def test_can_notify(notifier, mocker, frequency, expected, hour_of_day):
    """Tests that it triggers correctly given the last notification"""
    now = datetime(2018, 4, 18, hour_of_day, 0, 0, tzinfo=pytz.utc)
    if expected is False:
        offset = timedelta(0)
    else:
        offset = DELTA_ONE_DAY if frequency == FREQUENCY_DAILY else DELTA_ONE_WEEK
    mocker.patch("notifications.notifiers.base.now_in_utc", return_value=now)
    notifier.notification_settings = NotificationSettingsFactory.create(
        trigger_frequency=frequency
    )
    notification = mocker.Mock()
    notification.created_on = datetime(2018, 4, 18, 0, 0, 0, tzinfo=pytz.utc) - offset
    assert notifier.can_notify(notification) is expected
Esempio n. 10
0
def test_attempt_notify(notifier, mocker, can_notify):
    """Tests that this creates a new notification in pending status"""
    ns = NotificationSettingsFactory.create(immediate=True)
    notifier.notification_settings = ns
    mocker.patch.object(notifier, "can_notify", return_value=can_notify)

    notifier.attempt_notify()

    if can_notify:
        notifier.notification_cls.objects.create.assert_called_once_with(
            user=ns.user, notification_type=ns.notification_type
        )
    else:
        notifier.notification_cls.objects.create.assert_not_called()
Esempio n. 11
0
def test_send_email_notification_batch(mocker, should_cancel,
                                       notification_type, notifier_fqn):
    """Verify send_email_notification_batch calls the notifier for each of the notifications it is given"""
    notifications = EmailNotificationFactory.create_batch(
        5, notification_type=notification_type)
    for notification in notifications:
        NotificationSettingsFactory.create(user=notification.user,
                                           notification_type=notification_type)

    mock_notifier = mocker.patch(notifier_fqn).return_value

    if should_cancel:
        mock_notifier.send_notification.side_effect = CancelNotificationError

    api.send_email_notification_batch([note.id for note in notifications])

    assert mock_notifier.send_notification.call_count == len(notifications)

    for notification in notifications:
        notification.refresh_from_db()
        mock_notifier.send_notification.assert_any_call(notification)

        if should_cancel:
            assert notification.state == EmailNotification.STATE_CANCELED
Esempio n. 12
0
def test_can_notify(settings, mocker, is_enabled, can_notify, via_email):
    """Test can_notify"""
    can_notify_mock = mocker.patch(
        "notifications.notifiers.base.BaseNotifier.can_notify",
        return_value=can_notify)
    ns = NotificationSettingsFactory.create(via_email=via_email)
    notifier = email.EmailNotifier("frontpage", ns)
    note_mock = mocker.Mock()
    settings.FEATURES[features.EMAIL_NOTIFICATIONS] = is_enabled

    expected = is_enabled and can_notify and via_email
    assert notifier.can_notify(note_mock) is expected

    if is_enabled and via_email:
        can_notify_mock.assert_called_once_with(note_mock)
def test_create_comment_event(is_immediate, is_comment):
    """Tests that create_comment_event works correctly"""
    ns = NotificationSettingsFactory.create(
        immediate=is_immediate, never=not is_immediate
    )
    notifier = comments.CommentNotifier(ns)
    subscription = SubscriptionFactory.create(user=ns.user, is_comment=is_comment)
    event = notifier.create_comment_event(subscription, "h")

    assert event.post_id == subscription.post_id
    assert event.comment_id == "h"

    if is_immediate:
        assert event.email_notification is not None
    else:
        assert event.email_notification is None
def test_send_notification_no_posts(mocker):
    """Tests send_notification if there are somehow no posts"""
    ns = NotificationSettingsFactory.create(via_email=True, weekly=True)
    notifier = frontpage.FrontpageDigestNotifier(ns)
    send_messages_mock = mocker.patch("mail.api.send_messages")
    serializer_mock = mocker.patch("channels.serializers.posts.PostSerializer")
    api_mock = mocker.patch("channels.api.Api")
    api_mock.return_value.front_page.return_value = []
    note = EmailNotificationFactory.create(
        user=ns.user, notification_type=ns.notification_type, sending=True)

    notifier.send_notification(note)

    serializer_mock.assert_not_called()
    send_messages_mock.assert_not_called()

    note.refresh_from_db()
    assert note.state == EmailNotification.STATE_CANCELED
def test_can_notify(
    settings,
    mocker,
    is_enabled,
    can_notify,
    has_posts,
    trigger_frequency,
    has_last_notification,
    has_posts_after,
):  # pylint: disable=too-many-arguments, too-many-locals
    """Test can_notify"""
    notification_settings = NotificationSettingsFactory.create(
        trigger_frequency=trigger_frequency)
    notification = (EmailNotificationFactory.create(
        user=notification_settings.user, frontpage_type=True, sent=True)
                    if has_last_notification else None)
    settings.FEATURES[features.FRONTPAGE_EMAIL_DIGESTS] = is_enabled
    can_notify_mock = mocker.patch(
        "notifications.notifiers.email.EmailNotifier.can_notify",
        return_value=can_notify,
    )
    created_on = notification.created_on if notification is not None else now_in_utc(
    )
    post = PostFactory.create()
    api_mock = mocker.patch("channels.api.Api")
    api_mock.return_value.front_page.return_value = ([
        mocker.Mock(
            id=post.post_id,
            created=int(
                (created_on +
                 timedelta(days=10 if has_posts_after else -10)).timestamp()),
            stickied=False,
        )
    ] if has_posts else [])
    notifier = frontpage.FrontpageDigestNotifier(notification_settings)

    expected = (is_enabled and can_notify and has_posts
                and (not has_last_notification or has_posts_after)
                and trigger_frequency in [FREQUENCY_DAILY, FREQUENCY_WEEKLY])
    assert notifier.can_notify(notification) is expected

    if is_enabled:
        can_notify_mock.assert_called_once_with(notification)
Esempio n. 16
0
def test_attempt_send_notification_batch(mocker, side_effect):
    """Verifies that attempt_send_notification_batch will attempt a notify on all settings"""
    notification_settings = NotificationSettingsFactory.create_batch(
        5, weekly=True, frontpage_type=True)
    mock_notifier = mocker.patch(
        "notifications.notifiers.frontpage.FrontpageDigestNotifier",
        autospec=True)
    mock_notifier_instance = mock_notifier.return_value
    mock_notifier_instance.side_effect = side_effect

    api.attempt_send_notification_batch(
        [ns.id for ns in notification_settings])

    assert mock_notifier.call_count == len(notification_settings)

    for notificiation_setting in notification_settings:
        mock_notifier.assert_any_call(notificiation_setting)

    assert mock_notifier_instance.attempt_notify.call_count == len(
        notification_settings)
Esempio n. 17
0
def test_send_daily_frontpage_digests(mocker, settings, mocked_celery):
    """Tests that send_daily_frontpage_digests calls the API method"""
    notification_settings = NotificationSettingsFactory.create_batch(
        4, daily=True, frontpage_type=True)

    settings.NOTIFICATION_ATTEMPT_CHUNK_SIZE = 2
    mock_attempt_send_notification_batch = mocker.patch(
        "notifications.tasks.attempt_send_notification_batch", autospec=True)

    with pytest.raises(mocked_celery.replace_exception_class):
        tasks.send_daily_frontpage_digests.delay()

    assert mocked_celery.group.call_count == 1

    # Celery's 'group' function takes a generator as an argument. In order to make assertions about the items
    # in that generator, 'list' is being called to force iteration through all of those items.
    list(mocked_celery.group.call_args[0][0])

    assert mock_attempt_send_notification_batch.si.call_count == 2

    mock_attempt_send_notification_batch.si.assert_any_call(
        [notification_settings[0].id, notification_settings[1].id])
    mock_attempt_send_notification_batch.si.assert_any_call(
        [notification_settings[2].id, notification_settings[3].id])
def test_can_notify_never():
    """Verify it returns False for notifications set to never"""
    notification_settings = NotificationSettingsFactory.create(never=True,
                                                               via_email=True)
    notifier = frontpage.FrontpageDigestNotifier(notification_settings)
    assert notifier.can_notify(None) is False
Esempio n. 19
0
def test_can_notify_immediate(notifier, mocker, is_active):
    """Tests that if the settings are for immediate the notification triggers"""
    notifier.notification_settings = NotificationSettingsFactory.create(
        immediate=True, user__is_active=is_active
    )
    assert notifier.can_notify(mocker.Mock()) is is_active
Esempio n. 20
0
def test_can_notify_never(notifier, mocker):
    """Tests that if the settings are for never the can_notify is False"""
    notifier.notification_settings = NotificationSettingsFactory.create(never=True)
    assert notifier.can_notify(mocker.Mock()) is False
Esempio n. 21
0
def notifier():
    """Fixture for EmailNotifier"""
    return email.EmailNotifier("frontpage",
                               NotificationSettingsFactory.create(daily=True))