def test_create_comment(
    user_client,
    reddit_factories,
    private_channel_and_contributor,
    mock_notify_subscribed_users,
    extra_params,
    extra_expected,
    score,
):  # pylint: disable=too-many-arguments
    """Create a comment"""
    channel, user = private_channel_and_contributor
    post = reddit_factories.text_post("a post", user, channel=channel)
    url = reverse("comment-list", kwargs={"post_id": post.id})
    resp = user_client.post(url,
                            data={
                                "text": "reply_to_post 2",
                                **extra_params
                            })
    assert resp.status_code == status.HTTP_201_CREATED
    assert resp.json() == {
        "author_id": user.username,
        "created": any_instance_of(str),
        "id": any_instance_of(str),
        "parent_id": None,
        "post_id": post.id,
        "score": 1,
        "text": "reply_to_post 2",
        "upvoted": True,
        "downvoted": False,
        "removed": False,
        "deleted": False,
        "subscribed": True,
        "profile_image": image_uri(user.profile),
        "author_name": user.profile.name,
        "author_headline": user.profile.headline,
        "edited": False,
        "comment_type": "comment",
        "num_reports": None,
        **extra_expected,
    }

    assert_properties_eq(
        Comment.objects.get(comment_id=resp.json()["id"]),
        {
            "author": user,
            "text": "reply_to_post 2",
            "score": score,
            "removed": False,
            "deleted": False,
            "edited": False,
            "created_on": any_instance_of(datetime),
        },
    )

    mock_notify_subscribed_users.assert_called_once_with(
        post.id, None,
        resp.json()["id"])
Beispiel #2
0
def test_create_article_post(user_client, private_channel_and_contributor):
    """
    Create a new article post
    """
    channel, user = private_channel_and_contributor
    url = reverse("post-list", kwargs={"channel_name": channel.name})
    article_text = "some text"
    article_content = [{
        "key": "value",
        "nested": {
            "number": 4
        },
        "text": article_text
    }]
    resp = user_client.post(url, {
        "title": "parameterized testing",
        "article_content": article_content
    })
    assert resp.status_code == status.HTTP_201_CREATED
    assert resp.json() == {
        "title": "parameterized testing",
        "text": "",
        "article_content": article_content,
        "plain_text": article_text,
        "url": None,
        "url_domain": None,
        "cover_image": None,
        "thumbnail": None,
        "author_id": user.username,
        "created": any_instance_of(str),
        "upvoted": True,
        "removed": False,
        "deleted": False,
        "subscribed": True,
        "id": any_instance_of(str),
        "slug": "parameterized-testing",
        "num_comments": 0,
        "score": 1,
        "channel_name": channel.name,
        "channel_title": channel.title,
        "channel_type": "private",
        "profile_image": image_uri(user.profile),
        "author_name": user.profile.name,
        "author_headline": user.profile.headline,
        "edited": False,
        "stickied": False,
        "num_reports": None,
        "post_type": EXTENDED_POST_TYPE_ARTICLE,
    }
    article = Article.objects.filter(post__post_id=resp.json()["id"])
    assert article.exists()
    assert article.first().content == article_content
Beispiel #3
0
def test_xpro_transform_courses(mock_xpro_courses_data):
    """Test that xpro courses data is correctly transformed into our normalized structure"""
    result = xpro.transform_courses(mock_xpro_courses_data)
    expected = [
        {
            "course_id": course_data["readable_id"],
            "platform": PlatformType.xpro.value,
            "title": course_data["title"],
            "image_src": course_data["thumbnail_url"],
            "short_description": course_data["description"],
            "offered_by": xpro.OFFERED_BY,
            "published": any(
                map(
                    lambda course_run: course_run.get("current_price", None),
                    course_data["courseruns"],
                )
            ),
            "topics": course_data.get("topics", []),
            "runs": [
                {
                    "run_id": course_run_data["courseware_id"],
                    "platform": PlatformType.xpro.value,
                    "start_date": any_instance_of(datetime, type(None)),
                    "end_date": any_instance_of(datetime, type(None)),
                    "enrollment_start": any_instance_of(datetime, type(None)),
                    "enrollment_end": any_instance_of(datetime, type(None)),
                    "best_start_date": _parse_datetime(
                        course_run_data["enrollment_start"]
                        or course_run_data["start_date"]
                    ),
                    "best_end_date": _parse_datetime(
                        course_run_data["enrollment_end"] or course_run_data["end_date"]
                    ),
                    "offered_by": xpro.OFFERED_BY,
                    "published": bool(course_run_data["current_price"]),
                    "prices": [{"price": course_run_data["current_price"]}]
                    if course_run_data["current_price"]
                    else [],
                    "instructors": [
                        {"full_name": instructor["name"]}
                        for instructor in course_run_data["instructors"]
                    ],
                }
                for course_run_data in course_data["courseruns"]
            ],
        }
        for course_data in mock_xpro_courses_data
    ]
    assert expected == result
def assert_api_call(
    client,
    url,
    payload,
    expected,
    expect_authenticated=False,
    expect_status=status.HTTP_200_OK,
    use_defaults=True,
):
    """Run the API call and perform basic assertions"""
    assert bool(get_user(client).is_authenticated) is False

    response = client.post(reverse(url), payload)
    actual = response.json()

    defaults = {
        "errors": [],
        "redirect_url": None,
        "extra_data": {},
        "state": None,
        "provider": None,
        "flow": None,
        "partial_token": any_instance_of(str),
    }

    assert actual == ({**defaults, **expected} if use_defaults else expected)
    assert response.status_code == expect_status

    assert bool(get_user(client).is_authenticated) is expect_authenticated

    return actual
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)])
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)])
Beispiel #7
0
def test_create_url_post_existing_meta(user_client,
                                       private_channel_and_contributor, mocker,
                                       settings):
    """
    Create a new url post
    """
    settings.EMBEDLY_KEY = "FAKE"
    channel, user = private_channel_and_contributor
    link_url = "http://micromasters.mit.edu/🐨"
    thumbnail = "http://fake/thumb.jpg"
    embedly_stub = mocker.patch("channels.utils.get_embedly_summary")
    LinkMetaFactory.create(url=link_url, thumbnail=thumbnail)
    url = reverse("post-list", kwargs={"channel_name": channel.name})
    resp = user_client.post(url, {"title": "url title 🐨", "url": link_url})
    embedly_stub.assert_not_called()
    assert resp.status_code == status.HTTP_201_CREATED
    assert resp.json() == {
        "title": "url title 🐨",
        "post_type": LINK_TYPE_LINK,
        "url": link_url,
        "url_domain": "micromasters.mit.edu",
        "cover_image": None,
        "thumbnail": thumbnail,
        "text": None,
        "article_content": None,
        "plain_text": None,
        "author_id": user.username,
        "created": any_instance_of(str),
        "upvoted": True,
        "id": any_instance_of(str),
        "slug": "url-title",
        "num_comments": 0,
        "removed": False,
        "deleted": False,
        "subscribed": True,
        "score": 1,
        "channel_name": channel.name,
        "channel_title": channel.title,
        "channel_type": channel.channel_type,
        "profile_image": image_uri(user.profile),
        "author_name": user.profile.name,
        "author_headline": user.profile.headline,
        "edited": False,
        "stickied": False,
        "num_reports": None,
    }
def test_any_instance_of():
    """Tests any_instance_of()"""
    any_number = any_instance_of(int, float)

    assert any_number == 0.405
    assert any_number == 8_675_309
    assert any_number != "not a number"
    assert any_number != {}
    assert any_number != []
Beispiel #9
0
def test_create_text_post(user_client, private_channel_and_contributor):
    """
    Create a new text post
    """
    channel, user = private_channel_and_contributor
    url = reverse("post-list", kwargs={"channel_name": channel.name})
    resp = user_client.post(url, {
        "title": "parameterized testing",
        "text": "tests are great"
    })
    assert resp.status_code == status.HTTP_201_CREATED
    assert resp.json() == {
        "title": "parameterized testing",
        "text": "tests are great",
        "article_content": None,
        "plain_text": "tests are great",
        "url": None,
        "url_domain": None,
        "cover_image": None,
        "thumbnail": None,
        "author_id": user.username,
        "created": any_instance_of(str),
        "upvoted": True,
        "removed": False,
        "deleted": False,
        "subscribed": True,
        "id": any_instance_of(str),
        "slug": "parameterized-testing",
        "num_comments": 0,
        "score": 1,
        "channel_name": channel.name,
        "channel_title": channel.title,
        "channel_type": channel.channel_type,
        "profile_image": image_uri(user.profile),
        "author_name": user.profile.name,
        "author_headline": user.profile.headline,
        "edited": False,
        "stickied": False,
        "num_reports": None,
        "post_type": LINK_TYPE_SELF,
    }
Beispiel #10
0
def test_send_notification(notifier, mocker):
    """Tests send_notification"""
    send_messages_mock = mocker.patch("mail.api.send_messages")
    note = EmailNotificationFactory.create(
        user=notifier.user,
        notification_type=notifier.notification_settings.notification_type,
        sending=True,
    )

    notifier.send_notification(note)

    send_messages_mock.assert_called_once_with([any_instance_of(EmailMessage)])
def test_create_comment_reply_to_comment(
    user_client,
    reddit_factories,
    private_channel_and_contributor,
    mock_notify_subscribed_users,
):
    """Create a comment that's a reply to another comment"""
    channel, user = private_channel_and_contributor
    post = reddit_factories.text_post("a post", user, channel=channel)
    comment = reddit_factories.comment("comment", user, post_id=post.id)
    url = reverse("comment-list", kwargs={"post_id": post.id})
    resp = user_client.post(url,
                            data={
                                "text": "reply_to_comment 3",
                                "comment_id": comment.id
                            })
    assert resp.status_code == status.HTTP_201_CREATED
    assert resp.json() == {
        "author_id": user.username,
        "created": any_instance_of(str),
        "id": any_instance_of(str),
        "parent_id": comment.id,
        "post_id": post.id,
        "score": 1,
        "text": "reply_to_comment 3",
        "upvoted": True,
        "downvoted": False,
        "removed": False,
        "deleted": False,
        "subscribed": True,
        "profile_image": image_uri(user.profile),
        "author_name": user.profile.name,
        "author_headline": user.profile.headline,
        "edited": False,
        "comment_type": "comment",
        "num_reports": None,
    }
    mock_notify_subscribed_users.assert_called_once_with(
        post.id, comment.id,
        resp.json()["id"])
def test_context_for_user(settings, test_user, extra_context):
    """Tests that context_for_user returns the expected values"""
    user_ctx = ({
        "user": test_user,
        "anon_token": any_instance_of(str)
    } if test_user else {})

    assert context_for_user(user=test_user, extra_context=extra_context) == {
        "base_url": settings.SITE_BASE_URL,
        "site_name": get_default_site().title,
        **(extra_context or {}),
        **user_ctx,
    }
def test_create_or_update_micromasters_social_auth(user):
    """Test that we create a MM social auth"""
    username = "******"
    email = "test@localhost"
    email2 = "test2@localhost"

    assert UserSocialAuth.objects.count() == 0
    assert (api.create_or_update_micromasters_social_auth(
        user, username, {"email": email}) is not None)

    assert UserSocialAuth.objects.count() == 1

    social = UserSocialAuth.objects.first()
    assert social.user == user
    assert social.uid == username
    assert social.provider == "micromasters"
    assert social.extra_data == {
        "email": email,
        "username": username,
        "auth_time": any_instance_of(int),
    }

    # should be the same one as before, except email has updated
    assert (api.create_or_update_micromasters_social_auth(
        user, username, {"email": email2}) == social)

    social.refresh_from_db()
    assert social.user == user
    assert social.uid == username
    assert social.extra_data == {
        "email": email2,
        "username": username,
        "auth_time": any_instance_of(int),
    }

    assert UserSocialAuth.objects.count() == 1
Beispiel #14
0
def test_send_verification_email(mocker, rf):
    """Test that send_verification_email sends an email with the link in it"""
    send_messages_mock = mocker.patch("mail.api.send_messages")
    email = "test@localhost"
    request = rf.post(reverse("social:complete", args=("email", )),
                      {"email": email})
    # social_django depends on request.sesssion, so use the middleware to set that
    SessionMiddleware().process_request(request)
    strategy = load_strategy(request)
    backend = load_backend(strategy, EmailAuth.name, None)
    code = mocker.Mock(code="abc")
    verification_api.send_verification_email(strategy, backend, code, "def")

    send_messages_mock.assert_called_once_with([any_instance_of(EmailMessage)])

    email_body = send_messages_mock.call_args[0][0][0].body
    assert "/signup/confirm/?verification_code=abc&partial_token=def" in email_body
def test_transform_course(
    openedx_config,
    openedx_extract_transform,
    mitx_course_data,
    has_runs,
    is_course_deleted,
    is_course_run_deleted,
):  # pylint: disable=too-many-arguments
    """Test that the transform function normalizes and filters out data"""
    extracted = mitx_course_data["results"]
    expected = extracted if not is_course_deleted and has_runs else []
    for course in extracted:
        if not has_runs:
            course["course_runs"] = []
        if is_course_deleted:
            course["title"] = f"[delete] {course['title']}"
        if is_course_run_deleted:
            for run in course["course_runs"]:
                run["title"] = f"[delete] {run['title']}"
    assert openedx_extract_transform.transform(extracted) == [
        {
            "title": "The Analytics Edge",
            "course_id": "MITx+15.071x",
            "short_description": "short_description",
            "full_description": "full description",
            "platform": openedx_config.platform,
            "offered_by": [{"name": openedx_config.offered_by}],
            "image_src": "https://prod-discovery.edx-cdn.org/media/course/image/ff1df27b-3c97-42ee-a9b3-e031ffd41a4f-747c9c2f216e.small.jpg",
            "image_description": "Image description",
            "last_modified": any_instance_of(datetime),
            "topics": [{"name": "Data Analysis & Statistics"}],
            "url": f"{openedx_config.alt_url}MITx+15.071x/course/",
            "runs": []
            if is_course_run_deleted
            else [
                {
                    "availability": "Starting Soon",
                    "best_end_date": "2019-05-22T23:30:00Z",
                    "best_start_date": "2019-02-20T15:00:00Z",
                    "run_id": "course-v1:MITx+15.071x+1T2019",
                    "end_date": "2019-05-22T23:30:00Z",
                    "platform": openedx_config.platform,
                    "enrollment_end": None,
                    "enrollment_start": None,
                    "full_description": "<p>Full Description</p>",
                    "image_description": None,
                    "image_src": "https://prod-discovery.edx-cdn.org/media/course/image/ff1df27b-3c97-42ee-a9b3-e031ffd41a4f-747c9c2f216e.small.jpg",
                    "instructors": [
                        {"first_name": "Dimitris", "last_name": "Bertsimas"},
                        {"first_name": "Allison", "last_name": "O'Hair"},
                    ],
                    "language": "en-us",
                    "last_modified": any_instance_of(datetime),
                    "level": "Intermediate",
                    "offered_by": [{"name": openedx_config.offered_by}],
                    "prices": [
                        {
                            "mode": "verified",
                            "price": "150.00",
                            "upgrade_deadline": "2019-03-20T15:00:00Z",
                        },
                        {"mode": "audit", "price": "0.00", "upgrade_deadline": None},
                    ],
                    "semester": "spring",
                    "short_description": "short_description",
                    "start_date": "2019-02-20T15:00:00Z",
                    "title": "The Analytics Edge",
                    "url": f"{openedx_config.alt_url}course-v1:MITx+15.071x+1T2019/course/",
                    "year": 2019,
                }
            ],
            "raw_json": course,
        }
        for course in expected
    ]