예제 #1
0
def test_video_endpoint(client):
    """Test video endpoint"""
    video1 = VideoFactory.create(
        last_modified=datetime(2019, 10, 4, tzinfo=pytz.utc))
    video2 = VideoFactory.create(
        last_modified=datetime(2019, 10, 6, tzinfo=pytz.utc))
    video3 = VideoFactory.create(
        last_modified=datetime(2019, 10, 5, tzinfo=pytz.utc))

    resp = client.get(reverse("videos-list"))
    assert resp.data.get("count") == 3
    assert list(map(lambda video: video["id"], resp.data.get("results"))) == [
        video1.id,
        video2.id,
        video3.id,
    ]

    resp = client.get(reverse("videos-list") + "new/")
    assert resp.data.get("count") == 3
    assert list(map(lambda video: video["id"], resp.data.get("results"))) == [
        video2.id,
        video3.id,
        video1.id,
    ]

    resp = client.get(reverse("videos-detail", args=[video1.id]))
    assert resp.data.get("video_id") == video1.video_id
예제 #2
0
def test_extract_videos_topics(mocker, use_video_ids):
    """Tests that extract_videos_topics yields objects for each video with topics"""
    published_videos = VideoFactory.create_batch(3, published=True)
    # shouldn't be extracted
    VideoFactory.create_batch(3, published=False)

    topic_results = [[f"topic-{idx}-a", f"topic-{idx}-b"]
                     for idx in range(len(published_videos))]

    mock_get_similar_topics = mocker.patch(
        "course_catalog.etl.video.get_similar_topics",
        side_effect=topic_results)

    if use_video_ids:
        published_videos = published_videos[:1]

    result = list(
        extract_videos_topics(
            video_ids=[published_videos[0].id] if use_video_ids else None))

    assert len(result) == len(published_videos)

    for video, topics in zip(published_videos, topic_results):
        assert {
            "video_id": video.video_id,
            "platform": video.platform,
            "topics": [{
                "name": topic
            } for topic in topics],
        } in result

    assert mock_get_similar_topics.call_count == (1 if use_video_ids else
                                                  len(published_videos))
def test_delete_video(mocker):
    """Tests that deleting a video triggers a delete on a video document"""
    patched_delete_task = mocker.patch("search.task_helpers.delete_document")
    video = VideoFactory.create()
    delete_video(video)
    assert patched_delete_task.delay.called is True
    assert patched_delete_task.delay.call_args[0] == (gen_video_id(video), VIDEO_TYPE)
예제 #4
0
def test_load_playlist(mock_tasks):
    """Test load_playlist"""
    channel = VideoChannelFactory.create(playlists=None)
    playlist = PlaylistFactory.build()
    assert Playlist.objects.count() == 0
    assert Video.objects.count() == 0

    videos_records = VideoFactory.build_batch(5, published=True)
    videos_data = [model_to_dict(video) for video in videos_records]

    for video_data in videos_data:
        video_data["runs"] = [{
            "run_id": video_data["video_id"],
            "platform": video_data["platform"],
            "prices": [{
                "price": 0
            }],
        }]

    props = model_to_dict(playlist)

    del props["id"]
    del props["channel"]
    props["videos"] = videos_data

    result = load_playlist(channel, props)

    assert isinstance(result, Playlist)

    assert result.videos.count() == len(videos_records)
    assert result.channel == channel

    mock_tasks.get_video_topics.delay.assert_called_once_with(video_ids=list(
        result.videos.order_by("id").values_list("id", flat=True)))
def test_upsert_video(mocker):
    """
    Tests that upsert_video calls update_field_values_by_query with the right parameters
    """
    patched_task = mocker.patch("search.tasks.upsert_video")
    video = VideoFactory.create()
    upsert_video(video.id)
    patched_task.delay.assert_called_once_with(video.id)
예제 #6
0
def test_serialize_video_for_bulk():
    """
    Test that serialize_video_for_bulk yields a valid ESVideoSerializer
    """
    video = VideoFactory.create()
    assert serialize_video_for_bulk(video) == {
        "_id": gen_video_id(video),
        **ESVideoSerializer(video).data,
    }
예제 #7
0
def test_serialize_bulk_video(mocker):
    """
    Test that serialize_bulk_video calls serialize_video_for_bulk for every existing video
    """
    mock_serialize_video = mocker.patch("search.serializers.serialize_video_for_bulk")
    videos = VideoFactory.create_batch(5)
    list(serialize_bulk_videos(Video.objects.values_list("id", flat=True)))
    for video in videos:
        mock_serialize_video.assert_any_call(video)
예제 #8
0
def test_load_video(mock_upsert_tasks, video_exists, is_published):
    """Test that load_video loads the video"""
    video = (VideoFactory.create(
        published=is_published) if video_exists else VideoFactory.build())
    assert Video.objects.count() == (1 if video_exists else 0)

    props = model_to_dict(
        VideoFactory.build(video_id=video.video_id,
                           platform=video.platform,
                           published=is_published))
    del props["id"]

    props["runs"] = [{
        "run_id": video.video_id,
        "platform": video.platform,
        "prices": [{
            "price": 0
        }]
    }]

    result = load_video(props)

    if video_exists and not is_published:
        mock_upsert_tasks.delete_video.assert_called_with(result)
    elif is_published:
        mock_upsert_tasks.upsert_video.assert_called_with(result.id)
    else:
        mock_upsert_tasks.delete_video.assert_not_called()
        mock_upsert_tasks.upsert_video.assert_not_called()

    assert Video.objects.count() == 1

    # assert we got a course back
    assert isinstance(result, Video)

    # verify a free price
    assert result.runs.count() == 1
    assert result.runs.first().prices.count() == 1
    assert result.runs.first().prices.first().price == 0

    for key, value in props.items():
        assert getattr(result,
                       key) == value, f"Property {key} should equal {value}"
예제 #9
0
def test_load_video_channels_unpublish(mock_upsert_tasks):
    """Test load_video_channels when a video/playlist gets unpublished"""
    channel = VideoChannelFactory.create()
    playlist = PlaylistFactory.create(channel=channel, published=True)
    video = VideoFactory.create()
    PlaylistVideo.objects.create(playlist=playlist, video=video, position=0)
    unpublished_playlist = PlaylistFactory.create(channel=channel,
                                                  published=False)
    unpublished_video = VideoFactory.create()
    PlaylistVideo.objects.create(playlist=unpublished_playlist,
                                 video=unpublished_video,
                                 position=0)

    # inputs don't matter here
    load_video_channels([])

    video.refresh_from_db()
    unpublished_video.refresh_from_db()
    assert video.published is True
    assert unpublished_video.published is False

    mock_upsert_tasks.delete_video.assert_called_once_with(unpublished_video)
예제 #10
0
def test_extract_topics(settings, mocker):
    """Tests that extract_topics looks up similar topics given a video"""
    video = VideoFactory.create()
    topics = ["topic a", "topic b"]
    mock_get_similar_topics = mocker.patch(
        "course_catalog.etl.video.get_similar_topics", return_value=topics)

    assert extract_topics(video) == [{"name": topic} for topic in topics]

    mock_get_similar_topics.assert_called_once_with(
        {
            "title": video.title,
            "short_description": video.short_description
        },
        settings.OPEN_VIDEO_MAX_TOPICS,
        settings.OPEN_VIDEO_MIN_TERM_FREQ,
        settings.OPEN_VIDEO_MIN_DOC_FREQ,
    )
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
        ],
    )
예제 #12
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),
    }
예제 #13
0
def test_load_videos():
    """Verify that load_videos loads a list of videos"""
    assert Video.objects.count() == 0

    videos_records = VideoFactory.build_batch(5, published=True)
    videos_data = [model_to_dict(video) for video in videos_records]

    for video_data in videos_data:
        video_data["runs"] = [{
            "run_id": video_data["video_id"],
            "platform": video_data["platform"],
            "prices": [{
                "price": 0
            }],
        }]

    results = load_videos(videos_data)

    assert len(results) == len(videos_records)

    assert Video.objects.count() == len(videos_records)
예제 #14
0
def test_get_youtube_videos_for_transcripts_job(overwrite, created_after,
                                                created_minutes):
    """Verify that get_youtube_videos_for_transcripts_job applies filters correctly"""

    video1 = VideoFactory.create(transcript="saved already")
    video2 = VideoFactory.create(transcript="")
    video3 = VideoFactory.create(transcript="saved already")
    video3.created_on = datetime(2019, 10, 1, tzinfo=pytz.utc)
    video3.save()
    video4 = VideoFactory.create(transcript="")
    video4.created_on = datetime(2019, 10, 1, tzinfo=pytz.utc)
    video4.save()
    video5 = VideoFactory.create(transcript="saved already")
    video5.created_on = datetime(2019, 10, 5, tzinfo=pytz.utc)
    video5.save()
    video6 = VideoFactory.create(transcript="")
    video6.created_on = datetime(2019, 10, 5, tzinfo=pytz.utc)
    video6.save()

    result = youtube.get_youtube_videos_for_transcripts_job(
        created_after=created_after,
        created_minutes=created_minutes,
        overwrite=overwrite,
    )

    if overwrite:
        if created_after:
            assert list(
                result.order_by("id")) == [video1, video2, video5, video6]
        elif created_minutes:
            assert list(result.order_by("id")) == [video1, video2]
        else:
            assert list(result.order_by("id")) == [
                video1,
                video2,
                video3,
                video4,
                video5,
                video6,
            ]
    else:
        if created_after:
            assert list(result.order_by("id")) == [video2, video6]
        elif created_minutes:
            assert list(result.order_by("id")) == [video2]
        else:
            assert list(result.order_by("id")) == [video2, video4, video6]
예제 #15
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()