Skip to content
Snippets Groups Projects
test_radios.py 6.06 KiB
Newer Older
  • Learn to ignore specific revisions
  • import json
    import random
    import pytest
    
    from django.urls import reverse
    from django.core.exceptions import ValidationError
    
    
    from funkwhale_api.radios import radios
    from funkwhale_api.radios import models
    from funkwhale_api.favorites.models import TrackFavorite
    
    
    def test_can_pick_track_from_choices():
        choices = [1, 2, 3, 4, 5]
    
        radio = radios.SimpleRadio()
    
        first_pick = radio.pick(choices=choices)
    
        assert first_pick in choices
    
        previous_choices = [first_pick]
        for remaining_choice in choices:
            pick = radio.pick(choices=choices, previous_choices=previous_choices)
            assert pick in set(choices).difference(previous_choices)
    
    
    def test_can_pick_by_weight():
        choices_with_weight = [
            # choice, weight
            (1, 1),
            (2, 2),
            (3, 3),
            (4, 4),
            (5, 5),
        ]
    
        picks = {choice: 0 for choice, weight in choices_with_weight}
    
        for i in range(1000):
            radio = radios.SimpleRadio()
            pick = radio.weighted_pick(choices=choices_with_weight)
            picks[pick] = picks[pick] + 1
    
        assert picks[5] > picks[4]
        assert picks[4] > picks[3]
        assert picks[3] > picks[2]
        assert picks[2] > picks[1]
    
    
    def test_can_get_choices_for_favorites_radio(factories):
        tracks = factories['music.Track'].create_batch(100)
        user = factories['users.User']()
        for i in range(20):
            TrackFavorite.add(track=random.choice(tracks), user=user)
    
        radio = radios.FavoritesRadio()
        choices = radio.get_choices(user=user)
    
        assert choices.count() == user.track_favorites.all().count()
    
        for favorite in user.track_favorites.all():
            assert favorite.track in choices
    
        for i in range(20):
            pick = radio.pick(user=user)
            assert pick in choices
    
    
    def test_can_use_radio_session_to_filter_choices(factories):
        tracks = factories['music.Track'].create_batch(30)
        user = factories['users.User']()
        radio = radios.RandomRadio()
        session = radio.start_session(user)
    
        for i in range(30):
            p = radio.pick()
    
        # ensure 30 differents tracks have been suggested
        tracks_id = [
            session_track.track.pk
            for session_track in session.session_tracks.all()]
        assert len(set(tracks_id)) == 30
    
    
    def test_can_restore_radio_from_previous_session(factories):
        user = factories['users.User']()
        radio = radios.RandomRadio()
        session = radio.start_session(user)
    
        restarted_radio = radios.RandomRadio(session)
        assert radio.session == restarted_radio.session
    
    
    def test_can_start_radio_for_logged_in_user(logged_in_client):
        url = reverse('api:v1:radios:sessions-list')
        response = logged_in_client.post(url, {'radio_type': 'random'})
        session = models.RadioSession.objects.latest('id')
        assert session.radio_type == 'random'
        assert session.user == logged_in_client.user
    
    
    def test_can_start_radio_for_anonymous_user(client, db):
        url = reverse('api:v1:radios:sessions-list')
        response = client.post(url, {'radio_type': 'random'})
        session = models.RadioSession.objects.latest('id')
    
        assert session.radio_type == 'random'
        assert session.user is None
        assert session.session_key == client.session.session_key
    
    
    def test_can_get_track_for_session_from_api(factories, logged_in_client):
        tracks = factories['music.Track'].create_batch(size=1)
    
        url = reverse('api:v1:radios:sessions-list')
        response = logged_in_client.post(url, {'radio_type': 'random'})
        session = models.RadioSession.objects.latest('id')
    
        url = reverse('api:v1:radios:tracks-list')
        response = logged_in_client.post(url, {'session': session.pk})
        data = json.loads(response.content.decode('utf-8'))
    
        assert data['track']['id'] == tracks[0].id
        assert data['position'] == 1
    
        next_track = factories['music.Track']()
        response = logged_in_client.post(url, {'session': session.pk})
        data = json.loads(response.content.decode('utf-8'))
    
        assert data['track']['id'] == next_track.id
        assert data['position'] == 2
    
    
    def test_related_object_radio_validate_related_object(factories):
        user = factories['users.User']()
        # cannot start without related object
        radio = radios.ArtistRadio()
        with pytest.raises(ValidationError):
            radio.start_session(user)
    
        # cannot start with bad related object type
        radio = radios.ArtistRadio()
        with pytest.raises(ValidationError):
            radio.start_session(user, related_object=user)
    
    
    def test_can_start_artist_radio(factories):
        user = factories['users.User']()
        artist = factories['music.Artist']()
        wrong_tracks = factories['music.Track'].create_batch(5)
        good_tracks = factories['music.Track'].create_batch(5, artist=artist)
    
        radio = radios.ArtistRadio()
        session = radio.start_session(user, related_object=artist)
        assert session.radio_type == 'artist'
        for i in range(5):
            assert radio.pick() in good_tracks
    
    
    def test_can_start_tag_radio(factories):
        user = factories['users.User']()
        tag = factories['taggit.Tag']()
        wrong_tracks = factories['music.Track'].create_batch(5)
        good_tracks = factories['music.Track'].create_batch(5, tags=[tag])
    
        radio = radios.TagRadio()
        session = radio.start_session(user, related_object=tag)
        assert session.radio_type =='tag'
        for i in range(5):
            assert radio.pick() in good_tracks
    
    
    def test_can_start_artist_radio_from_api(client, factories):
        artist = factories['music.Artist']()
        url = reverse('api:v1:radios:sessions-list')
    
        response = client.post(
            url, {'radio_type': 'artist', 'related_object_id': artist.id})
        session = models.RadioSession.objects.latest('id')
        assert session.radio_type, 'artist'
        assert session.related_object, artist
    
    
    def test_can_start_less_listened_radio(factories):
        user = factories['users.User']()
        history = factories['history.Listening'].create_batch(5, user=user)
        wrong_tracks = [h.track for h in history]
        good_tracks = factories['music.Track'].create_batch(size=5)
        radio = radios.LessListenedRadio()
        session = radio.start_session(user)
        assert session.related_object == user
        for i in range(5):
            assert radio.pick() in good_tracks