mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-15 00:42:54 +01:00
library: cover every credited artist in plays, downloads and menus
Credit all album artists in play aggregation and recorded plays, include the relation rows in the downloaded artist list, and fall back to the album artist display name in download groups. Also keep the chooser scrollable, close it when the track changes, keep the singular id in the album-artist label, stop a nested artists container from swallowing later artist elements, and make the refs encoding length-prefixed so tag values cannot corrupt it.
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
package com.subtracks.data.model
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class ArtistRefsCodecTest {
|
||||
@Test
|
||||
fun roundTripsNamesWithTheOldSeparatorsAndColons() {
|
||||
val refs =
|
||||
listOf(
|
||||
ArtistRef("ar1", "Name\u001Ewith\u001Fseparators"),
|
||||
ArtistRef("ar:2", "1:Colon Artist"),
|
||||
ArtistRef("", ""),
|
||||
)
|
||||
|
||||
assertEquals(refs, ArtistRefsCodec.decode(ArtistRefsCodec.encode(refs)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun decodesEmptyAndMalformedValuesAsEmpty() {
|
||||
assertEquals(emptyList<ArtistRef>(), ArtistRefsCodec.decode(""))
|
||||
assertEquals(emptyList<ArtistRef>(), ArtistRefsCodec.decode("not a ref"))
|
||||
assertEquals(emptyList<ArtistRef>(), ArtistRefsCodec.decode("9:short4:name"))
|
||||
}
|
||||
}
|
||||
@@ -191,6 +191,27 @@ class SubsonicXmlTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun ignoresNestedArtistsOutsideTheArtistsContainer() {
|
||||
val songs =
|
||||
songs(
|
||||
"""
|
||||
<subsonic-response status="ok">
|
||||
<song id="s1" title="Collab" albumId="al1">
|
||||
<artists>
|
||||
<artist id="ar1" name="A"/>
|
||||
</artists>
|
||||
<contributors>
|
||||
<artist id="ar9" role="composer"/>
|
||||
</contributors>
|
||||
</song>
|
||||
</subsonic-response>
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
assertEquals(listOf(ArtistRef("ar1", "A")), songs.single().artists)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mapsNestedSongArtistRefs() {
|
||||
val songs =
|
||||
@@ -205,6 +226,9 @@ class SubsonicXmlTest {
|
||||
<albumArtists>
|
||||
<artist id="ar3" name="Album Artist"/>
|
||||
</albumArtists>
|
||||
<contributors>
|
||||
<artist id="ar4" role="composer"/>
|
||||
</contributors>
|
||||
</song>
|
||||
</subsonic-response>
|
||||
""".trimIndent(),
|
||||
|
||||
@@ -1045,6 +1045,44 @@ class SyncServiceTest {
|
||||
assertEquals(listOf("A", "B"), filtered.map { it.name })
|
||||
assertEquals(listOf(1L, 1L), filtered.map { it.albumCount })
|
||||
assertEquals(ListDownloadStatus(total = 1, downloaded = 1), db.downloadDao().artistStatus(1, "a2").first())
|
||||
assertEquals(
|
||||
setOf("A", "B"),
|
||||
db
|
||||
.libraryDao()
|
||||
.downloadedArtists(1)
|
||||
.allRows()
|
||||
.map { it.name }
|
||||
.toSet(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun playsOnASharedAlbumReachEveryAlbumArtist() =
|
||||
runTest {
|
||||
insertSource()
|
||||
val source =
|
||||
FakeMusicSource(
|
||||
artists = listOf(artist("a1", "A"), artist("a2", "B")),
|
||||
albums =
|
||||
listOf(
|
||||
album("al1").copy(
|
||||
artistId = "a1",
|
||||
artists = listOf(ArtistRef("a1", "A"), ArtistRef("a2", "B")),
|
||||
),
|
||||
),
|
||||
songs = listOf(song("s1").copy(albumId = "al1", playCount = 3, played = 100)),
|
||||
)
|
||||
|
||||
SyncService(db, source).sync()
|
||||
|
||||
assertEquals(3L, db.libraryDao().artistOnce(1, "a2")!!.playCount)
|
||||
assertEquals(100L, db.libraryDao().artistOnce(1, "a2")!!.played)
|
||||
|
||||
db.libraryDao().recordPlay(1, "s1", 500)
|
||||
|
||||
assertEquals(4L, db.libraryDao().artistOnce(1, "a1")!!.playCount)
|
||||
assertEquals(4L, db.libraryDao().artistOnce(1, "a2")!!.playCount)
|
||||
assertEquals(500L, db.libraryDao().artistOnce(1, "a2")!!.played)
|
||||
}
|
||||
|
||||
private suspend fun totalChanges(): Long =
|
||||
|
||||
@@ -5,6 +5,7 @@ import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.junit4.v2.createAndroidComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performScrollTo
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.subtracks.data.model.ArtistRef
|
||||
import com.subtracks.ui.theme.SubtracksTheme
|
||||
@@ -43,4 +44,27 @@ class ArtistChooserSheetTest {
|
||||
|
||||
assertEquals(ArtistRef("ar2", "B"), opened)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun longListsScrollToTheLastArtist() {
|
||||
var opened: ArtistRef? = null
|
||||
val artists = (1..20).map { ArtistRef("ar$it", "Artist $it") }
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
ArtistChooserSheet(
|
||||
artists = artists,
|
||||
onArtistClick = { opened = it },
|
||||
onDismiss = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
composeRule.onNodeWithText("Artist 20").performScrollTo().assertIsDisplayed()
|
||||
|
||||
composeRule.mainClock.autoAdvance = false
|
||||
composeRule.onNodeWithText("Artist 20").performClick()
|
||||
composeRule.mainClock.advanceTimeBy(1_000)
|
||||
|
||||
assertEquals(ArtistRef("ar20", "Artist 20"), opened)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.subtracks.ui.library
|
||||
|
||||
import com.subtracks.data.model.Album
|
||||
import com.subtracks.data.model.ArtistRef
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class AlbumArtistLabelTest {
|
||||
@Test
|
||||
fun creditsBothTheSingularIdAndEveryPluralRef() {
|
||||
val album =
|
||||
album(
|
||||
artistId = "a1",
|
||||
artists = listOf(ArtistRef("a2", "B")),
|
||||
)
|
||||
|
||||
assertTrue(isAlbumArtist(listOf(album), "a1"))
|
||||
assertTrue(isAlbumArtist(listOf(album), "a2"))
|
||||
assertFalse(isAlbumArtist(listOf(album), "a3"))
|
||||
}
|
||||
|
||||
private fun album(
|
||||
artistId: String?,
|
||||
artists: List<ArtistRef>,
|
||||
) = Album(
|
||||
sourceId = 1,
|
||||
id = "al1",
|
||||
artistId = artistId,
|
||||
name = "Album",
|
||||
albumArtist = "Various Artists",
|
||||
created = 0,
|
||||
coverArt = null,
|
||||
genre = null,
|
||||
year = null,
|
||||
starred = null,
|
||||
songCount = 1,
|
||||
artists = artists,
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user