Resolve "Hide an artist in the UI"

This commit is contained in:
Eliot Berriot 2019-02-14 10:49:06 +01:00
parent d4d4e60e39
commit bdf83bd8ff
50 changed files with 1051 additions and 49 deletions

View file

@ -0,0 +1,30 @@
from funkwhale_api.favorites import filters
from funkwhale_api.favorites import models
def test_track_favorite_filter_track_artist(factories, mocker, queryset_equal_list):
factories["favorites.TrackFavorite"]()
cf = factories["moderation.UserFilter"](for_artist=True)
hidden_fav = factories["favorites.TrackFavorite"](track__artist=cf.target_artist)
qs = models.TrackFavorite.objects.all()
filterset = filters.TrackFavoriteFilter(
{"hidden": "true"}, request=mocker.Mock(user=cf.user), queryset=qs
)
assert filterset.qs == [hidden_fav]
def test_track_favorite_filter_track_album_artist(
factories, mocker, queryset_equal_list
):
factories["favorites.TrackFavorite"]()
cf = factories["moderation.UserFilter"](for_artist=True)
hidden_fav = factories["favorites.TrackFavorite"](
track__album__artist=cf.target_artist
)
qs = models.TrackFavorite.objects.all()
filterset = filters.TrackFavoriteFilter(
{"hidden": "true"}, request=mocker.Mock(user=cf.user), queryset=qs
)
assert filterset.qs == [hidden_fav]

View file

@ -0,0 +1,28 @@
from funkwhale_api.history import filters
from funkwhale_api.history import models
def test_listening_filter_track_artist(factories, mocker, queryset_equal_list):
factories["history.Listening"]()
cf = factories["moderation.UserFilter"](for_artist=True)
hidden_listening = factories["history.Listening"](track__artist=cf.target_artist)
qs = models.Listening.objects.all()
filterset = filters.ListeningFilter(
{"hidden": "true"}, request=mocker.Mock(user=cf.user), queryset=qs
)
assert filterset.qs == [hidden_listening]
def test_listening_filter_track_album_artist(factories, mocker, queryset_equal_list):
factories["history.Listening"]()
cf = factories["moderation.UserFilter"](for_artist=True)
hidden_listening = factories["history.Listening"](
track__album__artist=cf.target_artist
)
qs = models.Listening.objects.all()
filterset = filters.ListeningFilter(
{"hidden": "true"}, request=mocker.Mock(user=cf.user), queryset=qs
)
assert filterset.qs == [hidden_listening]

View file

View file

@ -0,0 +1,68 @@
from funkwhale_api.moderation import filters
from funkwhale_api.music import models as music_models
def test_hidden_defaults_to_true(factories, queryset_equal_list, mocker):
user = factories["users.User"]()
artist = factories["music.Artist"]()
hidden_artist = factories["music.Artist"]()
factories["moderation.UserFilter"](target_artist=hidden_artist, user=user)
class FS(filters.HiddenContentFilterSet):
class Meta:
hidden_content_fields_mapping = {"target_artist": ["pk"]}
filterset = FS(
data={},
queryset=music_models.Artist.objects.all(),
request=mocker.Mock(user=user),
)
assert filterset.data["hidden"] is False
queryset = filterset.filter_hidden_content(
music_models.Artist.objects.all(), "", False
)
assert queryset == [artist]
def test_hidden_false(factories, queryset_equal_list, mocker):
user = factories["users.User"]()
factories["music.Artist"]()
hidden_artist = factories["music.Artist"]()
factories["moderation.UserFilter"](target_artist=hidden_artist, user=user)
class FS(filters.HiddenContentFilterSet):
class Meta:
hidden_content_fields_mapping = {"target_artist": ["pk"]}
filterset = FS(
data={},
queryset=music_models.Artist.objects.all(),
request=mocker.Mock(user=user),
)
queryset = filterset.filter_hidden_content(
music_models.Artist.objects.all(), "", True
)
assert queryset == [hidden_artist]
def test_hidden_anonymous(factories, queryset_equal_list, mocker, anonymous_user):
artist = factories["music.Artist"]()
class FS(filters.HiddenContentFilterSet):
class Meta:
hidden_content_fields_mapping = {"target_artist": ["pk"]}
filterset = FS(
data={},
queryset=music_models.Artist.objects.all(),
request=mocker.Mock(user=anonymous_user),
)
queryset = filterset.filter_hidden_content(
music_models.Artist.objects.all(), "", True
)
assert queryset == [artist]

View file

@ -0,0 +1,30 @@
from funkwhale_api.moderation import serializers
def test_user_filter_serializer_repr(factories):
artist = factories["music.Artist"]()
content_filter = factories["moderation.UserFilter"](target_artist=artist)
expected = {
"uuid": str(content_filter.uuid),
"target": {"type": "artist", "id": artist.pk, "name": artist.name},
"creation_date": content_filter.creation_date.isoformat().replace(
"+00:00", "Z"
),
}
serializer = serializers.UserFilterSerializer(content_filter)
assert serializer.data == expected
def test_user_filter_serializer_save(factories):
artist = factories["music.Artist"]()
user = factories["users.User"]()
data = {"target": {"type": "artist", "id": artist.pk}}
serializer = serializers.UserFilterSerializer(data=data)
serializer.is_valid(raise_exception=True)
content_filter = serializer.save(user=user)
assert content_filter.target_artist == artist

View file

@ -0,0 +1,24 @@
from django.urls import reverse
def test_restrict_to_own_filters(factories, logged_in_api_client):
cf = factories["moderation.UserFilter"](
for_artist=True, user=logged_in_api_client.user
)
factories["moderation.UserFilter"](for_artist=True)
url = reverse("api:v1:moderation:content-filters-list")
response = logged_in_api_client.get(url)
assert response.status_code == 200
assert response.data["count"] == 1
assert response.data["results"][0]["uuid"] == str(cf.uuid)
def test_create_filter(factories, logged_in_api_client):
artist = factories["music.Artist"]()
url = reverse("api:v1:moderation:content-filters-list")
data = {"target": {"type": "artist", "id": artist.pk}}
response = logged_in_api_client.post(url, data, format="json")
cf = logged_in_api_client.user.content_filters.latest("id")
assert cf.target_artist == artist
assert response.status_code == 201

View file

@ -0,0 +1,54 @@
from funkwhale_api.music import filters
from funkwhale_api.music import models
def test_album_filter_hidden(factories, mocker, queryset_equal_list):
factories["music.Album"]()
cf = factories["moderation.UserFilter"](for_artist=True)
hidden_album = factories["music.Album"](artist=cf.target_artist)
qs = models.Album.objects.all()
filterset = filters.AlbumFilter(
{"hidden": "true"}, request=mocker.Mock(user=cf.user), queryset=qs
)
assert filterset.qs == [hidden_album]
def test_artist_filter_hidden(factories, mocker, queryset_equal_list):
factories["music.Artist"]()
cf = factories["moderation.UserFilter"](for_artist=True)
hidden_artist = cf.target_artist
qs = models.Artist.objects.all()
filterset = filters.ArtistFilter(
{"hidden": "true"}, request=mocker.Mock(user=cf.user), queryset=qs
)
assert filterset.qs == [hidden_artist]
def test_artist_filter_track_artist(factories, mocker, queryset_equal_list):
factories["music.Track"]()
cf = factories["moderation.UserFilter"](for_artist=True)
hidden_track = factories["music.Track"](artist=cf.target_artist)
qs = models.Track.objects.all()
filterset = filters.TrackFilter(
{"hidden": "true"}, request=mocker.Mock(user=cf.user), queryset=qs
)
assert filterset.qs == [hidden_track]
def test_artist_filter_track_album_artist(factories, mocker, queryset_equal_list):
factories["music.Track"]()
cf = factories["moderation.UserFilter"](for_artist=True)
hidden_track = factories["music.Track"](album__artist=cf.target_artist)
qs = models.Track.objects.all()
filterset = filters.TrackFilter(
{"hidden": "true"}, request=mocker.Mock(user=cf.user), queryset=qs
)
assert filterset.qs == [hidden_track]

View file

@ -254,3 +254,27 @@ def test_similar_radio_track(factories):
factories["history.Listening"](track=expected_next, user=l1.user)
assert radio.pick(filter_playable=False) == expected_next
def test_session_radio_get_queryset_ignore_filtered_track_artist(
factories, queryset_equal_list
):
cf = factories["moderation.UserFilter"](for_artist=True)
factories["music.Track"](artist=cf.target_artist)
valid_track = factories["music.Track"]()
radio = radios.RandomRadio()
radio.start_session(user=cf.user)
assert radio.get_queryset() == [valid_track]
def test_session_radio_get_queryset_ignore_filtered_track_album_artist(
factories, queryset_equal_list
):
cf = factories["moderation.UserFilter"](for_artist=True)
factories["music.Track"](album__artist=cf.target_artist)
valid_track = factories["music.Track"]()
radio = radios.RandomRadio()
radio.start_session(user=cf.user)
assert radio.get_queryset() == [valid_track]

View file

@ -7,6 +7,7 @@ from django.utils import timezone
from rest_framework.response import Response
import funkwhale_api
from funkwhale_api.moderation import filters as moderation_filters
from funkwhale_api.music import models as music_models
from funkwhale_api.music import views as music_views
from funkwhale_api.subsonic import renderers, serializers
@ -100,20 +101,31 @@ def test_ping(f, db, api_client):
def test_get_artists(
f, db, logged_in_api_client, factories, mocker, queryset_equal_queries
):
factories["moderation.UserFilter"](
user=logged_in_api_client.user,
target_artist=factories["music.Artist"](playable=True),
)
url = reverse("api:subsonic-get_artists")
assert url.endswith("getArtists") is True
factories["music.Artist"].create_batch(size=3, playable=True)
playable_by = mocker.spy(music_models.ArtistQuerySet, "playable_by")
exclude_query = moderation_filters.get_filtered_content_query(
moderation_filters.USER_FILTER_CONFIG["ARTIST"], logged_in_api_client.user
)
assert exclude_query is not None
expected = {
"artists": serializers.GetArtistsSerializer(
music_models.Artist.objects.all()
music_models.Artist.objects.all().exclude(exclude_query)
).data
}
response = logged_in_api_client.get(url, {"f": f})
assert response.status_code == 200
assert response.data == expected
playable_by.assert_called_once_with(music_models.Artist.objects.all(), None)
playable_by.assert_called_once_with(
music_models.Artist.objects.all().exclude(exclude_query),
logged_in_api_client.user.actor,
)
@pytest.mark.parametrize("f", ["json"])
@ -502,12 +514,20 @@ def test_get_music_folders(f, db, logged_in_api_client, factories):
def test_get_indexes(
f, db, logged_in_api_client, factories, mocker, queryset_equal_queries
):
factories["moderation.UserFilter"](
user=logged_in_api_client.user,
target_artist=factories["music.Artist"](playable=True),
)
exclude_query = moderation_filters.get_filtered_content_query(
moderation_filters.USER_FILTER_CONFIG["ARTIST"], logged_in_api_client.user
)
url = reverse("api:subsonic-get_indexes")
assert url.endswith("getIndexes") is True
factories["music.Artist"].create_batch(size=3, playable=True)
expected = {
"indexes": serializers.GetArtistsSerializer(
music_models.Artist.objects.all()
music_models.Artist.objects.all().exclude(exclude_query)
).data
}
playable_by = mocker.spy(music_models.ArtistQuerySet, "playable_by")
@ -516,7 +536,10 @@ def test_get_indexes(
assert response.status_code == 200
assert response.data == expected
playable_by.assert_called_once_with(music_models.Artist.objects.all(), None)
playable_by.assert_called_once_with(
music_models.Artist.objects.all().exclude(exclude_query),
logged_in_api_client.user.actor,
)
def test_get_cover_art_album(factories, logged_in_api_client):