Пример #1
0
def test_load_playlists_unpublish():
    """Test load_playlists when a video/playlist gets unpublished"""
    channel = VideoChannelFactory.create()

    userlist1 = UserListFactory.create()
    userlist2 = UserListFactory.create()

    playlist1 = PlaylistFactory.create(channel=channel,
                                       published=True,
                                       has_user_list=True,
                                       user_list=userlist1)
    playlist2 = PlaylistFactory.create(channel=channel,
                                       published=True,
                                       has_user_list=True,
                                       user_list=userlist2)
    playlist3 = PlaylistFactory.create(channel=channel,
                                       published=True,
                                       has_user_list=True,
                                       user_list=None)
    playlist4 = PlaylistFactory.create(channel=channel,
                                       published=True,
                                       has_user_list=False,
                                       user_list=None)

    playlists_data = [{
        "playlist_id": playlist1.playlist_id,
        "platform": playlist1.platform,
        "videos": [],
    }]

    load_playlists(channel, playlists_data)

    playlist1.refresh_from_db()
    playlist2.refresh_from_db()
    playlist3.refresh_from_db()
    playlist4.refresh_from_db()

    assert playlist1.published is True
    assert playlist1.has_user_list is True

    assert playlist2.published is False
    assert playlist2.has_user_list is False

    assert playlist3.published is False
    assert playlist3.has_user_list is False

    assert playlist4.published is False
    assert playlist4.has_user_list is False

    assert UserList.objects.filter(id=userlist1.id).count() == 1
    assert UserList.objects.filter(id=userlist2.id).count() == 0
Пример #2
0
def test_user_list_items_endpoint_update_item(client, user, is_author,
                                              mock_user_list_index):
    """Test userlistitems endpoint for updating UserListItem positions"""
    author = UserFactory.create()
    topics = CourseTopicFactory.create_batch(3)
    userlist = UserListFactory.create(author=author,
                                      privacy_level=PrivacyLevel.public.value,
                                      topics=topics)
    list_item_1 = UserListItemFactory.create(user_list=userlist, position=0)
    list_item_2 = UserListItemFactory.create(user_list=userlist, position=1)
    list_item_3 = UserListItemFactory.create(user_list=userlist, position=2)

    client.force_login(author if is_author else user)

    data = {"position": 0}

    resp = client.patch(
        reverse("userlistitems-detail", args=[userlist.id, list_item_3.id]),
        data=data,
        format="json",
    )
    assert resp.status_code == (200 if is_author else 403)
    if resp.status_code == 200:
        assert resp.json()["position"] == 0
        mock_user_list_index.upsert_user_list.assert_called_once_with(
            userlist.id)
        for idx, item in enumerate([list_item_3, list_item_1, list_item_2]):
            item.refresh_from_db()
            assert item.position == idx
Пример #3
0
def test_user_list_items_endpoint_delete_items(client, user, is_author,
                                               mock_user_list_index):
    """Test userlistitems endpoint for deleting UserListItems"""
    author = UserFactory.create()
    userlist = UserListFactory.create(author=author,
                                      privacy_level=PrivacyLevel.public.value)
    list_items = sorted(
        UserListItemFactory.create_batch(2, user_list=userlist),
        key=lambda item: item.id,
    )

    client.force_login(author if is_author else user)

    resp = client.delete(
        reverse("userlistitems-detail", args=[userlist.id, list_items[0].id]),
        format="json",
    )
    assert resp.status_code == (204 if is_author else 403)
    if resp.status_code == 204:
        mock_user_list_index.upsert_user_list_view.assert_called_with(
            userlist.id)
        client.delete(
            reverse("userlistitems-detail",
                    args=[userlist.id, list_items[1].id]),
            format="json",
        )
        mock_user_list_index.delete_user_list.assert_called_with(userlist)
Пример #4
0
def test_es_userlist_serializer_image_src():
    """
    Test that ESUserListSerializer uses 1st non-list list item image_src if the list image_src is None
    """
    user_list = UserListFactory.create(image_src=None)
    UserListItemFactory.create(user_list=user_list, position=1, is_userlist=True)
    list_item_course = UserListItemFactory.create(
        user_list=user_list, position=2, is_course=True
    )
    serialized = ESUserListSerializer(user_list).data
    assert_json_equal(
        serialized,
        {
            "author": user_list.author.id,
            "object_type": user_list.list_type,
            "list_type": user_list.list_type,
            "privacy_level": user_list.privacy_level,
            "id": user_list.id,
            "short_description": user_list.short_description,
            "title": user_list.title,
            "image_src": list_item_course.item.image_src,
            "topics": list(user_list.topics.values_list("name", flat=True)),
            "created": drf_datetime(user_list.created_on),
            "default_search_priority": 0,
            "minimum_price": 0,
        },
    )
Пример #5
0
def test_es_userlist_serializer(list_type, privacy_level, user):
    """
    Test that ESUserListSerializer correctly serializes a UserList object
    """
    user_list = UserListFactory.create(
        list_type=list_type, privacy_level=privacy_level, author=user
    )
    serialized = ESUserListSerializer(user_list).data
    assert_json_equal(
        serialized,
        {
            "author": user.id,
            "object_type": list_type,
            "list_type": list_type,
            "privacy_level": privacy_level,
            "id": user_list.id,
            "short_description": user_list.short_description,
            "title": user_list.title,
            "image_src": user_list.image_src.url,
            "topics": list(user_list.topics.values_list("name", flat=True)),
            "created": drf_datetime(user_list.created_on),
            "default_search_priority": 0,
            "minimum_price": 0,
        },
    )
Пример #6
0
def test_favorites_serializer():
    """
    Test that the favorite serializer generic foreign key works and also rejects unexpected classes
    """
    user = UserFactory.create()
    course = CourseFactory.create()
    bootcamp = BootcampFactory.create()
    user_list = UserListFactory.create(author=user)
    program = ProgramFactory.create()
    course_topic = CourseTopicFactory.create()

    favorite_item = FavoriteItem(user=user, item=course)
    serializer = FavoriteItemSerializer(favorite_item)
    assert serializer.data.get("content_data") == CourseSerializer(course).data

    favorite_item = FavoriteItem(user=user, item=bootcamp)
    serializer = FavoriteItemSerializer(favorite_item)
    assert serializer.data.get("content_data") == BootcampSerializer(
        bootcamp).data

    favorite_item = FavoriteItem(user=user, item=user_list)
    serializer = FavoriteItemSerializer(favorite_item)
    assert serializer.data.get("content_data") == UserListSerializer(
        user_list).data

    favorite_item = FavoriteItem(user=user, item=program)
    serializer = FavoriteItemSerializer(favorite_item)
    assert serializer.data.get("content_data") == ProgramSerializer(
        program).data

    favorite_item = FavoriteItem(user=user, item=course_topic)
    serializer = FavoriteItemSerializer(favorite_item)
    with pytest.raises(Exception):
        assert serializer.data.get("content_data").get("id") == course_topic.id
def test_upsert_user_list(mocker, list_type):
    """
    Tests that upsert_user_list calls update_field_values_by_query with the right parameters
    """
    patched_task = mocker.patch("search.tasks.upsert_user_list")
    user_list = UserListFactory.create(list_type=list_type)
    upsert_user_list(user_list.id)
    patched_task.delay.assert_called_once_with(user_list.id)
def test_delete_user_list(mocker, list_type):
    """Tests that deleting a UserList triggers a delete on a UserList document"""
    patched_delete_task = mocker.patch("search.task_helpers.delete_document")
    user_list = UserListFactory.create(list_type=list_type)
    delete_user_list(user_list)
    assert patched_delete_task.delay.called is True
    assert patched_delete_task.delay.call_args[0] == (
        gen_user_list_id(user_list),
        USER_LIST_TYPE,
    )
Пример #9
0
def test_cascade_delete_listitems(kwargs):
    """
    When a resource is deleted, UserListItems for that resource should be deleted
    """
    user_list = UserListFactory.create()
    list_item = UserListItemFactory.create(user_list=user_list, **kwargs)
    assert user_list.items.count() == 1
    resource = list_item.item
    resource.delete()
    assert user_list.items.count() == 0
Пример #10
0
def test_user_list_endpoint_get(client, is_public, is_author, user):
    """Test learning path endpoint"""
    author = UserFactory.create()
    user_list = UserListFactory.create(
        author=author,
        privacy_level=PrivacyLevel.public.value
        if is_public else PrivacyLevel.private.value,
    )

    another_user_list = UserListFactory.create(
        author=UserFactory.create(),
        privacy_level=PrivacyLevel.public.value
        if is_public else PrivacyLevel.private.value,
    )

    UserListItemFactory.create(user_list=user_list,
                               position=1,
                               is_bootcamp=True)
    UserListItemFactory.create(user_list=user_list, position=2)

    # Anonymous users should get no results
    resp = client.get(reverse("userlists-list"))
    assert resp.data.get("count") == 0

    # Logged in user should get own lists
    client.force_login(author if is_author else user)
    resp = client.get(reverse("userlists-list"))
    assert resp.data.get("count") == (1 if is_author else 0)
    if is_author:
        assert "content_data" not in resp.data.get("results")[0]

    resp = client.get(reverse("userlists-detail", args=[user_list.id]))
    assert resp.status_code == (403 if not (is_public or is_author) else 200)
    if resp.status_code == 200:
        assert resp.data.get("title") == user_list.title
        assert len(resp.data.get("lists")) == 0
        assert resp.data.get("item_count") == 2

    # Logged in user should see other person's public list
    resp = client.get(reverse("userlists-detail", args=[another_user_list.id]))
    assert resp.status_code == (403 if not is_public else 200)
    if resp.status_code == 200:
        assert resp.data.get("title") == another_user_list.title
Пример #11
0
def test_favorite_lists_other_user(user_client, privacy_level):
    """Test favoriting and unfavoriting someone else's list"""
    is_public = privacy_level == PrivacyLevel.public.value
    userlist = UserListFactory.create(privacy_level=privacy_level)
    resp = user_client.post(
        reverse("userlists-detail", args=[userlist.id]) + "favorite/")
    assert resp.status_code == 200 if is_public else 403

    resp = user_client.post(
        reverse("userlists-detail", args=[userlist.id]) + "unfavorite/")
    assert resp.status_code == 200 if is_public else 403
Пример #12
0
def test_generic_foreign_key_serializer_classes(factory, valid_type):
    """
    Test that generic foreign key serializer properly accepts expected classes and rejects others
    """
    userlist = UserListFactory.create()
    obj = getattr(factories, factory).create()
    list_item = UserListItem(user_list=userlist, item=obj)
    serializer = UserListItemSerializer(list_item)
    if valid_type:
        assert serializer.data.get("content_data").get("id") == obj.id
    else:
        with pytest.raises(Exception):
            assert serializer.data.get("content_data").get("id") == obj.id
Пример #13
0
def test_user_list_endpoint_delete(client, user, is_author,
                                   mock_user_list_index):
    """Test userlist endpoint for deleting a UserList"""
    author = UserFactory.create()
    userlist = UserListFactory.create(author=author,
                                      privacy_level=PrivacyLevel.public.value)

    client.force_login(author if is_author else user)

    resp = client.delete(reverse("userlists-detail", args=[userlist.id]))
    assert resp.status_code == (204 if is_author else 403)
    assert UserList.objects.filter(id=userlist.id).exists() is not is_author
    assert mock_user_list_index.delete_user_list.call_count == (1 if is_author
                                                                else 0)
def test_userlist_object_permissions(mocker, user, is_public, is_author):
    """
    HasUserListPermissions.has_object_permission should return correct permission depending
    on privacy level and author.
    """
    userlist = UserListFactory.create(
        author=user,
        privacy_level=PrivacyLevel.public.value
        if is_public else PrivacyLevel.private.value,
    )

    request = mocker.MagicMock(
        method="GET", user=(user if is_author else UserFactory.create()))
    assert HasUserListPermissions().has_object_permission(
        request, mocker.MagicMock(), userlist) is (is_public or is_author)
def test_userlistitems_permissions(mocker, user, is_safe, is_public,
                                   is_author):
    """
    HasUserListItemPermissions.has_permission should return correct permission depending
    on privacy level, author, and request method.
    """
    userlist = UserListFactory.create(
        author=user if is_author else UserFactory.create(),
        privacy_level=PrivacyLevel.public.value
        if is_public else PrivacyLevel.private.value,
    )
    request = mocker.MagicMock(method="GET" if is_safe else "POST", user=user)

    view = mocker.MagicMock(kwargs={"parent_lookup_user_list_id": userlist.id})
    assert HasUserListItemPermissions().has_permission(
        request, view) is (is_author or (is_safe and is_public))
Пример #16
0
def test_bootcamp_detail_endpoint_lists(user_client, user):
    """Test that author's list ids are included"""
    bootcamp = BootcampFactory.create()
    user_lists = UserListFactory.create_batch(2, author=user)
    list_items = sorted(
        [
            UserListItemFactory.create(content_object=bootcamp,
                                       user_list=user_list)
            for user_list in user_lists
        ],
        key=lambda x: x.id,
    )
    resp = user_client.get(reverse("bootcamps-detail", args=[bootcamp.id]))
    assert sorted(resp.data.get("lists"), key=lambda x: x["item_id"]) == [
        MicroUserListItemSerializer(list_item).data for list_item in list_items
    ]
Пример #17
0
def test_userlistitem_serializer_validation(content_type, factory, valid_type,
                                            object_exists):
    """
    Test that the UserListItemSerializer validates content_type and object correctly
    """
    userlist = UserListFactory.create()
    # pylint:disable=redefined-builtin
    object_id = getattr(factories,
                        factory).create().id if object_exists else 1_001_001
    data = {
        "content_type": content_type,
        "object_id": object_id,
        "user_list": userlist.id,
    }
    serializer = UserListItemSerializer(data=data)
    assert serializer.is_valid() == (valid_type and object_exists)
Пример #18
0
def test_user_list_items_endpoint_update_items_wrong_list(client, user):
    """Verify that trying an update via userlistitems api in wrong list fails"""
    userlist = UserListFactory.create(author=user,
                                      privacy_level=PrivacyLevel.public.value)
    list_item_incorrect = UserListItemFactory.create()

    client.force_login(user)

    data = {"id": list_item_incorrect.id, "position": 44}

    resp = client.patch(
        reverse("userlistitems-detail",
                args=[userlist.id, list_item_incorrect.id]),
        data=data,
        format="json",
    )
    assert resp.status_code == 404
def test_userlist_favorite_permissions(mocker, user, is_public, is_author,
                                       action):
    """
    HasUserListPermissions.has_object_permission should return correct permission depending
    on privacy level and author when favoriting or unfavoriting.
    """
    userlist = UserListFactory.create(
        author=user,
        privacy_level=PrivacyLevel.public.value
        if is_public else PrivacyLevel.private.value,
    )

    request = mocker.MagicMock(
        method="POST", user=(user if is_author else UserFactory.create()))
    assert HasUserListPermissions().has_object_permission(
        request, mocker.MagicMock(action=action),
        userlist) is ((is_public and "favorite" in action) or is_author)
Пример #20
0
def test_user_list_items_endpoint_create_item_bad_data(client, user):
    """Test userlistitems endpoint for creating a UserListItem"""
    userlist = UserListFactory.create(author=user,
                                      privacy_level=PrivacyLevel.public.value)
    course = CourseFactory.create()

    client.force_login(user)

    data = {"content_type": "bad_content", "object_id": course.id}

    resp = client.post(reverse("userlistitems-list", args=[userlist.id]),
                       data=data,
                       format="json")
    assert resp.status_code == 400
    assert resp.json() == {
        "non_field_errors": ["Incorrect object type bad_content"],
        "error_type": "ValidationError",
    }
Пример #21
0
def test_user_list_items_endpoint_create_item(client, user, is_author,
                                              mock_user_list_index):
    """Test userlistitems endpoint for creating a UserListItem"""
    author = UserFactory.create()
    userlist = UserListFactory.create(author=author,
                                      privacy_level=PrivacyLevel.public.value)
    course = CourseFactory.create()

    client.force_login(author if is_author else user)

    data = {"content_type": "course", "object_id": course.id}

    resp = client.post(reverse("userlistitems-list", args=[userlist.id]),
                       data=data,
                       format="json")
    assert resp.status_code == (201 if is_author else 403)
    if resp.status_code == 201:
        assert resp.json().get("object_id") == course.id
        mock_user_list_index.upsert_user_list.assert_called_once_with(
            userlist.id)
def test_popular_content_serializer(mocker, is_deleted, user):
    """Test PopularContentSerializer"""
    resources = [
        VideoFactory.create(),
        ProgramFactory.create(),
        CourseFactory.create(),
        UserListFactory.create(),
        BootcampFactory.create(),
    ]

    data = [{
        "content_type_id": ContentType.objects.get_for_model(resource).id,
        "content_id": resource.id,
    } for resource in resources]

    if is_deleted:
        for resource in resources:
            resource.delete()
        resources = []

    resources = [
        type(resource).objects.filter(
            id=resource.id).prefetch_list_items_for_user(
                user).annotate_is_favorite_for_user(user).first()
        for resource in resources
    ]

    context = {"request": mocker.Mock(user=user)}
    # NOTE: we test PopularContentSerializer instead of PopularContentListSerializer
    #       because the list serializer is never used directly, but rather many=True tells
    #       PopularContentSerializer to delegate to PopularContentListSerializer
    results = PopularContentSerializer(data, context=context, many=True).data

    # should be sorted by the same order they were passed in
    assert_json_equal(
        results,
        [
            GenericForeignKeyFieldSerializer(resource, context=context).data
            for resource in resources
        ],
    )
Пример #23
0
def test_popular_content_types(client, user, mocker):
    """Test the popular content types API"""
    # create 2 of each, generate interactions for only the first one
    # second one shouldn't show up in the results
    course = CourseFactory.create_batch(2)[0]
    bootcamp = BootcampFactory.create_batch(2)[0]
    program = ProgramFactory.create_batch(2)[0]
    user_list = UserListFactory.create_batch(2)[0]
    video = VideoFactory.create_batch(2)[0]

    # generate interactions with an increasing count
    interactions = [
        ContentTypeInteractionFactory.create_batch(count + 1,
                                                   content=content)[0]
        for count, content in enumerate(
            [user_list, bootcamp, video, course, program])
    ]

    response = client.get(reverse("popular_content-list"))

    # the response should be ordered such that items with a higher count of interactions are first
    # this ends up being the reverse order of `interactions` since we used `enumerate()`
    assert response.json() == {
        "results":
        PopularContentSerializer(
            [{
                "content_type_id": interaction.content_type_id,
                "content_id": interaction.content_id,
            } for interaction in reversed(interactions)],
            many=True,
            context={
                "request": mocker.Mock(user=user)
            },
        ).data,
        "next":
        None,
        "previous":
        None,
        "count":
        len(interactions),
    }
Пример #24
0
def test_user_list_endpoint_patch(client, user, mock_user_list_index,
                                  update_topics):
    """Test userlist endpoint for updating a UserList"""
    [original_topic, new_topic] = CourseTopicFactory.create_batch(2)
    userlist = UserListFactory.create(author=user,
                                      title="Title 1",
                                      topics=[original_topic])
    UserListItemFactory.create(user_list=userlist)

    client.force_login(user)

    data = {"title": "Title 2"}
    if update_topics:
        data["topics"] = [new_topic.id]

    resp = client.patch(reverse("userlists-detail", args=[userlist.id]),
                        data=data,
                        format="json")
    assert resp.status_code == 200
    assert UserList.objects.get(id=userlist.id).title == "Title 2"
    assert resp.data["topics"][0]["id"] == (new_topic.id if update_topics else
                                            original_topic.id)
    mock_user_list_index.upsert_user_list.assert_called_once_with(userlist.id)
Пример #25
0
def test_load_playlist_user_list(mock_upsert_tasks, settings, user, exists,
                                 has_user_list, user_list_title):
    # pylint: disable=too-many-arguments
    """Test that load_playlist_user_list updates or create the user list"""

    settings.OPEN_VIDEO_USER_LIST_OWNER = user.username

    playlist = PlaylistFactory.create(has_user_list=has_user_list)
    videos = VideoFactory.create_batch(3)
    for idx, video in enumerate(videos):
        PlaylistVideo.objects.create(playlist=playlist,
                                     video=video,
                                     position=idx)

    prune_video = VideoFactory.create()
    video_content_type = ContentType.objects.get_for_model(Video)
    user_list = None

    if exists:
        user_list = UserListFactory.create(is_list=True,
                                           is_public=True,
                                           author=user)
        UserListItem.objects.create(
            user_list=user_list,
            content_type=video_content_type,
            object_id=prune_video.id,
            position=0,
        )

        playlist.user_list = user_list
        playlist.save()
    else:
        assert playlist.user_list is None

    load_playlist_user_list(playlist, user_list_title)

    playlist.refresh_from_db()

    if has_user_list:
        if exists:
            assert playlist.user_list == user_list
        else:
            assert playlist.user_list is not None

        user_list = playlist.user_list

        assert user_list.author == user

        if user_list_title:
            assert user_list.title == user_list_title
        else:
            assert user_list.title == playlist.title

        assert user_list.privacy_level == PrivacyLevel.public.value
        assert user_list.list_type == ListType.LIST.value

        assert (UserListItem.objects.filter(
            user_list=user_list,
            content_type=video_content_type,
            object_id=prune_video.id,
        ).exists() is False)

        for video in videos:
            assert (UserListItem.objects.filter(
                user_list=user_list,
                content_type=video_content_type,
                object_id=video.id,
            ).exists() is True)
        mock_upsert_tasks.upsert_user_list.assert_called_once_with(
            user_list.id)
    else:
        assert playlist.user_list is None

        if exists:
            mock_upsert_tasks.delete_user_list.assert_called_once_with(
                user_list)
        else:
            mock_upsert_tasks.delete_user_list.assert_not_called()