Ejemplo n.º 1
0
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)])
Ejemplo n.º 2
0
def post_proxy(reddit_submission_obj):
    """A dummy PostProxy object based on the reddit_submission_obj fixture"""
    post = PostFactory.create(
        post_id=reddit_submission_obj.id,
        channel__name=reddit_submission_obj.subreddit.display_name,
        post_type=LINK_TYPE_SELF,
    )
    return PostProxy(reddit_submission_obj, post)
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
def test_populate_post_and_comment_fields(mocker, mocked_celery, settings):
    """
    populate_post_and_comment_fields should call sub-tasks with correct ids
    """
    posts = PostFactory.create_batch(4)
    settings.ELASTICSEARCH_INDEXING_CHUNK_SIZE = 2
    mock_populate_post_and_comment_fields_batch = mocker.patch(
        "channels.tasks.populate_post_and_comment_fields_batch")

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

    assert mocked_celery.group.call_count == 1
    list(mocked_celery.group.call_args[0][0])
    mock_populate_post_and_comment_fields_batch.si.assert_any_call(
        [posts[0].id, posts[1].id])
    mock_populate_post_and_comment_fields_batch.si.assert_any_call(
        [posts[2].id, posts[3].id])
    assert mocked_celery.replace.call_count == 1
Ejemplo n.º 5
0
def test_populate_post_and_comment_fields_batch(mocker):
    """
    populate_post_and_comment_fields_batch should call backpopulate APIs for each post
    """
    posts = PostFactory.create_batch(10, unpopulated=True)
    mock_api = mocker.patch("channels.api.Api", autospec=True)
    mock_backpopulate_api = mocker.patch("channels.tasks.backpopulate_api")

    tasks.populate_post_and_comment_fields_batch.delay(
        [post.id for post in posts])

    assert mock_api.return_value.get_submission.call_count == len(posts)
    assert mock_backpopulate_api.backpopulate_post.call_count == len(posts)
    assert mock_backpopulate_api.backpopulate_comments.call_count == len(posts)
    for post in posts:
        mock_api.return_value.get_submission.assert_any_call(post.post_id)
        mock_backpopulate_api.backpopulate_post.assert_any_call(
            post=post,
            submission=mock_api.return_value.get_submission.return_value)
        mock_backpopulate_api.backpopulate_comments.assert_any_call(
            post=post,
            submission=mock_api.return_value.get_submission.return_value)
Ejemplo n.º 6
0
def test_es_post_serializer(factory_kwargs):
    """
    Test that ESPostSerializer correctly serializes a post object
    """
    post = PostFactory.create(**factory_kwargs)
    serialized = ESPostSerializer(instance=post).data
    assert serialized == {
        "object_type": POST_TYPE,
        "article_content": post.article.content
        if getattr(post, "article", None) is not None
        else None,
        "plain_text": post.plain_text,
        "author_id": post.author.username if post.author is not None else None,
        "author_name": post.author.profile.name if post.author is not None else None,
        "author_headline": post.author.profile.headline
        if post.author is not None
        else None,
        "author_avatar_small": image_uri(
            post.author.profile if post.author is not None else None
        ),
        "channel_name": post.channel.name,
        "channel_title": post.channel.title,
        "channel_type": post.channel.channel_type,
        "text": post.text,
        "score": post.score,
        "removed": post.removed,
        "created": drf_datetime(post.created_on),
        "deleted": post.deleted,
        "num_comments": post.num_comments,
        "post_id": post.post_id,
        "post_title": post.title,
        "post_link_url": post.url,
        "post_link_thumbnail": post.thumbnail_url,
        "post_slug": post.slug,
        "post_type": post.post_type,
    }
def test_backpopulate_post(
    mocker,
    settings,
    post_type,
    has_author,
    author_exists,
    is_removed,
    is_deleted,
    is_edited,
):  # pylint: disable=too-many-arguments,too-many-locals
    """Tests backpopulate_post"""

    settings.EMBEDLY_KEY = "abc"
    author = UserFactory.create()
    post = PostFactory.create(unpopulated=True, post_type=None)
    if post_type == EXTENDED_POST_TYPE_ARTICLE:
        post.article = ArticleFactory.create(author=author)
        post.save()
    mock_author = mocker.Mock()
    mock_author.configure_mock(name=author.username if author_exists else "missing")

    if is_deleted:
        selftext = DELETED_COMMENT_OR_POST_TEXT
    elif post_type == LINK_TYPE_SELF:
        selftext = "content"
    else:
        selftext = ""

    url, link_meta = None, None
    if post_type == LINK_TYPE_LINK:
        url = "http://example.com"
        link_meta = LinkMetaFactory.create(url=url)

    mock_link_meta = mocker.patch(
        "channels.utils.get_or_create_link_meta", return_value=link_meta
    )

    submission = mocker.Mock(
        id=post.post_id,
        title="title",
        is_self=post_type != LINK_TYPE_LINK,
        author=mock_author if has_author else None,
        selftext=selftext,
        url=url,
        ups=12,
        num_comments=123,
        edited=is_edited,
        banned_by="abc" if is_removed else None,
        created=CREATED_TIMESTAMP,
    )
    backpopulate_api.backpopulate_post(post=post, submission=submission)

    post.refresh_from_db()

    if post_type == LINK_TYPE_LINK:
        mock_link_meta.assert_called_once_with(url)
    else:
        mock_link_meta.assert_not_called()

    assert_properties_eq(
        post,
        dict(
            author=author if has_author and author_exists else None,
            text=selftext if post_type == LINK_TYPE_SELF else None,
            link_meta=link_meta,
            title="title",
            edited=is_edited,
            score=12,
            url=url,
            num_comments=123,
            created_on=CREATED_ON_DATETIME,
            removed=is_removed,
            deleted=is_deleted,
            post_type=post_type,
        ),
    )
def test_backpopulate_comments(mocker):
    """Tests backpopulate_comments"""
    author = UserFactory.create()
    mock_author = mocker.Mock()
    mock_author.configure_mock(name=author.username)
    missing_author = mocker.Mock()
    missing_author.configure_mock(name="missing")
    post = PostFactory.create()
    submission = mocker.Mock(comments=mocker.MagicMock())
    comments = [
        mocker.Mock(
            id="1",
            parent_id=f"t3_{post.post_id}",
            author=mock_author,
            body="comment",
            score=12,
            edited=False,
            banned_by=None,
            created=CREATED_TIMESTAMP,
        ),
        # deleted
        mocker.Mock(
            id="2",
            parent_id=f"t3_{post.post_id}",
            author=mock_author,
            body=DELETED_COMMENT_OR_POST_TEXT,
            score=12,
            edited=False,
            banned_by=None,
            created=CREATED_TIMESTAMP,
        ),
        # removed
        mocker.Mock(
            id="3",
            parent_id=f"t3_{post.post_id}",
            author=mock_author,
            body="comment removed",
            score=12,
            edited=False,
            banned_by="abc",
            created=CREATED_TIMESTAMP,
        ),
        # edited
        mocker.Mock(
            id="4",
            parent_id=f"t3_{post.post_id}",
            author=mock_author,
            body="comment edited",
            score=12,
            edited=True,
            banned_by="abc",
            created=CREATED_TIMESTAMP,
        ),
        # missing author
        mocker.Mock(
            id="5",
            parent_id=f"t3_{post.post_id}",
            author=missing_author,
            body="comment missing author",
            score=12,
            edited=False,
            banned_by=None,
            created=CREATED_TIMESTAMP,
        ),
        # no author
        mocker.Mock(
            id="6",
            parent_id=f"t3_{post.post_id}",
            author=None,
            body="comment no author",
            score=12,
            edited=False,
            banned_by=None,
            created=CREATED_TIMESTAMP,
        ),
    ]
    submission.comments.list.return_value = comments

    result = backpopulate_api.backpopulate_comments(post=post, submission=submission)

    assert result == len(comments)

    submission.comments.replace_more.assert_called_once_with(limit=None)

    expected_values = [
        dict(
            author=author,
            text="comment",
            score=12,
            edited=False,
            removed=False,
            deleted=False,
            created_on=CREATED_ON_DATETIME,
        ),
        # deleted
        dict(
            author=author,
            text=DELETED_COMMENT_OR_POST_TEXT,
            score=12,
            edited=False,
            removed=False,
            deleted=True,
            created_on=CREATED_ON_DATETIME,
        ),
        # removed
        dict(
            author=author,
            text="comment removed",
            score=12,
            edited=False,
            removed=True,
            deleted=False,
            created_on=CREATED_ON_DATETIME,
        ),
        # edited
        dict(
            author=author,
            text="comment edited",
            score=12,
            edited=True,
            removed=True,
            deleted=False,
            created_on=CREATED_ON_DATETIME,
        ),
        # missing author
        dict(
            author=None,
            text="comment missing author",
            score=12,
            edited=False,
            removed=False,
            deleted=False,
            created_on=CREATED_ON_DATETIME,
        ),
        # no author
        dict(
            author=None,
            text="comment no author",
            score=12,
            edited=False,
            removed=False,
            deleted=False,
            created_on=CREATED_ON_DATETIME,
        ),
    ]

    populated_comments = list(
        Comment.objects.order_by("id").filter(
            comment_id__in=[comment.id for comment in comments]
        )
    )
    for comment, expected in zip(populated_comments, expected_values):
        assert_properties_eq(comment, expected)