Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
interfect
funkwhale
Commits
c8a2ae42
Verified
Commit
c8a2ae42
authored
Dec 26, 2017
by
Eliot Berriot
Browse files
Merge branch 'release/0.3'
parents
86c607de
7bbb7387
Changes
120
Hide whitespace changes
Inline
Side-by-side
CHANGELOG
View file @
c8a2ae42
...
...
@@ -5,6 +5,26 @@ Changelog
0.2.7 (Unreleased)
------------------
- Shortcuts: can now use the ``f`` shortcut to toggle the currently playing track
as a favorite (#53)
- Shortcuts: avoid collisions between shortcuts by using the exact modifier (#53)
- Player: Added looping controls and shortcuts (#52)
- Player: Added shuffling controls and shortcuts (#52)
- Favorites: can now modify the ordering of track list (#50)
- Library: can now search/reorder results on artist browsing view (#50)
- Upgraded celery to 4.1, added endpoint logic for fingerprinting audio files
- Fixed #56: invalidate tokens on password change, also added change password form
- Fixed #57: now refresh jwt token on page refresh
- removed ugly dividers in batch import list
- Fixed a few padding issues
- Now persist/restore queue/radio/player state automatically
- Removed old broken imports
- Now force tests paths
- Fixed #54: Now use pytest everywhere \o/
- Now use vuex to manage state for favorites
- Now use vuex to manage state for authentication
- Now use vuex to manage state for player/queue/radios
0.2.6 (2017-12-15)
------------------
...
...
api/config/api_urls.py
View file @
c8a2ae42
...
...
@@ -46,9 +46,8 @@ v1_patterns += [
include
(
(
'funkwhale_api.users.api_urls'
,
'users'
),
namespace
=
'users'
)),
url
(
r
'^token/'
,
jwt_views
.
obtain_jwt_token
),
url
(
r
'^token/refresh/'
,
jwt_views
.
refresh_jwt_token
),
url
(
r
'^token/$'
,
jwt_views
.
obtain_jwt_token
,
name
=
'token'
),
url
(
r
'^token/refresh/$'
,
jwt_views
.
refresh_jwt_token
,
name
=
'token_refresh'
),
]
urlpatterns
=
[
...
...
api/config/settings/common.py
View file @
c8a2ae42
...
...
@@ -280,8 +280,9 @@ JWT_AUTH = {
'JWT_EXPIRATION_DELTA'
:
datetime
.
timedelta
(
days
=
7
),
'JWT_REFRESH_EXPIRATION_DELTA'
:
datetime
.
timedelta
(
days
=
30
),
'JWT_AUTH_HEADER_PREFIX'
:
'JWT'
,
'JWT_GET_USER_SECRET_KEY'
:
lambda
user
:
user
.
secret_key
}
OLD_PASSWORD_FIELD_ENABLED
=
True
ACCOUNT_ADAPTER
=
'funkwhale_api.users.adapters.FunkwhaleAccountAdapter'
CORS_ORIGIN_ALLOW_ALL
=
True
# CORS_ORIGIN_WHITELIST = (
...
...
api/config/urls.py
View file @
c8a2ae42
...
...
@@ -31,3 +31,9 @@ if settings.DEBUG:
url
(
r
'^404/$'
,
default_views
.
page_not_found
),
url
(
r
'^500/$'
,
default_views
.
server_error
),
]
+
static
(
settings
.
MEDIA_URL
,
document_root
=
settings
.
MEDIA_ROOT
)
if
'debug_toolbar'
in
settings
.
INSTALLED_APPS
:
import
debug_toolbar
urlpatterns
+=
[
url
(
r
'^__debug__/'
,
include
(
debug_toolbar
.
urls
)),
]
api/funkwhale_api/__init__.py
View file @
c8a2ae42
# -*- coding: utf-8 -*-
__version__
=
'0.
2.6
'
__version__
=
'0.
3
'
__version_info__
=
tuple
([
int
(
num
)
if
num
.
isdigit
()
else
num
for
num
in
__version__
.
replace
(
'-'
,
'.'
,
1
).
split
(
'.'
)])
api/funkwhale_api/common/tests/test_jwt_querystring.py
deleted
100644 → 0
View file @
86c607de
from
test_plus.test
import
TestCase
from
rest_framework_jwt.settings
import
api_settings
from
funkwhale_api.users.models
import
User
jwt_payload_handler
=
api_settings
.
JWT_PAYLOAD_HANDLER
jwt_encode_handler
=
api_settings
.
JWT_ENCODE_HANDLER
class
TestJWTQueryString
(
TestCase
):
www_authenticate_realm
=
'api'
def
test_can_authenticate_using_token_param_in_url
(
self
):
user
=
User
.
objects
.
create_superuser
(
username
=
'test'
,
email
=
'test@test.com'
,
password
=
'test'
)
url
=
self
.
reverse
(
'api:v1:tracks-list'
)
with
self
.
settings
(
API_AUTHENTICATION_REQUIRED
=
True
):
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
401
)
payload
=
jwt_payload_handler
(
user
)
token
=
jwt_encode_handler
(
payload
)
print
(
payload
,
token
)
with
self
.
settings
(
API_AUTHENTICATION_REQUIRED
=
True
):
response
=
self
.
client
.
get
(
url
,
data
=
{
'jwt'
:
token
})
self
.
assertEqual
(
response
.
status_code
,
200
)
api/funkwhale_api/downloader/tests/test_downloader.py
deleted
100644 → 0
View file @
86c607de
import
os
from
test_plus.test
import
TestCase
from
..
import
downloader
from
funkwhale_api.utils.tests
import
TMPDirTestCaseMixin
class
TestDownloader
(
TMPDirTestCaseMixin
,
TestCase
):
def
test_can_download_audio_from_youtube_url_to_vorbis
(
self
):
data
=
downloader
.
download
(
'https://www.youtube.com/watch?v=tPEE9ZwTmy0'
,
target_directory
=
self
.
download_dir
)
self
.
assertEqual
(
data
[
'audio_file_path'
],
os
.
path
.
join
(
self
.
download_dir
,
'tPEE9ZwTmy0.ogg'
))
self
.
assertTrue
(
os
.
path
.
exists
(
data
[
'audio_file_path'
]))
api/funkwhale_api/factories.py
0 → 100644
View file @
c8a2ae42
import
factory
import
persisting_theory
class
FactoriesRegistry
(
persisting_theory
.
Registry
):
look_into
=
'factories'
def
prepare_name
(
self
,
data
,
name
=
None
):
return
name
or
data
.
_meta
.
model
.
_meta
.
label
registry
=
FactoriesRegistry
()
def
ManyToManyFromList
(
field_name
):
"""
To automate the pattern described in
http://factoryboy.readthedocs.io/en/latest/recipes.html#simple-many-to-many-relationship
"""
@
factory
.
post_generation
def
inner
(
self
,
create
,
extracted
,
**
kwargs
):
if
not
create
:
return
if
extracted
:
field
=
getattr
(
self
,
field_name
)
field
.
add
(
*
extracted
)
return
inner
api/funkwhale_api/favorites/factories.py
0 → 100644
View file @
c8a2ae42
import
factory
from
funkwhale_api.factories
import
registry
from
funkwhale_api.music.factories
import
TrackFactory
from
funkwhale_api.users.factories
import
UserFactory
@
registry
.
register
class
TrackFavorite
(
factory
.
django
.
DjangoModelFactory
):
track
=
factory
.
SubFactory
(
TrackFactory
)
user
=
factory
.
SubFactory
(
UserFactory
)
class
Meta
:
model
=
'favorites.TrackFavorite'
api/funkwhale_api/favorites/tests/test_favorites.py
deleted
100644 → 0
View file @
86c607de
import
json
from
test_plus.test
import
TestCase
from
django.urls
import
reverse
from
funkwhale_api.music.models
import
Track
,
Artist
from
funkwhale_api.favorites.models
import
TrackFavorite
from
funkwhale_api.users.models
import
User
class
TestFavorites
(
TestCase
):
def
setUp
(
self
):
super
().
setUp
()
self
.
artist
=
Artist
.
objects
.
create
(
name
=
'test'
)
self
.
track
=
Track
.
objects
.
create
(
title
=
'test'
,
artist
=
self
.
artist
)
self
.
user
=
User
.
objects
.
create_user
(
username
=
'test'
,
email
=
'test@test.com'
,
password
=
'test'
)
def
test_user_can_add_favorite
(
self
):
TrackFavorite
.
add
(
self
.
track
,
self
.
user
)
favorite
=
TrackFavorite
.
objects
.
latest
(
'id'
)
self
.
assertEqual
(
favorite
.
track
,
self
.
track
)
self
.
assertEqual
(
favorite
.
user
,
self
.
user
)
def
test_user_can_get_his_favorites
(
self
):
favorite
=
TrackFavorite
.
add
(
self
.
track
,
self
.
user
)
url
=
reverse
(
'api:v1:favorites:tracks-list'
)
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
'test'
)
response
=
self
.
client
.
get
(
url
)
expected
=
[
{
'track'
:
self
.
track
.
pk
,
'id'
:
favorite
.
id
,
'creation_date'
:
favorite
.
creation_date
.
isoformat
().
replace
(
'+00:00'
,
'Z'
),
}
]
parsed_json
=
json
.
loads
(
response
.
content
.
decode
(
'utf-8'
))
self
.
assertEqual
(
expected
,
parsed_json
[
'results'
])
def
test_user_can_add_favorite_via_api
(
self
):
url
=
reverse
(
'api:v1:favorites:tracks-list'
)
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
'test'
)
response
=
self
.
client
.
post
(
url
,
{
'track'
:
self
.
track
.
pk
})
favorite
=
TrackFavorite
.
objects
.
latest
(
'id'
)
expected
=
{
'track'
:
self
.
track
.
pk
,
'id'
:
favorite
.
id
,
'creation_date'
:
favorite
.
creation_date
.
isoformat
().
replace
(
'+00:00'
,
'Z'
),
}
parsed_json
=
json
.
loads
(
response
.
content
.
decode
(
'utf-8'
))
self
.
assertEqual
(
expected
,
parsed_json
)
self
.
assertEqual
(
favorite
.
track
,
self
.
track
)
self
.
assertEqual
(
favorite
.
user
,
self
.
user
)
def
test_user_can_remove_favorite_via_api
(
self
):
favorite
=
TrackFavorite
.
add
(
self
.
track
,
self
.
user
)
url
=
reverse
(
'api:v1:favorites:tracks-detail'
,
kwargs
=
{
'pk'
:
favorite
.
pk
})
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
'test'
)
response
=
self
.
client
.
delete
(
url
,
{
'track'
:
self
.
track
.
pk
})
self
.
assertEqual
(
response
.
status_code
,
204
)
self
.
assertEqual
(
TrackFavorite
.
objects
.
count
(),
0
)
def
test_user_can_remove_favorite_via_api_using_track_id
(
self
):
favorite
=
TrackFavorite
.
add
(
self
.
track
,
self
.
user
)
url
=
reverse
(
'api:v1:favorites:tracks-remove'
)
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
'test'
)
response
=
self
.
client
.
delete
(
url
,
json
.
dumps
({
'track'
:
self
.
track
.
pk
}),
content_type
=
'application/json'
)
self
.
assertEqual
(
response
.
status_code
,
204
)
self
.
assertEqual
(
TrackFavorite
.
objects
.
count
(),
0
)
from
funkwhale_api.users.models
import
User
def
test_can_restrict_api_views_to_authenticated_users
(
self
):
urls
=
[
(
'api:v1:favorites:tracks-list'
,
'get'
),
]
for
route_name
,
method
in
urls
:
url
=
self
.
reverse
(
route_name
)
with
self
.
settings
(
API_AUTHENTICATION_REQUIRED
=
True
):
response
=
getattr
(
self
.
client
,
method
)(
url
)
self
.
assertEqual
(
response
.
status_code
,
401
)
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
'test'
)
for
route_name
,
method
in
urls
:
url
=
self
.
reverse
(
route_name
)
with
self
.
settings
(
API_AUTHENTICATION_REQUIRED
=
False
):
response
=
getattr
(
self
.
client
,
method
)(
url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
def
test_can_filter_tracks_by_favorites
(
self
):
favorite
=
TrackFavorite
.
add
(
self
.
track
,
self
.
user
)
url
=
reverse
(
'api:v1:tracks-list'
)
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
'test'
)
response
=
self
.
client
.
get
(
url
,
data
=
{
'favorites'
:
True
})
parsed_json
=
json
.
loads
(
response
.
content
.
decode
(
'utf-8'
))
self
.
assertEqual
(
parsed_json
[
'count'
],
1
)
self
.
assertEqual
(
parsed_json
[
'results'
][
0
][
'id'
],
self
.
track
.
id
)
api/funkwhale_api/history/
tests/
factories.py
→
api/funkwhale_api/history/factories.py
View file @
c8a2ae42
import
factory
from
funkwhale_api.music.tests
import
factories
from
funkwhale_api.users.tests.factories
import
UserFactory
from
funkwhale_api.factories
import
registry
from
funkwhale_api.music
import
factories
from
funkwhale_api.users.factories
import
UserFactory
@
registry
.
register
class
ListeningFactory
(
factory
.
django
.
DjangoModelFactory
):
user
=
factory
.
SubFactory
(
UserFactory
)
track
=
factory
.
SubFactory
(
factories
.
TrackFactory
)
...
...
api/funkwhale_api/history/tests/test_history.py
deleted
100644 → 0
View file @
86c607de
import
random
import
json
from
test_plus.test
import
TestCase
from
django.urls
import
reverse
from
django.core.exceptions
import
ValidationError
from
django.utils
import
timezone
from
funkwhale_api.music.tests.factories
import
TrackFactory
from
funkwhale_api.users.models
import
User
from
funkwhale_api.history
import
models
class
TestHistory
(
TestCase
):
def
setUp
(
self
):
super
().
setUp
()
self
.
user
=
User
.
objects
.
create_user
(
username
=
'test'
,
email
=
'test@test.com'
,
password
=
'test'
)
def
test_can_create_listening
(
self
):
track
=
TrackFactory
()
now
=
timezone
.
now
()
l
=
models
.
Listening
.
objects
.
create
(
user
=
self
.
user
,
track
=
track
)
def
test_anonymous_user_can_create_listening_via_api
(
self
):
track
=
TrackFactory
()
url
=
self
.
reverse
(
'api:v1:history:listenings-list'
)
response
=
self
.
client
.
post
(
url
,
{
'track'
:
track
.
pk
,
})
listening
=
models
.
Listening
.
objects
.
latest
(
'id'
)
self
.
assertEqual
(
listening
.
track
,
track
)
self
.
assertIsNotNone
(
listening
.
session_key
)
def
test_logged_in_user_can_create_listening_via_api
(
self
):
track
=
TrackFactory
()
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
'test'
)
url
=
self
.
reverse
(
'api:v1:history:listenings-list'
)
response
=
self
.
client
.
post
(
url
,
{
'track'
:
track
.
pk
,
})
listening
=
models
.
Listening
.
objects
.
latest
(
'id'
)
self
.
assertEqual
(
listening
.
track
,
track
)
self
.
assertEqual
(
listening
.
user
,
self
.
user
)
api/funkwhale_api/music/
tests/
factories.py
→
api/funkwhale_api/music/factories.py
View file @
c8a2ae42
import
factory
import
os
from
funkwhale_api.users.tests.factories
import
UserFactory
from
funkwhale_api.factories
import
registry
,
ManyToManyFromList
from
funkwhale_api.users.factories
import
UserFactory
SAMPLES_PATH
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
SAMPLES_PATH
=
os
.
path
.
join
(
os
.
path
.
dirname
(
os
.
path
.
dirname
(
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
)))),
'tests'
,
'music'
)
@
registry
.
register
class
ArtistFactory
(
factory
.
django
.
DjangoModelFactory
):
name
=
factory
.
Faker
(
'name'
)
mbid
=
factory
.
Faker
(
'uuid4'
)
...
...
@@ -14,6 +19,7 @@ class ArtistFactory(factory.django.DjangoModelFactory):
model
=
'music.Artist'
@
registry
.
register
class
AlbumFactory
(
factory
.
django
.
DjangoModelFactory
):
title
=
factory
.
Faker
(
'sentence'
,
nb_words
=
3
)
mbid
=
factory
.
Faker
(
'uuid4'
)
...
...
@@ -26,17 +32,19 @@ class AlbumFactory(factory.django.DjangoModelFactory):
model
=
'music.Album'
@
registry
.
register
class
TrackFactory
(
factory
.
django
.
DjangoModelFactory
):
title
=
factory
.
Faker
(
'sentence'
,
nb_words
=
3
)
mbid
=
factory
.
Faker
(
'uuid4'
)
album
=
factory
.
SubFactory
(
AlbumFactory
)
artist
=
factory
.
SelfAttribute
(
'album.artist'
)
position
=
1
tags
=
ManyToManyFromList
(
'tags'
)
class
Meta
:
model
=
'music.Track'
@
registry
.
register
class
TrackFileFactory
(
factory
.
django
.
DjangoModelFactory
):
track
=
factory
.
SubFactory
(
TrackFactory
)
audio_file
=
factory
.
django
.
FileField
(
...
...
@@ -46,6 +54,7 @@ class TrackFileFactory(factory.django.DjangoModelFactory):
model
=
'music.TrackFile'
@
registry
.
register
class
ImportBatchFactory
(
factory
.
django
.
DjangoModelFactory
):
submitted_by
=
factory
.
SubFactory
(
UserFactory
)
...
...
@@ -53,14 +62,17 @@ class ImportBatchFactory(factory.django.DjangoModelFactory):
model
=
'music.ImportBatch'
@
registry
.
register
class
ImportJobFactory
(
factory
.
django
.
DjangoModelFactory
):
batch
=
factory
.
SubFactory
(
ImportBatchFactory
)
source
=
factory
.
Faker
(
'url'
)
mbid
=
factory
.
Faker
(
'uuid4'
)
class
Meta
:
model
=
'music.ImportJob'
@
registry
.
register
class
WorkFactory
(
factory
.
django
.
DjangoModelFactory
):
mbid
=
factory
.
Faker
(
'uuid4'
)
language
=
'eng'
...
...
@@ -71,6 +83,7 @@ class WorkFactory(factory.django.DjangoModelFactory):
model
=
'music.Work'
@
registry
.
register
class
LyricsFactory
(
factory
.
django
.
DjangoModelFactory
):
work
=
factory
.
SubFactory
(
WorkFactory
)
url
=
factory
.
Faker
(
'url'
)
...
...
@@ -80,6 +93,7 @@ class LyricsFactory(factory.django.DjangoModelFactory):
model
=
'music.Lyrics'
@
registry
.
register
class
TagFactory
(
factory
.
django
.
DjangoModelFactory
):
name
=
factory
.
SelfAttribute
(
'slug'
)
slug
=
factory
.
Faker
(
'slug'
)
...
...
api/funkwhale_api/music/filters.py
View file @
c8a2ae42
...
...
@@ -8,5 +8,5 @@ class ArtistFilter(django_filters.FilterSet):
class
Meta
:
model
=
models
.
Artist
fields
=
{
'name'
:
[
'exact'
,
'iexact'
,
'startswith'
]
'name'
:
[
'exact'
,
'iexact'
,
'startswith'
,
'icontains'
]
}
api/funkwhale_api/music/serializers.py
View file @
c8a2ae42
...
...
@@ -13,14 +13,14 @@ class TagSerializer(serializers.ModelSerializer):
class
SimpleArtistSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
model
=
models
.
Artist
fields
=
(
'id'
,
'mbid'
,
'name'
)
fields
=
(
'id'
,
'mbid'
,
'name'
,
'creation_date'
)
class
ArtistSerializer
(
serializers
.
ModelSerializer
):
tags
=
TagSerializer
(
many
=
True
,
read_only
=
True
)
class
Meta
:
model
=
models
.
Artist
fields
=
(
'id'
,
'mbid'
,
'name'
,
'tags'
)
fields
=
(
'id'
,
'mbid'
,
'name'
,
'tags'
,
'creation_date'
)
class
TrackFileSerializer
(
serializers
.
ModelSerializer
):
...
...
api/funkwhale_api/music/tests/test_api.py
deleted
100644 → 0
View file @
86c607de
import
json
import
unittest
from
test_plus.test
import
TestCase
from
django.urls
import
reverse
from
funkwhale_api.music
import
models
from
funkwhale_api.utils.tests
import
TMPDirTestCaseMixin
from
funkwhale_api.musicbrainz
import
api
from
funkwhale_api.music
import
serializers
from
funkwhale_api.users.models
import
User
from
.
import
data
as
api_data
from
.
import
factories
class
TestAPI
(
TMPDirTestCaseMixin
,
TestCase
):
@
unittest
.
mock
.
patch
(
'funkwhale_api.musicbrainz.api.artists.get'
,
return_value
=
api_data
.
artists
[
'get'
][
'adhesive_wombat'
])
@
unittest
.
mock
.
patch
(
'funkwhale_api.musicbrainz.api.releases.get'
,
return_value
=
api_data
.
albums
[
'get'
][
'marsupial'
])
@
unittest
.
mock
.
patch
(
'funkwhale_api.musicbrainz.api.recordings.get'
,
return_value
=
api_data
.
tracks
[
'get'
][
'8bitadventures'
])
@
unittest
.
mock
.
patch
(
'funkwhale_api.music.models.TrackFile.download_file'
,
return_value
=
None
)
def
test_can_submit_youtube_url_for_track_import
(
self
,
*
mocks
):
mbid
=
'9968a9d6-8d92-4051-8f76-674e157b6eed'
video_id
=
'tPEE9ZwTmy0'
url
=
reverse
(
'api:v1:submit-single'
)
user
=
User
.
objects
.
create_superuser
(
username
=
'test'
,
email
=
'test@test.com'
,
password
=
'test'
)
self
.
client
.
login
(
username
=
user
.
username
,
password
=
'test'
)
response
=
self
.
client
.
post
(
url
,
{
'import_url'
:
'https://www.youtube.com/watch?v={0}'
.
format
(
video_id
),
'mbid'
:
mbid
})
track
=
models
.
Track
.
objects
.
get
(
mbid
=
mbid
)
self
.
assertEqual
(
track
.
artist
.
name
,
'Adhesive Wombat'
)
self
.
assertEqual
(
track
.
album
.
title
,
'Marsupial Madness'
)
# self.assertIn(video_id, track.files.first().audio_file.name)
def
test_import_creates_an_import_with_correct_data
(
self
):
user
=
User
.
objects
.
create_superuser
(
username
=
'test'
,
email
=
'test@test.com'
,
password
=
'test'
)
mbid
=
'9968a9d6-8d92-4051-8f76-674e157b6eed'
video_id
=
'tPEE9ZwTmy0'
url
=
reverse
(
'api:v1:submit-single'
)
self
.
client
.
login
(
username
=
user
.
username
,
password
=
'test'
)
with
self
.
settings
(
CELERY_ALWAYS_EAGER
=
False
):
response
=
self
.
client
.
post
(
url
,
{
'import_url'
:
'https://www.youtube.com/watch?v={0}'
.
format
(
video_id
),
'mbid'
:
mbid
})
batch
=
models
.
ImportBatch
.
objects
.
latest
(
'id'
)
self
.
assertEqual
(
batch
.
jobs
.
count
(),
1
)
self
.
assertEqual
(
batch
.
submitted_by
,
user
)
self
.
assertEqual
(
batch
.
status
,
'pending'
)
job
=
batch
.
jobs
.
first
()
self
.
assertEqual
(
str
(
job
.
mbid
),
mbid
)
self
.
assertEqual
(
job
.
status
,
'pending'
)
self
.
assertEqual
(
job
.
source
,
'https://www.youtube.com/watch?v={0}'
.
format
(
video_id
))
@
unittest
.
mock
.
patch
(
'funkwhale_api.musicbrainz.api.artists.get'
,
return_value
=
api_data
.
artists
[
'get'
][
'soad'
])
@
unittest
.
mock
.
patch
(
'funkwhale_api.musicbrainz.api.images.get_front'
,
return_value
=
b
''
)
@
unittest
.
mock
.
patch
(
'funkwhale_api.musicbrainz.api.releases.get'
,
return_value
=
api_data
.
albums
[
'get_with_includes'
][
'hypnotize'
])
def
test_can_import_whole_album
(
self
,
*
mocks
):
user
=
User
.
objects
.
create_superuser
(
username
=
'test'
,
email
=
'test@test.com'
,
password
=
'test'
)
payload
=
{
'releaseId'
:
'47ae093f-1607-49a3-be11-a15d335ccc94'
,
'tracks'
:
[
{
'mbid'
:
'1968a9d6-8d92-4051-8f76-674e157b6eed'
,
'source'
:
'https://www.youtube.com/watch?v=1111111111'
,
},
{
'mbid'
:
'2968a9d6-8d92-4051-8f76-674e157b6eed'
,
'source'
:
'https://www.youtube.com/watch?v=2222222222'
,
},
{
'mbid'
:
'3968a9d6-8d92-4051-8f76-674e157b6eed'
,
'source'
:
'https://www.youtube.com/watch?v=3333333333'
,
},
]
}
url
=
reverse
(
'api:v1:submit-album'
)
self
.
client
.
login
(
username
=
user
.
username
,
password
=
'test'
)
with
self
.
settings
(
CELERY_ALWAYS_EAGER
=
False
):
response
=
self
.
client
.
post
(
url
,
json
.
dumps
(
payload
),
content_type
=
"application/json"
)
batch
=
models
.
ImportBatch
.
objects
.
latest
(
'id'
)
self
.
assertEqual
(
batch
.
jobs
.
count
(),
3
)
self
.
assertEqual
(
batch
.
submitted_by
,
user
)
self
.
assertEqual
(
batch
.
status
,
'pending'
)
album
=
models
.
Album
.
objects
.
latest
(
'id'
)
self
.
assertEqual
(
str
(
album
.
mbid
),
'47ae093f-1607-49a3-be11-a15d335ccc94'
)
medium_data
=
api_data
.
albums
[
'get_with_includes'
][
'hypnotize'
][
'release'
][
'medium-list'
][
0
]
self
.
assertEqual
(
int
(
medium_data
[
'track-count'
]),
album
.
tracks
.
all
().
count
())
for
track
in
medium_data
[
'track-list'
]:
instance
=
models
.
Track
.
objects
.
get
(
mbid
=
track
[
'recording'
][
'id'
])
self
.
assertEqual
(
instance
.
title
,
track
[
'recording'
][
'title'
])
self
.
assertEqual
(
instance
.
position
,
int
(
track
[
'position'
]))
self
.
assertEqual
(
instance
.
title
,
track
[
'recording'
][
'title'
])
for
row
in
payload
[
'tracks'
]:
job
=
models
.
ImportJob
.
objects
.
get
(
mbid
=
row
[
'mbid'
])
self
.
assertEqual
(
str
(
job
.
mbid
),
row
[
'mbid'
])
self
.
assertEqual
(
job
.
status
,
'pending'
)
self
.
assertEqual
(
job
.
source
,
row
[
'source'
])
@
unittest
.
mock
.
patch
(
'funkwhale_api.musicbrainz.api.artists.get'
,
return_value
=
api_data
.
artists
[
'get'
][
'soad'
])
@
unittest
.
mock
.
patch
(
'funkwhale_api.musicbrainz.api.images.get_front'
,
return_value
=
b
''
)
@
unittest
.
mock
.
patch
(
'funkwhale_api.musicbrainz.api.releases.get'
,
return_value
=
api_data
.
albums
[
'get_with_includes'
][
'hypnotize'
])
def
test_can_import_whole_artist
(
self
,
*
mocks
):
user
=
User
.
objects
.
create_superuser
(
username
=
'test'
,
email
=
'test@test.com'
,
password
=
'test'
)
payload
=
{
'artistId'
:
'mbid'
,
'albums'
:
[
{
'releaseId'
:
'47ae093f-1607-49a3-be11-a15d335ccc94'
,
'tracks'
:
[
{
'mbid'
:
'1968a9d6-8d92-4051-8f76-674e157b6eed'
,
'source'
:
'https://www.youtube.com/watch?v=1111111111'
,
},
{
'mbid'
:
'2968a9d6-8d92-4051-8f76-674e157b6eed'
,
'source'
:
'https://www.youtube.com/watch?v=2222222222'
,
},
{
'mbid'
:
'3968a9d6-8d92-4051-8f76-674e157b6eed'
,
'source'
:
'https://www.youtube.com/watch?v=3333333333'
,
},
]
}
]
}