diff --git a/CHANGELOG b/CHANGELOG
index 768b53c3869ecef71ef53c88cd4ac19b1dde0488..731f0745ce0abfb15e74e0a9994d68839d21ef44 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -10,7 +10,7 @@ This changelog is viewable on the web at https://docs.funkwhale.audio/changelog.
 
 .. towncrier
 
-0.19.1 (2018-06-28)
+0.19.1 (2019-06-28)
 -------------------
 
 Upgrade instructions are available at
diff --git a/api/funkwhale_api/federation/migrations/0015_populate_domains.py b/api/funkwhale_api/federation/migrations/0015_populate_domains.py
index 0f0036c947fb3cf71ea1eb29062eb7059681d5c7..71b486b1b305960a0e4cc846164ce91d9722589c 100644
--- a/api/funkwhale_api/federation/migrations/0015_populate_domains.py
+++ b/api/funkwhale_api/federation/migrations/0015_populate_domains.py
@@ -10,7 +10,7 @@ def populate_domains(apps, schema_editor):
     Actor = apps.get_model("federation", "Actor")
 
     domains = set(
-        [v.lower() for v in Actor.objects.values_list("old_domain", flat=True)]
+        [v.lower() for v in Actor.objects.values_list("old_domain", flat=True) if v]
     )
     for domain in sorted(domains):
         print("Populating domain {}...".format(domain))
diff --git a/api/funkwhale_api/federation/serializers.py b/api/funkwhale_api/federation/serializers.py
index 473585fe7f56d1d519bf2e721bc982da4b31fbb5..f7210e324bc2092b99a4e692b4d63bdc43ad7978 100644
--- a/api/funkwhale_api/federation/serializers.py
+++ b/api/funkwhale_api/federation/serializers.py
@@ -14,8 +14,6 @@ from funkwhale_api.music import tasks as music_tasks
 
 from . import activity, actors, contexts, jsonld, models, tasks, utils
 
-AP_CONTEXT = jsonld.get_default_context()
-
 logger = logging.getLogger(__name__)
 
 
@@ -116,7 +114,7 @@ class ActorSerializer(jsonld.JsonLdSerializer):
         if instance.manually_approves_followers is not None:
             ret["manuallyApprovesFollowers"] = instance.manually_approves_followers
 
-        ret["@context"] = AP_CONTEXT
+        ret["@context"] = jsonld.get_default_context()
         if instance.public_key:
             ret["publicKey"] = {
                 "owner": instance.fid,
@@ -324,7 +322,7 @@ class FollowSerializer(serializers.Serializer):
 
     def to_representation(self, instance):
         return {
-            "@context": AP_CONTEXT,
+            "@context": jsonld.get_default_context(),
             "actor": instance.actor.fid,
             "id": instance.get_federation_id(),
             "object": instance.target.fid,
@@ -396,7 +394,7 @@ class AcceptFollowSerializer(serializers.Serializer):
             actor = instance.target
 
         return {
-            "@context": AP_CONTEXT,
+            "@context": jsonld.get_default_context(),
             "id": instance.get_federation_id() + "/accept",
             "type": "Accept",
             "actor": actor.fid,
@@ -450,7 +448,7 @@ class UndoFollowSerializer(serializers.Serializer):
 
     def to_representation(self, instance):
         return {
-            "@context": AP_CONTEXT,
+            "@context": jsonld.get_default_context(),
             "id": instance.get_federation_id() + "/undo",
             "type": "Undo",
             "actor": instance.actor.fid,
@@ -530,7 +528,7 @@ class ActivitySerializer(serializers.Serializer):
         d.update(conf)
 
         if self.context.get("include_ap_context", True):
-            d["@context"] = AP_CONTEXT
+            d["@context"] = jsonld.get_default_context()
         return d
 
 
@@ -624,7 +622,7 @@ class PaginatedCollectionSerializer(jsonld.JsonLdSerializer):
         }
         d.update(get_additional_fields(conf))
         if self.context.get("include_ap_context", True):
-            d["@context"] = AP_CONTEXT
+            d["@context"] = jsonld.get_default_context()
         return d
 
 
@@ -771,7 +769,7 @@ class CollectionPageSerializer(jsonld.JsonLdSerializer):
             )
         d.update(get_additional_fields(conf))
         if self.context.get("include_ap_context", True):
-            d["@context"] = AP_CONTEXT
+            d["@context"] = jsonld.get_default_context()
         return d
 
 
@@ -828,7 +826,7 @@ class ArtistSerializer(MusicEntitySerializer):
         }
 
         if self.context.get("include_ap_context", self.parent is None):
-            d["@context"] = AP_CONTEXT
+            d["@context"] = jsonld.get_default_context()
         return d
 
 
@@ -883,7 +881,7 @@ class AlbumSerializer(MusicEntitySerializer):
                 or "image/jpeg",
             }
         if self.context.get("include_ap_context", self.parent is None):
-            d["@context"] = AP_CONTEXT
+            d["@context"] = jsonld.get_default_context()
         return d
 
 
@@ -946,7 +944,7 @@ class TrackSerializer(MusicEntitySerializer):
         }
 
         if self.context.get("include_ap_context", self.parent is None):
-            d["@context"] = AP_CONTEXT
+            d["@context"] = jsonld.get_default_context()
         return d
 
     def create(self, validated_data):
@@ -1106,7 +1104,7 @@ class UploadSerializer(jsonld.JsonLdSerializer):
             d["updated"] = instance.modification_date.isoformat()
 
         if self.context.get("include_ap_context", self.parent is None):
-            d["@context"] = AP_CONTEXT
+            d["@context"] = jsonld.get_default_context()
         return d
 
 
diff --git a/api/requirements/test.txt b/api/requirements/test.txt
index 1a4f7e1cd61b07bd2b0054e5700dc0d00b4250b5..051a117dfe19543c3209e697e1b1b5c3f8ef74f9 100644
--- a/api/requirements/test.txt
+++ b/api/requirements/test.txt
@@ -1,15 +1,13 @@
 # Test dependencies go here.
 
 flake8
-pytest
-# pytest-django until a new release containing django_assert_num_queries
-# is deployed to pypi
-git+https://github.com/pytest-dev/pytest-django.git@d3d9bb3ef6f0377cb5356eb368992a0834692378
-
+pytest>=5
+pytest-django>=3.5.1
 pytest-mock
 pytest-sugar
 pytest-xdist
 pytest-cov
 pytest-env
 requests-mock
+pytest-randomly
 pytest-profiling<1.4
diff --git a/api/tests/federation/test_api_serializers.py b/api/tests/federation/test_api_serializers.py
index 2eacda1a8d3926aaf2b0c275e1050dc3d47ee257..df55df7ae30b52e905551f1b54eb63869972f4b1 100644
--- a/api/tests/federation/test_api_serializers.py
+++ b/api/tests/federation/test_api_serializers.py
@@ -72,9 +72,10 @@ def test_library_follow_serializer_do_not_allow_own_library(factories):
     library = factories["music.Library"](actor=actor)
     serializer = api_serializers.LibraryFollowSerializer(context={"actor": actor})
 
-    with pytest.raises(api_serializers.serializers.ValidationError) as e:
+    with pytest.raises(
+        api_serializers.serializers.ValidationError, match=r".*own library.*"
+    ):
         serializer.validate_target(library)
-    assert "own library" in str(e)
 
 
 def test_manage_upload_action_read(factories):
diff --git a/api/tests/federation/test_jsonld.py b/api/tests/federation/test_jsonld.py
index ad201b7486e9c10e9d93f486c5f7876f52dd392d..7bf906d50ca690e1c71818c136326b1e9866eb1c 100644
--- a/api/tests/federation/test_jsonld.py
+++ b/api/tests/federation/test_jsonld.py
@@ -132,13 +132,13 @@ def test_expand_remote_doc(r_mock):
 
 async def test_fetch_many(a_responses):
     doc = {
-        "@context": ["https://www.w3.org/ns/activitystreams", {}],
+        "@context": jsonld.get_default_context(),
         "id": "https://noop/federation/actors/demo",
         "type": "Person",
         "followers": "https://noop/federation/actors/demo/followers",
     }
     followers_doc = {
-        "@context": ["https://www.w3.org/ns/activitystreams", {}],
+        "@context": jsonld.get_default_context(),
         "id": "https://noop/federation/actors/demo/followers",
         "type": "Collection",
     }
@@ -152,13 +152,13 @@ async def test_fetch_many(a_responses):
 def test_dereference():
 
     followers_doc = {
-        "@context": ["https://www.w3.org/ns/activitystreams", {}],
+        "@context": jsonld.get_default_context(),
         "id": "https://noop/federation/actors/demo/followers",
         "type": "Collection",
     }
 
     actor_doc = {
-        "@context": ["https://www.w3.org/ns/activitystreams", {}],
+        "@context": jsonld.get_default_context(),
         "id": "https://noop/federation/actors/demo",
         "type": "Person",
         "followers": "https://noop/federation/actors/demo/followers",
@@ -281,7 +281,7 @@ def test_jsonld_serializer_fallback():
             }
 
     payload = {
-        "@context": ["https://www.w3.org/ns/activitystreams", {}],
+        "@context": jsonld.get_default_context(),
         "id": "https://noop.url/federation/actors/demo",
         "type": "Person",
         "name": "Hello",
@@ -313,14 +313,14 @@ def test_jsonld_serializer_dereference(a_responses):
             }
 
     payload = {
-        "@context": ["https://www.w3.org/ns/activitystreams", {}],
+        "@context": jsonld.get_default_context(),
         "id": "https://noop.url/federation/actors/demo",
         "type": "Person",
         "followers": "https://noop.url/federation/actors/demo/followers",
     }
 
     followers_doc = {
-        "@context": ["https://www.w3.org/ns/activitystreams", {}],
+        "@context": jsonld.get_default_context(),
         "id": "https://noop.url/federation/actors/demo/followers",
         "type": "Collection",
     }
diff --git a/api/tests/federation/test_migrations.py b/api/tests/federation/test_migrations.py
index 4a9ce427478a07bf201370106270fdefd7a0f2c8..db3f8aaa54ff668fddf0d71ab00b26c39989861b 100644
--- a/api/tests/federation/test_migrations.py
+++ b/api/tests/federation/test_migrations.py
@@ -5,13 +5,19 @@ def test_domain_14_migration(migrator):
     old_apps = migrator.loader.project_state([(a, f)]).apps
     Actor = old_apps.get_model(a, "Actor")
     a1 = Actor.objects.create(
-        fid="http://test1.com", preferred_username="test1", old_domain="dOmaiN1.com"
+        fid="http://testmigration1.com",
+        preferred_username="test1",
+        old_domain="dOmaiN1.com",
     )
     a2 = Actor.objects.create(
-        fid="http://test2.com", preferred_username="test2", old_domain="domain1.com"
+        fid="http://testmigration2.com",
+        preferred_username="test2",
+        old_domain="domain1.com",
     )
     a3 = Actor.objects.create(
-        fid="http://test3.com", preferred_username="test2", old_domain="domain2.com"
+        fid="http://testmigration3.com",
+        preferred_username="test2",
+        old_domain="domain2.com",
     )
 
     migrator.loader.build_graph()
diff --git a/api/tests/federation/test_serializers.py b/api/tests/federation/test_serializers.py
index 5e3259e18facd0a57c30bc765492697f39642c71..43b465d5480fa0096ea8fcc99e889fdde3826a0e 100644
--- a/api/tests/federation/test_serializers.py
+++ b/api/tests/federation/test_serializers.py
@@ -561,7 +561,7 @@ def test_music_library_serializer_from_private(factories, mocker):
 def test_activity_pub_artist_serializer_to_ap(factories):
     artist = factories["music.Artist"](attributed=True)
     expected = {
-        "@context": serializers.AP_CONTEXT,
+        "@context": jsonld.get_default_context(),
         "type": "Artist",
         "id": artist.fid,
         "name": artist.name,
@@ -578,7 +578,7 @@ def test_activity_pub_album_serializer_to_ap(factories):
     album = factories["music.Album"](attributed=True)
 
     expected = {
-        "@context": serializers.AP_CONTEXT,
+        "@context": jsonld.get_default_context(),
         "type": "Album",
         "id": album.fid,
         "name": album.title,
@@ -607,7 +607,7 @@ def test_activity_pub_track_serializer_to_ap(factories):
         license="cc-by-4.0", copyright="test", disc_number=3, attributed=True
     )
     expected = {
-        "@context": serializers.AP_CONTEXT,
+        "@context": jsonld.get_default_context(),
         "published": track.creation_date.isoformat(),
         "type": "Track",
         "musicbrainzId": track.mbid,
@@ -737,7 +737,7 @@ def test_activity_pub_upload_serializer_from_ap(factories, mocker, r_mock):
     updated = timezone.now()
     released = timezone.now().date()
     data = {
-        "@context": serializers.AP_CONTEXT,
+        "@context": jsonld.get_default_context(),
         "type": "Audio",
         "id": "https://track.file",
         "name": "Ignored",
@@ -825,7 +825,7 @@ def test_activity_pub_audio_serializer_to_ap(factories):
         mimetype="audio/mp3", bitrate=42, duration=43, size=44
     )
     expected = {
-        "@context": serializers.AP_CONTEXT,
+        "@context": jsonld.get_default_context(),
         "type": "Audio",
         "id": upload.fid,
         "name": upload.track.full_name,
diff --git a/api/tests/test_import_audio_file.py b/api/tests/test_import_audio_file.py
index c6b8aea60e59b084edff401d25ff2af163f3f756..c7d5a976c753cd7bee6d40e7a3d36063af3e9116 100644
--- a/api/tests/test_import_audio_file.py
+++ b/api/tests/test_import_audio_file.py
@@ -11,22 +11,21 @@ DATA_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "files")
 def test_management_command_requires_a_valid_library_id(factories):
     path = os.path.join(DATA_DIR, "dummy_file.ogg")
 
-    with pytest.raises(CommandError) as e:
+    with pytest.raises(CommandError, match=r".*Invalid library id.*"):
         call_command("import_files", "wrong_id", path, interactive=False)
-    assert "Invalid library id" in str(e)
 
 
 def test_in_place_import_only_from_music_dir(factories, settings):
     library = factories["music.Library"](actor__local=True)
     settings.MUSIC_DIRECTORY_PATH = "/nope"
     path = os.path.join(DATA_DIR, "dummy_file.ogg")
-    with pytest.raises(CommandError) as e:
+    with pytest.raises(
+        CommandError, match=r".*Importing in-place only works if importing.*"
+    ):
         call_command(
             "import_files", str(library.uuid), path, in_place=True, interactive=False
         )
 
-    assert "Importing in-place only works if importing" in str(e)
-
 
 def test_import_with_multiple_argument(factories, mocker):
     library = factories["music.Library"](actor__local=True)
diff --git a/changes/changelog.d/871.bugfix b/changes/changelog.d/871.bugfix
new file mode 100644
index 0000000000000000000000000000000000000000..153b45bfcc0d585eee692c95721ba1f2d85ce809
--- /dev/null
+++ b/changes/changelog.d/871.bugfix
@@ -0,0 +1 @@
+Fixed broken URL to artist and album on album and track pages (#871)
diff --git a/front/src/components/library/AlbumBase.vue b/front/src/components/library/AlbumBase.vue
index 2b3c978bced83a60574a49380e786e7312828182..016be2c3779e99ddc14c9dcd1ca585ea8e462a59 100644
--- a/front/src/components/library/AlbumBase.vue
+++ b/front/src/components/library/AlbumBase.vue
@@ -192,7 +192,7 @@ export default {
     subtitle () {
       let route = this.$router.resolve({name: 'library.artists.detail', params: {id: this.object.artist.id }})
       let msg = this.$npgettext('Content/Album/Header.Title', 'Album containing %{ count } track, by <a class="internal" href="%{ artistUrl }">%{ artist }</a>', 'Album containing %{ count } tracks, by <a class="internal" href="%{ artistUrl }">%{ artist }</a>', this.object.tracks.length)
-      return this.$gettextInterpolate(msg, {count: this.object.tracks.length, artist: this.object.artist.name, artistUrl: route.location.path})
+      return this.$gettextInterpolate(msg, {count: this.object.tracks.length, artist: this.object.artist.name, artistUrl: route.href})
     }
   },
   watch: {
diff --git a/front/src/components/library/TrackBase.vue b/front/src/components/library/TrackBase.vue
index 4edd00c5de9ae92f32254636bec9bc19f4643751..2f3cc51a9d74b1b855e2edefa6288704a6bcb0db 100644
--- a/front/src/components/library/TrackBase.vue
+++ b/front/src/components/library/TrackBase.vue
@@ -210,11 +210,11 @@ export default {
     },
     albumUrl () {
       let route = this.$router.resolve({name: 'library.albums.detail', params: {id: this.track.album.id }})
-      return route.location.path
+      return route.href
     },
     artistUrl () {
       let route = this.$router.resolve({name: 'library.artists.detail', params: {id: this.track.artist.id }})
-      return route.location.path
+      return route.href
     },
     headerStyle() {
       if (!this.cover) {