Updated Gradle to 6.5

Tried to satisfy ktlint rules
This commit is contained in:
Nite 2020-06-13 19:04:31 +02:00
parent b23c1b4a6a
commit de7eaef668
No known key found for this signature in database
GPG Key ID: 1D1AD59B1C6386C1
98 changed files with 1157 additions and 817 deletions

View File

@ -20,14 +20,14 @@ private val artistSerializer get() = object : ObjectSerializer<Artist>(SERIALIZE
item: Artist item: Artist
) { ) {
output.writeString(item.id) output.writeString(item.id)
.writeString(item.name) .writeString(item.name)
.writeString(item.index) .writeString(item.index)
.writeString(item.coverArt) .writeString(item.coverArt)
.apply { .apply {
val albumCount = item.albumCount val albumCount = item.albumCount
if (albumCount != null) writeLong(albumCount) else writeNull() if (albumCount != null) writeLong(albumCount) else writeNull()
} }
.writeInt(item.closeness) .writeInt(item.closeness)
} }
override fun deserializeObject( override fun deserializeObject(

View File

@ -20,9 +20,9 @@ private val indexesSerializer get() = object : ObjectSerializer<Indexes>(SERIALI
) { ) {
val artistListSerializer = getArtistListSerializer() val artistListSerializer = getArtistListSerializer()
output.writeLong(item.lastModified) output.writeLong(item.lastModified)
.writeString(item.ignoredArticles) .writeString(item.ignoredArticles)
.writeObject<MutableList<Artist>>(context, item.shortcuts, artistListSerializer) .writeObject<MutableList<Artist>>(context, item.shortcuts, artistListSerializer)
.writeObject<MutableList<Artist>>(context, item.artists, artistListSerializer) .writeObject<MutableList<Artist>>(context, item.artists, artistListSerializer)
} }
override fun deserializeObject( override fun deserializeObject(
@ -37,8 +37,10 @@ private val indexesSerializer get() = object : ObjectSerializer<Indexes>(SERIALI
val ignoredArticles = input.readString() ?: return null val ignoredArticles = input.readString() ?: return null
val shortcutsList = input.readObject(context, artistListDeserializer) ?: return null val shortcutsList = input.readObject(context, artistListDeserializer) ?: return null
val artistsList = input.readObject(context, artistListDeserializer) ?: return null val artistsList = input.readObject(context, artistListDeserializer) ?: return null
return Indexes(lastModified, ignoredArticles, shortcutsList.toMutableList(), return Indexes(
artistsList.toMutableList()) lastModified, ignoredArticles, shortcutsList.toMutableList(),
artistsList.toMutableList()
)
} }
} }

View File

@ -41,10 +41,10 @@ private val musicFolderSerializer = object : ObjectSerializer<MusicFolder>(SERIA
fun getMusicFolderSerializer(): DomainEntitySerializer<MusicFolder> = musicFolderSerializer fun getMusicFolderSerializer(): DomainEntitySerializer<MusicFolder> = musicFolderSerializer
private val musicFolderListSerializer = private val musicFolderListSerializer =
CollectionSerializers.getListSerializer(musicFolderSerializer) CollectionSerializers.getListSerializer(musicFolderSerializer)
/** /**
* Serializer/deserializer for [List] of [MusicFolder] items. * Serializer/deserializer for [List] of [MusicFolder] items.
*/ */
fun getMusicFolderListSerializer(): DomainEntitySerializer<List<MusicFolder>> = fun getMusicFolderListSerializer(): DomainEntitySerializer<List<MusicFolder>> =
musicFolderListSerializer musicFolderListSerializer

View File

@ -2,11 +2,11 @@ package org.moire.ultrasonic.cache
import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.mock
import com.twitter.serial.util.SerializationUtils import com.twitter.serial.util.SerializationUtils
import java.io.File
import org.amshove.kluent.`it returns` import org.amshove.kluent.`it returns`
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.rules.TemporaryFolder import org.junit.rules.TemporaryFolder
import java.io.File
internal const val INTERNAL_DATA_FOLDER = "data" internal const val INTERNAL_DATA_FOLDER = "data"
internal const val INTERNAL_CACHE_FOLDER = "cache" internal const val INTERNAL_CACHE_FOLDER = "cache"

View File

@ -1,12 +1,12 @@
package org.moire.ultrasonic.cache package org.moire.ultrasonic.cache
import java.io.File
import org.amshove.kluent.`should be equal to` import org.amshove.kluent.`should be equal to`
import org.amshove.kluent.`should contain` import org.amshove.kluent.`should contain`
import org.amshove.kluent.`should equal` import org.amshove.kluent.`should equal`
import org.junit.Test import org.junit.Test
import org.moire.ultrasonic.cache.serializers.getMusicFolderSerializer import org.moire.ultrasonic.cache.serializers.getMusicFolderSerializer
import org.moire.ultrasonic.domain.MusicFolder import org.moire.ultrasonic.domain.MusicFolder
import java.io.File
/** /**
* Integration test for [PermanentFileStorage]. * Integration test for [PermanentFileStorage].

View File

@ -32,8 +32,8 @@ class ArtistSerializerTest : BaseStorageTest() {
@Test @Test
fun `Should correctly serialize list of Artists`() { fun `Should correctly serialize list of Artists`() {
val itemsList = listOf( val itemsList = listOf(
Artist(id = "1"), Artist(id = "1"),
Artist(id = "2", name = "some") Artist(id = "2", name = "some")
) )
storage.store("some-name", itemsList, getArtistListSerializer()) storage.store("some-name", itemsList, getArtistListSerializer())
@ -45,8 +45,8 @@ class ArtistSerializerTest : BaseStorageTest() {
fun `Should correctly deserialize list of Artists`() { fun `Should correctly deserialize list of Artists`() {
val name = "some-name" val name = "some-name"
val itemsList = listOf( val itemsList = listOf(
Artist(id = "1"), Artist(id = "1"),
Artist(id = "2", name = "some") Artist(id = "2", name = "some")
) )
storage.store(name, itemsList, getArtistListSerializer()) storage.store(name, itemsList, getArtistListSerializer())

View File

@ -12,11 +12,10 @@ import org.moire.ultrasonic.domain.Indexes
class IndexesSerializerTest : BaseStorageTest() { class IndexesSerializerTest : BaseStorageTest() {
@Test @Test
fun `Should correctly serialize Indexes object`() { fun `Should correctly serialize Indexes object`() {
val item = Indexes(220L, "", mutableListOf( val item = Indexes(
Artist("12") 220L, "", mutableListOf(Artist("12")),
), mutableListOf( mutableListOf(Artist("233", "some"))
Artist("233", "some") )
))
storage.store("some-name", item, getIndexesSerializer()) storage.store("some-name", item, getIndexesSerializer())
@ -26,11 +25,10 @@ class IndexesSerializerTest : BaseStorageTest() {
@Test @Test
fun `Should correctly deserialize Indexes object`() { fun `Should correctly deserialize Indexes object`() {
val name = "some-name" val name = "some-name"
val item = Indexes(220L, "", mutableListOf( val item = Indexes(
Artist("12") 220L, "", mutableListOf(Artist("12")),
), mutableListOf( mutableListOf(Artist("233", "some"))
Artist("233", "some") )
))
storage.store(name, item, getIndexesSerializer()) storage.store(name, item, getIndexesSerializer())
val loadedItem = storage.load(name, getIndexesSerializer()) val loadedItem = storage.load(name, getIndexesSerializer())

View File

@ -32,8 +32,8 @@ class MusicFolderSerializerTest : BaseStorageTest() {
@Test @Test
fun `Should correctly serialize list of MusicFolders objects`() { fun `Should correctly serialize list of MusicFolders objects`() {
val itemsList = listOf( val itemsList = listOf(
MusicFolder("1", "1"), MusicFolder("1", "1"),
MusicFolder("2", "2") MusicFolder("2", "2")
) )
storage.store("some-name", itemsList, getMusicFolderListSerializer()) storage.store("some-name", itemsList, getMusicFolderListSerializer())
@ -45,8 +45,8 @@ class MusicFolderSerializerTest : BaseStorageTest() {
fun `Should correctly deserialize list of MusicFolder objects`() { fun `Should correctly deserialize list of MusicFolder objects`() {
val name = "some-name" val name = "some-name"
val itemsList = listOf( val itemsList = listOf(
MusicFolder("1", "1"), MusicFolder("1", "1"),
MusicFolder("2", "2") MusicFolder("2", "2")
) )
storage.store(name, itemsList, getMusicFolderListSerializer()) storage.store(name, itemsList, getMusicFolderListSerializer())

View File

@ -1,9 +1,8 @@
package org.moire.ultrasonic.domain package org.moire.ultrasonic.domain
import org.moire.ultrasonic.domain.MusicDirectory.Entry
import java.io.Serializable import java.io.Serializable
import java.util.Date import java.util.Date
import org.moire.ultrasonic.domain.MusicDirectory.Entry
data class Bookmark( data class Bookmark(
val position: Int = 0, val position: Int = 0,

View File

@ -1,7 +1,7 @@
package org.moire.ultrasonic.domain package org.moire.ultrasonic.domain
import org.moire.ultrasonic.domain.MusicDirectory.Entry
import java.io.Serializable import java.io.Serializable
import org.moire.ultrasonic.domain.MusicDirectory.Entry
data class Share( data class Share(
var id: String? = null, var id: String? = null,

View File

@ -93,7 +93,7 @@ final class ActionBarHelperCompat {
Class supportActivity = activity.getClass(); Class supportActivity = activity.getClass();
Method getActionBar = supportActivity.getMethod("getSupportActionBar"); Method getActionBar = supportActivity.getMethod("getSupportActionBar");
mActionBar = getActionBar.invoke(activity, null); mActionBar = getActionBar.invoke(activity, (Object)null);
Class supportActionBar = mActionBar.getClass(); Class supportActionBar = mActionBar.getClass();
mHomeAsUpEnabled = supportActionBar.getMethod("setDisplayHomeAsUpEnabled", Boolean.TYPE); mHomeAsUpEnabled = supportActionBar.getMethod("setDisplayHomeAsUpEnabled", Boolean.TYPE);

View File

@ -1,7 +1,7 @@
package org.moire.ultrasonic.subsonic.loader.image package org.moire.ultrasonic.subsonic.loader.image
import okio.Okio
import java.io.InputStream import java.io.InputStream
import okio.Okio
fun Any.loadResourceStream(name: String): InputStream { fun Any.loadResourceStream(name: String): InputStream {
val source = Okio.buffer(Okio.source(javaClass.classLoader.getResourceAsStream(name))) val source = Okio.buffer(Okio.source(javaClass.classLoader.getResourceAsStream(name)))

View File

@ -7,6 +7,7 @@ import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever import com.nhaarman.mockito_kotlin.whenever
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import com.squareup.picasso.Request import com.squareup.picasso.Request
import java.io.IOException
import org.amshove.kluent.`should equal` import org.amshove.kluent.`should equal`
import org.amshove.kluent.`should not be` import org.amshove.kluent.`should not be`
import org.amshove.kluent.`should throw` import org.amshove.kluent.`should throw`
@ -16,7 +17,6 @@ import org.junit.runner.RunWith
import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient
import org.moire.ultrasonic.api.subsonic.response.StreamResponse import org.moire.ultrasonic.api.subsonic.response.StreamResponse
import org.robolectric.RobolectricTestRunner import org.robolectric.RobolectricTestRunner
import java.io.IOException
@RunWith(RobolectricTestRunner::class) @RunWith(RobolectricTestRunner::class)
class CoverArtRequestHandlerTest { class CoverArtRequestHandlerTest {

View File

@ -3,9 +3,9 @@ package org.moire.ultrasonic.subsonic.loader.image
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import com.squareup.picasso.Request import com.squareup.picasso.Request
import com.squareup.picasso.RequestHandler import com.squareup.picasso.RequestHandler
import java.io.IOException
import okio.Okio import okio.Okio
import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient
import java.io.IOException
/** /**
* Loads avatars from subsonic api. * Loads avatars from subsonic api.

View File

@ -3,9 +3,9 @@ package org.moire.ultrasonic.subsonic.loader.image
import com.squareup.picasso.Picasso.LoadedFrom.NETWORK import com.squareup.picasso.Picasso.LoadedFrom.NETWORK
import com.squareup.picasso.Request import com.squareup.picasso.Request
import com.squareup.picasso.RequestHandler import com.squareup.picasso.RequestHandler
import java.io.IOException
import okio.Okio import okio.Okio
import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient
import java.io.IOException
/** /**
* Loads cover arts from subsonic api. * Loads cover arts from subsonic api.
@ -14,8 +14,8 @@ class CoverArtRequestHandler(private val apiClient: SubsonicAPIClient) : Request
override fun canHandleRequest(data: Request): Boolean { override fun canHandleRequest(data: Request): Boolean {
return with(data.uri) { return with(data.uri) {
scheme == SCHEME && scheme == SCHEME &&
authority == AUTHORITY && authority == AUTHORITY &&
path == "/$COVER_ART_PATH" path == "/$COVER_ART_PATH"
} }
} }

View File

@ -3,7 +3,7 @@ package org.moire.ultrasonic.subsonic.loader.image
import android.net.Uri import android.net.Uri
internal const val SCHEME = "subsonic_api" internal const val SCHEME = "subsonic_api"
internal const val AUTHORITY = BuildConfig.APPLICATION_ID internal const val AUTHORITY = BuildConfig.LIBRARY_PACKAGE_NAME
internal const val COVER_ART_PATH = "cover_art" internal const val COVER_ART_PATH = "cover_art"
internal const val AVATAR_PATH = "avatar" internal const val AVATAR_PATH = "avatar"
internal const val QUERY_ID = "id" internal const val QUERY_ID = "id"

View File

@ -1,5 +1,11 @@
package org.moire.ultrasonic.api.subsonic package org.moire.ultrasonic.api.subsonic
import java.io.InputStream
import java.nio.charset.Charset
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import java.util.TimeZone
import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer import okhttp3.mockwebserver.MockWebServer
import okio.Okio import okio.Okio
@ -9,30 +15,29 @@ import org.amshove.kluent.`should not be`
import org.moire.ultrasonic.api.subsonic.response.SubsonicResponse import org.moire.ultrasonic.api.subsonic.response.SubsonicResponse
import org.moire.ultrasonic.api.subsonic.rules.MockWebServerRule import org.moire.ultrasonic.api.subsonic.rules.MockWebServerRule
import retrofit2.Response import retrofit2.Response
import java.io.InputStream
import java.nio.charset.Charset
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import java.util.TimeZone
const val USERNAME = "some-user" const val USERNAME = "some-user"
const val PASSWORD = "some-password" const val PASSWORD = "some-password"
val CLIENT_VERSION = SubsonicAPIVersions.V1_16_0 val CLIENT_VERSION = SubsonicAPIVersions.V1_16_0
const val CLIENT_ID = "test-client" const val CLIENT_ID = "test-client"
val dateFormat by lazy(LazyThreadSafetyMode.NONE, { val dateFormat by lazy(
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US) LazyThreadSafetyMode.NONE,
}) {
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US)
}
)
fun MockWebServerRule.enqueueResponse(resourceName: String) { fun MockWebServerRule.enqueueResponse(resourceName: String) {
mockWebServer.enqueueResponse(resourceName) mockWebServer.enqueueResponse(resourceName)
} }
fun MockWebServer.enqueueResponse(resourceName: String) { fun MockWebServer.enqueueResponse(resourceName: String) {
enqueue(MockResponse() enqueue(
MockResponse()
.setBody(loadJsonResponse(resourceName)) .setBody(loadJsonResponse(resourceName))
.setHeader("Content-Type", "application/json;charset=UTF-8")) .setHeader("Content-Type", "application/json;charset=UTF-8")
)
} }
fun Any.loadJsonResponse(name: String): String { fun Any.loadJsonResponse(name: String): String {

View File

@ -31,7 +31,7 @@ class GetStreamUrlTest {
client = SubsonicAPIClient(config) client = SubsonicAPIClient(config)
val baseExpectedUrl = mockWebServerRule.mockWebServer.url("").toString() val baseExpectedUrl = mockWebServerRule.mockWebServer.url("").toString()
expectedUrl = "$baseExpectedUrl/rest/stream.view?id=$id&u=$USERNAME" + expectedUrl = "$baseExpectedUrl/rest/stream.view?id=$id&u=$USERNAME" +
"&c=$CLIENT_ID&f=json&v=${V1_6_0.restApiVersion}&p=enc:${PASSWORD.toHexBytes()}" "&c=$CLIENT_ID&f=json&v=${V1_6_0.restApiVersion}&p=enc:${PASSWORD.toHexBytes()}"
} }
@Test @Test

View File

@ -26,8 +26,10 @@ class SubsonicApiCreatePlaylistTest : SubsonicAPIClientTest() {
fun `Should pass id param in request`() { fun `Should pass id param in request`() {
val id = "56" val id = "56"
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "playlistId=$id") { responseResourceName = "ping_ok.json",
expectedParam = "playlistId=$id"
) {
client.api.createPlaylist(id = id).execute() client.api.createPlaylist(id = id).execute()
} }
} }
@ -36,8 +38,10 @@ class SubsonicApiCreatePlaylistTest : SubsonicAPIClientTest() {
fun `Should pass name param in request`() { fun `Should pass name param in request`() {
val name = "some-name" val name = "some-name"
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "name=$name") { responseResourceName = "ping_ok.json",
expectedParam = "name=$name"
) {
client.api.createPlaylist(name = name).execute() client.api.createPlaylist(name = name).execute()
} }
} }
@ -46,8 +50,10 @@ class SubsonicApiCreatePlaylistTest : SubsonicAPIClientTest() {
fun `Should pass song id param in request`() { fun `Should pass song id param in request`() {
val songId = listOf("4410", "852") val songId = listOf("4410", "852")
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "songId=${songId[0]}&songId=${songId[1]}") { responseResourceName = "ping_ok.json",
expectedParam = "songId=${songId[0]}&songId=${songId[1]}"
) {
client.api.createPlaylist(songIds = songId).execute() client.api.createPlaylist(songIds = songId).execute()
} }
} }

View File

@ -1,10 +1,10 @@
package org.moire.ultrasonic.api.subsonic package org.moire.ultrasonic.api.subsonic
import java.util.Calendar
import org.amshove.kluent.`should be equal to` import org.amshove.kluent.`should be equal to`
import org.amshove.kluent.`should equal` import org.amshove.kluent.`should equal`
import org.junit.Test import org.junit.Test
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
import java.util.Calendar
/** /**
* Instrumentation test for [SubsonicAPIDefinition.createShare] call. * Instrumentation test for [SubsonicAPIDefinition.createShare] call.
@ -30,9 +30,9 @@ class SubsonicApiCreateShareTest : SubsonicAPIClientTest() {
with(response.body()!!.shares[0]) { with(response.body()!!.shares[0]) {
id `should be equal to` "0" id `should be equal to` "0"
url `should be equal to` "https://subsonic.com/ext/share/awdwo?jwt=" + url `should be equal to` "https://subsonic.com/ext/share/awdwo?jwt=" +
"eyJhbGciOiJIUzI1NiJ9." + "eyJhbGciOiJIUzI1NiJ9." +
"eyJwYXRoIjoiL2V4dC9zaGFyZS9hd2R3byIsImV4cCI6MTU0MTYyNjQzMX0.iy8dkt_ZZc8hJ692" + "eyJwYXRoIjoiL2V4dC9zaGFyZS9hd2R3byIsImV4cCI6MTU0MTYyNjQzMX0.iy8dkt_ZZc8hJ692" +
"UxorHdHWFU2RB-fMCmCA4IJ_dTw" "UxorHdHWFU2RB-fMCmCA4IJ_dTw"
username `should be equal to` "admin" username `should be equal to` "admin"
created `should equal` parseDate("2017-11-07T21:33:51.748Z") created `should equal` parseDate("2017-11-07T21:33:51.748Z")
expires `should equal` parseDate("2018-11-07T21:33:51.748Z") expires `should equal` parseDate("2018-11-07T21:33:51.748Z")
@ -40,20 +40,25 @@ class SubsonicApiCreateShareTest : SubsonicAPIClientTest() {
description `should be equal to` "Awesome link!" description `should be equal to` "Awesome link!"
visitCount `should be equal to` 0 visitCount `should be equal to` 0
items.size `should be equal to` 1 items.size `should be equal to` 1
items[0] `should equal` MusicDirectoryChild(id = "4212", parent = "4186", isDir = false, items[0] `should equal` MusicDirectoryChild(
title = "Heaven Knows", album = "Going to Hell", artist = "The Pretty Reckless", id = "4212", parent = "4186", isDir = false,
track = 3, year = 2014, genre = "Hard Rock", coverArt = "4186", size = 9025090, title = "Heaven Knows", album = "Going to Hell", artist = "The Pretty Reckless",
contentType = "audio/mpeg", suffix = "mp3", duration = 225, bitRate = 320, track = 3, year = 2014, genre = "Hard Rock", coverArt = "4186", size = 9025090,
path = "The Pretty Reckless/Going to Hell/03 Heaven Knows.mp3", isVideo = false, contentType = "audio/mpeg", suffix = "mp3", duration = 225, bitRate = 320,
playCount = 2, discNumber = 1, created = parseDate("2016-10-23T21:30:40.000Z"), path = "The Pretty Reckless/Going to Hell/03 Heaven Knows.mp3", isVideo = false,
albumId = "388", artistId = "238", type = "music") playCount = 2, discNumber = 1,
created = parseDate("2016-10-23T21:30:40.000Z"),
albumId = "388", artistId = "238", type = "music"
)
} }
} }
@Test @Test
fun `Should pass ids in request param`() { fun `Should pass ids in request param`() {
val idsList = listOf("some-id1", "some-id2") val idsList = listOf("some-id1", "some-id2")
mockWebServerRule.assertRequestParam(expectedParam = "id=${idsList[0]}&id=${idsList[1]}") { mockWebServerRule.assertRequestParam(
expectedParam = "id=${idsList[0]}&id=${idsList[1]}"
) {
client.api.createShare(idsList).execute() client.api.createShare(idsList).execute()
} }
} }
@ -64,7 +69,7 @@ class SubsonicApiCreateShareTest : SubsonicAPIClientTest() {
mockWebServerRule.assertRequestParam(expectedParam = "description=$description") { mockWebServerRule.assertRequestParam(expectedParam = "description=$description") {
client.api.createShare(idsToShare = listOf("id1", "id2"), description = description) client.api.createShare(idsToShare = listOf("id1", "id2"), description = description)
.execute() .execute()
} }
} }

View File

@ -26,8 +26,10 @@ class SubsonicApiDeletePlaylistTest : SubsonicAPIClientTest() {
fun `Should pass id param in request`() { fun `Should pass id param in request`() {
val id = "534" val id = "534"
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "id=$id") { responseResourceName = "ping_ok.json",
expectedParam = "id=$id"
) {
client.api.deletePlaylist(id).execute() client.api.deletePlaylist(id).execute()
} }
} }

View File

@ -1,5 +1,6 @@
package org.moire.ultrasonic.api.subsonic package org.moire.ultrasonic.api.subsonic
import java.io.IOException
import org.amshove.kluent.`should equal` import org.amshove.kluent.`should equal`
import org.amshove.kluent.`should not be` import org.amshove.kluent.`should not be`
import org.amshove.kluent.`should throw` import org.amshove.kluent.`should throw`
@ -15,7 +16,6 @@ import org.moire.ultrasonic.api.subsonic.SubsonicError.UserNotAuthorizedForOpera
import org.moire.ultrasonic.api.subsonic.SubsonicError.WrongUsernameOrPassword import org.moire.ultrasonic.api.subsonic.SubsonicError.WrongUsernameOrPassword
import org.moire.ultrasonic.api.subsonic.response.SubsonicResponse import org.moire.ultrasonic.api.subsonic.response.SubsonicResponse
import retrofit2.Response import retrofit2.Response
import java.io.IOException
/** /**
* Integration test that checks validity of api errors parsing. * Integration test that checks validity of api errors parsing.
@ -150,8 +150,8 @@ class SubsonicApiErrorsTest : SubsonicAPIClientTest() {
} }
private fun Response<SubsonicResponse>.assertError(expectedError: SubsonicError) = private fun Response<SubsonicResponse>.assertError(expectedError: SubsonicError) =
with(body()!!) { with(body()!!) {
error `should not be` null error `should not be` null
error `should equal` expectedError error `should equal` expectedError
} }
} }

View File

@ -30,14 +30,18 @@ class SubsonicApiGetAlbumList2Test : SubsonicAPIClientTest() {
assertResponseSuccessful(response) assertResponseSuccessful(response)
with(response.body()!!.albumList) { with(response.body()!!.albumList) {
this.size `should be equal to` 2 this.size `should be equal to` 2
this[0] `should equal` Album(id = "962", name = "Fury", artist = "Sick Puppies", this[0] `should equal` Album(
artistId = "473", coverArt = "al-962", songCount = 13, duration = 2591, id = "962", name = "Fury", artist = "Sick Puppies",
created = parseDate("2017-09-02T17:34:51.000Z"), year = 2016, artistId = "473", coverArt = "al-962", songCount = 13, duration = 2591,
genre = "Alternative Rock") created = parseDate("2017-09-02T17:34:51.000Z"), year = 2016,
this[1] `should equal` Album(id = "961", name = "Endless Forms Most Beautiful", genre = "Alternative Rock"
artist = "Nightwish", artistId = "559", coverArt = "al-961", songCount = 22, )
duration = 9469, created = parseDate("2017-09-02T16:22:47.000Z"), this[1] `should equal` Album(
year = 2015, genre = "Symphonic Metal") id = "961", name = "Endless Forms Most Beautiful",
artist = "Nightwish", artistId = "559", coverArt = "al-961", songCount = 22,
duration = 9469, created = parseDate("2017-09-02T16:22:47.000Z"),
year = 2015, genre = "Symphonic Metal"
)
} }
} }
@ -45,8 +49,10 @@ class SubsonicApiGetAlbumList2Test : SubsonicAPIClientTest() {
fun `Should pass type in request params`() { fun `Should pass type in request params`() {
val type = AlbumListType.SORTED_BY_NAME val type = AlbumListType.SORTED_BY_NAME
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "type=${type.typeName}") { responseResourceName = "get_album_list_2_ok.json",
expectedParam = "type=${type.typeName}"
) {
client.api.getAlbumList2(type = type).execute() client.api.getAlbumList2(type = type).execute()
} }
} }
@ -55,8 +61,10 @@ class SubsonicApiGetAlbumList2Test : SubsonicAPIClientTest() {
fun `Should pass size in request param`() { fun `Should pass size in request param`() {
val size = 45 val size = 45
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "size=$size") { responseResourceName = "get_album_list_2_ok.json",
expectedParam = "size=$size"
) {
client.api.getAlbumList2(STARRED, size = size).execute() client.api.getAlbumList2(STARRED, size = size).execute()
} }
} }
@ -65,8 +73,10 @@ class SubsonicApiGetAlbumList2Test : SubsonicAPIClientTest() {
fun `Should pass offset in request param`() { fun `Should pass offset in request param`() {
val offset = 33 val offset = 33
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "offset=$offset") { responseResourceName = "get_album_list_2_ok.json",
expectedParam = "offset=$offset"
) {
client.api.getAlbumList2(STARRED, offset = offset).execute() client.api.getAlbumList2(STARRED, offset = offset).execute()
} }
} }
@ -75,8 +85,10 @@ class SubsonicApiGetAlbumList2Test : SubsonicAPIClientTest() {
fun `Should pass from year in request params`() { fun `Should pass from year in request params`() {
val fromYear = 3030 val fromYear = 3030
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "fromYear=$fromYear") { responseResourceName = "get_album_list_2_ok.json",
expectedParam = "fromYear=$fromYear"
) {
client.api.getAlbumList2(STARRED, fromYear = fromYear).execute() client.api.getAlbumList2(STARRED, fromYear = fromYear).execute()
} }
} }
@ -85,8 +97,10 @@ class SubsonicApiGetAlbumList2Test : SubsonicAPIClientTest() {
fun `Should pass toYear in request param`() { fun `Should pass toYear in request param`() {
val toYear = 2014 val toYear = 2014
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "toYear=$toYear") { responseResourceName = "get_album_list_2_ok.json",
expectedParam = "toYear=$toYear"
) {
client.api.getAlbumList2(STARRED, toYear = toYear).execute() client.api.getAlbumList2(STARRED, toYear = toYear).execute()
} }
} }
@ -95,8 +109,10 @@ class SubsonicApiGetAlbumList2Test : SubsonicAPIClientTest() {
fun `Should pass genre in request param`() { fun `Should pass genre in request param`() {
val genre = "MathRock" val genre = "MathRock"
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "genre=$genre") { responseResourceName = "get_album_list_2_ok.json",
expectedParam = "genre=$genre"
) {
client.api.getAlbumList2(STARRED, genre = genre).execute() client.api.getAlbumList2(STARRED, genre = genre).execute()
} }
} }
@ -105,8 +121,10 @@ class SubsonicApiGetAlbumList2Test : SubsonicAPIClientTest() {
fun `Should pass music folder id in request param`() { fun `Should pass music folder id in request param`() {
val musicFolderId = "9422" val musicFolderId = "9422"
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "musicFolderId=$musicFolderId") { responseResourceName = "get_album_list_2_ok.json",
expectedParam = "musicFolderId=$musicFolderId"
) {
client.api.getAlbumList2(STARRED, musicFolderId = musicFolderId).execute() client.api.getAlbumList2(STARRED, musicFolderId = musicFolderId).execute()
} }
} }

View File

@ -29,11 +29,13 @@ class SubsonicApiGetAlbumListRequestTest : SubsonicAPIClientTest() {
assertResponseSuccessful(response) assertResponseSuccessful(response)
with(response.body()!!.albumList) { with(response.body()!!.albumList) {
size `should be equal to` 2 size `should be equal to` 2
this[1] `should equal` MusicDirectoryChild(id = "9997", parent = "9996", isDir = true, this[1] `should equal` MusicDirectoryChild(
title = "Endless Forms Most Beautiful", album = "Endless Forms Most Beautiful", id = "9997", parent = "9996", isDir = true,
artist = "Nightwish", year = 2015, genre = "Symphonic Metal", title = "Endless Forms Most Beautiful", album = "Endless Forms Most Beautiful",
coverArt = "9997", playCount = 11, artist = "Nightwish", year = 2015, genre = "Symphonic Metal",
created = parseDate("2017-09-02T16:22:49.000Z")) coverArt = "9997", playCount = 11,
created = parseDate("2017-09-02T16:22:49.000Z")
)
} }
} }
@ -41,8 +43,10 @@ class SubsonicApiGetAlbumListRequestTest : SubsonicAPIClientTest() {
fun `Should pass type in request params`() { fun `Should pass type in request params`() {
val listType = AlbumListType.HIGHEST val listType = AlbumListType.HIGHEST
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "type=${listType.typeName}") { responseResourceName = "get_album_list_ok.json",
expectedParam = "type=${listType.typeName}"
) {
client.api.getAlbumList(type = listType).execute() client.api.getAlbumList(type = listType).execute()
} }
} }
@ -51,8 +55,10 @@ class SubsonicApiGetAlbumListRequestTest : SubsonicAPIClientTest() {
fun `Should pass size in request params`() { fun `Should pass size in request params`() {
val size = 45 val size = 45
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "size=$size") { responseResourceName = "get_album_list_ok.json",
expectedParam = "size=$size"
) {
client.api.getAlbumList(type = BY_GENRE, size = size).execute() client.api.getAlbumList(type = BY_GENRE, size = size).execute()
} }
} }
@ -61,8 +67,10 @@ class SubsonicApiGetAlbumListRequestTest : SubsonicAPIClientTest() {
fun `Should pass offset in request params`() { fun `Should pass offset in request params`() {
val offset = 3 val offset = 3
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "offset=$offset") { responseResourceName = "get_album_list_ok.json",
expectedParam = "offset=$offset"
) {
client.api.getAlbumList(type = BY_GENRE, offset = offset).execute() client.api.getAlbumList(type = BY_GENRE, offset = offset).execute()
} }
} }
@ -71,8 +79,10 @@ class SubsonicApiGetAlbumListRequestTest : SubsonicAPIClientTest() {
fun `Should pass from year in request params`() { fun `Should pass from year in request params`() {
val fromYear = 2001 val fromYear = 2001
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "fromYear=$fromYear") { responseResourceName = "get_album_list_ok.json",
expectedParam = "fromYear=$fromYear"
) {
client.api.getAlbumList(type = BY_GENRE, fromYear = fromYear).execute() client.api.getAlbumList(type = BY_GENRE, fromYear = fromYear).execute()
} }
} }
@ -81,8 +91,10 @@ class SubsonicApiGetAlbumListRequestTest : SubsonicAPIClientTest() {
fun `Should pass to year in request params`() { fun `Should pass to year in request params`() {
val toYear = 2017 val toYear = 2017
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "toYear=$toYear") { responseResourceName = "get_album_list_ok.json",
expectedParam = "toYear=$toYear"
) {
client.api.getAlbumList(type = BY_GENRE, toYear = toYear).execute() client.api.getAlbumList(type = BY_GENRE, toYear = toYear).execute()
} }
} }
@ -91,8 +103,10 @@ class SubsonicApiGetAlbumListRequestTest : SubsonicAPIClientTest() {
fun `Should pass genre in request params`() { fun `Should pass genre in request params`() {
val genre = "Rock" val genre = "Rock"
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "genre=$genre") { responseResourceName = "get_album_list_ok.json",
expectedParam = "genre=$genre"
) {
client.api.getAlbumList(type = BY_GENRE, genre = genre).execute() client.api.getAlbumList(type = BY_GENRE, genre = genre).execute()
} }
} }
@ -101,8 +115,10 @@ class SubsonicApiGetAlbumListRequestTest : SubsonicAPIClientTest() {
fun `Should pass music folder id in request params`() { fun `Should pass music folder id in request params`() {
val folderId = "545" val folderId = "545"
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_list_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "musicFolderId=$folderId") { responseResourceName = "get_album_list_ok.json",
expectedParam = "musicFolderId=$folderId"
) {
client.api.getAlbumList(type = BY_GENRE, musicFolderId = folderId).execute() client.api.getAlbumList(type = BY_GENRE, musicFolderId = folderId).execute()
} }
} }

View File

@ -25,8 +25,10 @@ class SubsonicApiGetAlbumTest : SubsonicAPIClientTest() {
fun `Should add id to request params`() { fun `Should add id to request params`() {
val id = "76" val id = "76"
mockWebServerRule.assertRequestParam(responseResourceName = "get_album_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "id=$id") { responseResourceName = "get_album_ok.json",
expectedParam = "id=$id"
) {
client.api.getAlbum(id).execute() client.api.getAlbum(id).execute()
} }
} }
@ -50,22 +52,26 @@ class SubsonicApiGetAlbumTest : SubsonicAPIClientTest() {
year `should be equal to` 2008 year `should be equal to` 2008
genre `should be equal to` "Hard Rock" genre `should be equal to` "Hard Rock"
songList.size `should be equal to` 15 songList.size `should be equal to` 15
songList[0] `should equal` MusicDirectoryChild(id = "6491", parent = "6475", songList[0] `should equal` MusicDirectoryChild(
isDir = false, title = "Rock 'n' Roll Train", album = "Black Ice", id = "6491", parent = "6475",
artist = "AC/DC", track = 1, year = 2008, genre = "Hard Rock", isDir = false, title = "Rock 'n' Roll Train", album = "Black Ice",
coverArt = "6475", size = 7205451, contentType = "audio/mpeg", suffix = "mp3", artist = "AC/DC", track = 1, year = 2008, genre = "Hard Rock",
duration = 261, bitRate = 219, coverArt = "6475", size = 7205451, contentType = "audio/mpeg", suffix = "mp3",
path = "AC_DC/Black Ice/01 Rock 'n' Roll Train.mp3", duration = 261, bitRate = 219,
isVideo = false, playCount = 0, discNumber = 1, path = "AC_DC/Black Ice/01 Rock 'n' Roll Train.mp3",
created = parseDate("2016-10-23T15:31:20.000Z"), isVideo = false, playCount = 0, discNumber = 1,
albumId = "618", artistId = "362", type = "music") created = parseDate("2016-10-23T15:31:20.000Z"),
songList[5] `should equal` MusicDirectoryChild(id = "6492", parent = "6475", albumId = "618", artistId = "362", type = "music"
isDir = false, title = "Smash 'n' Grab", album = "Black Ice", artist = "AC/DC", )
track = 6, year = 2008, genre = "Hard Rock", coverArt = "6475", size = 6697204, songList[5] `should equal` MusicDirectoryChild(
contentType = "audio/mpeg", suffix = "mp3", duration = 246, bitRate = 216, id = "6492", parent = "6475",
path = "AC_DC/Black Ice/06 Smash 'n' Grab.mp3", isVideo = false, playCount = 0, isDir = false, title = "Smash 'n' Grab", album = "Black Ice", artist = "AC/DC",
discNumber = 1, created = parseDate("2016-10-23T15:31:20.000Z"), track = 6, year = 2008, genre = "Hard Rock", coverArt = "6475", size = 6697204,
albumId = "618", artistId = "362", type = "music") contentType = "audio/mpeg", suffix = "mp3", duration = 246, bitRate = 216,
path = "AC_DC/Black Ice/06 Smash 'n' Grab.mp3", isVideo = false, playCount = 0,
discNumber = 1, created = parseDate("2016-10-23T15:31:20.000Z"),
albumId = "618", artistId = "362", type = "music"
)
} }
} }
} }

View File

@ -25,8 +25,10 @@ class SubsonicApiGetArtistTest : SubsonicAPIClientTest() {
fun `Should pass id param in request`() { fun `Should pass id param in request`() {
val id = "929" val id = "929"
mockWebServerRule.assertRequestParam(responseResourceName = "get_artist_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "id=$id") { responseResourceName = "get_artist_ok.json",
expectedParam = "id=$id"
) {
client.api.getArtist(id).execute() client.api.getArtist(id).execute()
} }
} }
@ -44,14 +46,18 @@ class SubsonicApiGetArtistTest : SubsonicAPIClientTest() {
coverArt `should be equal to` "ar-362" coverArt `should be equal to` "ar-362"
albumCount `should be equal to` 2 albumCount `should be equal to` 2
albumsList.size `should be equal to` 2 albumsList.size `should be equal to` 2
albumsList[0] `should equal` Album(id = "618", name = "Black Ice", artist = "AC/DC", albumsList[0] `should equal` Album(
artistId = "362", coverArt = "al-618", songCount = 15, duration = 3331, id = "618", name = "Black Ice", artist = "AC/DC",
created = parseDate("2016-10-23T15:31:22.000Z"), artistId = "362", coverArt = "al-618", songCount = 15, duration = 3331,
year = 2008, genre = "Hard Rock") created = parseDate("2016-10-23T15:31:22.000Z"),
albumsList[1] `should equal` Album(id = "617", name = "Rock or Bust", artist = "AC/DC", year = 2008, genre = "Hard Rock"
artistId = "362", coverArt = "al-617", songCount = 11, duration = 2095, )
created = parseDate("2016-10-23T15:31:23.000Z"), albumsList[1] `should equal` Album(
year = 2014, genre = "Hard Rock") id = "617", name = "Rock or Bust", artist = "AC/DC",
artistId = "362", coverArt = "al-617", songCount = 11, duration = 2095,
created = parseDate("2016-10-23T15:31:23.000Z"),
year = 2014, genre = "Hard Rock"
)
} }
} }
} }

View File

@ -35,17 +35,26 @@ class SubsonicApiGetArtistsTest : SubsonicAPIClientTest() {
shortcutList `should equal` emptyList() shortcutList `should equal` emptyList()
indexList.size `should be equal to` 2 indexList.size `should be equal to` 2
indexList `should equal` listOf( indexList `should equal` listOf(
Index(name = "A", artists = listOf( Index(
Artist(id = "362", name = "AC/DC", coverArt = "ar-362", albumCount = 2), name = "A",
Artist(id = "254", name = "Acceptance", coverArt = "ar-254", artists = listOf(
albumCount = 1) Artist(id = "362", name = "AC/DC", coverArt = "ar-362", albumCount = 2),
)), Artist(id = "254", name = "Acceptance", coverArt = "ar-254", albumCount = 1)
Index(name = "T", artists = listOf( )
Artist(id = "516", name = "Tangerine Dream", coverArt = "ar-516", ),
albumCount = 1), Index(
Artist(id = "242", name = "Taproot", coverArt = "ar-242", name = "T",
albumCount = 2) artists = listOf(
)) Artist(
id = "516", name = "Tangerine Dream", coverArt = "ar-516",
albumCount = 1
),
Artist(
id = "242", name = "Taproot", coverArt = "ar-242",
albumCount = 2
)
)
)
) )
} }
} }
@ -55,8 +64,10 @@ class SubsonicApiGetArtistsTest : SubsonicAPIClientTest() {
mockWebServerRule.enqueueResponse("get_artists_ok.json") mockWebServerRule.enqueueResponse("get_artists_ok.json")
val musicFolderId = "101" val musicFolderId = "101"
mockWebServerRule.assertRequestParam(responseResourceName = "get_artists_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "musicFolderId=$musicFolderId") { responseResourceName = "get_artists_ok.json",
expectedParam = "musicFolderId=$musicFolderId"
) {
client.api.getArtists(musicFolderId).execute() client.api.getArtists(musicFolderId).execute()
} }
} }

View File

@ -40,8 +40,10 @@ class SubsonicApiGetAvatarTest : SubsonicAPIClientTest() {
@Test @Test
fun `Should return successful call stream`() { fun `Should return successful call stream`() {
mockWebServerRule.mockWebServer.enqueue(MockResponse() mockWebServerRule.mockWebServer.enqueue(
.setBody(mockWebServerRule.loadJsonResponse("ping_ok.json"))) MockResponse()
.setBody(mockWebServerRule.loadJsonResponse("ping_ok.json"))
)
val response = client.stream("some") val response = client.stream("some")

View File

@ -32,15 +32,17 @@ class SubsonicApiGetBookmarksTest : SubsonicAPIClientTest() {
comment `should be equal to` "Look at this" comment `should be equal to` "Look at this"
created `should equal` parseDate("2017-11-18T15:22:22.144Z") created `should equal` parseDate("2017-11-18T15:22:22.144Z")
changed `should equal` parseDate("2017-11-18T15:22:22.144Z") changed `should equal` parseDate("2017-11-18T15:22:22.144Z")
entry `should equal` MusicDirectoryChild(id = "10349", parent = "10342", entry `should equal` MusicDirectoryChild(
isDir = false, title = "Amerika", album = "Home of the Strange", id = "10349", parent = "10342",
artist = "Young the Giant", track = 1, year = 2016, genre = "Indie Rock", isDir = false, title = "Amerika", album = "Home of the Strange",
coverArt = "10342", size = 9628673, contentType = "audio/mpeg", artist = "Young the Giant", track = 1, year = 2016, genre = "Indie Rock",
suffix = "mp3", duration = 240, bitRate = 320, coverArt = "10342", size = 9628673, contentType = "audio/mpeg",
path = "Young the Giant/Home of the Strange/01 Amerika.mp3", suffix = "mp3", duration = 240, bitRate = 320,
isVideo = false, playCount = 2, discNumber = 1, path = "Young the Giant/Home of the Strange/01 Amerika.mp3",
created = parseDate("2017-11-01T17:46:52.000Z"), isVideo = false, playCount = 2, discNumber = 1,
albumId = "984", artistId = "571", type = "music") created = parseDate("2017-11-01T17:46:52.000Z"),
albumId = "984", artistId = "571", type = "music"
)
} }
} }
} }

View File

@ -27,10 +27,14 @@ class SubsonicApiGetChatMessagesTest : SubsonicAPIClientTest() {
assertResponseSuccessful(response) assertResponseSuccessful(response)
with(response.body()!!.chatMessages) { with(response.body()!!.chatMessages) {
size `should be equal to` 2 size `should be equal to` 2
this[0] `should equal` ChatMessage(username = "sindre", time = 1269771845310, this[0] `should equal` ChatMessage(
message = "Sindre was here") username = "sindre", time = 1269771845310,
this[1] `should equal` ChatMessage(username = "ben", time = 1269771842504, message = "Sindre was here"
message = "Ben too") )
this[1] `should equal` ChatMessage(
username = "ben", time = 1269771842504,
message = "Ben too"
)
} }
} }

View File

@ -40,8 +40,10 @@ class SubsonicApiGetCoverArtTest : SubsonicAPIClientTest() {
@Test @Test
fun `Should return successful call stream`() { fun `Should return successful call stream`() {
mockWebServerRule.mockWebServer.enqueue(MockResponse() mockWebServerRule.mockWebServer.enqueue(
.setBody(mockWebServerRule.loadJsonResponse("ping_ok.json"))) MockResponse()
.setBody(mockWebServerRule.loadJsonResponse("ping_ok.json"))
)
val response = client.getCoverArt("some-id") val response = client.getCoverArt("some-id")

View File

@ -23,19 +23,27 @@ class SubsonicApiGetIndexesTest : SubsonicAPIClientTest() {
lastModified `should equal` 1491069027523 lastModified `should equal` 1491069027523
ignoredArticles `should equal` "The El La Los Las Le Les" ignoredArticles `should equal` "The El La Los Las Le Les"
shortcutList `should equal` listOf( shortcutList `should equal` listOf(
Artist(id = "889", name = "podcasts"), Artist(id = "889", name = "podcasts"),
Artist(id = "890", name = "audiobooks") Artist(id = "890", name = "audiobooks")
) )
indexList `should equal` mutableListOf( indexList `should equal` mutableListOf(
Index("A", listOf( Index(
Artist(id = "50", name = "Ace Of Base", "A",
starred = parseDate("2017-04-02T20:16:29.815Z")), listOf(
Artist(id = "379", name = "A Perfect Circle") Artist(
)), id = "50", name = "Ace Of Base",
Index("H", listOf( starred = parseDate("2017-04-02T20:16:29.815Z")
Artist(id = "299", name = "Haddaway"), ),
Artist(id = "297", name = "Halestorm") Artist(id = "379", name = "A Perfect Circle")
)) )
),
Index(
"H",
listOf(
Artist(id = "299", name = "Haddaway"),
Artist(id = "297", name = "Halestorm")
)
)
) )
} }
} }
@ -44,8 +52,10 @@ class SubsonicApiGetIndexesTest : SubsonicAPIClientTest() {
fun `Should add music folder id as a query param for getIndexes api call`() { fun `Should add music folder id as a query param for getIndexes api call`() {
val musicFolderId = "9" val musicFolderId = "9"
mockWebServerRule.assertRequestParam(responseResourceName = "get_indexes_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "musicFolderId=$musicFolderId") { responseResourceName = "get_indexes_ok.json",
expectedParam = "musicFolderId=$musicFolderId"
) {
client.api.getIndexes(musicFolderId, null).execute() client.api.getIndexes(musicFolderId, null).execute()
} }
} }
@ -54,8 +64,10 @@ class SubsonicApiGetIndexesTest : SubsonicAPIClientTest() {
fun `Should add ifModifiedSince as a query param for getIndexes api call`() { fun `Should add ifModifiedSince as a query param for getIndexes api call`() {
val ifModifiedSince = System.currentTimeMillis() val ifModifiedSince = System.currentTimeMillis()
mockWebServerRule.assertRequestParam(responseResourceName = "get_indexes_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "ifModifiedSince=$ifModifiedSince") { responseResourceName = "get_indexes_ok.json",
expectedParam = "ifModifiedSince=$ifModifiedSince"
) {
client.api.getIndexes(null, ifModifiedSince).execute() client.api.getIndexes(null, ifModifiedSince).execute()
} }
} }

View File

@ -18,10 +18,12 @@ class SubsonicApiGetLicenseTest : SubsonicAPIClientTest() {
assertResponseSuccessful(response) assertResponseSuccessful(response)
with(response.body()!!) { with(response.body()!!) {
assertBaseResponseOk() assertBaseResponseOk()
license `should equal` License(valid = true, license `should equal` License(
trialExpires = parseDate("2016-11-23T20:17:15.206Z"), valid = true,
email = "someone@example.net", trialExpires = parseDate("2016-11-23T20:17:15.206Z"),
licenseExpires = parseDate("8994-08-17T07:12:55.807Z")) email = "someone@example.net",
licenseExpires = parseDate("8994-08-17T07:12:55.807Z")
)
} }
} }

View File

@ -25,7 +25,7 @@ class SubsonicApiGetLyricsTest : SubsonicAPIClientTest() {
artist `should be equal to` "Amorphis" artist `should be equal to` "Amorphis"
title `should be equal to` "Alone" title `should be equal to` "Alone"
text `should be equal to` "Tear dimmed rememberance\nIn a womb of time\nBreath upon " + text `should be equal to` "Tear dimmed rememberance\nIn a womb of time\nBreath upon " +
"me\nPossessed by the" "me\nPossessed by the"
} }
} }
@ -33,8 +33,10 @@ class SubsonicApiGetLyricsTest : SubsonicAPIClientTest() {
fun `Should pass artist param in request`() { fun `Should pass artist param in request`() {
val artist = "some-artist" val artist = "some-artist"
mockWebServerRule.assertRequestParam(responseResourceName = "get_lyrics_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "artist=$artist") { responseResourceName = "get_lyrics_ok.json",
expectedParam = "artist=$artist"
) {
client.api.getLyrics(artist = artist).execute() client.api.getLyrics(artist = artist).execute()
} }
} }
@ -43,8 +45,10 @@ class SubsonicApiGetLyricsTest : SubsonicAPIClientTest() {
fun `Should pass title param in request`() { fun `Should pass title param in request`() {
val title = "some-title" val title = "some-title"
mockWebServerRule.assertRequestParam(responseResourceName = "get_lyrics_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "title=$title") { responseResourceName = "get_lyrics_ok.json",
expectedParam = "title=$title"
) {
client.api.getLyrics(title = title).execute() client.api.getLyrics(title = title).execute()
} }
} }

View File

@ -26,8 +26,10 @@ class SubsonicApiGetMusicDirectoryTest : SubsonicAPIClientTest() {
fun `GetMusicDirectory should add directory id to query params`() { fun `GetMusicDirectory should add directory id to query params`() {
val directoryId = "124" val directoryId = "124"
mockWebServerRule.assertRequestParam(responseResourceName = "get_music_directory_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "id=$directoryId") { responseResourceName = "get_music_directory_ok.json",
expectedParam = "id=$directoryId"
) {
client.api.getMusicDirectory(directoryId).execute() client.api.getMusicDirectory(directoryId).execute()
} }
} }
@ -50,22 +52,26 @@ class SubsonicApiGetMusicDirectoryTest : SubsonicAPIClientTest() {
starred `should equal` null starred `should equal` null
playCount `should be equal to` 1 playCount `should be equal to` 1
childList.size `should be` 2 childList.size `should be` 2
childList[0] `should equal` MusicDirectoryChild(id = "4844", parent = "4836", childList[0] `should equal` MusicDirectoryChild(
isDir = false, title = "Crash", album = "12 Stones", artist = "12 Stones", id = "4844", parent = "4836",
track = 1, year = 2002, genre = "Alternative Rock", coverArt = "4836", isDir = false, title = "Crash", album = "12 Stones", artist = "12 Stones",
size = 5348318L, contentType = "audio/mpeg", suffix = "mp3", duration = 222, track = 1, year = 2002, genre = "Alternative Rock", coverArt = "4836",
bitRate = 192, path = "12 Stones/12 Stones/01 Crash.mp3", isVideo = false, size = 5348318L, contentType = "audio/mpeg", suffix = "mp3", duration = 222,
playCount = 0, discNumber = 1, bitRate = 192, path = "12 Stones/12 Stones/01 Crash.mp3", isVideo = false,
created = parseDate("2016-10-23T15:19:10.000Z"), playCount = 0, discNumber = 1,
albumId = "454", artistId = "288", type = "music") created = parseDate("2016-10-23T15:19:10.000Z"),
childList[1] `should equal` MusicDirectoryChild(id = "4845", parent = "4836", albumId = "454", artistId = "288", type = "music"
isDir = false, title = "Broken", album = "12 Stones", artist = "12 Stones", )
track = 2, year = 2002, genre = "Alternative Rock", coverArt = "4836", childList[1] `should equal` MusicDirectoryChild(
size = 4309043L, contentType = "audio/mpeg", suffix = "mp3", duration = 179, id = "4845", parent = "4836",
bitRate = 192, path = "12 Stones/12 Stones/02 Broken.mp3", isVideo = false, isDir = false, title = "Broken", album = "12 Stones", artist = "12 Stones",
playCount = 0, discNumber = 1, track = 2, year = 2002, genre = "Alternative Rock", coverArt = "4836",
created = parseDate("2016-10-23T15:19:09.000Z"), size = 4309043L, contentType = "audio/mpeg", suffix = "mp3", duration = 179,
albumId = "454", artistId = "288", type = "music") bitRate = 192, path = "12 Stones/12 Stones/02 Broken.mp3", isVideo = false,
playCount = 0, discNumber = 1,
created = parseDate("2016-10-23T15:19:09.000Z"),
albumId = "454", artistId = "288", type = "music"
)
} }
} }
} }

View File

@ -18,8 +18,9 @@ class SubsonicApiGetMusicFoldersTest : SubsonicAPIClientTest() {
with(response.body()!!) { with(response.body()!!) {
assertBaseResponseOk() assertBaseResponseOk()
musicFolders `should equal` listOf( musicFolders `should equal` listOf(
MusicFolder("0", "Music"), MusicFolder("0", "Music"),
MusicFolder("2", "Test")) MusicFolder("2", "Test")
)
} }
} }

View File

@ -39,15 +39,17 @@ class SubsonicApiGetPlaylistTest : SubsonicAPIClientTest() {
changed `should equal` parseDate("2017-08-27T11:17:26.218Z") changed `should equal` parseDate("2017-08-27T11:17:26.218Z")
coverArt `should be equal to` "pl-0" coverArt `should be equal to` "pl-0"
entriesList.size `should be equal to` 2 entriesList.size `should be equal to` 2
entriesList[1] `should equal` MusicDirectoryChild(id = "4215", parent = "4186", entriesList[1] `should equal` MusicDirectoryChild(
isDir = false, title = "Going to Hell", album = "Going to Hell", id = "4215", parent = "4186",
artist = "The Pretty Reckless", track = 2, year = 2014, isDir = false, title = "Going to Hell", album = "Going to Hell",
genre = "Hard Rock", coverArt = "4186", size = 11089627, artist = "The Pretty Reckless", track = 2, year = 2014,
contentType = "audio/mpeg", suffix = "mp3", duration = 277, bitRate = 320, genre = "Hard Rock", coverArt = "4186", size = 11089627,
path = "The Pretty Reckless/Going to Hell/02 Going to Hell.mp3", contentType = "audio/mpeg", suffix = "mp3", duration = 277, bitRate = 320,
isVideo = false, playCount = 0, discNumber = 1, path = "The Pretty Reckless/Going to Hell/02 Going to Hell.mp3",
created = parseDate("2016-10-23T21:30:41.000Z"), isVideo = false, playCount = 0, discNumber = 1,
albumId = "388", artistId = "238", type = "music") created = parseDate("2016-10-23T21:30:41.000Z"),
albumId = "388", artistId = "238", type = "music"
)
} }
} }
@ -55,8 +57,10 @@ class SubsonicApiGetPlaylistTest : SubsonicAPIClientTest() {
fun `Should pass id as request param`() { fun `Should pass id as request param`() {
val playlistId = "453" val playlistId = "453"
mockWebServerRule.assertRequestParam(responseResourceName = "get_playlist_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "id=$playlistId") { responseResourceName = "get_playlist_ok.json",
expectedParam = "id=$playlistId"
) {
client.api.getPlaylist(playlistId).execute() client.api.getPlaylist(playlistId).execute()
} }
} }

View File

@ -29,12 +29,14 @@ class SubsonicApiGetPlaylistsTest : SubsonicAPIClientTest() {
assertResponseSuccessful(response) assertResponseSuccessful(response)
with(response.body()!!.playlists) { with(response.body()!!.playlists) {
size `should be equal to` 1 size `should be equal to` 1
this[0] `should equal` Playlist(id = "0", name = "Aug 27, 2017 11:17 AM", this[0] `should equal` Playlist(
owner = "admin", public = false, songCount = 16, duration = 3573, id = "0", name = "Aug 27, 2017 11:17 AM",
comment = "Some comment", owner = "admin", public = false, songCount = 16, duration = 3573,
created = parseDate("2017-08-27T11:17:26.216Z"), comment = "Some comment",
changed = parseDate("2017-08-27T11:17:26.218Z"), created = parseDate("2017-08-27T11:17:26.216Z"),
coverArt = "pl-0") changed = parseDate("2017-08-27T11:17:26.218Z"),
coverArt = "pl-0"
)
} }
} }
@ -42,8 +44,10 @@ class SubsonicApiGetPlaylistsTest : SubsonicAPIClientTest() {
fun `Should pass username as a parameter`() { fun `Should pass username as a parameter`() {
val username = "SomeUsername" val username = "SomeUsername"
mockWebServerRule.assertRequestParam(responseResourceName = "get_playlists_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "username=$username") { responseResourceName = "get_playlists_ok.json",
expectedParam = "username=$username"
) {
client.api.getPlaylists(username = username).execute() client.api.getPlaylists(username = username).execute()
} }
} }

View File

@ -34,33 +34,35 @@ class SubsonicApiGetPodcastsTest : SubsonicAPIClientTest() {
url `should be equal to` "http://feeds.codenewbie.org/cnpodcast.xml" url `should be equal to` "http://feeds.codenewbie.org/cnpodcast.xml"
title `should be equal to` "CodeNewbie" title `should be equal to` "CodeNewbie"
description `should be equal to` "Stories and interviews from people on their coding " + description `should be equal to` "Stories and interviews from people on their coding " +
"journey." "journey."
coverArt `should be equal to` "pod-2" coverArt `should be equal to` "pod-2"
originalImageUrl `should be equal to` "http://codenewbie.blubrry.com/wp-content/" + originalImageUrl `should be equal to` "http://codenewbie.blubrry.com/wp-content/" +
"uploads/powerpress/220808.jpg" "uploads/powerpress/220808.jpg"
status `should be equal to` "completed" status `should be equal to` "completed"
errorMessage `should be equal to` "" errorMessage `should be equal to` ""
episodeList.size `should be equal to` 10 episodeList.size `should be equal to` 10
episodeList[0] `should equal` MusicDirectoryChild(id = "148", parent = "9959", episodeList[0] `should equal` MusicDirectoryChild(
isDir = false, id = "148", parent = "9959",
title = "S1:EP3 How to teach yourself computer science (Vaidehi Joshi)", isDir = false,
album = "CodeNewbie", artist = "podcasts", coverArt = "9959", title = "S1:EP3 How to teach yourself computer science (Vaidehi Joshi)",
size = 38274221, contentType = "audio/mpeg", suffix = "mp3", album = "CodeNewbie", artist = "podcasts", coverArt = "9959",
duration = 2397, bitRate = 128, isVideo = false, playCount = 0, size = 38274221, contentType = "audio/mpeg", suffix = "mp3",
created = parseDate("2017-08-30T09:33:39.000Z"), type = "podcast", duration = 2397, bitRate = 128, isVideo = false, playCount = 0,
streamId = "9982", channelId = "2", created = parseDate("2017-08-30T09:33:39.000Z"), type = "podcast",
description = "Vaidehi decided to take on a year-long challenge. " + streamId = "9982", channelId = "2",
"She'd pick a computer science topic every week, do tons of research " + description = "Vaidehi decided to take on a year-long challenge. " +
"and write a technical blog post explaining it in simple terms and " + "She'd pick a computer science topic every week, do tons of research " +
"beautiful illustrations. And then she actually did it. She tells us " + "and write a technical blog post explaining it in simple terms and " +
"about her project, basecs, how it's changed her as a developer, and " + "beautiful illustrations. And then she actually did it. She tells us " +
"how she handles the trolls and negativity from people who don't " + "about her project, basecs, how it's changed her as a developer, and " +
"appreciate her work. Show Notes Technical Writer position at " + "how she handles the trolls and negativity from people who don't " +
"CodeNewbie basecs 100 Days of Code Conway's Game of Life Hexes and " + "appreciate her work. Show Notes Technical Writer position at " +
"Other Magical Numbers (Vaidehi's blog post) Bits, Bytes, Building " + "CodeNewbie basecs 100 Days of Code Conway's Game of Life Hexes and " +
"With Binary (Vaidehi's blog post) Rust", "Other Magical Numbers (Vaidehi's blog post) Bits, Bytes, Building " +
status = "completed", "With Binary (Vaidehi's blog post) Rust",
publishDate = parseDate("2017-08-29T00:01:01.000Z")) status = "completed",
publishDate = parseDate("2017-08-29T00:01:01.000Z")
)
} }
} }
@ -68,8 +70,10 @@ class SubsonicApiGetPodcastsTest : SubsonicAPIClientTest() {
fun `Should pass include episodes in request`() { fun `Should pass include episodes in request`() {
val includeEpisodes = true val includeEpisodes = true
mockWebServerRule.assertRequestParam(responseResourceName = "get_podcasts_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "includeEpisodes=$includeEpisodes") { responseResourceName = "get_podcasts_ok.json",
expectedParam = "includeEpisodes=$includeEpisodes"
) {
client.api.getPodcasts(includeEpisodes = includeEpisodes).execute() client.api.getPodcasts(includeEpisodes = includeEpisodes).execute()
} }
} }
@ -78,8 +82,10 @@ class SubsonicApiGetPodcastsTest : SubsonicAPIClientTest() {
fun `Should pass id in request param`() { fun `Should pass id in request param`() {
val id = "249" val id = "249"
mockWebServerRule.assertRequestParam(responseResourceName = "get_podcasts_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "id=$id") { responseResourceName = "get_podcasts_ok.json",
expectedParam = "id=$id"
) {
client.api.getPodcasts(id = id).execute() client.api.getPodcasts(id = id).execute()
} }
} }

View File

@ -27,14 +27,16 @@ class SubsonicApiGetRandomSongsTest : SubsonicAPIClientTest() {
assertResponseSuccessful(response) assertResponseSuccessful(response)
with(response.body()!!.songsList) { with(response.body()!!.songsList) {
size `should be equal to` 3 size `should be equal to` 3
this[1] `should equal` MusicDirectoryChild(id = "3061", parent = "3050", isDir = false, this[1] `should equal` MusicDirectoryChild(
title = "Sure as Hell", album = "Who Are You Now?", artist = "This Providence", id = "3061", parent = "3050", isDir = false,
track = 1, year = 2009, genre = "Indie Rock", coverArt = "3050", title = "Sure as Hell", album = "Who Are You Now?", artist = "This Providence",
size = 1969692, contentType = "audio/mpeg", suffix = "mp3", duration = 110, track = 1, year = 2009, genre = "Indie Rock", coverArt = "3050",
bitRate = 142, path = "This Providence/Who Are You Now_/01 Sure as Hell.mp3", size = 1969692, contentType = "audio/mpeg", suffix = "mp3", duration = 110,
isVideo = false, playCount = 0, discNumber = 1, bitRate = 142, path = "This Providence/Who Are You Now_/01 Sure as Hell.mp3",
created = parseDate("2016-10-23T21:32:46.000Z"), albumId = "272", isVideo = false, playCount = 0, discNumber = 1,
artistId = "152", type = "music") created = parseDate("2016-10-23T21:32:46.000Z"), albumId = "272",
artistId = "152", type = "music"
)
} }
} }
@ -42,8 +44,10 @@ class SubsonicApiGetRandomSongsTest : SubsonicAPIClientTest() {
fun `Should pass size in request param`() { fun `Should pass size in request param`() {
val size = 384433 val size = 384433
mockWebServerRule.assertRequestParam(responseResourceName = "get_random_songs_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "size=$size") { responseResourceName = "get_random_songs_ok.json",
expectedParam = "size=$size"
) {
client.api.getRandomSongs(size = size).execute() client.api.getRandomSongs(size = size).execute()
} }
} }
@ -52,8 +56,10 @@ class SubsonicApiGetRandomSongsTest : SubsonicAPIClientTest() {
fun `Should pass genre in request param`() { fun `Should pass genre in request param`() {
val genre = "PostRock" val genre = "PostRock"
mockWebServerRule.assertRequestParam(responseResourceName = "get_random_songs_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "genre=$genre") { responseResourceName = "get_random_songs_ok.json",
expectedParam = "genre=$genre"
) {
client.api.getRandomSongs(genre = genre).execute() client.api.getRandomSongs(genre = genre).execute()
} }
} }
@ -62,8 +68,10 @@ class SubsonicApiGetRandomSongsTest : SubsonicAPIClientTest() {
fun `Should pass from year in request param`() { fun `Should pass from year in request param`() {
val fromYear = 1919 val fromYear = 1919
mockWebServerRule.assertRequestParam(responseResourceName = "get_random_songs_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "fromYear=$fromYear") { responseResourceName = "get_random_songs_ok.json",
expectedParam = "fromYear=$fromYear"
) {
client.api.getRandomSongs(fromYear = fromYear).execute() client.api.getRandomSongs(fromYear = fromYear).execute()
} }
} }
@ -72,8 +80,10 @@ class SubsonicApiGetRandomSongsTest : SubsonicAPIClientTest() {
fun `Should pass to year in request params`() { fun `Should pass to year in request params`() {
val toYear = 2012 val toYear = 2012
mockWebServerRule.assertRequestParam(responseResourceName = "get_random_songs_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "toYear=$toYear") { responseResourceName = "get_random_songs_ok.json",
expectedParam = "toYear=$toYear"
) {
client.api.getRandomSongs(toYear = toYear).execute() client.api.getRandomSongs(toYear = toYear).execute()
} }
} }
@ -82,8 +92,10 @@ class SubsonicApiGetRandomSongsTest : SubsonicAPIClientTest() {
fun `Should pass music folder id in request param`() { fun `Should pass music folder id in request param`() {
val musicFolderId = "4919" val musicFolderId = "4919"
mockWebServerRule.assertRequestParam(responseResourceName = "get_random_songs_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "musicFolderId=$musicFolderId") { responseResourceName = "get_random_songs_ok.json",
expectedParam = "musicFolderId=$musicFolderId"
) {
client.api.getRandomSongs(musicFolderId = musicFolderId).execute() client.api.getRandomSongs(musicFolderId = musicFolderId).execute()
} }
} }

View File

@ -29,8 +29,8 @@ class SubsonicApiGetSharesTest : SubsonicAPIClientTest() {
with(response.body()!!.shares[0]) { with(response.body()!!.shares[0]) {
id `should be equal to` "0" id `should be equal to` "0"
url `should be equal to` "https://subsonic.com/ext/share/awdwo?jwt=eyJhbGciOiJIUzI1" + url `should be equal to` "https://subsonic.com/ext/share/awdwo?jwt=eyJhbGciOiJIUzI1" +
"NiJ9.eyJwYXRoIjoiL2V4dC9zaGFyZS9hd2R3byIsImV4cCI6MTU0MTYyNjQzMX0.iy8dkt_ZZc8" + "NiJ9.eyJwYXRoIjoiL2V4dC9zaGFyZS9hd2R3byIsImV4cCI6MTU0MTYyNjQzMX0.iy8dkt_ZZc8" +
"hJ692UxorHdHWFU2RB-fMCmCA4IJ_dTw" "hJ692UxorHdHWFU2RB-fMCmCA4IJ_dTw"
username `should be equal to` "admin" username `should be equal to` "admin"
created `should equal` parseDate("2017-11-07T21:33:51.748Z") created `should equal` parseDate("2017-11-07T21:33:51.748Z")
expires `should equal` parseDate("2018-11-07T21:33:51.748Z") expires `should equal` parseDate("2018-11-07T21:33:51.748Z")
@ -38,13 +38,15 @@ class SubsonicApiGetSharesTest : SubsonicAPIClientTest() {
visitCount `should be equal to` 0 visitCount `should be equal to` 0
description `should be equal to` "Awesome link!" description `should be equal to` "Awesome link!"
items.size `should be equal to` 1 items.size `should be equal to` 1
items[0] `should equal` MusicDirectoryChild(id = "4212", parent = "4186", isDir = false, items[0] `should equal` MusicDirectoryChild(
title = "Heaven Knows", album = "Going to Hell", artist = "The Pretty Reckless", id = "4212", parent = "4186", isDir = false,
track = 3, year = 2014, genre = "Hard Rock", coverArt = "4186", size = 9025090, title = "Heaven Knows", album = "Going to Hell", artist = "The Pretty Reckless",
contentType = "audio/mpeg", suffix = "mp3", duration = 225, bitRate = 320, track = 3, year = 2014, genre = "Hard Rock", coverArt = "4186", size = 9025090,
path = "The Pretty Reckless/Going to Hell/03 Heaven Knows.mp3", isVideo = false, contentType = "audio/mpeg", suffix = "mp3", duration = 225, bitRate = 320,
playCount = 2, discNumber = 1, created = parseDate("2016-10-23T21:30:40.000Z"), path = "The Pretty Reckless/Going to Hell/03 Heaven Knows.mp3", isVideo = false,
albumId = "388", artistId = "238", type = "music") playCount = 2, discNumber = 1, created = parseDate("2016-10-23T21:30:40.000Z"),
albumId = "388", artistId = "238", type = "music"
)
} }
} }
} }

View File

@ -27,23 +27,27 @@ class SubsonicApiGetSongsByGenreTest : SubsonicAPIClientTest() {
assertResponseSuccessful(response) assertResponseSuccessful(response)
response.body()!!.songsList.size `should be equal to` 2 response.body()!!.songsList.size `should be equal to` 2
with(response.body()!!.songsList) { with(response.body()!!.songsList) {
this[0] `should equal` MusicDirectoryChild(id = "575", parent = "576", isDir = false, this[0] `should equal` MusicDirectoryChild(
title = "Time Machine (Vadim Zhukov Remix)", album = "668", id = "575", parent = "576", isDir = false,
artist = "Tasadi", year = 2008, genre = "Trance", size = 22467672, title = "Time Machine (Vadim Zhukov Remix)", album = "668",
contentType = "audio/mpeg", suffix = "mp3", duration = 561, bitRate = 320, artist = "Tasadi", year = 2008, genre = "Trance", size = 22467672,
path = "Tasadi/668/00 Time Machine (Vadim Zhukov Remix).mp3", contentType = "audio/mpeg", suffix = "mp3", duration = 561, bitRate = 320,
isVideo = false, playCount = 0, created = parseDate("2016-10-23T21:58:29.000Z"), path = "Tasadi/668/00 Time Machine (Vadim Zhukov Remix).mp3",
albumId = "0", artistId = "0", type = "music") isVideo = false, playCount = 0, created = parseDate("2016-10-23T21:58:29.000Z"),
this[1] `should equal` MusicDirectoryChild(id = "621", parent = "622", isDir = false, albumId = "0", artistId = "0", type = "music"
title = "My Heart (Vadim Zhukov Remix)", album = "668", )
artist = "DJ Polyakov PPK Feat Kate Cameron", year = 2009, genre = "Trance", this[1] `should equal` MusicDirectoryChild(
size = 26805932, contentType = "audio/mpeg", suffix = "mp3", duration = 670, id = "621", parent = "622", isDir = false,
bitRate = 320, title = "My Heart (Vadim Zhukov Remix)", album = "668",
path = "DJ Polyakov PPK Feat Kate Cameron/668/00 My Heart (Vadim Zhukov " + artist = "DJ Polyakov PPK Feat Kate Cameron", year = 2009, genre = "Trance",
"Remix).mp3", size = 26805932, contentType = "audio/mpeg", suffix = "mp3", duration = 670,
isVideo = false, playCount = 2, bitRate = 320,
created = parseDate("2016-10-23T21:58:29.000Z"), path = "DJ Polyakov PPK Feat Kate Cameron/668/00 My Heart (Vadim Zhukov " +
albumId = "5", artistId = "4", type = "music") "Remix).mp3",
isVideo = false, playCount = 2,
created = parseDate("2016-10-23T21:58:29.000Z"),
albumId = "5", artistId = "4", type = "music"
)
} }
} }

View File

@ -30,8 +30,10 @@ class SubsonicApiGetStarred2Test : SubsonicAPIClientTest() {
with(response.body()!!.starred2) { with(response.body()!!.starred2) {
albumList `should equal` emptyList() albumList `should equal` emptyList()
artistList.size `should be equal to` 1 artistList.size `should be equal to` 1
artistList[0] `should equal` Artist(id = "364", name = "Parov Stelar", artistList[0] `should equal` Artist(
starred = parseDate("2017-08-12T18:32:58.768Z")) id = "364", name = "Parov Stelar",
starred = parseDate("2017-08-12T18:32:58.768Z")
)
songList `should equal` emptyList() songList `should equal` emptyList()
} }
} }
@ -40,8 +42,10 @@ class SubsonicApiGetStarred2Test : SubsonicAPIClientTest() {
fun `Should pass music folder id in request param`() { fun `Should pass music folder id in request param`() {
val musicFolderId = "441" val musicFolderId = "441"
mockWebServerRule.assertRequestParam(responseResourceName = "get_starred_2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "musicFolderId=$musicFolderId") { responseResourceName = "get_starred_2_ok.json",
expectedParam = "musicFolderId=$musicFolderId"
) {
client.api.getStarred2(musicFolderId = musicFolderId).execute() client.api.getStarred2(musicFolderId = musicFolderId).execute()
} }
} }

View File

@ -29,8 +29,10 @@ class SubsonicApiGetStarredTest : SubsonicAPIClientTest() {
with(response.body()!!.starred) { with(response.body()!!.starred) {
albumList `should equal` emptyList() albumList `should equal` emptyList()
artistList.size `should be equal to` 1 artistList.size `should be equal to` 1
artistList[0] `should equal` Artist(id = "364", name = "Parov Stelar", artistList[0] `should equal` Artist(
starred = parseDate("2017-08-12T18:32:58.768Z")) id = "364", name = "Parov Stelar",
starred = parseDate("2017-08-12T18:32:58.768Z")
)
songList `should equal` emptyList() songList `should equal` emptyList()
} }
} }
@ -39,8 +41,10 @@ class SubsonicApiGetStarredTest : SubsonicAPIClientTest() {
fun `Should pass music folder id in request param`() { fun `Should pass music folder id in request param`() {
val musicFolderId = "441" val musicFolderId = "441"
mockWebServerRule.assertRequestParam(responseResourceName = "get_starred_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "musicFolderId=$musicFolderId") { responseResourceName = "get_starred_ok.json",
expectedParam = "musicFolderId=$musicFolderId"
) {
client.api.getStarred(musicFolderId = musicFolderId).execute() client.api.getStarred(musicFolderId = musicFolderId).execute()
} }
} }

View File

@ -27,13 +27,15 @@ class SubsonicApiGetVideosListTest : SubsonicAPIClientTest() {
assertResponseSuccessful(response) assertResponseSuccessful(response)
with(response.body()!!.videosList) { with(response.body()!!.videosList) {
size `should be equal to` 1 size `should be equal to` 1
this[0] `should equal` MusicDirectoryChild(id = "10402", parent = "10401", this[0] `should equal` MusicDirectoryChild(
isDir = false, title = "MVI_0512", album = "Incoming", size = 21889646, id = "10402", parent = "10401",
contentType = "video/avi", suffix = "avi", isDir = false, title = "MVI_0512", album = "Incoming", size = 21889646,
transcodedContentType = "video/x-flv", transcodedSuffix = "flv", contentType = "video/avi", suffix = "avi",
path = "Incoming/MVI_0512.avi", isVideo = true, transcodedContentType = "video/x-flv", transcodedSuffix = "flv",
playCount = 0, created = parseDate("2017-11-19T12:34:33.000Z"), path = "Incoming/MVI_0512.avi", isVideo = true,
type = "video") playCount = 0, created = parseDate("2017-11-19T12:34:33.000Z"),
type = "video"
)
} }
} }
} }

View File

@ -51,15 +51,17 @@ class SubsonicApiJukeboxControlTest : SubsonicAPIClientTest() {
gain `should be equal to` 0.88f gain `should be equal to` 0.88f
position `should be equal to` 2 position `should be equal to` 2
playlistEntries.size `should be equal to` 2 playlistEntries.size `should be equal to` 2
playlistEntries[1] `should equal` MusicDirectoryChild(id = "4215", parent = "4186", playlistEntries[1] `should equal` MusicDirectoryChild(
isDir = false, title = "Going to Hell", album = "Going to Hell", id = "4215", parent = "4186",
artist = "The Pretty Reckless", track = 2, year = 2014, genre = "Hard Rock", isDir = false, title = "Going to Hell", album = "Going to Hell",
coverArt = "4186", size = 11089627, contentType = "audio/mpeg", artist = "The Pretty Reckless", track = 2, year = 2014, genre = "Hard Rock",
suffix = "mp3", duration = 277, bitRate = 320, coverArt = "4186", size = 11089627, contentType = "audio/mpeg",
path = "The Pretty Reckless/Going to Hell/02 Going to Hell.mp3", suffix = "mp3", duration = 277, bitRate = 320,
isVideo = false, playCount = 0, discNumber = 1, path = "The Pretty Reckless/Going to Hell/02 Going to Hell.mp3",
created = parseDate("2016-10-23T21:30:41.000Z"), albumId = "388", isVideo = false, playCount = 0, discNumber = 1,
artistId = "238", type = "music") created = parseDate("2016-10-23T21:30:41.000Z"), albumId = "388",
artistId = "238", type = "music"
)
} }
} }

View File

@ -1,10 +1,5 @@
package org.moire.ultrasonic.api.subsonic package org.moire.ultrasonic.api.subsonic
import okhttp3.mockwebserver.MockWebServer
import org.amshove.kluent.`should throw`
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.io.InputStream import java.io.InputStream
import java.net.InetAddress import java.net.InetAddress
import java.security.KeyStore import java.security.KeyStore
@ -14,6 +9,11 @@ import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.SSLContext import javax.net.ssl.SSLContext
import javax.net.ssl.SSLHandshakeException import javax.net.ssl.SSLHandshakeException
import javax.net.ssl.TrustManagerFactory import javax.net.ssl.TrustManagerFactory
import okhttp3.mockwebserver.MockWebServer
import org.amshove.kluent.`should throw`
import org.junit.After
import org.junit.Before
import org.junit.Test
private const val PORT = 8443 private const val PORT = 8443
private const val HOST = "localhost" private const val HOST = "localhost"
@ -26,8 +26,11 @@ class SubsonicApiSSLTest {
@Before @Before
fun setUp() { fun setUp() {
val sslContext = createSSLContext(loadResourceStream("self-signed.pem"), val sslContext = createSSLContext(
loadResourceStream("self-signed.p12"), "") loadResourceStream("self-signed.pem"),
loadResourceStream("self-signed.p12"),
""
)
mockWebServer.useHttps(sslContext.socketFactory, false) mockWebServer.useHttps(sslContext.socketFactory, false)
mockWebServer.start(InetAddress.getByName(HOST), PORT) mockWebServer.start(InetAddress.getByName(HOST), PORT)
} }
@ -47,11 +50,13 @@ class SubsonicApiSSLTest {
trustStore.load(null) trustStore.load(null)
certificatePemStream.use { certificatePemStream.use {
cert = (CertificateFactory.getInstance("X.509") cert = (
.generateCertificate(certificatePemStream)) as X509Certificate CertificateFactory.getInstance("X.509")
.generateCertificate(certificatePemStream)
) as X509Certificate
} }
val alias = cert?.subjectX500Principal?.name val alias = cert?.subjectX500Principal?.name
?: throw IllegalStateException("Failed to load certificate") ?: throw IllegalStateException("Failed to load certificate")
trustStore.setCertificateEntry(alias, cert) trustStore.setCertificateEntry(alias, cert)
val tmf = TrustManagerFactory.getInstance("X509") val tmf = TrustManagerFactory.getInstance("X509")

View File

@ -1,7 +1,7 @@
package org.moire.ultrasonic.api.subsonic package org.moire.ultrasonic.api.subsonic
import org.junit.Test
import java.util.Calendar import java.util.Calendar
import org.junit.Test
/** /**
* Integration test for [SubsonicAPIClient] for scrobble call. * Integration test for [SubsonicAPIClient] for scrobble call.
@ -27,8 +27,10 @@ class SubsonicApiScrobbleTest : SubsonicAPIClientTest() {
fun `Should pass id param in request`() { fun `Should pass id param in request`() {
val id = "some-id" val id = "some-id"
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "id=$id") { responseResourceName = "ping_ok.json",
expectedParam = "id=$id"
) {
client.api.scrobble(id = id).execute() client.api.scrobble(id = id).execute()
} }
} }
@ -37,8 +39,10 @@ class SubsonicApiScrobbleTest : SubsonicAPIClientTest() {
fun `Should pass time param in request`() { fun `Should pass time param in request`() {
val time = Calendar.getInstance().timeInMillis val time = Calendar.getInstance().timeInMillis
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "time=$time") { responseResourceName = "ping_ok.json",
expectedParam = "time=$time"
) {
client.api.scrobble(id = "some-id", time = time).execute() client.api.scrobble(id = "some-id", time = time).execute()
} }
} }
@ -47,8 +51,10 @@ class SubsonicApiScrobbleTest : SubsonicAPIClientTest() {
fun `Should pass submission param in request`() { fun `Should pass submission param in request`() {
val submission = false val submission = false
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "submission=$submission") { responseResourceName = "ping_ok.json",
expectedParam = "submission=$submission"
) {
client.api.scrobble(id = "some-id", submission = submission).execute() client.api.scrobble(id = "some-id", submission = submission).execute()
} }
} }

View File

@ -1,12 +1,12 @@
package org.moire.ultrasonic.api.subsonic package org.moire.ultrasonic.api.subsonic
import java.util.Calendar
import org.amshove.kluent.`should be equal to` import org.amshove.kluent.`should be equal to`
import org.amshove.kluent.`should equal` import org.amshove.kluent.`should equal`
import org.amshove.kluent.`should not be` import org.amshove.kluent.`should not be`
import org.junit.Test import org.junit.Test
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
import org.moire.ultrasonic.api.subsonic.models.SearchResult import org.moire.ultrasonic.api.subsonic.models.SearchResult
import java.util.Calendar
/** /**
* Integration test for [SubsonicAPIClient] for search call. * Integration test for [SubsonicAPIClient] for search call.
@ -33,17 +33,19 @@ class SubsonicApiSearchTest : SubsonicAPIClientTest() {
offset `should be equal to` 10 offset `should be equal to` 10
totalHits `should be equal to` 53 totalHits `should be equal to` 53
matchList.size `should be equal to` 1 matchList.size `should be equal to` 1
matchList[0] `should equal` MusicDirectoryChild(id = "5831", parent = "5766", matchList[0] `should equal` MusicDirectoryChild(
isDir = false, title = "You'll Be Under My Wheels", id = "5831", parent = "5766",
album = "Need for Speed Most Wanted", artist = "The Prodigy", isDir = false, title = "You'll Be Under My Wheels",
track = 17, year = 2005, genre = "Rap", coverArt = "5766", album = "Need for Speed Most Wanted", artist = "The Prodigy",
size = 5607024, contentType = "audio/mpeg", suffix = "mp3", duration = 233, track = 17, year = 2005, genre = "Rap", coverArt = "5766",
bitRate = 192, size = 5607024, contentType = "audio/mpeg", suffix = "mp3", duration = 233,
path = "Compilations/Need for Speed Most Wanted/17 You'll Be Under My Wheels" + bitRate = 192,
".mp3", path = "Compilations/Need for Speed Most Wanted/17 You'll Be Under My Wheels" +
isVideo = false, playCount = 0, discNumber = 1, ".mp3",
created = parseDate("2016-10-23T20:09:02.000Z"), albumId = "568", isVideo = false, playCount = 0, discNumber = 1,
artistId = "505", type = "music") created = parseDate("2016-10-23T20:09:02.000Z"), albumId = "568",
artistId = "505", type = "music"
)
} }
} }
@ -51,8 +53,10 @@ class SubsonicApiSearchTest : SubsonicAPIClientTest() {
fun `Should pass artist param`() { fun `Should pass artist param`() {
val artist = "some-artist" val artist = "some-artist"
mockWebServerRule.assertRequestParam(responseResourceName = "search_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "artist=$artist") { responseResourceName = "search_ok.json",
expectedParam = "artist=$artist"
) {
client.api.search(artist = artist).execute() client.api.search(artist = artist).execute()
} }
} }
@ -61,8 +65,10 @@ class SubsonicApiSearchTest : SubsonicAPIClientTest() {
fun `Should pass album param`() { fun `Should pass album param`() {
val album = "some-album" val album = "some-album"
mockWebServerRule.assertRequestParam(responseResourceName = "search_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "album=$album") { responseResourceName = "search_ok.json",
expectedParam = "album=$album"
) {
client.api.search(album = album).execute() client.api.search(album = album).execute()
} }
} }
@ -71,8 +77,10 @@ class SubsonicApiSearchTest : SubsonicAPIClientTest() {
fun `Should pass title param`() { fun `Should pass title param`() {
val title = "some-title" val title = "some-title"
mockWebServerRule.assertRequestParam(responseResourceName = "search_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "title=$title") { responseResourceName = "search_ok.json",
expectedParam = "title=$title"
) {
client.api.search(title = title).execute() client.api.search(title = title).execute()
} }
} }
@ -81,8 +89,10 @@ class SubsonicApiSearchTest : SubsonicAPIClientTest() {
fun `Should contain any param`() { fun `Should contain any param`() {
val any = "AnyString" val any = "AnyString"
mockWebServerRule.assertRequestParam(responseResourceName = "search_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "any=$any") { responseResourceName = "search_ok.json",
expectedParam = "any=$any"
) {
client.api.search(any = any).execute() client.api.search(any = any).execute()
} }
} }
@ -91,8 +101,10 @@ class SubsonicApiSearchTest : SubsonicAPIClientTest() {
fun `Should contain count param`() { fun `Should contain count param`() {
val count = 11 val count = 11
mockWebServerRule.assertRequestParam(responseResourceName = "search_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "count=$count") { responseResourceName = "search_ok.json",
expectedParam = "count=$count"
) {
client.api.search(count = count).execute() client.api.search(count = count).execute()
} }
} }
@ -101,8 +113,10 @@ class SubsonicApiSearchTest : SubsonicAPIClientTest() {
fun `Should contain offset param`() { fun `Should contain offset param`() {
val offset = 54 val offset = 54
mockWebServerRule.assertRequestParam(responseResourceName = "search_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "offset=$offset") { responseResourceName = "search_ok.json",
expectedParam = "offset=$offset"
) {
client.api.search(offset = offset).execute() client.api.search(offset = offset).execute()
} }
} }
@ -111,8 +125,10 @@ class SubsonicApiSearchTest : SubsonicAPIClientTest() {
fun `Should contain newerThan param`() { fun `Should contain newerThan param`() {
val newerThan = Calendar.getInstance() val newerThan = Calendar.getInstance()
mockWebServerRule.assertRequestParam(responseResourceName = "search_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "newerThan=${newerThan.time.time}") { responseResourceName = "search_ok.json",
expectedParam = "newerThan=${newerThan.time.time}"
) {
client.api.search(newerThan = newerThan.time.time).execute() client.api.search(newerThan = newerThan.time.time).execute()
} }
} }

View File

@ -32,26 +32,32 @@ class SubsonicApiSearchThreeTest : SubsonicAPIClientTest() {
assertResponseSuccessful(response) assertResponseSuccessful(response)
with(response.body()!!.searchResult) { with(response.body()!!.searchResult) {
artistList.size `should be equal to` 1 artistList.size `should be equal to` 1
artistList[0] `should equal` Artist(id = "505", name = "The Prodigy", artistList[0] `should equal` Artist(
coverArt = "ar-505", albumCount = 5) id = "505", name = "The Prodigy",
coverArt = "ar-505", albumCount = 5
)
albumList.size `should be equal to` 1 albumList.size `should be equal to` 1
albumList[0] `should equal` Album(id = "855", albumList[0] `should equal` Album(
name = "Always Outnumbered, Never Outgunned", id = "855",
artist = "The Prodigy", artistId = "505", coverArt = "al-855", songCount = 12, name = "Always Outnumbered, Never Outgunned",
duration = 3313, created = parseDate("2016-10-23T20:57:27.000Z"), artist = "The Prodigy", artistId = "505", coverArt = "al-855", songCount = 12,
year = 2004, genre = "Electronic") duration = 3313, created = parseDate("2016-10-23T20:57:27.000Z"),
year = 2004, genre = "Electronic"
)
songList.size `should be equal to` 1 songList.size `should be equal to` 1
songList[0] `should equal` MusicDirectoryChild(id = "5831", parent = "5766", songList[0] `should equal` MusicDirectoryChild(
isDir = false, id = "5831", parent = "5766",
title = "You'll Be Under My Wheels", album = "Need for Speed Most Wanted", isDir = false,
artist = "The Prodigy", track = 17, year = 2005, genre = "Rap", title = "You'll Be Under My Wheels", album = "Need for Speed Most Wanted",
coverArt = "5766", size = 5607024, contentType = "audio/mpeg", artist = "The Prodigy", track = 17, year = 2005, genre = "Rap",
suffix = "mp3", duration = 233, bitRate = 192, coverArt = "5766", size = 5607024, contentType = "audio/mpeg",
path = "Compilations/Need for Speed Most Wanted/17 You'll Be Under My Wheels" + suffix = "mp3", duration = 233, bitRate = 192,
".mp3", path = "Compilations/Need for Speed Most Wanted/17 You'll Be Under My Wheels" +
isVideo = false, playCount = 0, discNumber = 1, ".mp3",
created = parseDate("2016-10-23T20:09:02.000Z"), albumId = "568", isVideo = false, playCount = 0, discNumber = 1,
artistId = "505", type = "music") created = parseDate("2016-10-23T20:09:02.000Z"), albumId = "568",
artistId = "505", type = "music"
)
} }
} }
@ -59,8 +65,10 @@ class SubsonicApiSearchThreeTest : SubsonicAPIClientTest() {
fun `Should pass query as request param`() { fun `Should pass query as request param`() {
val query = "some-wip-query" val query = "some-wip-query"
mockWebServerRule.assertRequestParam(responseResourceName = "search3_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "query=$query") { responseResourceName = "search3_ok.json",
expectedParam = "query=$query"
) {
client.api.search3(query = query).execute() client.api.search3(query = query).execute()
} }
} }
@ -69,8 +77,10 @@ class SubsonicApiSearchThreeTest : SubsonicAPIClientTest() {
fun `Should pass artist count as request param`() { fun `Should pass artist count as request param`() {
val artistCount = 67 val artistCount = 67
mockWebServerRule.assertRequestParam(responseResourceName = "search3_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "artistCount=$artistCount") { responseResourceName = "search3_ok.json",
expectedParam = "artistCount=$artistCount"
) {
client.api.search3("some", artistCount = artistCount).execute() client.api.search3("some", artistCount = artistCount).execute()
} }
} }
@ -79,8 +89,10 @@ class SubsonicApiSearchThreeTest : SubsonicAPIClientTest() {
fun `Should pass artist offset as request param`() { fun `Should pass artist offset as request param`() {
val artistOffset = 34 val artistOffset = 34
mockWebServerRule.assertRequestParam(responseResourceName = "search3_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "artistOffset=$artistOffset") { responseResourceName = "search3_ok.json",
expectedParam = "artistOffset=$artistOffset"
) {
client.api.search3("some", artistOffset = artistOffset).execute() client.api.search3("some", artistOffset = artistOffset).execute()
} }
} }
@ -89,8 +101,10 @@ class SubsonicApiSearchThreeTest : SubsonicAPIClientTest() {
fun `Should pass album count as request param`() { fun `Should pass album count as request param`() {
val albumCount = 21 val albumCount = 21
mockWebServerRule.assertRequestParam(responseResourceName = "search3_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "albumCount=$albumCount") { responseResourceName = "search3_ok.json",
expectedParam = "albumCount=$albumCount"
) {
client.api.search3("some", albumCount = albumCount).execute() client.api.search3("some", albumCount = albumCount).execute()
} }
} }
@ -99,8 +113,10 @@ class SubsonicApiSearchThreeTest : SubsonicAPIClientTest() {
fun `Should pass album offset as request param`() { fun `Should pass album offset as request param`() {
val albumOffset = 43 val albumOffset = 43
mockWebServerRule.assertRequestParam(responseResourceName = "search3_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "albumOffset=$albumOffset") { responseResourceName = "search3_ok.json",
expectedParam = "albumOffset=$albumOffset"
) {
client.api.search3("some", albumOffset = albumOffset).execute() client.api.search3("some", albumOffset = albumOffset).execute()
} }
} }
@ -109,8 +125,10 @@ class SubsonicApiSearchThreeTest : SubsonicAPIClientTest() {
fun `Should pass song count as request param`() { fun `Should pass song count as request param`() {
val songCount = 15 val songCount = 15
mockWebServerRule.assertRequestParam(responseResourceName = "search3_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "songCount=$songCount") { responseResourceName = "search3_ok.json",
expectedParam = "songCount=$songCount"
) {
client.api.search3("some", songCount = songCount).execute() client.api.search3("some", songCount = songCount).execute()
} }
} }
@ -119,8 +137,10 @@ class SubsonicApiSearchThreeTest : SubsonicAPIClientTest() {
fun `Should pass music folder id as request param`() { fun `Should pass music folder id as request param`() {
val musicFolderId = "43" val musicFolderId = "43"
mockWebServerRule.assertRequestParam(responseResourceName = "search3_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "musicFolderId=$musicFolderId") { responseResourceName = "search3_ok.json",
expectedParam = "musicFolderId=$musicFolderId"
) {
client.api.search3("some", musicFolderId = musicFolderId).execute() client.api.search3("some", musicFolderId = musicFolderId).execute()
} }
} }

View File

@ -33,23 +33,27 @@ class SubsonicApiSearchTwoTest : SubsonicAPIClientTest() {
artistList.size `should be equal to` 1 artistList.size `should be equal to` 1
artistList[0] `should equal` Artist(id = "522", name = "The Prodigy") artistList[0] `should equal` Artist(id = "522", name = "The Prodigy")
albumList.size `should be equal to` 1 albumList.size `should be equal to` 1
albumList[0] `should equal` MusicDirectoryChild(id = "8867", parent = "522", albumList[0] `should equal` MusicDirectoryChild(
isDir = true, title = "Always Outnumbered, Never Outgunned", id = "8867", parent = "522",
album = "Always Outnumbered, Never Outgunned", artist = "The Prodigy", isDir = true, title = "Always Outnumbered, Never Outgunned",
year = 2004, genre = "Electronic", coverArt = "8867", playCount = 0, album = "Always Outnumbered, Never Outgunned", artist = "The Prodigy",
created = parseDate("2016-10-23T20:57:27.000Z")) year = 2004, genre = "Electronic", coverArt = "8867", playCount = 0,
created = parseDate("2016-10-23T20:57:27.000Z")
)
songList.size `should be equal to` 1 songList.size `should be equal to` 1
songList[0] `should equal` MusicDirectoryChild(id = "5831", parent = "5766", songList[0] `should equal` MusicDirectoryChild(
isDir = false, id = "5831", parent = "5766",
title = "You'll Be Under My Wheels", album = "Need for Speed Most Wanted", isDir = false,
artist = "The Prodigy", track = 17, year = 2005, genre = "Rap", title = "You'll Be Under My Wheels", album = "Need for Speed Most Wanted",
coverArt = "5766", size = 5607024, contentType = "audio/mpeg", artist = "The Prodigy", track = 17, year = 2005, genre = "Rap",
suffix = "mp3", duration = 233, bitRate = 192, coverArt = "5766", size = 5607024, contentType = "audio/mpeg",
path = "Compilations/Need for Speed Most Wanted/17 You'll Be Under My Wheels" + suffix = "mp3", duration = 233, bitRate = 192,
".mp3", path = "Compilations/Need for Speed Most Wanted/17 You'll Be Under My Wheels" +
isVideo = false, playCount = 0, discNumber = 1, ".mp3",
created = parseDate("2016-10-23T20:09:02.000Z"), isVideo = false, playCount = 0, discNumber = 1,
albumId = "568", artistId = "505", type = "music") created = parseDate("2016-10-23T20:09:02.000Z"),
albumId = "568", artistId = "505", type = "music"
)
} }
} }
@ -57,8 +61,10 @@ class SubsonicApiSearchTwoTest : SubsonicAPIClientTest() {
fun `Should pass query id in request param`() { fun `Should pass query id in request param`() {
val query = "some" val query = "some"
mockWebServerRule.assertRequestParam(responseResourceName = "search2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "query=$query") { responseResourceName = "search2_ok.json",
expectedParam = "query=$query"
) {
client.api.search2(query).execute() client.api.search2(query).execute()
} }
} }
@ -67,8 +73,10 @@ class SubsonicApiSearchTwoTest : SubsonicAPIClientTest() {
fun `Should pass artist count in request param`() { fun `Should pass artist count in request param`() {
val artistCount = 45 val artistCount = 45
mockWebServerRule.assertRequestParam(responseResourceName = "search2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "artistCount=$artistCount") { responseResourceName = "search2_ok.json",
expectedParam = "artistCount=$artistCount"
) {
client.api.search2("some", artistCount = artistCount).execute() client.api.search2("some", artistCount = artistCount).execute()
} }
} }
@ -77,8 +85,10 @@ class SubsonicApiSearchTwoTest : SubsonicAPIClientTest() {
fun `Should pass artist offset in request param`() { fun `Should pass artist offset in request param`() {
val artistOffset = 13 val artistOffset = 13
mockWebServerRule.assertRequestParam(responseResourceName = "search2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "artistOffset=$artistOffset") { responseResourceName = "search2_ok.json",
expectedParam = "artistOffset=$artistOffset"
) {
client.api.search2("some", artistOffset = artistOffset).execute() client.api.search2("some", artistOffset = artistOffset).execute()
} }
} }
@ -87,8 +97,10 @@ class SubsonicApiSearchTwoTest : SubsonicAPIClientTest() {
fun `Should pass album count in request param`() { fun `Should pass album count in request param`() {
val albumCount = 30 val albumCount = 30
mockWebServerRule.assertRequestParam(responseResourceName = "search2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "albumCount=$albumCount") { responseResourceName = "search2_ok.json",
expectedParam = "albumCount=$albumCount"
) {
client.api.search2("some", albumCount = albumCount).execute() client.api.search2("some", albumCount = albumCount).execute()
} }
} }
@ -97,8 +109,10 @@ class SubsonicApiSearchTwoTest : SubsonicAPIClientTest() {
fun `Should pass album offset in request param`() { fun `Should pass album offset in request param`() {
val albumOffset = 91 val albumOffset = 91
mockWebServerRule.assertRequestParam(responseResourceName = "search2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "albumOffset=$albumOffset") { responseResourceName = "search2_ok.json",
expectedParam = "albumOffset=$albumOffset"
) {
client.api.search2("some", albumOffset = albumOffset).execute() client.api.search2("some", albumOffset = albumOffset).execute()
} }
} }
@ -107,8 +121,10 @@ class SubsonicApiSearchTwoTest : SubsonicAPIClientTest() {
fun `Should pass song count in request param`() { fun `Should pass song count in request param`() {
val songCount = 22 val songCount = 22
mockWebServerRule.assertRequestParam(responseResourceName = "search2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "songCount=$songCount") { responseResourceName = "search2_ok.json",
expectedParam = "songCount=$songCount"
) {
client.api.search2("some", songCount = songCount).execute() client.api.search2("some", songCount = songCount).execute()
} }
} }
@ -117,8 +133,10 @@ class SubsonicApiSearchTwoTest : SubsonicAPIClientTest() {
fun `Should pass music folder id in request param`() { fun `Should pass music folder id in request param`() {
val musicFolderId = "565" val musicFolderId = "565"
mockWebServerRule.assertRequestParam(responseResourceName = "search2_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "musicFolderId=$musicFolderId") { responseResourceName = "search2_ok.json",
expectedParam = "musicFolderId=$musicFolderId"
) {
client.api.search2("some", musicFolderId = musicFolderId).execute() client.api.search2("some", musicFolderId = musicFolderId).execute()
} }
} }

View File

@ -36,8 +36,10 @@ class SubsonicApiSetRatingTest : SubsonicAPIClientTest() {
val id = "110" val id = "110"
val rating = 5 val rating = 5
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "id=$id") { responseResourceName = "ping_ok.json",
expectedParam = "id=$id"
) {
client.api.setRating(id, rating).execute() client.api.setRating(id, rating).execute()
} }
} }
@ -47,8 +49,10 @@ class SubsonicApiSetRatingTest : SubsonicAPIClientTest() {
val id = "110" val id = "110"
val rating = 5 val rating = 5
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "rating=$rating") { responseResourceName = "ping_ok.json",
expectedParam = "rating=$rating"
) {
client.api.setRating(id, rating).execute() client.api.setRating(id, rating).execute()
} }
} }

View File

@ -29,8 +29,10 @@ class SubsonicApiStarTest : SubsonicAPIClientTest() {
fun `Should pass id param`() { fun `Should pass id param`() {
val id = "110" val id = "110"
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "id=$id") { responseResourceName = "ping_ok.json",
expectedParam = "id=$id"
) {
client.api.star(id = id).execute() client.api.star(id = id).execute()
} }
} }
@ -39,8 +41,10 @@ class SubsonicApiStarTest : SubsonicAPIClientTest() {
fun `Should pass artist id param`() { fun `Should pass artist id param`() {
val artistId = "123" val artistId = "123"
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "artistId=$artistId") { responseResourceName = "ping_ok.json",
expectedParam = "artistId=$artistId"
) {
client.api.star(artistId = artistId).execute() client.api.star(artistId = artistId).execute()
} }
} }
@ -49,8 +53,10 @@ class SubsonicApiStarTest : SubsonicAPIClientTest() {
fun `Should pass album id param`() { fun `Should pass album id param`() {
val albumId = "1001" val albumId = "1001"
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "albumId=$albumId") { responseResourceName = "ping_ok.json",
expectedParam = "albumId=$albumId"
) {
client.api.star(albumId = albumId).execute() client.api.star(albumId = albumId).execute()
} }
} }

View File

@ -40,8 +40,10 @@ class SubsonicApiStreamTest : SubsonicAPIClientTest() {
@Test @Test
fun `Should return successfull call stream`() { fun `Should return successfull call stream`() {
mockWebServerRule.mockWebServer.enqueue(MockResponse() mockWebServerRule.mockWebServer.enqueue(
.setBody(mockWebServerRule.loadJsonResponse("ping_ok.json"))) MockResponse()
.setBody(mockWebServerRule.loadJsonResponse("ping_ok.json"))
)
val response = client.stream("some-id") val response = client.stream("some-id")
@ -67,8 +69,10 @@ class SubsonicApiStreamTest : SubsonicAPIClientTest() {
fun `Should pass max bit rate as param`() { fun `Should pass max bit rate as param`() {
val maxBitRate = 360 val maxBitRate = 360
mockWebServerRule.assertRequestParam("ping_ok.json", mockWebServerRule.assertRequestParam(
"maxBitRate=$maxBitRate") { "ping_ok.json",
"maxBitRate=$maxBitRate"
) {
client.api.stream("some-id", maxBitRate = maxBitRate).execute() client.api.stream("some-id", maxBitRate = maxBitRate).execute()
} }
} }
@ -77,8 +81,10 @@ class SubsonicApiStreamTest : SubsonicAPIClientTest() {
fun `Should pass format as param`() { fun `Should pass format as param`() {
val format = "aac" val format = "aac"
mockWebServerRule.assertRequestParam("ping_ok.json", mockWebServerRule.assertRequestParam(
"format=$format") { "ping_ok.json",
"format=$format"
) {
client.api.stream("some-id", format = format).execute() client.api.stream("some-id", format = format).execute()
} }
} }
@ -87,8 +93,10 @@ class SubsonicApiStreamTest : SubsonicAPIClientTest() {
fun `Should pass time offset as param`() { fun `Should pass time offset as param`() {
val timeOffset = 155 val timeOffset = 155
mockWebServerRule.assertRequestParam("ping_ok.json", mockWebServerRule.assertRequestParam(
"timeOffset=$timeOffset") { "ping_ok.json",
"timeOffset=$timeOffset"
) {
client.api.stream("some-id", timeOffset = timeOffset).execute() client.api.stream("some-id", timeOffset = timeOffset).execute()
} }
} }
@ -97,8 +105,10 @@ class SubsonicApiStreamTest : SubsonicAPIClientTest() {
fun `Should pass video size as param`() { fun `Should pass video size as param`() {
val videoSize = "44144" val videoSize = "44144"
mockWebServerRule.assertRequestParam("ping_ok.json", mockWebServerRule.assertRequestParam(
"size=$videoSize") { "ping_ok.json",
"size=$videoSize"
) {
client.api.stream("some-id", videoSize = videoSize).execute() client.api.stream("some-id", videoSize = videoSize).execute()
} }
} }
@ -107,8 +117,10 @@ class SubsonicApiStreamTest : SubsonicAPIClientTest() {
fun `Should pass estimate content length as param`() { fun `Should pass estimate content length as param`() {
val estimateContentLength = true val estimateContentLength = true
mockWebServerRule.assertRequestParam("ping_ok.json", mockWebServerRule.assertRequestParam(
"estimateContentLength=$estimateContentLength") { "ping_ok.json",
"estimateContentLength=$estimateContentLength"
) {
client.api.stream("some-id", estimateContentLength = estimateContentLength).execute() client.api.stream("some-id", estimateContentLength = estimateContentLength).execute()
} }
} }
@ -117,8 +129,10 @@ class SubsonicApiStreamTest : SubsonicAPIClientTest() {
fun `Should pass converted as param`() { fun `Should pass converted as param`() {
val converted = false val converted = false
mockWebServerRule.assertRequestParam("ping_ok.json", mockWebServerRule.assertRequestParam(
"converted=$converted") { "ping_ok.json",
"converted=$converted"
) {
client.api.stream("some-id", converted = converted).execute() client.api.stream("some-id", converted = converted).execute()
} }
} }

View File

@ -20,17 +20,22 @@ class SubsonicApiUnstarTest : SubsonicAPIClientTest() {
@Test @Test
fun `Should parse error response`() { fun `Should parse error response`() {
checkErrorCallParsed(mockWebServerRule, { checkErrorCallParsed(
client.api.unstar().execute() mockWebServerRule,
}) {
client.api.unstar().execute()
}
)
} }
@Test @Test
fun `Should pass id param`() { fun `Should pass id param`() {
val id = "545" val id = "545"
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "id=$id") { responseResourceName = "ping_ok.json",
expectedParam = "id=$id"
) {
client.api.unstar(id = id).execute() client.api.unstar(id = id).execute()
} }
} }
@ -39,8 +44,10 @@ class SubsonicApiUnstarTest : SubsonicAPIClientTest() {
fun `Should pass artistId param`() { fun `Should pass artistId param`() {
val artistId = "644" val artistId = "644"
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "artistId=$artistId") { responseResourceName = "ping_ok.json",
expectedParam = "artistId=$artistId"
) {
client.api.unstar(artistId = artistId).execute() client.api.unstar(artistId = artistId).execute()
} }
} }
@ -49,8 +56,10 @@ class SubsonicApiUnstarTest : SubsonicAPIClientTest() {
fun `Should pass albumId param`() { fun `Should pass albumId param`() {
val albumId = "3344" val albumId = "3344"
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "albumId=$albumId") { responseResourceName = "ping_ok.json",
expectedParam = "albumId=$albumId"
) {
client.api.unstar(albumId = albumId).execute() client.api.unstar(albumId = albumId).execute()
} }
} }

View File

@ -26,8 +26,10 @@ class SubsonicApiUpdatePlaylistTest : SubsonicAPIClientTest() {
fun `Should pass playlist id param in request`() { fun `Should pass playlist id param in request`() {
val id = "5453" val id = "5453"
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "playlistId=$id") { responseResourceName = "ping_ok.json",
expectedParam = "playlistId=$id"
) {
client.api.updatePlaylist(id = id).execute() client.api.updatePlaylist(id = id).execute()
} }
} }
@ -36,8 +38,10 @@ class SubsonicApiUpdatePlaylistTest : SubsonicAPIClientTest() {
fun `Should pass name param in request`() { fun `Should pass name param in request`() {
val name = "some-name" val name = "some-name"
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "name=$name") { responseResourceName = "ping_ok.json",
expectedParam = "name=$name"
) {
client.api.updatePlaylist("22", name = name).execute() client.api.updatePlaylist("22", name = name).execute()
} }
} }
@ -46,8 +50,10 @@ class SubsonicApiUpdatePlaylistTest : SubsonicAPIClientTest() {
fun `Should pass comment param in request`() { fun `Should pass comment param in request`() {
val comment = "some-unusual-comment" val comment = "some-unusual-comment"
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "comment=$comment") { responseResourceName = "ping_ok.json",
expectedParam = "comment=$comment"
) {
client.api.updatePlaylist("42", comment = comment).execute() client.api.updatePlaylist("42", comment = comment).execute()
} }
} }
@ -56,8 +62,10 @@ class SubsonicApiUpdatePlaylistTest : SubsonicAPIClientTest() {
fun `Should pass public param in request`() { fun `Should pass public param in request`() {
val public = true val public = true
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "public=$public") { responseResourceName = "ping_ok.json",
expectedParam = "public=$public"
) {
client.api.updatePlaylist("53", public = public).execute() client.api.updatePlaylist("53", public = public).execute()
} }
} }
@ -66,8 +74,10 @@ class SubsonicApiUpdatePlaylistTest : SubsonicAPIClientTest() {
fun `Should pass song ids to update in request`() { fun `Should pass song ids to update in request`() {
val songIds = listOf("45", "81") val songIds = listOf("45", "81")
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "songIdToAdd=${songIds[0]}&songIdToAdd=${songIds[1]}") { responseResourceName = "ping_ok.json",
expectedParam = "songIdToAdd=${songIds[0]}&songIdToAdd=${songIds[1]}"
) {
client.api.updatePlaylist("25", songIdsToAdd = songIds).execute() client.api.updatePlaylist("25", songIdsToAdd = songIds).execute()
} }
} }
@ -76,9 +86,11 @@ class SubsonicApiUpdatePlaylistTest : SubsonicAPIClientTest() {
fun `Should pass song indexes to remove in request`() { fun `Should pass song indexes to remove in request`() {
val songIndexesToRemove = listOf(129, 1) val songIndexesToRemove = listOf(129, 1)
mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", mockWebServerRule.assertRequestParam(
expectedParam = "songIndexToRemove=${songIndexesToRemove[0]}&" + responseResourceName = "ping_ok.json",
"songIndexToRemove=${songIndexesToRemove[1]}") { expectedParam = "songIndexToRemove=${songIndexesToRemove[0]}&" +
"songIndexToRemove=${songIndexesToRemove[1]}"
) {
client.api.updatePlaylist("49", songIndexesToRemove = songIndexesToRemove).execute() client.api.updatePlaylist("49", songIndexesToRemove = songIndexesToRemove).execute()
} }
} }

View File

@ -29,7 +29,7 @@ abstract class BaseInterceptorTest {
* params to the [Request]. * params to the [Request].
*/ */
fun createRequest(additionalParams: (Request.Builder) -> Unit): Request = Request.Builder() fun createRequest(additionalParams: (Request.Builder) -> Unit): Request = Request.Builder()
.url(mockWebServerRule.mockWebServer.url("/")) .url(mockWebServerRule.mockWebServer.url("/"))
.also { additionalParams(it) } .also { additionalParams(it) }
.build() .build()
} }

View File

@ -1,12 +1,12 @@
package org.moire.ultrasonic.api.subsonic.interceptors package org.moire.ultrasonic.api.subsonic.interceptors
import java.security.MessageDigest
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.MockResponse
import org.amshove.kluent.`should contain` import org.amshove.kluent.`should contain`
import org.amshove.kluent.`should not contain` import org.amshove.kluent.`should not contain`
import org.apache.commons.codec.binary.Hex import org.apache.commons.codec.binary.Hex
import org.junit.Test import org.junit.Test
import java.security.MessageDigest
/** /**
* Integration test for [PasswordMD5Interceptor]. * Integration test for [PasswordMD5Interceptor].
@ -28,9 +28,14 @@ class PasswordMD5InterceptorTest : BaseInterceptorTest() {
requestLine `should not contain` "p=enc:" requestLine `should not contain` "p=enc:"
val salt = requestLine.split('&').find { it.startsWith("s=") } val salt = requestLine.split('&').find { it.startsWith("s=") }
?.substringAfter('=')?.substringBefore(" ") ?.substringAfter('=')?.substringBefore(" ")
val expectedToken = String(Hex.encodeHex(MessageDigest.getInstance("MD5") val expectedToken = String(
.digest("$password$salt".toByteArray()), true)) Hex.encodeHex(
MessageDigest.getInstance("MD5")
.digest("$password$salt".toByteArray()),
true
)
)
requestLine `should contain` "t=$expectedToken" requestLine `should contain` "t=$expectedToken"
} }
} }

View File

@ -1,5 +1,6 @@
package org.moire.ultrasonic.api.subsonic.interceptors package org.moire.ultrasonic.api.subsonic.interceptors
import kotlin.LazyThreadSafetyMode.NONE
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.MockResponse
import org.amshove.kluent.`should contain` import org.amshove.kluent.`should contain`
@ -7,7 +8,6 @@ import org.amshove.kluent.`should equal`
import org.junit.Test import org.junit.Test
import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions
import org.moire.ultrasonic.api.subsonic.enqueueResponse import org.moire.ultrasonic.api.subsonic.enqueueResponse
import kotlin.LazyThreadSafetyMode.NONE
/** /**
* Integration test for [VersionInterceptor]. * Integration test for [VersionInterceptor].
@ -41,7 +41,7 @@ class VersionInterceptorTest : BaseInterceptorTest() {
client.newCall(createRequest {}).execute() client.newCall(createRequest {}).execute()
(interceptor as VersionInterceptor) (interceptor as VersionInterceptor)
.protocolVersion `should equal` SubsonicAPIVersions.V1_13_0 .protocolVersion `should equal` SubsonicAPIVersions.V1_13_0
} }
@Test @Test
@ -51,7 +51,7 @@ class VersionInterceptorTest : BaseInterceptorTest() {
client.newCall(createRequest {}).execute() client.newCall(createRequest {}).execute()
(interceptor as VersionInterceptor) (interceptor as VersionInterceptor)
.protocolVersion `should equal` SubsonicAPIVersions.V1_16_0 .protocolVersion `should equal` SubsonicAPIVersions.V1_16_0
} }
@Test @Test
@ -65,9 +65,11 @@ class VersionInterceptorTest : BaseInterceptorTest() {
@Test @Test
fun `Should not update version on non-json response`() { fun `Should not update version on non-json response`() {
mockWebServerRule.mockWebServer.enqueue(MockResponse() mockWebServerRule.mockWebServer.enqueue(
MockResponse()
.setBody("asdqwnekjnqwkjen") .setBody("asdqwnekjnqwkjen")
.setHeader("Content-Type", "application/octet-stream")) .setHeader("Content-Type", "application/octet-stream")
)
client.newCall(createRequest {}).execute() client.newCall(createRequest {}).execute()

View File

@ -82,8 +82,9 @@ internal class ApiVersionCheckWrapper(
): Call<SearchTwoResponse> { ): Call<SearchTwoResponse> {
checkVersion(V1_4_0) checkVersion(V1_4_0)
checkParamVersion(musicFolderId, V1_12_0) checkParamVersion(musicFolderId, V1_12_0)
return api.search2(query, artistCount, artistOffset, albumCount, albumOffset, songCount, return api.search2(
musicFolderId) query, artistCount, artistOffset, albumCount, albumOffset, songCount, musicFolderId
)
} }
override fun search3( override fun search3(
@ -97,8 +98,9 @@ internal class ApiVersionCheckWrapper(
): Call<SearchThreeResponse> { ): Call<SearchThreeResponse> {
checkVersion(V1_8_0) checkVersion(V1_8_0)
checkParamVersion(musicFolderId, V1_12_0) checkParamVersion(musicFolderId, V1_12_0)
return api.search3(query, artistCount, artistOffset, albumCount, albumOffset, return api.search3(
songCount, musicFolderId) query, artistCount, artistOffset, albumCount, albumOffset, songCount, musicFolderId
)
} }
override fun getPlaylists(username: String?): Call<GetPlaylistsResponse> { override fun getPlaylists(username: String?): Call<GetPlaylistsResponse> {
@ -216,8 +218,9 @@ internal class ApiVersionCheckWrapper(
checkParamVersion(videoSize, V1_6_0) checkParamVersion(videoSize, V1_6_0)
checkParamVersion(estimateContentLength, V1_8_0) checkParamVersion(estimateContentLength, V1_8_0)
checkParamVersion(converted, V1_14_0) checkParamVersion(converted, V1_14_0)
return api.stream(id, maxBitRate, format, timeOffset, videoSize, return api.stream(
estimateContentLength, converted) id, maxBitRate, format, timeOffset, videoSize, estimateContentLength, converted
)
} }
override fun jukeboxControl( override fun jukeboxControl(

View File

@ -4,6 +4,11 @@ import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule import com.fasterxml.jackson.module.kotlin.KotlinModule
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit.MILLISECONDS
import javax.net.ssl.SSLContext
import javax.net.ssl.X509TrustManager
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.ResponseBody import okhttp3.ResponseBody
import okhttp3.logging.HttpLoggingInterceptor import okhttp3.logging.HttpLoggingInterceptor
@ -17,11 +22,6 @@ import org.moire.ultrasonic.api.subsonic.response.SubsonicResponse
import retrofit2.Response import retrofit2.Response
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.jackson.JacksonConverterFactory import retrofit2.converter.jackson.JacksonConverterFactory
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit.MILLISECONDS
import javax.net.ssl.SSLContext
import javax.net.ssl.X509TrustManager
private const val READ_TIMEOUT = 60_000L private const val READ_TIMEOUT = 60_000L
@ -44,10 +44,10 @@ class SubsonicAPIClient(
} }
private val proxyPasswordInterceptor = ProxyPasswordInterceptor( private val proxyPasswordInterceptor = ProxyPasswordInterceptor(
config.minimalProtocolVersion, config.minimalProtocolVersion,
PasswordHexInterceptor(config.password), PasswordHexInterceptor(config.password),
PasswordMD5Interceptor(config.password), PasswordMD5Interceptor(config.password),
config.enableLdapUserSupport config.enableLdapUserSupport
) )
/** /**
@ -61,38 +61,38 @@ class SubsonicAPIClient(
} }
private val okHttpClient = baseOkClient.newBuilder() private val okHttpClient = baseOkClient.newBuilder()
.readTimeout(READ_TIMEOUT, MILLISECONDS) .readTimeout(READ_TIMEOUT, MILLISECONDS)
.apply { if (config.allowSelfSignedCertificate) allowSelfSignedCertificates() } .apply { if (config.allowSelfSignedCertificate) allowSelfSignedCertificates() }
.addInterceptor { chain -> .addInterceptor { chain ->
// Adds default request params // Adds default request params
val originalRequest = chain.request() val originalRequest = chain.request()
val newUrl = originalRequest.url().newBuilder() val newUrl = originalRequest.url().newBuilder()
.addQueryParameter("u", config.username) .addQueryParameter("u", config.username)
.addQueryParameter("c", config.clientID) .addQueryParameter("c", config.clientID)
.addQueryParameter("f", "json") .addQueryParameter("f", "json")
.build() .build()
chain.proceed(originalRequest.newBuilder().url(newUrl).build()) chain.proceed(originalRequest.newBuilder().url(newUrl).build())
} }
.addInterceptor(versionInterceptor) .addInterceptor(versionInterceptor)
.addInterceptor(proxyPasswordInterceptor) .addInterceptor(proxyPasswordInterceptor)
.addInterceptor(RangeHeaderInterceptor()) .addInterceptor(RangeHeaderInterceptor())
.apply { if (config.debug) addLogging() } .apply { if (config.debug) addLogging() }
.build() .build()
private val jacksonMapper = ObjectMapper() private val jacksonMapper = ObjectMapper()
.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true) .configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.registerModule(KotlinModule()) .registerModule(KotlinModule())
private val retrofit = Retrofit.Builder() private val retrofit = Retrofit.Builder()
.baseUrl("${config.baseUrl}/rest/") .baseUrl("${config.baseUrl}/rest/")
.client(okHttpClient) .client(okHttpClient)
.addConverterFactory(JacksonConverterFactory.create(jacksonMapper)) .addConverterFactory(JacksonConverterFactory.create(jacksonMapper))
.build() .build()
private val wrappedApi = ApiVersionCheckWrapper( private val wrappedApi = ApiVersionCheckWrapper(
retrofit.create(SubsonicAPIDefinition::class.java), retrofit.create(SubsonicAPIDefinition::class.java),
config.minimalProtocolVersion config.minimalProtocolVersion
) )
val api: SubsonicAPIDefinition get() = wrappedApi val api: SubsonicAPIDefinition get() = wrappedApi
@ -118,9 +118,9 @@ class SubsonicAPIClient(
* Prefer this method over [SubsonicAPIDefinition.stream] as this handles error cases. * Prefer this method over [SubsonicAPIDefinition.stream] as this handles error cases.
*/ */
fun stream(id: String, maxBitrate: Int? = null, offset: Long? = null): StreamResponse = fun stream(id: String, maxBitrate: Int? = null, offset: Long? = null): StreamResponse =
handleStreamResponse { handleStreamResponse {
api.stream(id, maxBitrate, offset = offset).execute() api.stream(id, maxBitrate, offset = offset).execute()
} }
/** /**
* Convenient method to get user avatar using [username]. * Convenient method to get user avatar using [username].
@ -138,14 +138,18 @@ class SubsonicAPIClient(
return if (response.isSuccessful) { return if (response.isSuccessful) {
val responseBody = response.body() val responseBody = response.body()
val contentType = responseBody?.contentType() val contentType = responseBody?.contentType()
if (contentType != null && if (
contentType.type().equals("application", true) && contentType != null &&
contentType.subtype().equals("json", true)) { contentType.type().equals("application", true) &&
contentType.subtype().equals("json", true)
) {
val error = jacksonMapper.readValue<SubsonicResponse>(responseBody.byteStream()) val error = jacksonMapper.readValue<SubsonicResponse>(responseBody.byteStream())
StreamResponse(apiError = error.error, responseHttpCode = response.code()) StreamResponse(apiError = error.error, responseHttpCode = response.code())
} else { } else {
StreamResponse(stream = responseBody?.byteStream(), StreamResponse(
responseHttpCode = response.code()) stream = responseBody?.byteStream(),
responseHttpCode = response.code()
)
} }
} else { } else {
StreamResponse(responseHttpCode = response.code()) StreamResponse(responseHttpCode = response.code())

View File

@ -149,7 +149,7 @@ interface SubsonicAPIDefinition {
@Query("songIdToAdd") songIdsToAdd: List<String>? = null, @Query("songIdToAdd") songIdsToAdd: List<String>? = null,
@Query("songIndexToRemove") songIndexesToRemove: List<Int>? = null @Query("songIndexToRemove") songIndexesToRemove: List<Int>? = null
): ):
Call<SubsonicResponse> Call<SubsonicResponse>
@GET("getPodcasts.view") @GET("getPodcasts.view")
fun getPodcasts( fun getPodcasts(

View File

@ -1,9 +1,9 @@
package org.moire.ultrasonic.api.subsonic.interceptors package org.moire.ultrasonic.api.subsonic.interceptors
import kotlin.LazyThreadSafetyMode.NONE
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.Interceptor.Chain import okhttp3.Interceptor.Chain
import okhttp3.Response import okhttp3.Response
import kotlin.LazyThreadSafetyMode.NONE
/** /**
* Adds password param converted to hex string in request url. * Adds password param converted to hex string in request url.
@ -19,7 +19,7 @@ class PasswordHexInterceptor(private val password: String) : Interceptor {
override fun intercept(chain: Chain): Response { override fun intercept(chain: Chain): Response {
val originalRequest = chain.request() val originalRequest = chain.request()
val updatedUrl = originalRequest.url().newBuilder() val updatedUrl = originalRequest.url().newBuilder()
.addEncodedQueryParameter("p", passwordHex).build() .addEncodedQueryParameter("p", passwordHex).build()
return chain.proceed(originalRequest.newBuilder().url(updatedUrl).build()) return chain.proceed(originalRequest.newBuilder().url(updatedUrl).build())
} }
} }

View File

@ -1,12 +1,12 @@
package org.moire.ultrasonic.api.subsonic.interceptors package org.moire.ultrasonic.api.subsonic.interceptors
import okhttp3.Interceptor
import okhttp3.Interceptor.Chain
import okhttp3.Response
import java.math.BigInteger import java.math.BigInteger
import java.security.MessageDigest import java.security.MessageDigest
import java.security.NoSuchAlgorithmException import java.security.NoSuchAlgorithmException
import java.security.SecureRandom import java.security.SecureRandom
import okhttp3.Interceptor
import okhttp3.Interceptor.Chain
import okhttp3.Response
/** /**
* Adds password param as MD5 hash with random salt. Salt is also added as a param. * Adds password param as MD5 hash with random salt. Salt is also added as a param.
@ -32,9 +32,9 @@ class PasswordMD5Interceptor(private val password: String) : Interceptor {
override fun intercept(chain: Chain): Response { override fun intercept(chain: Chain): Response {
val originalRequest = chain.request() val originalRequest = chain.request()
val updatedUrl = originalRequest.url().newBuilder() val updatedUrl = originalRequest.url().newBuilder()
.addQueryParameter("t", passwordMD5Hash) .addQueryParameter("t", passwordMD5Hash)
.addQueryParameter("s", salt) .addQueryParameter("s", salt)
.build() .build()
return chain.proceed(originalRequest.newBuilder().url(updatedUrl).build()) return chain.proceed(originalRequest.newBuilder().url(updatedUrl).build())
} }

View File

@ -20,10 +20,9 @@ internal class ProxyPasswordInterceptor(
var apiVersion: SubsonicAPIVersions = initialAPIVersions var apiVersion: SubsonicAPIVersions = initialAPIVersions
override fun intercept(chain: Chain): Response = override fun intercept(chain: Chain): Response =
if (apiVersion < SubsonicAPIVersions.V1_13_0 || if (apiVersion < SubsonicAPIVersions.V1_13_0 || forceHexPassword) {
forceHexPassword) { hexInterceptor.intercept(chain)
hexInterceptor.intercept(chain) } else {
} else { mD5Interceptor.intercept(chain)
mD5Interceptor.intercept(chain) }
}
} }

View File

@ -1,9 +1,9 @@
package org.moire.ultrasonic.api.subsonic.interceptors package org.moire.ultrasonic.api.subsonic.interceptors
import java.util.concurrent.TimeUnit.MILLISECONDS
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.Interceptor.Chain import okhttp3.Interceptor.Chain
import okhttp3.Response import okhttp3.Response
import java.util.concurrent.TimeUnit.MILLISECONDS
internal const val SOCKET_READ_TIMEOUT_DOWNLOAD = 30 * 1000 internal const val SOCKET_READ_TIMEOUT_DOWNLOAD = 30 * 1000
// Allow 20 seconds extra timeout pear MB offset. // Allow 20 seconds extra timeout pear MB offset.
@ -24,9 +24,11 @@ internal class RangeHeaderInterceptor : Interceptor {
val offsetValue = headers["Range"] ?: "0" val offsetValue = headers["Range"] ?: "0"
val offset = "bytes=$offsetValue-" val offset = "bytes=$offsetValue-"
chain.withReadTimeout(getReadTimeout(offsetValue.toInt()), MILLISECONDS) chain.withReadTimeout(getReadTimeout(offsetValue.toInt()), MILLISECONDS)
.proceed(originalRequest.newBuilder() .proceed(
.removeHeader("Range").addHeader("Range", offset) originalRequest.newBuilder()
.build()) .removeHeader("Range").addHeader("Range", offset)
.build()
)
} else { } else {
chain.proceed(originalRequest) chain.proceed(originalRequest)
} }
@ -37,5 +39,5 @@ internal class RangeHeaderInterceptor : Interceptor {
// on the server. In that case, the server uses a long time before sending any data, // on the server. In that case, the server uses a long time before sending any data,
// causing the client to time out. // causing the client to time out.
private fun getReadTimeout(offset: Int) = private fun getReadTimeout(offset: Int) =
(SOCKET_READ_TIMEOUT_DOWNLOAD + offset * TIMEOUT_MILLIS_PER_OFFSET_BYTE).toInt() (SOCKET_READ_TIMEOUT_DOWNLOAD + offset * TIMEOUT_MILLIS_PER_OFFSET_BYTE).toInt()
} }

View File

@ -3,11 +3,11 @@ package org.moire.ultrasonic.api.subsonic.interceptors
import com.fasterxml.jackson.core.JsonFactory import com.fasterxml.jackson.core.JsonFactory
import com.fasterxml.jackson.core.JsonParseException import com.fasterxml.jackson.core.JsonParseException
import com.fasterxml.jackson.core.JsonToken import com.fasterxml.jackson.core.JsonToken
import java.io.IOException
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.Interceptor.Chain import okhttp3.Interceptor.Chain
import okhttp3.Response import okhttp3.Response
import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions
import java.io.IOException
private const val DEFAULT_PEEK_BYTE_COUNT = 1000L private const val DEFAULT_PEEK_BYTE_COUNT = 1000L
@ -29,12 +29,14 @@ internal class VersionInterceptor(
val originalRequest = chain.request() val originalRequest = chain.request()
val newRequest = originalRequest.newBuilder() val newRequest = originalRequest.newBuilder()
.url(originalRequest .url(
.url() originalRequest
.newBuilder() .url()
.addQueryParameter("v", protocolVersion.restApiVersion) .newBuilder()
.build()) .addQueryParameter("v", protocolVersion.restApiVersion)
.build() .build()
)
.build()
val response = chain.proceed(newRequest) val response = chain.proceed(newRequest)
if (response.isSuccessful) { if (response.isSuccessful) {
@ -54,8 +56,10 @@ internal class VersionInterceptor(
val jsonReader = jsonFactory.createParser(content) val jsonReader = jsonFactory.createParser(content)
jsonReader.nextToken() jsonReader.nextToken()
if (jsonReader.currentToken == JsonToken.START_OBJECT) { if (jsonReader.currentToken == JsonToken.START_OBJECT) {
while (jsonReader.currentName != "version" && while (
jsonReader.currentToken != null) { jsonReader.currentName != "version" &&
jsonReader.currentToken != null
) {
jsonReader.nextToken() jsonReader.nextToken()
} }
val versionStr = jsonReader.nextTextValue() val versionStr = jsonReader.nextTextValue()

View File

@ -1,7 +1,7 @@
package org.moire.ultrasonic.api.subsonic.response package org.moire.ultrasonic.api.subsonic.response
import org.moire.ultrasonic.api.subsonic.SubsonicError
import java.io.InputStream import java.io.InputStream
import org.moire.ultrasonic.api.subsonic.SubsonicError
/** /**
* Special response that contains either [stream] of data from api, or [apiError], * Special response that contains either [stream] of data from api, or [apiError],

View File

@ -24,14 +24,16 @@ open class SubsonicResponse(
companion object { companion object {
fun getStatusFromJson(jsonValue: String) = values() fun getStatusFromJson(jsonValue: String) = values()
.filter { it.jsonValue == jsonValue }.firstOrNull() .filter { it.jsonValue == jsonValue }.firstOrNull()
?: throw IllegalArgumentException("Unknown status value: $jsonValue") ?: throw IllegalArgumentException("Unknown status value: $jsonValue")
class StatusJsonDeserializer : JsonDeserializer<Status>() { class StatusJsonDeserializer : JsonDeserializer<Status>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): Status { override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): Status {
if (p.currentName != "status") { if (p.currentName != "status") {
throw JsonParseException(p, throw JsonParseException(
"Current token is not status. Current token name ${p.currentName}.") p,
"Current token is not status. Current token name ${p.currentName}."
)
} }
return getStatusFromJson(p.text) return getStatusFromJson(p.text)
} }

View File

@ -16,8 +16,10 @@ class ProxyPasswordInterceptorTest {
private val mockPasswordMd5Interceptor = mock<PasswordMD5Interceptor>() private val mockPasswordMd5Interceptor = mock<PasswordMD5Interceptor>()
private val mockChain = mock<Chain>() private val mockChain = mock<Chain>()
private val proxyInterceptor = ProxyPasswordInterceptor(V1_12_0, private val proxyInterceptor = ProxyPasswordInterceptor(
mockPasswordHexInterceptor, mockPasswordMd5Interceptor, false) V1_12_0,
mockPasswordHexInterceptor, mockPasswordMd5Interceptor, false
)
@Test @Test
fun `Should use hex password on versions less then 1 13 0`() { fun `Should use hex password on versions less then 1 13 0`() {
@ -37,8 +39,10 @@ class ProxyPasswordInterceptorTest {
@Test @Test
fun `Should use hex password if forceHex is true`() { fun `Should use hex password if forceHex is true`() {
val interceptor = ProxyPasswordInterceptor(V1_16_0, mockPasswordHexInterceptor, val interceptor = ProxyPasswordInterceptor(
mockPasswordMd5Interceptor, true) V1_16_0, mockPasswordHexInterceptor,
mockPasswordMd5Interceptor, true
)
interceptor.intercept(mockChain) interceptor.intercept(mockChain)

View File

@ -11,7 +11,7 @@ class StreamResponseTest {
@Test @Test
fun `Should have error if subsonic error is not null`() { fun `Should have error if subsonic error is not null`() {
StreamResponse(apiError = RequestedDataWasNotFound, responseHttpCode = 200) StreamResponse(apiError = RequestedDataWasNotFound, responseHttpCode = 200)
.hasError() `should be equal to` true .hasError() `should be equal to` true
} }
@Test @Test

View File

@ -2,13 +2,13 @@ ext.versions = [
minSdk : 14, minSdk : 14,
targetSdk : 23, targetSdk : 23,
compileSdk : 28, compileSdk : 28,
gradle : '4.6', gradle : '6.5',
androidTools : "3.6.3", androidTools : "4.0.0",
ktlint : "0.28.0", ktlint : "0.37.1",
ktlintGradle : "5.1.0", ktlintGradle : "9.2.1",
detekt : "1.0.0.RC6-4", detekt : "1.0.0.RC6-4",
jacoco : "0.8.2", jacoco : "0.8.5",
androidSupport : "22.2.1", androidSupport : "22.2.1",
androidLegacySupport : "1.0.0", androidLegacySupport : "1.0.0",
@ -39,7 +39,7 @@ ext.versions = [
ext.gradlePlugins = [ ext.gradlePlugins = [
androidTools : "com.android.tools.build:gradle:$versions.androidTools", androidTools : "com.android.tools.build:gradle:$versions.androidTools",
kotlin : "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin", kotlin : "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin",
ktlintGradle : "gradle.plugin.org.jlleitschuh.gradle:ktlint-gradle:$versions.ktlintGradle", ktlintGradle : "org.jlleitschuh.gradle:ktlint-gradle:$versions.ktlintGradle",
detekt : "gradle.plugin.io.gitlab.arturbosch.detekt:detekt-gradle-plugin:$versions.detekt", detekt : "gradle.plugin.io.gitlab.arturbosch.detekt:detekt-gradle-plugin:$versions.detekt",
jacoco : "org.jacoco:org.jacoco.core:$versions.jacoco" jacoco : "org.jacoco:org.jacoco.core:$versions.jacoco"
] ]

View File

@ -1,6 +1,6 @@
#Sun Apr 26 07:18:18 CEST 2020 #Sat Jun 13 17:12:11 CEST 2020
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip

View File

@ -31,9 +31,9 @@ tasks.create(name: 'jacocoFullReport', type: JacocoReport, dependsOn: 'jacocoMer
group = "Reporting" group = "Reporting"
description = "Generate full Jacoco coverage report including all modules." description = "Generate full Jacoco coverage report including all modules."
classDirectories = files() getClassDirectories().setFrom(files())
sourceDirectories = files() getSourceDirectories().setFrom(files())
executionData = files() getExecutionData().setFrom(files())
reports { reports {
xml.enabled = true xml.enabled = true

View File

@ -41,9 +41,9 @@ jacocoTestReport {
} }
afterEvaluate { afterEvaluate {
classDirectories = files(classDirectories.files.collect { getClassDirectories().setFrom(files(classDirectories.files.collect {
fileTree(dir: it, excludes: jacocoExclude) fileTree(dir: it, excludes: jacocoExclude)
}) }))
} }
} }

View File

@ -13,7 +13,8 @@ class UApp : MultiDexApplication() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
startKoin(this, startKoin(
this,
listOf( listOf(
directoriesModule, directoriesModule,
appPermanentStorage, appPermanentStorage,

View File

@ -3,6 +3,7 @@ package org.moire.ultrasonic.di
import android.content.SharedPreferences import android.content.SharedPreferences
import android.util.Log import android.util.Log
import kotlin.math.abs
import org.koin.dsl.module.module import org.koin.dsl.module.module
import org.moire.ultrasonic.BuildConfig import org.moire.ultrasonic.BuildConfig
import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient
@ -16,7 +17,6 @@ import org.moire.ultrasonic.service.OfflineMusicService
import org.moire.ultrasonic.service.RESTMusicService import org.moire.ultrasonic.service.RESTMusicService
import org.moire.ultrasonic.subsonic.loader.image.SubsonicImageLoader import org.moire.ultrasonic.subsonic.loader.image.SubsonicImageLoader
import org.moire.ultrasonic.util.Constants import org.moire.ultrasonic.util.Constants
import kotlin.math.abs
internal const val MUSIC_SERVICE_CONTEXT = "CurrentMusicService" internal const val MUSIC_SERVICE_CONTEXT = "CurrentMusicService"
internal const val ONLINE_MUSIC_SERVICE = "OnlineMusicService" internal const val ONLINE_MUSIC_SERVICE = "OnlineMusicService"
@ -26,91 +26,91 @@ private const val UNKNOWN_SERVER_URL = "not-exists"
private const val LOG_TAG = "MusicServiceModule" private const val LOG_TAG = "MusicServiceModule"
val musicServiceModule = module(MUSIC_SERVICE_CONTEXT) { val musicServiceModule = module(MUSIC_SERVICE_CONTEXT) {
subsonicApiModule() subsonicApiModule()
single(name = "ServerInstance") { single(name = "ServerInstance") {
return@single get<SharedPreferences>(SP_NAME).getInt( return@single get<SharedPreferences>(SP_NAME).getInt(
Constants.PREFERENCES_KEY_SERVER_INSTANCE, Constants.PREFERENCES_KEY_SERVER_INSTANCE,
DEFAULT_SERVER_INSTANCE DEFAULT_SERVER_INSTANCE
) )
}
single(name = "ServerID") {
val serverInstance = get<Int>(name = "ServerInstance")
val sp: SharedPreferences = get(SP_NAME)
val serverUrl = sp.getString(
Constants.PREFERENCES_KEY_SERVER_URL + serverInstance,
null
)
return@single if (serverUrl == null) {
UNKNOWN_SERVER_URL
} else {
abs("$serverUrl$serverInstance".hashCode()).toString()
}
}
single {
val serverId = get<String>(name = "ServerID")
return@single PermanentFileStorage(get(), serverId, BuildConfig.DEBUG)
}
single {
val instance = get<Int>(name = "ServerInstance")
val sp: SharedPreferences = get(SP_NAME)
val serverUrl = sp.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null)
val username = sp.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null)
val password = sp.getString(Constants.PREFERENCES_KEY_PASSWORD + instance, null)
val allowSelfSignedCertificate = sp.getBoolean(
Constants.PREFERENCES_KEY_ALLOW_SELF_SIGNED_CERTIFICATE + instance,
false
)
val enableLdapUserSupport = sp.getBoolean(
Constants.PREFERENCES_KEY_LDAP_SUPPORT + instance,
false
)
if (serverUrl == null ||
username == null ||
password == null
) {
Log.i(LOG_TAG, "Server credentials is not available")
return@single SubsonicClientConfiguration(
baseUrl = "http://localhost",
username = "",
password = "",
minimalProtocolVersion = SubsonicAPIVersions.fromApiVersion(
Constants.REST_PROTOCOL_VERSION
),
clientID = Constants.REST_CLIENT_ID,
allowSelfSignedCertificate = allowSelfSignedCertificate,
enableLdapUserSupport = enableLdapUserSupport,
debug = BuildConfig.DEBUG
)
} else {
return@single SubsonicClientConfiguration(
baseUrl = serverUrl,
username = username,
password = password,
minimalProtocolVersion = SubsonicAPIVersions.fromApiVersion(
Constants.REST_PROTOCOL_VERSION
),
clientID = Constants.REST_CLIENT_ID,
allowSelfSignedCertificate = allowSelfSignedCertificate,
enableLdapUserSupport = enableLdapUserSupport,
debug = BuildConfig.DEBUG
)
}
}
single { SubsonicAPIClient(get()) }
single<MusicService>(name = ONLINE_MUSIC_SERVICE) {
CachedMusicService(RESTMusicService(get(), get()))
}
single<MusicService>(name = OFFLINE_MUSIC_SERVICE) {
OfflineMusicService(get(), get())
}
single { SubsonicImageLoader(getProperty(DiProperties.APP_CONTEXT), get()) }
} }
single(name = "ServerID") {
val serverInstance = get<Int>(name = "ServerInstance")
val sp: SharedPreferences = get(SP_NAME)
val serverUrl = sp.getString(
Constants.PREFERENCES_KEY_SERVER_URL + serverInstance,
null
)
return@single if (serverUrl == null) {
UNKNOWN_SERVER_URL
} else {
abs("$serverUrl$serverInstance".hashCode()).toString()
}
}
single {
val serverId = get<String>(name = "ServerID")
return@single PermanentFileStorage(get(), serverId, BuildConfig.DEBUG)
}
single {
val instance = get<Int>(name = "ServerInstance")
val sp: SharedPreferences = get(SP_NAME)
val serverUrl = sp.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null)
val username = sp.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null)
val password = sp.getString(Constants.PREFERENCES_KEY_PASSWORD + instance, null)
val allowSelfSignedCertificate = sp.getBoolean(
Constants.PREFERENCES_KEY_ALLOW_SELF_SIGNED_CERTIFICATE + instance,
false
)
val enableLdapUserSupport = sp.getBoolean(
Constants.PREFERENCES_KEY_LDAP_SUPPORT + instance,
false
)
if (serverUrl == null ||
username == null ||
password == null
) {
Log.i(LOG_TAG, "Server credentials is not available")
return@single SubsonicClientConfiguration(
baseUrl = "http://localhost",
username = "",
password = "",
minimalProtocolVersion = SubsonicAPIVersions.fromApiVersion(
Constants.REST_PROTOCOL_VERSION
),
clientID = Constants.REST_CLIENT_ID,
allowSelfSignedCertificate = allowSelfSignedCertificate,
enableLdapUserSupport = enableLdapUserSupport,
debug = BuildConfig.DEBUG
)
} else {
return@single SubsonicClientConfiguration(
baseUrl = serverUrl,
username = username,
password = password,
minimalProtocolVersion = SubsonicAPIVersions.fromApiVersion(
Constants.REST_PROTOCOL_VERSION
),
clientID = Constants.REST_CLIENT_ID,
allowSelfSignedCertificate = allowSelfSignedCertificate,
enableLdapUserSupport = enableLdapUserSupport,
debug = BuildConfig.DEBUG
)
}
}
single { SubsonicAPIClient(get()) }
single<MusicService>(name = ONLINE_MUSIC_SERVICE) {
CachedMusicService(RESTMusicService(get(), get()))
}
single<MusicService>(name = OFFLINE_MUSIC_SERVICE) {
OfflineMusicService(get(), get())
}
single { SubsonicImageLoader(getProperty(DiProperties.APP_CONTEXT), get()) }
}

View File

@ -11,4 +11,4 @@ fun ApiChatMessage.toDomainEntity(): ChatMessage = ChatMessage(
) )
fun List<ApiChatMessage>.toDomainEntitiesList(): List<ChatMessage> = this fun List<ApiChatMessage>.toDomainEntitiesList(): List<ChatMessage> = this
.map { it.toDomainEntity() } .map { it.toDomainEntity() }

View File

@ -6,11 +6,12 @@ package org.moire.ultrasonic.domain
import org.moire.ultrasonic.api.subsonic.models.Index import org.moire.ultrasonic.api.subsonic.models.Index
import org.moire.ultrasonic.api.subsonic.models.Indexes as APIIndexes import org.moire.ultrasonic.api.subsonic.models.Indexes as APIIndexes
fun APIIndexes.toDomainEntity(): Indexes = Indexes(this.lastModified, this.ignoredArticles, fun APIIndexes.toDomainEntity(): Indexes = Indexes(
this.shortcutList.map { it.toDomainEntity() }.toMutableList(), this.lastModified, this.ignoredArticles,
this.indexList.foldIndexToArtistList().toMutableList() this.shortcutList.map { it.toDomainEntity() }.toMutableList(),
this.indexList.foldIndexToArtistList().toMutableList()
) )
private fun List<Index>.foldIndexToArtistList(): List<Artist> = this.fold(listOf(), { private fun List<Index>.foldIndexToArtistList(): List<Artist> = this.fold(
acc, index -> acc + index.artists.map { it.toDomainEntity() } listOf(), { acc, index -> acc + index.artists.map { it.toDomainEntity() } }
}) )

View File

@ -3,11 +3,11 @@
@file:JvmName("APIMusicDirectoryConverter") @file:JvmName("APIMusicDirectoryConverter")
package org.moire.ultrasonic.domain package org.moire.ultrasonic.domain
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
import java.text.DateFormat import java.text.DateFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
import org.moire.ultrasonic.api.subsonic.models.MusicDirectory as APIMusicDirectory import org.moire.ultrasonic.api.subsonic.models.MusicDirectory as APIMusicDirectory
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
internal val dateFormat: DateFormat by lazy { internal val dateFormat: DateFormat by lazy {
SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.getDefault()) SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.getDefault())

View File

@ -8,4 +8,4 @@ import org.moire.ultrasonic.api.subsonic.models.MusicFolder as APIMusicFolder
fun APIMusicFolder.toDomainEntity(): MusicFolder = MusicFolder(this.id, this.name) fun APIMusicFolder.toDomainEntity(): MusicFolder = MusicFolder(this.id, this.name)
fun List<APIMusicFolder>.toDomainEntityList(): List<MusicFolder> = fun List<APIMusicFolder>.toDomainEntityList(): List<MusicFolder> =
this.map { it.toDomainEntity() } this.map { it.toDomainEntity() }

View File

@ -14,9 +14,11 @@ fun APIPlaylist.toMusicDirectoryDomainEntity(): MusicDirectory = MusicDirectory(
addAll(this@toMusicDirectoryDomainEntity.entriesList.map { it.toDomainEntity() }) addAll(this@toMusicDirectoryDomainEntity.entriesList.map { it.toDomainEntity() })
} }
fun APIPlaylist.toDomainEntity(): Playlist = Playlist(this.id, this.name, this.owner, fun APIPlaylist.toDomainEntity(): Playlist = Playlist(
this.comment, this.songCount.toString(), this.id, this.name, this.owner,
this.created?.let { playlistDateFormat.format(it.time) } ?: "", this.comment, this.songCount.toString(),
public) this.created?.let { playlistDateFormat.format(it.time) } ?: "",
public
)
fun List<APIPlaylist>.toDomainEntitiesList(): List<Playlist> = this.map { it.toDomainEntity() } fun List<APIPlaylist>.toDomainEntitiesList(): List<Playlist> = this.map { it.toDomainEntity() }

View File

@ -6,7 +6,8 @@ package org.moire.ultrasonic.domain
import org.moire.ultrasonic.api.subsonic.models.PodcastChannel import org.moire.ultrasonic.api.subsonic.models.PodcastChannel
fun PodcastChannel.toDomainEntity(): PodcastsChannel = PodcastsChannel( fun PodcastChannel.toDomainEntity(): PodcastsChannel = PodcastsChannel(
this.id, this.title, this.url, this.description, this.status) this.id, this.title, this.url, this.description, this.status
)
fun List<PodcastChannel>.toDomainEntitiesList(): List<PodcastsChannel> = this fun List<PodcastChannel>.toDomainEntitiesList(): List<PodcastsChannel> = this
.map { it.toDomainEntity() } .map { it.toDomainEntity() }

View File

@ -3,19 +3,23 @@
@file:JvmName("APISearchConverter") @file:JvmName("APISearchConverter")
package org.moire.ultrasonic.domain package org.moire.ultrasonic.domain
import org.moire.ultrasonic.api.subsonic.models.SearchResult as APISearchResult
import org.moire.ultrasonic.api.subsonic.models.SearchThreeResult import org.moire.ultrasonic.api.subsonic.models.SearchThreeResult
import org.moire.ultrasonic.api.subsonic.models.SearchTwoResult import org.moire.ultrasonic.api.subsonic.models.SearchTwoResult
import org.moire.ultrasonic.api.subsonic.models.SearchResult as APISearchResult
fun APISearchResult.toDomainEntity(): SearchResult = SearchResult(emptyList(), emptyList(), fun APISearchResult.toDomainEntity(): SearchResult = SearchResult(
this.matchList.map { it.toDomainEntity() }) emptyList(), emptyList(),
this.matchList.map { it.toDomainEntity() }
)
fun SearchTwoResult.toDomainEntity(): SearchResult = SearchResult( fun SearchTwoResult.toDomainEntity(): SearchResult = SearchResult(
this.artistList.map { it.toDomainEntity() }, this.artistList.map { it.toDomainEntity() },
this.albumList.map { it.toDomainEntity() }, this.albumList.map { it.toDomainEntity() },
this.songList.map { it.toDomainEntity() }) this.songList.map { it.toDomainEntity() }
)
fun SearchThreeResult.toDomainEntity(): SearchResult = SearchResult( fun SearchThreeResult.toDomainEntity(): SearchResult = SearchResult(
this.artistList.map { it.toDomainEntity() }, this.artistList.map { it.toDomainEntity() },
this.albumList.map { it.toDomainEntity() }, this.albumList.map { it.toDomainEntity() },
this.songList.map { it.toDomainEntity() }) this.songList.map { it.toDomainEntity() }
)

View File

@ -19,27 +19,27 @@ import org.moire.ultrasonic.service.SubsonicRESTException
* display error reason for user. * display error reason for user.
*/ */
fun SubsonicRESTException.getLocalizedErrorMessage(context: Context): String = fun SubsonicRESTException.getLocalizedErrorMessage(context: Context): String =
when (error) { when (error) {
is Generic -> { is Generic -> {
val message = error.message val message = error.message
val errorMessage = if (message == "") { val errorMessage = if (message == "") {
context.getString(R.string.api_subsonic_generic_no_message) context.getString(R.string.api_subsonic_generic_no_message)
} else { } else {
message message
}
context.getString(R.string.api_subsonic_generic, errorMessage)
} }
RequiredParamMissing -> context.getString(R.string.api_subsonic_param_missing) context.getString(R.string.api_subsonic_generic, errorMessage)
IncompatibleClientProtocolVersion -> context
.getString(R.string.api_subsonic_upgrade_client)
IncompatibleServerProtocolVersion -> context
.getString(R.string.api_subsonic_upgrade_server)
WrongUsernameOrPassword -> context.getString(R.string.api_subsonic_not_authenticated)
TokenAuthNotSupportedForLDAP -> context
.getString(R.string.api_subsonic_token_auth_not_supported_for_ldap)
UserNotAuthorizedForOperation -> context
.getString(R.string.api_subsonic_not_authorized)
TrialPeriodIsOver -> context.getString(R.string.api_subsonic_trial_period_is_over)
RequestedDataWasNotFound -> context
.getString(R.string.api_subsonic_requested_data_was_not_found)
} }
RequiredParamMissing -> context.getString(R.string.api_subsonic_param_missing)
IncompatibleClientProtocolVersion ->
context.getString(R.string.api_subsonic_upgrade_client)
IncompatibleServerProtocolVersion ->
context.getString(R.string.api_subsonic_upgrade_server)
WrongUsernameOrPassword -> context.getString(R.string.api_subsonic_not_authenticated)
TokenAuthNotSupportedForLDAP ->
context.getString(R.string.api_subsonic_token_auth_not_supported_for_ldap)
UserNotAuthorizedForOperation ->
context.getString(R.string.api_subsonic_not_authorized)
TrialPeriodIsOver -> context.getString(R.string.api_subsonic_trial_period_is_over)
RequestedDataWasNotFound ->
context.getString(R.string.api_subsonic_requested_data_was_not_found)
}

View File

@ -31,7 +31,8 @@ class SubsonicImageLoaderProxy(
if (id != null && if (id != null &&
view != null && view != null &&
view is ImageView) { view is ImageView
) {
val request = ImageRequest.CoverArt( val request = ImageRequest.CoverArt(
id, id,
view, view,
@ -52,7 +53,8 @@ class SubsonicImageLoaderProxy(
) { ) {
if (username != null && if (username != null &&
view != null && view != null &&
view is ImageView) { view is ImageView
) {
val request = ImageRequest.Avatar( val request = ImageRequest.Avatar(
username, username,
view, view,

View File

@ -2,12 +2,12 @@
package org.moire.ultrasonic.domain package org.moire.ultrasonic.domain
import java.util.Calendar
import org.amshove.kluent.`should be equal to` import org.amshove.kluent.`should be equal to`
import org.amshove.kluent.`should equal` import org.amshove.kluent.`should equal`
import org.junit.Test import org.junit.Test
import org.moire.ultrasonic.api.subsonic.models.Album import org.moire.ultrasonic.api.subsonic.models.Album
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
import java.util.Calendar
/** /**
* Unit test for extension functions in [APIAlbumConverter.kt] file. * Unit test for extension functions in [APIAlbumConverter.kt] file.
@ -15,9 +15,11 @@ import java.util.Calendar
class APIAlbumConverterTest { class APIAlbumConverterTest {
@Test @Test
fun `Should convert Album to domain entity`() { fun `Should convert Album to domain entity`() {
val entity = Album(id = "387", name = "some-name", coverArt = "asdas", val entity = Album(
artist = "some-artist", artistId = "390", songCount = 12, duration = 841, id = "387", name = "some-name", coverArt = "asdas",
created = Calendar.getInstance(), year = 2017, genre = "some-genre") artist = "some-artist", artistId = "390", songCount = 12, duration = 841,
created = Calendar.getInstance(), year = 2017, genre = "some-genre"
)
val convertedEntity = entity.toDomainEntity() val convertedEntity = entity.toDomainEntity()
@ -38,10 +40,12 @@ class APIAlbumConverterTest {
@Test @Test
fun `Should convert to MusicDirectory domain entity`() { fun `Should convert to MusicDirectory domain entity`() {
val entity = Album(id = "101", name = "some-album", artist = "some-artist", artistId = "54", val entity = Album(
coverArt = "some-id", songCount = 10, duration = 456, id = "101", name = "some-album", artist = "some-artist", artistId = "54",
created = Calendar.getInstance(), year = 2022, genre = "Hard Rock", coverArt = "some-id", songCount = 10, duration = 456,
songList = listOf(MusicDirectoryChild())) created = Calendar.getInstance(), year = 2022, genre = "Hard Rock",
songList = listOf(MusicDirectoryChild())
)
val convertedEntity = entity.toMusicDirectoryDomainEntity() val convertedEntity = entity.toMusicDirectoryDomainEntity()

View File

@ -2,11 +2,11 @@
package org.moire.ultrasonic.domain package org.moire.ultrasonic.domain
import java.util.Calendar
import org.amshove.kluent.`should equal` import org.amshove.kluent.`should equal`
import org.junit.Test import org.junit.Test
import org.moire.ultrasonic.api.subsonic.models.Album import org.moire.ultrasonic.api.subsonic.models.Album
import org.moire.ultrasonic.api.subsonic.models.Artist import org.moire.ultrasonic.api.subsonic.models.Artist
import java.util.Calendar
/** /**
* Unit test for extension functions in APIArtistConverter.kt file. * Unit test for extension functions in APIArtistConverter.kt file.
@ -26,18 +26,24 @@ class APIArtistConverterTest {
@Test @Test
fun `Should convert Artist entity to domain MusicDirectory entity`() { fun `Should convert Artist entity to domain MusicDirectory entity`() {
val entity = Artist(id = "101", name = "artist-name", coverArt = "some-art", val entity = Artist(
albumCount = 10, id = "101", name = "artist-name", coverArt = "some-art",
albumsList = listOf(Album(id = "562", name = "some-name", coverArt = "zzz", albumCount = 10,
artist = "artist-name", artistId = "256", songCount = 10, duration = 345, albumsList = listOf(
created = Calendar.getInstance(), year = 2011, genre = "Math Rock"))) Album(
id = "562", name = "some-name", coverArt = "zzz",
artist = "artist-name", artistId = "256", songCount = 10, duration = 345,
created = Calendar.getInstance(), year = 2011, genre = "Math Rock"
)
)
)
val convertedEntity = entity.toMusicDirectoryDomainEntity() val convertedEntity = entity.toMusicDirectoryDomainEntity()
with(convertedEntity) { with(convertedEntity) {
name `should equal` entity.name name `should equal` entity.name
getAllChild() `should equal` entity.albumsList getAllChild() `should equal` entity.albumsList
.map { it.toDomainEntity() }.toMutableList() .map { it.toDomainEntity() }.toMutableList()
} }
} }
} }

View File

@ -2,12 +2,12 @@
package org.moire.ultrasonic.domain package org.moire.ultrasonic.domain
import java.util.Calendar
import org.amshove.kluent.`should be equal to` import org.amshove.kluent.`should be equal to`
import org.amshove.kluent.`should equal` import org.amshove.kluent.`should equal`
import org.junit.Test import org.junit.Test
import org.moire.ultrasonic.api.subsonic.models.Bookmark import org.moire.ultrasonic.api.subsonic.models.Bookmark
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
import java.util.Calendar
/** /**
* Unit test for function that converts [Bookmark] api entity to domain. * Unit test for function that converts [Bookmark] api entity to domain.
@ -15,8 +15,10 @@ import java.util.Calendar
class APIBookmarkConverterTest { class APIBookmarkConverterTest {
@Test @Test
fun `Should convert to domain entity`() { fun `Should convert to domain entity`() {
val entity = Bookmark(412313L, "Awesemo", "Nice", Calendar.getInstance(), val entity = Bookmark(
Calendar.getInstance(), MusicDirectoryChild(id = "12333")) 412313L, "Awesemo", "Nice", Calendar.getInstance(),
Calendar.getInstance(), MusicDirectoryChild(id = "12333")
)
val domainEntity = entity.toDomainEntity() val domainEntity = entity.toDomainEntity()

View File

@ -16,15 +16,21 @@ class APIIndexesConverterTest {
@Test @Test
fun `Should convert Indexes entity`() { fun `Should convert Indexes entity`() {
val artistsA = listOf( val artistsA = listOf(
Artist(id = "4", name = "AC/DC"), Artist(id = "4", name = "AC/DC"),
Artist(id = "45", name = "ABBA")) Artist(id = "45", name = "ABBA")
)
val artistsT = listOf( val artistsT = listOf(
Artist(id = "10", name = "Taproot"), Artist(id = "10", name = "Taproot"),
Artist(id = "12", name = "Teebee")) Artist(id = "12", name = "Teebee")
val entity = Indexes(lastModified = 154, ignoredArticles = "Le Tre Ze", indexList = listOf( )
val entity = Indexes(
lastModified = 154, ignoredArticles = "Le Tre Ze",
indexList = listOf(
Index(name = "A", artists = artistsA), Index(name = "A", artists = artistsA),
Index(name = "T", artists = artistsT) Index(name = "T", artists = artistsT)
), shortcutList = artistsA) ),
shortcutList = artistsA
)
val convertedEntity = entity.toDomainEntity() val convertedEntity = entity.toDomainEntity()

View File

@ -2,12 +2,12 @@
package org.moire.ultrasonic.domain package org.moire.ultrasonic.domain
import java.util.Calendar
import org.amshove.kluent.`should be equal to` import org.amshove.kluent.`should be equal to`
import org.amshove.kluent.`should equal` import org.amshove.kluent.`should equal`
import org.junit.Test import org.junit.Test
import org.moire.ultrasonic.api.subsonic.models.MusicDirectory import org.moire.ultrasonic.api.subsonic.models.MusicDirectory
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
import java.util.Calendar
/** /**
* Unit test for extension functions in APIMusicDirectoryConverter.kt file. * Unit test for extension functions in APIMusicDirectoryConverter.kt file.
@ -15,9 +15,11 @@ import java.util.Calendar
class APIMusicDirectoryConverterTest { class APIMusicDirectoryConverterTest {
@Test @Test
fun `Should convert MusicDirectory entity`() { fun `Should convert MusicDirectory entity`() {
val entity = MusicDirectory(id = "1982", parent = "345", name = "some-name", userRating = 3, val entity = MusicDirectory(
averageRating = 3.4f, starred = Calendar.getInstance(), playCount = 10, id = "1982", parent = "345", name = "some-name", userRating = 3,
childList = listOf(MusicDirectoryChild("1"), MusicDirectoryChild("2"))) averageRating = 3.4f, starred = Calendar.getInstance(), playCount = 10,
childList = listOf(MusicDirectoryChild("1"), MusicDirectoryChild("2"))
)
val convertedEntity = entity.toDomainEntity() val convertedEntity = entity.toDomainEntity()
@ -25,21 +27,23 @@ class APIMusicDirectoryConverterTest {
name `should equal` entity.name name `should equal` entity.name
getAllChild().size `should be equal to` entity.childList.size getAllChild().size `should be equal to` entity.childList.size
getAllChild() `should equal` entity.childList getAllChild() `should equal` entity.childList
.map { it.toDomainEntity() }.toMutableList() .map { it.toDomainEntity() }.toMutableList()
} }
} }
@Test @Test
fun `Should convert MusicDirectoryChild entity`() { fun `Should convert MusicDirectoryChild entity`() {
val entity = MusicDirectoryChild(id = "929", parent = "11", title = "some-title", val entity = MusicDirectoryChild(
album = "some-album", albumId = "231", artist = "some-artist", artistId = "1233", id = "929", parent = "11", title = "some-title",
track = 12, year = 2002, genre = "some-genre", coverArt = "952", size = 9418123L, album = "some-album", albumId = "231", artist = "some-artist", artistId = "1233",
contentType = "some-content-type", suffix = "some-suffix", track = 12, year = 2002, genre = "some-genre", coverArt = "952", size = 9418123L,
transcodedContentType = "some-transcoded-content-type", contentType = "some-content-type", suffix = "some-suffix",
transcodedSuffix = "some-transcoded-suffix", duration = 11, bitRate = 256, transcodedContentType = "some-transcoded-content-type",
path = "some-path", isDir = true, isVideo = true, playCount = 323, discNumber = 2, transcodedSuffix = "some-transcoded-suffix", duration = 11, bitRate = 256,
created = Calendar.getInstance(), type = "some-type", path = "some-path", isDir = true, isVideo = true, playCount = 323, discNumber = 2,
starred = Calendar.getInstance(), userRating = 3, averageRating = 2.99F) created = Calendar.getInstance(), type = "some-type",
starred = Calendar.getInstance(), userRating = 3, averageRating = 2.99F
)
val convertedEntity = entity.toDomainEntity() val convertedEntity = entity.toDomainEntity()
@ -76,8 +80,10 @@ class APIMusicDirectoryConverterTest {
@Test @Test
fun `Should convert MusicDirectoryChild podcast entity`() { fun `Should convert MusicDirectoryChild podcast entity`() {
val entity = MusicDirectoryChild(id = "584", streamId = "394", val entity = MusicDirectoryChild(
artist = "some-artist", publishDate = Calendar.getInstance()) id = "584", streamId = "394",
artist = "some-artist", publishDate = Calendar.getInstance()
)
val convertedEntity = entity.toDomainEntity() val convertedEntity = entity.toDomainEntity()

View File

@ -23,8 +23,9 @@ class APIMusicFolderConverterTest {
@Test @Test
fun `Should convert list of MusicFolder entities`() { fun `Should convert list of MusicFolder entities`() {
val entityList = listOf( val entityList = listOf(
MusicFolder(id = "3", name = "some-name-3"), MusicFolder(id = "3", name = "some-name-3"),
MusicFolder(id = "4", name = "some-name-4")) MusicFolder(id = "4", name = "some-name-4")
)
val convertedList = entityList.toDomainEntityList() val convertedList = entityList.toDomainEntityList()

View File

@ -2,12 +2,12 @@
package org.moire.ultrasonic.domain package org.moire.ultrasonic.domain
import java.util.Calendar
import org.amshove.kluent.`should be equal to` import org.amshove.kluent.`should be equal to`
import org.amshove.kluent.`should equal` import org.amshove.kluent.`should equal`
import org.junit.Test import org.junit.Test
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
import org.moire.ultrasonic.api.subsonic.models.Playlist import org.moire.ultrasonic.api.subsonic.models.Playlist
import java.util.Calendar
/** /**
* Unit test for extension functions that converts api playlist entity to domain. * Unit test for extension functions that converts api playlist entity to domain.
@ -15,10 +15,13 @@ import java.util.Calendar
class APIPlaylistConverterTest { class APIPlaylistConverterTest {
@Test @Test
fun `Should convert Playlist to MusicDirectory domain entity`() { fun `Should convert Playlist to MusicDirectory domain entity`() {
val entity = Playlist(name = "some-playlist-name", entriesList = listOf( val entity = Playlist(
name = "some-playlist-name",
entriesList = listOf(
MusicDirectoryChild(id = "10", parent = "1393"), MusicDirectoryChild(id = "10", parent = "1393"),
MusicDirectoryChild(id = "11", parent = "1393") MusicDirectoryChild(id = "11", parent = "1393")
)) )
)
val convertedEntity = entity.toMusicDirectoryDomainEntity() val convertedEntity = entity.toMusicDirectoryDomainEntity()
@ -32,10 +35,12 @@ class APIPlaylistConverterTest {
@Test @Test
fun `Should convert playlist to domain entity`() { fun `Should convert playlist to domain entity`() {
val entity = Playlist(id = "634", name = "some-name", owner = "some-owner", val entity = Playlist(
comment = "some-comment", public = false, songCount = 256, duration = 1150, id = "634", name = "some-name", owner = "some-owner",
created = Calendar.getInstance(), changed = Calendar.getInstance(), comment = "some-comment", public = false, songCount = 256, duration = 1150,
coverArt = "some-art") created = Calendar.getInstance(), changed = Calendar.getInstance(),
coverArt = "some-art"
)
val convertedEntity = entity.toDomainEntity() val convertedEntity = entity.toDomainEntity()

View File

@ -13,9 +13,11 @@ import org.moire.ultrasonic.api.subsonic.models.PodcastChannel
class APIPodcastConverterTest { class APIPodcastConverterTest {
@Test @Test
fun `Should convert podcast channel entity to domain entity`() { fun `Should convert podcast channel entity to domain entity`() {
val entity = PodcastChannel(id = "452", url = "some-url", title = "some-title", val entity = PodcastChannel(
description = "some-description", coverArt = "cA", originalImageUrl = "image-url", id = "452", url = "some-url", title = "some-title",
status = "podcast-status", errorMessage = "some-error-message") description = "some-description", coverArt = "cA", originalImageUrl = "image-url",
status = "podcast-status", errorMessage = "some-error-message"
)
val converterEntity = entity.toDomainEntity() val converterEntity = entity.toDomainEntity()
@ -31,8 +33,9 @@ class APIPodcastConverterTest {
@Test @Test
fun `Should convert list of podcasts channels to domain entites list`() { fun `Should convert list of podcasts channels to domain entites list`() {
val entitiesList = listOf( val entitiesList = listOf(
PodcastChannel(id = "932", title = "title1"), PodcastChannel(id = "932", title = "title1"),
PodcastChannel(id = "12", title = "title2")) PodcastChannel(id = "12", title = "title2")
)
val converted = entitiesList.toDomainEntitiesList() val converted = entitiesList.toDomainEntitiesList()

View File

@ -19,9 +19,13 @@ import org.moire.ultrasonic.api.subsonic.models.SearchTwoResult
class APISearchConverterTest { class APISearchConverterTest {
@Test @Test
fun `Should convert SearchResult to domain entity`() { fun `Should convert SearchResult to domain entity`() {
val entity = SearchResult(offset = 10, totalHits = 3, matchList = listOf( val entity = SearchResult(
offset = 10,
totalHits = 3,
matchList = listOf(
MusicDirectoryChild(id = "101") MusicDirectoryChild(id = "101")
)) )
)
val convertedEntity = entity.toDomainEntity() val convertedEntity = entity.toDomainEntity()
@ -37,13 +41,11 @@ class APISearchConverterTest {
@Test @Test
fun `Should convert SearchTwoResult to domain entity`() { fun `Should convert SearchTwoResult to domain entity`() {
val entity = SearchTwoResult(listOf( val entity = SearchTwoResult(
Artist(id = "82", name = "great-artist-name") listOf(Artist(id = "82", name = "great-artist-name")),
), listOf( listOf(MusicDirectoryChild(id = "762", artist = "bzz")),
MusicDirectoryChild(id = "762", artist = "bzz") listOf(MusicDirectoryChild(id = "9118", parent = "112"))
), listOf( )
MusicDirectoryChild(id = "9118", parent = "112")
))
val convertedEntity = entity.toDomainEntity() val convertedEntity = entity.toDomainEntity()
@ -60,9 +62,9 @@ class APISearchConverterTest {
@Test @Test
fun `Should convert SearchThreeResult to domain entity`() { fun `Should convert SearchThreeResult to domain entity`() {
val entity = SearchThreeResult( val entity = SearchThreeResult(
artistList = listOf(Artist(id = "612", name = "artist1")), artistList = listOf(Artist(id = "612", name = "artist1")),
albumList = listOf(Album(id = "221", name = "album1")), albumList = listOf(Album(id = "221", name = "album1")),
songList = listOf(MusicDirectoryChild(id = "7123", title = "song1")) songList = listOf(MusicDirectoryChild(id = "7123", title = "song1"))
) )
val convertedEntity = entity.toDomainEntity() val convertedEntity = entity.toDomainEntity()

View File

@ -2,12 +2,12 @@
package org.moire.ultrasonic.domain package org.moire.ultrasonic.domain
import java.util.Calendar
import org.amshove.kluent.`should be equal to` import org.amshove.kluent.`should be equal to`
import org.amshove.kluent.`should equal` import org.amshove.kluent.`should equal`
import org.junit.Test import org.junit.Test
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
import org.moire.ultrasonic.api.subsonic.models.Share import org.moire.ultrasonic.api.subsonic.models.Share
import java.util.Calendar
/** /**
* Unit test for api to domain share entity converter functions. * Unit test for api to domain share entity converter functions.
@ -33,17 +33,20 @@ class APIShareConverterTest {
} }
private fun createFakeShare(): Share { private fun createFakeShare(): Share {
return Share(id = "45", url = "some-long-url", username = "Bender", return Share(
created = Calendar.getInstance(), expires = Calendar.getInstance(), visitCount = 24, id = "45", url = "some-long-url", username = "Bender",
description = "Kiss my shiny metal ass", lastVisited = Calendar.getInstance(), created = Calendar.getInstance(), expires = Calendar.getInstance(), visitCount = 24,
items = listOf(MusicDirectoryChild())) description = "Kiss my shiny metal ass", lastVisited = Calendar.getInstance(),
items = listOf(MusicDirectoryChild())
)
} }
@Test @Test
fun `Should parse list of shares into domain entity list`() { fun `Should parse list of shares into domain entity list`() {
val entityList = listOf( val entityList = listOf(
createFakeShare(), createFakeShare(),
createFakeShare().copy(id = "554", lastVisited = null)) createFakeShare().copy(id = "554", lastVisited = null)
)
val domainEntityList = entityList.toDomainEntitiesList() val domainEntityList = entityList.toDomainEntitiesList()

View File

@ -13,8 +13,10 @@ import org.moire.ultrasonic.api.subsonic.models.User
class APIUserConverterTest { class APIUserConverterTest {
@Test @Test
fun `Should convert to domain entity`() { fun `Should convert to domain entity`() {
val entity = User(username = "Awsemo", email = "none@none.net", scrobblingEnabled = false, val entity = User(
shareRole = true, streamRole = true) username = "Awsemo", email = "none@none.net", scrobblingEnabled = false,
shareRole = true, streamRole = true
)
val domainEntity = entity.toDomainEntity() val domainEntity = entity.toDomainEntity()

View File

@ -26,8 +26,9 @@ class ApiGenreConverterTest {
@Test @Test
fun `Should convert a list entites to domain entities`() { fun `Should convert a list entites to domain entities`() {
val entitiesList = listOf( val entitiesList = listOf(
Genre(41, 2, "some-name"), Genre(41, 2, "some-name"),
Genre(12, 3, "other-name")) Genre(12, 3, "other-name")
)
val domainEntitiesList = entitiesList.toDomainEntityList() val domainEntitiesList = entitiesList.toDomainEntityList()