def test_can_fetch_data_from_api(api_client, factories): url = reverse("api:v1:users:users-me") response = api_client.get(url) # login required assert response.status_code == 401 user = factories["users.User"](permission_library=True, with_actor=True) summary = {"content_type": "text/plain", "text": "Hello"} summary_obj = common_utils.attach_content(user.actor, "summary_obj", summary) avatar = factories["common.Attachment"]() user.actor.attachment_icon = avatar user.actor.save() api_client.login(username=user.username, password="******") response = api_client.get(url) assert response.status_code == 200 assert response.data["username"] == user.username assert response.data["is_staff"] == user.is_staff assert response.data["is_superuser"] == user.is_superuser assert response.data["email"] == user.email assert response.data["name"] == user.name assert response.data["permissions"] == user.get_permissions() assert ( response.data["avatar"] == common_serializers.AttachmentSerializer(avatar).data ) assert ( response.data["summary"] == common_serializers.ContentSerializer(summary_obj).data )
class UserReadSerializer(serializers.ModelSerializer): permissions = serializers.SerializerMethodField() full_username = serializers.SerializerMethodField() avatar = common_serializers.AttachmentSerializer(source="get_avatar") class Meta: model = models.User fields = [ "id", "username", "full_username", "name", "email", "is_staff", "is_superuser", "permissions", "date_joined", "privacy_level", "avatar", ] def get_permissions(self, o): return o.get_permissions() def get_full_username(self, o): if o.actor: return o.actor.full_username
def test_api_full_actor_serializer(factories, to_api_date): summary = factories["common.Content"]() icon = factories["common.Attachment"]() user = factories["users.User"]() actor = user.create_actor(summary_obj=summary, attachment_icon=icon) expected = { "fid": actor.fid, "url": actor.url, "creation_date": to_api_date(actor.creation_date), "last_fetch_date": to_api_date(actor.last_fetch_date), "user": users_serializers.UserBasicSerializer(user).data, "is_channel": False, "domain": actor.domain_id, "type": actor.type, "manually_approves_followers": actor.manually_approves_followers, "full_username": actor.full_username, "name": actor.name, "preferred_username": actor.preferred_username, "is_local": actor.is_local, "summary": common_serializers.ContentSerializer(summary).data, "icon": common_serializers.AttachmentSerializer(icon).data, } serializer = api_serializers.FullActorSerializer(actor) assert serializer.data == expected
def test_attachment_serializer_remote_file(factories, to_api_date): attachment = factories["common.Attachment"](file=None) proxy_url = reverse("api:v1:attachments-proxy", kwargs={"uuid": attachment.uuid}) expected = { "uuid": str(attachment.uuid), "size": attachment.size, "mimetype": attachment.mimetype, "creation_date": to_api_date(attachment.creation_date), # everything is the same, except for the urls field because: # - the file isn't available on the local pod # - we need to return different URLs so that the client can trigger # a fetch and get redirected to the desired version # "urls": { "source": attachment.url, "original": federation_utils.full_url(proxy_url + "?next=original"), "medium_square_crop": federation_utils.full_url( proxy_url + "?next=medium_square_crop" ), "large_square_crop": federation_utils.full_url( proxy_url + "?next=large_square_crop" ), }, } serializer = serializers.AttachmentSerializer(attachment) assert serializer.data == expected
def test_album_serializer(factories, to_api_date): actor = factories["federation.Actor"]() track1 = factories["music.Track"](position=2, album__attributed_to=actor, album__with_cover=True) factories["music.Track"](position=1, album=track1.album) album = track1.album expected = { "id": album.id, "fid": album.fid, "mbid": str(album.mbid), "title": album.title, "artist": serializers.serialize_artist_simple(album.artist), "creation_date": to_api_date(album.creation_date), "is_playable": False, "cover": common_serializers.AttachmentSerializer(album.attachment_cover).data, "release_date": to_api_date(album.release_date), "tracks_count": 2, "is_local": album.is_local, "tags": [], "attributed_to": federation_serializers.APIActorSerializer(actor).data, } serializer = serializers.AlbumSerializer( album.__class__.objects.with_tracks_count().get(pk=album.pk)) assert serializer.data == expected
def test_attachment_serializer_existing_file(factories, to_api_date): attachment = factories["common.Attachment"]() expected = { "uuid": str(attachment.uuid), "size": attachment.size, "mimetype": attachment.mimetype, "creation_date": to_api_date(attachment.creation_date), "urls": { "source": attachment.url, "original": federation_utils.full_url(attachment.file.url), "medium_square_crop": federation_utils.full_url(attachment.file.crop["200x200"].url), }, # XXX: BACKWARD COMPATIBILITY "original": federation_utils.full_url(attachment.file.url), "medium_square_crop": federation_utils.full_url(attachment.file.crop["200x200"].url), "small_square_crop": federation_utils.full_url(attachment.file.crop["200x200"].url), "square_crop": federation_utils.full_url(attachment.file.crop["200x200"].url), } serializer = serializers.AttachmentSerializer(attachment) assert serializer.data == expected
def test_artist_with_albums_serializer_channel(factories, to_api_date): actor = factories["federation.Actor"]() channel = factories["audio.Channel"](attributed_to=actor, artist__with_cover=True) track = factories["music.Track"](album__artist=channel.artist) artist = track.artist artist = artist.__class__.objects.with_albums().get(pk=artist.pk) album = list(artist.albums.all())[0] setattr(artist, "_prefetched_tracks", range(42)) expected = { "id": artist.id, "fid": artist.fid, "mbid": str(artist.mbid), "name": artist.name, "is_local": artist.is_local, "content_category": artist.content_category, "creation_date": to_api_date(artist.creation_date), "albums": [serializers.ArtistAlbumSerializer(album).data], "tags": [], "attributed_to": federation_serializers.APIActorSerializer(actor).data, "tracks_count": 42, "cover": common_serializers.AttachmentSerializer(artist.attachment_cover).data, "channel": { "uuid": str(channel.uuid), "actor": { "full_username": channel.actor.full_username, "preferred_username": channel.actor.preferred_username, "domain": channel.actor.domain_id, }, }, } serializer = serializers.ArtistWithAlbumsSerializer(artist) assert serializer.data == expected
def test_track_serializer(factories, to_api_date): actor = factories["federation.Actor"]() upload = factories["music.Upload"]( track__license="cc-by-4.0", track__copyright="test", track__disc_number=2, track__attributed_to=actor, track__with_cover=True, ) track = upload.track setattr(track, "playable_uploads", [upload]) expected = { "id": track.id, "fid": track.fid, "artist": serializers.serialize_artist_simple(track.artist), "album": serializers.TrackAlbumSerializer(track.album).data, "mbid": str(track.mbid), "title": track.title, "position": track.position, "disc_number": track.disc_number, "uploads": [serializers.serialize_upload(upload)], "creation_date": to_api_date(track.creation_date), "listen_url": track.listen_url, "license": upload.track.license.code, "copyright": upload.track.copyright, "is_local": upload.track.is_local, "tags": [], "attributed_to": federation_serializers.APIActorSerializer(actor).data, "cover": common_serializers.AttachmentSerializer(track.attachment_cover).data, "downloads_count": track.downloads_count, } serializer = serializers.TrackSerializer(track) assert serializer.data == expected
def test_manage_album_serializer(factories, now, to_api_date): album = factories["music.Album"](attributed=True, with_cover=True) factories["music.Track"](album=album) setattr(album, "_tracks_count", 42) expected = { "id": album.id, "domain": album.domain_name, "is_local": album.is_local, "fid": album.fid, "title": album.title, "mbid": album.mbid, "creation_date": to_api_date(album.creation_date), "release_date": album.release_date.isoformat(), "cover": common_serializers.AttachmentSerializer(album.attachment_cover).data, "artist": serializers.ManageNestedArtistSerializer(album.artist).data, "attributed_to": serializers.ManageBaseActorSerializer(album.attributed_to).data, "tags": [], "tracks_count": 1, } s = serializers.ManageAlbumSerializer(album) assert s.data == expected
def test_manage_nested_album_serializer(factories, now, to_api_date): album = factories["music.Album"](with_cover=True) setattr(album, "tracks_count", 44) expected = { "id": album.id, "domain": album.domain_name, "is_local": album.is_local, "fid": album.fid, "title": album.title, "mbid": album.mbid, "creation_date": to_api_date(album.creation_date), "release_date": album.release_date.isoformat(), "cover": common_serializers.AttachmentSerializer(album.attachment_cover).data, "tracks_count": 44, } s = serializers.ManageNestedAlbumSerializer(album) assert s.data == expected
def test_manage_track_serializer(factories, now, to_api_date): track = factories["music.Track"](attributed=True, with_cover=True) setattr(track, "uploads_count", 44) expected = { "id": track.id, "domain": track.domain_name, "is_local": track.is_local, "fid": track.fid, "title": track.title, "mbid": track.mbid, "disc_number": track.disc_number, "position": track.position, "copyright": track.copyright, "license": track.license, "creation_date": to_api_date(track.creation_date), "artist": serializers.ManageNestedArtistSerializer(track.artist).data, "album": serializers.ManageTrackAlbumSerializer(track.album).data, "attributed_to": serializers.ManageBaseActorSerializer(track.attributed_to).data, "uploads_count": 44, "tags": [], "cover": common_serializers.AttachmentSerializer(track.attachment_cover).data, } s = serializers.ManageTrackSerializer(track) assert s.data == expected
def test_artist_album_serializer(factories, to_api_date): track = factories["music.Track"](album__with_cover=True) album = track.album album = album.__class__.objects.with_tracks_count().get(pk=album.pk) expected = { "id": album.id, "fid": album.fid, "mbid": str(album.mbid), "title": album.title, "artist": album.artist.id, "creation_date": to_api_date(album.creation_date), "tracks_count": 1, "is_playable": None, "cover": common_serializers.AttachmentSerializer(album.attachment_cover).data, "release_date": to_api_date(album.release_date), "is_local": album.is_local, } serializer = serializers.ArtistAlbumSerializer(album) assert serializer.data == expected
def test_attachment_proxy_redirects_original( next, expected, factories, logged_in_api_client, mocker, avatar, r_mock, now ): attachment = factories["common.Attachment"](file=None) avatar_content = avatar.read() fetch_remote_attachment = mocker.spy(tasks, "fetch_remote_attachment") m = r_mock.get(attachment.url, body=io.BytesIO(avatar_content)) proxy_url = reverse("api:v1:attachments-proxy", kwargs={"uuid": attachment.uuid}) response = logged_in_api_client.get(proxy_url, {"next": next}) attachment.refresh_from_db() urls = serializers.AttachmentSerializer(attachment).data["urls"] assert attachment.file.read() == avatar_content assert attachment.last_fetch_date == now fetch_remote_attachment.assert_called_once_with(attachment) assert len(m.request_history) == 1 assert response.status_code == 302 assert response["Location"] == urls[expected]
def test_manage_artist_serializer(factories, now, to_api_date): artist = factories["music.Artist"](attributed=True, with_cover=True) channel = factories["audio.Channel"](artist=artist) # put channel in cache artist.get_channel() setattr(artist, "_tracks_count", 12) setattr(artist, "_albums_count", 13) expected = { "id": artist.id, "domain": artist.domain_name, "is_local": artist.is_local, "fid": artist.fid, "name": artist.name, "mbid": artist.mbid, "creation_date": to_api_date(artist.creation_date), "tracks_count": 12, "albums_count": 13, "attributed_to": serializers.ManageBaseActorSerializer(artist.attributed_to).data, "tags": [], "channel": str(channel.uuid), "content_category": artist.content_category, "cover": common_serializers.AttachmentSerializer(artist.attachment_cover).data, } s = serializers.ManageArtistSerializer(artist) assert s.data == expected
class FullActorSerializer(serializers.Serializer): fid = serializers.URLField() url = serializers.URLField() domain = serializers.CharField(source="domain_id") creation_date = serializers.DateTimeField() last_fetch_date = serializers.DateTimeField() name = serializers.CharField() preferred_username = serializers.CharField() full_username = serializers.CharField() type = serializers.CharField() is_local = serializers.BooleanField() is_channel = serializers.SerializerMethodField() manually_approves_followers = serializers.BooleanField() user = users_serializers.UserBasicSerializer() summary = common_serializers.ContentSerializer(source="summary_obj") icon = common_serializers.AttachmentSerializer(source="attachment_icon") def get_is_channel(self, o): try: return bool(o.channel) except ObjectDoesNotExist: return False
def to_representation(self, instance): r = super().to_representation(instance) r["avatar"] = common_serializers.AttachmentSerializer( instance.get_avatar()).data return r
class UserBasicSerializer(serializers.ModelSerializer): avatar = common_serializers.AttachmentSerializer(source="get_avatar") class Meta: model = models.User fields = ["id", "username", "name", "date_joined", "avatar"]