mirror of
https://github.com/ultrasonic/ultrasonic
synced 2025-02-09 08:18:50 +01:00
Split Subsonic API integration test into a smaller classes.
It will be easier to maintain and add new tests. Signed-off-by: Yahor Berdnikau <egorr.berd@gmail.com>
This commit is contained in:
parent
2b484ad667
commit
b3dde1938f
@ -0,0 +1,65 @@
|
|||||||
|
package org.moire.ultrasonic.api.subsonic
|
||||||
|
|
||||||
|
import okhttp3.mockwebserver.MockResponse
|
||||||
|
import okio.Okio
|
||||||
|
import org.amshove.kluent.`should be`
|
||||||
|
import org.amshove.kluent.`should not be`
|
||||||
|
import org.moire.ultrasonic.api.subsonic.response.SubsonicResponse
|
||||||
|
import org.moire.ultrasonic.api.subsonic.rules.MockWebServerRule
|
||||||
|
import retrofit2.Response
|
||||||
|
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 PASSWORD = "some-password"
|
||||||
|
val CLIENT_VERSION = SubsonicAPIVersions.V1_13_0
|
||||||
|
const val CLIENT_ID = "test-client"
|
||||||
|
|
||||||
|
val dateFormat by lazy(LazyThreadSafetyMode.NONE, {
|
||||||
|
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US)
|
||||||
|
})
|
||||||
|
|
||||||
|
fun MockWebServerRule.enqueueResponse(resourceName: String) {
|
||||||
|
this.mockWebServer.enqueue(MockResponse()
|
||||||
|
.setBody(loadJsonResponse(this, resourceName)))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadJsonResponse(rule: MockWebServerRule, name: String): String {
|
||||||
|
val source = Okio.buffer(Okio.source(rule.javaClass.classLoader.getResourceAsStream(name)))
|
||||||
|
return source.readString(Charset.forName("UTF-8"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> assertResponseSuccessful(response: Response<T>) {
|
||||||
|
response.isSuccessful `should be` true
|
||||||
|
response.body() `should not be` null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseDate(dateAsString: String): Calendar {
|
||||||
|
val result = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
|
||||||
|
result.time = dateFormat.parse(dateAsString.replace("Z$".toRegex(), "+0000"))
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T: SubsonicResponse> checkErrorCallParsed(mockWebServerRule: MockWebServerRule,
|
||||||
|
apiRequest: () -> Response<T>): T {
|
||||||
|
mockWebServerRule.enqueueResponse("generic_error_response.json")
|
||||||
|
|
||||||
|
val response = apiRequest()
|
||||||
|
|
||||||
|
assertResponseSuccessful(response)
|
||||||
|
with(response.body()) {
|
||||||
|
status `should be` SubsonicResponse.Status.ERROR
|
||||||
|
error `should be` SubsonicError.GENERIC
|
||||||
|
}
|
||||||
|
return response.body()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun SubsonicResponse.assertBaseResponseOk() {
|
||||||
|
status `should be` SubsonicResponse.Status.OK
|
||||||
|
version `should be` SubsonicAPIVersions.V1_13_0
|
||||||
|
error `should be` null
|
||||||
|
}
|
@ -1,365 +1,20 @@
|
|||||||
package org.moire.ultrasonic.api.subsonic
|
package org.moire.ultrasonic.api.subsonic
|
||||||
|
|
||||||
import okhttp3.mockwebserver.MockResponse
|
|
||||||
import okio.Okio
|
|
||||||
import org.amshove.kluent.`should be`
|
|
||||||
import org.amshove.kluent.`should contain`
|
|
||||||
import org.amshove.kluent.`should equal to`
|
|
||||||
import org.amshove.kluent.`should equal`
|
|
||||||
import org.amshove.kluent.`should not be`
|
|
||||||
import org.amshove.kluent.`should not contain`
|
|
||||||
import org.apache.commons.codec.binary.Hex
|
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
|
||||||
import org.moire.ultrasonic.api.subsonic.models.Artist
|
|
||||||
import org.moire.ultrasonic.api.subsonic.models.Index
|
|
||||||
import org.moire.ultrasonic.api.subsonic.models.License
|
|
||||||
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
|
|
||||||
import org.moire.ultrasonic.api.subsonic.models.MusicFolder
|
|
||||||
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 java.nio.charset.Charset
|
|
||||||
import java.security.MessageDigest
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Calendar
|
|
||||||
import java.util.Locale
|
|
||||||
import java.util.TimeZone
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration test for [SubsonicAPIClient] class.
|
* Base class for integration tests for [SubsonicAPIClient] class.
|
||||||
*/
|
*/
|
||||||
@Suppress("TooManyFunctions", "LargeClass")
|
abstract class SubsonicAPIClientTest {
|
||||||
class SubsonicAPIClientTest {
|
|
||||||
companion object {
|
|
||||||
const val USERNAME = "some-user"
|
|
||||||
const val PASSWORD = "some-password"
|
|
||||||
val CLIENT_VERSION = SubsonicAPIVersions.V1_13_0
|
|
||||||
const val CLIENT_ID = "test-client"
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmField @Rule val mockWebServerRule = MockWebServerRule()
|
@JvmField @Rule val mockWebServerRule = MockWebServerRule()
|
||||||
|
|
||||||
private lateinit var client: SubsonicAPIClient
|
protected lateinit var client: SubsonicAPIClient
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
client = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(), USERNAME, PASSWORD,
|
client = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(), USERNAME, PASSWORD,
|
||||||
CLIENT_VERSION, CLIENT_ID)
|
CLIENT_VERSION, CLIENT_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should pass password hash and salt in query params for api version 1 13 0`() {
|
|
||||||
val clientV12 = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(), USERNAME,
|
|
||||||
PASSWORD, SubsonicAPIVersions.V1_14_0, CLIENT_ID)
|
|
||||||
enqueueResponse("ping_ok.json")
|
|
||||||
|
|
||||||
clientV12.api.ping().execute()
|
|
||||||
|
|
||||||
with(mockWebServerRule.mockWebServer.takeRequest()) {
|
|
||||||
requestLine `should contain` "&s="
|
|
||||||
requestLine `should contain` "&t="
|
|
||||||
requestLine `should not contain` "&p=enc:"
|
|
||||||
|
|
||||||
val salt = requestLine.split('&').find { it.startsWith("s=") }?.substringAfter('=')
|
|
||||||
val token = requestLine.split('&').find { it.startsWith("t=") }?.substringAfter('=')
|
|
||||||
val expectedToken = String(Hex.encodeHex(MessageDigest.getInstance("MD5")
|
|
||||||
.digest("$PASSWORD$salt".toByteArray()), false))
|
|
||||||
token!! `should equal` expectedToken
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should pass hex encoded password in query params for api version 1 12 0`() {
|
|
||||||
val clientV11 = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(), USERNAME,
|
|
||||||
PASSWORD, SubsonicAPIVersions.V1_12_0, CLIENT_ID)
|
|
||||||
enqueueResponse("ping_ok.json")
|
|
||||||
|
|
||||||
clientV11.api.ping().execute()
|
|
||||||
|
|
||||||
with(mockWebServerRule.mockWebServer.takeRequest()) {
|
|
||||||
requestLine `should not contain` "&s="
|
|
||||||
requestLine `should not contain` "&t="
|
|
||||||
requestLine `should contain` "&p=enc:"
|
|
||||||
val passParam = requestLine.split('&').find { it.startsWith("p=enc:") }
|
|
||||||
val encodedPassword = String(Hex.encodeHex(PASSWORD.toByteArray(), false))
|
|
||||||
passParam `should equal` "p=enc:$encodedPassword"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should parse ping ok response`() {
|
|
||||||
enqueueResponse("ping_ok.json")
|
|
||||||
|
|
||||||
val response = client.api.ping().execute()
|
|
||||||
|
|
||||||
assertResponseSuccessful(response)
|
|
||||||
with(response.body()) {
|
|
||||||
assertBaseResponseOk()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should parse ping error response`() {
|
|
||||||
checkErrorCallParsed { client.api.ping().execute() }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should parse get license ok response`() {
|
|
||||||
enqueueResponse("license_ok.json")
|
|
||||||
|
|
||||||
val response = client.api.getLicense().execute()
|
|
||||||
|
|
||||||
assertResponseSuccessful(response)
|
|
||||||
with(response.body()) {
|
|
||||||
assertBaseResponseOk()
|
|
||||||
license `should equal` License(valid = true,
|
|
||||||
trialExpires = parseDate("2016-11-23T20:17:15.206Z"),
|
|
||||||
email = "someone@example.net",
|
|
||||||
licenseExpires = parseDate("8994-08-17T07:12:55.807Z"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should parse get license error response`() {
|
|
||||||
val response = checkErrorCallParsed { client.api.getLicense().execute() }
|
|
||||||
|
|
||||||
response.license `should not be` null
|
|
||||||
with(response.license) {
|
|
||||||
email `should equal to` ""
|
|
||||||
valid `should equal to` false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should parse get music folders ok response`() {
|
|
||||||
enqueueResponse("get_music_folders_ok.json")
|
|
||||||
|
|
||||||
val response = client.api.getMusicFolders().execute()
|
|
||||||
|
|
||||||
assertResponseSuccessful(response)
|
|
||||||
with(response.body()) {
|
|
||||||
assertBaseResponseOk()
|
|
||||||
musicFolders `should equal` listOf(MusicFolder(0, "Music"), MusicFolder(2, "Test"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should parse get music folders error response`() {
|
|
||||||
val response = checkErrorCallParsed { client.api.getMusicFolders().execute() }
|
|
||||||
|
|
||||||
response.musicFolders `should equal` emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should parse get indexes ok response`() {
|
|
||||||
enqueueResponse("get_indexes_ok.json")
|
|
||||||
|
|
||||||
val response = client.api.getIndexes(null, null).execute()
|
|
||||||
|
|
||||||
assertResponseSuccessful(response)
|
|
||||||
response.body().indexes `should not be` null
|
|
||||||
with(response.body().indexes) {
|
|
||||||
lastModified `should equal` 1491069027523
|
|
||||||
ignoredArticles `should equal` "The El La Los Las Le Les"
|
|
||||||
shortcutList `should equal` listOf(
|
|
||||||
Artist(id = 889L, name = "podcasts"),
|
|
||||||
Artist(id = 890L, name = "audiobooks")
|
|
||||||
)
|
|
||||||
indexList `should equal` mutableListOf(
|
|
||||||
Index("A", listOf(
|
|
||||||
Artist(id = 50L, name = "Ace Of Base",
|
|
||||||
starred = parseDate("2017-04-02T20:16:29.815Z")),
|
|
||||||
Artist(id = 379L, name = "A Perfect Circle")
|
|
||||||
)),
|
|
||||||
Index("H", listOf(
|
|
||||||
Artist(id = 299, name = "Haddaway"),
|
|
||||||
Artist(id = 297, name = "Halestorm")
|
|
||||||
))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should add music folder id as a query param for getIndexes api call`() {
|
|
||||||
enqueueResponse("get_indexes_ok.json")
|
|
||||||
val musicFolderId = 9L
|
|
||||||
|
|
||||||
client.api.getIndexes(musicFolderId, null).execute()
|
|
||||||
|
|
||||||
with(mockWebServerRule.mockWebServer.takeRequest()) {
|
|
||||||
requestLine `should contain` "musicFolderId=$musicFolderId"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should add ifModifiedSince as a query param for getIndexes api call`() {
|
|
||||||
enqueueResponse("get_indexes_ok.json")
|
|
||||||
val ifModifiedSince = System.currentTimeMillis()
|
|
||||||
|
|
||||||
client.api.getIndexes(null, ifModifiedSince).execute()
|
|
||||||
|
|
||||||
with(mockWebServerRule.mockWebServer.takeRequest()) {
|
|
||||||
requestLine `should contain` "ifModifiedSince=$ifModifiedSince"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should add both params to query for getIndexes api call`() {
|
|
||||||
enqueueResponse("get_indexes_ok.json")
|
|
||||||
val musicFolderId = 110L
|
|
||||||
val ifModifiedSince = System.currentTimeMillis()
|
|
||||||
|
|
||||||
client.api.getIndexes(musicFolderId, ifModifiedSince).execute()
|
|
||||||
|
|
||||||
with(mockWebServerRule.mockWebServer.takeRequest()) {
|
|
||||||
requestLine `should contain` "musicFolderId=$musicFolderId"
|
|
||||||
requestLine `should contain` "ifModifiedSince=$ifModifiedSince"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should parse get indexes error response`() {
|
|
||||||
val response = checkErrorCallParsed { client.api.getIndexes(null, null).execute() }
|
|
||||||
|
|
||||||
response.indexes `should not be` null
|
|
||||||
with(response.indexes) {
|
|
||||||
lastModified `should equal to` 0
|
|
||||||
ignoredArticles `should equal to` ""
|
|
||||||
indexList.size `should equal to` 0
|
|
||||||
shortcutList.size `should equal to` 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should parse getMusicDirectory error response`() {
|
|
||||||
val response = checkErrorCallParsed { client.api.getMusicDirectory(1).execute() }
|
|
||||||
|
|
||||||
response.musicDirectory `should be` null
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `GetMusicDirectory should add directory id to query params`() {
|
|
||||||
enqueueResponse("get_music_directory_ok.json")
|
|
||||||
val directoryId = 124L
|
|
||||||
|
|
||||||
client.api.getMusicDirectory(directoryId).execute()
|
|
||||||
|
|
||||||
mockWebServerRule.mockWebServer.takeRequest().requestLine `should contain` "id=$directoryId"
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should parse get music directory ok response`() {
|
|
||||||
enqueueResponse("get_music_directory_ok.json")
|
|
||||||
|
|
||||||
val response = client.api.getMusicDirectory(1).execute()
|
|
||||||
|
|
||||||
assertResponseSuccessful(response)
|
|
||||||
|
|
||||||
response.body().musicDirectory `should not be` null
|
|
||||||
with(response.body().musicDirectory!!) {
|
|
||||||
id `should equal` 382L
|
|
||||||
name `should equal` "AC_DC"
|
|
||||||
starred `should equal` parseDate("2017-04-02T20:16:29.815Z")
|
|
||||||
childList.size `should be` 2
|
|
||||||
childList[0] `should equal` MusicDirectoryChild(583L, 382L, true, "Black Ice",
|
|
||||||
"Black Ice", "AC/DC", 2008, "Hard Rock", 583L,
|
|
||||||
parseDate("2016-10-23T15:31:22.000Z"), parseDate("2017-04-02T20:16:15.724Z"))
|
|
||||||
childList[1] `should equal` MusicDirectoryChild(582L, 382L, true, "Rock or Bust",
|
|
||||||
"Rock or Bust", "AC/DC", 2014, "Hard Rock", 582L,
|
|
||||||
parseDate("2016-10-23T15:31:24.000Z"), null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should parse get artists error response`() {
|
|
||||||
val response = checkErrorCallParsed { client.api.getArtists(null).execute() }
|
|
||||||
|
|
||||||
response.indexes `should not be` null
|
|
||||||
with(response.indexes) {
|
|
||||||
lastModified `should equal to` 0
|
|
||||||
ignoredArticles `should equal to` ""
|
|
||||||
indexList.size `should equal to` 0
|
|
||||||
shortcutList.size `should equal to` 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should parse get artists ok reponse`() {
|
|
||||||
enqueueResponse("get_artists_ok.json")
|
|
||||||
|
|
||||||
val response = client.api.getArtists(null).execute()
|
|
||||||
|
|
||||||
assertResponseSuccessful(response)
|
|
||||||
with(response.body().indexes) {
|
|
||||||
lastModified `should equal to` 0L
|
|
||||||
ignoredArticles `should equal to` "The El La Los Las Le Les"
|
|
||||||
shortcutList `should equal` emptyList()
|
|
||||||
indexList.size `should equal to` 2
|
|
||||||
indexList `should equal` listOf(
|
|
||||||
Index(name = "A", artists = listOf(
|
|
||||||
Artist(id = 362L, name = "AC/DC", coverArt = "ar-362", albumCount = 2),
|
|
||||||
Artist(id = 254L, name = "Acceptance", coverArt = "ar-254", albumCount = 1)
|
|
||||||
)),
|
|
||||||
Index(name = "T", artists = listOf(
|
|
||||||
Artist(id = 516L, name = "Tangerine Dream", coverArt = "ar-516", albumCount = 1),
|
|
||||||
Artist(id = 242L, name = "Taproot", coverArt = "ar-242", albumCount = 2)
|
|
||||||
))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Should pass param on query for get artists call`() {
|
|
||||||
enqueueResponse("get_artists_ok.json")
|
|
||||||
val musicFolderId = 101L
|
|
||||||
client.api.getArtists(musicFolderId).execute()
|
|
||||||
|
|
||||||
val request = mockWebServerRule.mockWebServer.takeRequest()
|
|
||||||
|
|
||||||
request.requestLine `should contain` "musicFolderId=$musicFolderId"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun enqueueResponse(resourceName: String) {
|
|
||||||
mockWebServerRule.mockWebServer.enqueue(MockResponse()
|
|
||||||
.setBody(loadJsonResponse(resourceName)))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadJsonResponse(name: String): String {
|
|
||||||
val source = Okio.buffer(Okio.source(javaClass.classLoader.getResourceAsStream(name)))
|
|
||||||
return source.readString(Charset.forName("UTF-8"))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <T> assertResponseSuccessful(response: Response<T>) {
|
|
||||||
response.isSuccessful `should be` true
|
|
||||||
response.body() `should not be` null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseDate(dateAsString: String): Calendar {
|
|
||||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US)
|
|
||||||
val result = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
|
|
||||||
result.time = dateFormat.parse(dateAsString.replace("Z$".toRegex(), "+0000"))
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <T: SubsonicResponse> checkErrorCallParsed(apiRequest: () -> Response<T>): T {
|
|
||||||
enqueueResponse("generic_error_response.json")
|
|
||||||
|
|
||||||
val response = apiRequest()
|
|
||||||
|
|
||||||
assertResponseSuccessful(response)
|
|
||||||
with(response.body()) {
|
|
||||||
status `should be` SubsonicResponse.Status.ERROR
|
|
||||||
error `should be` SubsonicError.GENERIC
|
|
||||||
}
|
|
||||||
return response.body()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun SubsonicResponse.assertBaseResponseOk() {
|
|
||||||
status `should be` SubsonicResponse.Status.OK
|
|
||||||
version `should be` SubsonicAPIVersions.V1_13_0
|
|
||||||
error `should be` null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
package org.moire.ultrasonic.api.subsonic
|
||||||
|
|
||||||
|
import org.amshove.kluent.`should contain`
|
||||||
|
import org.amshove.kluent.`should equal to`
|
||||||
|
import org.amshove.kluent.`should equal`
|
||||||
|
import org.amshove.kluent.`should not be`
|
||||||
|
import org.junit.Test
|
||||||
|
import org.moire.ultrasonic.api.subsonic.models.Artist
|
||||||
|
import org.moire.ultrasonic.api.subsonic.models.Index
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration test for [SubsonicAPIClient] for getArtists() request.
|
||||||
|
*/
|
||||||
|
class SubsonicApiGetArtistsTest : SubsonicAPIClientTest() {
|
||||||
|
@Test
|
||||||
|
fun `Should parse get artists error response`() {
|
||||||
|
val response = checkErrorCallParsed(mockWebServerRule, {
|
||||||
|
client.api.getArtists(null).execute()
|
||||||
|
})
|
||||||
|
|
||||||
|
response.indexes `should not be` null
|
||||||
|
with(response.indexes) {
|
||||||
|
lastModified `should equal to` 0
|
||||||
|
ignoredArticles `should equal to` ""
|
||||||
|
indexList.size `should equal to` 0
|
||||||
|
shortcutList.size `should equal to` 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should parse get artists ok reponse`() {
|
||||||
|
mockWebServerRule.enqueueResponse("get_artists_ok.json")
|
||||||
|
|
||||||
|
val response = client.api.getArtists(null).execute()
|
||||||
|
|
||||||
|
assertResponseSuccessful(response)
|
||||||
|
with(response.body().indexes) {
|
||||||
|
lastModified `should equal to` 0L
|
||||||
|
ignoredArticles `should equal to` "The El La Los Las Le Les"
|
||||||
|
shortcutList `should equal` emptyList()
|
||||||
|
indexList.size `should equal to` 2
|
||||||
|
indexList `should equal` listOf(
|
||||||
|
Index(name = "A", artists = listOf(
|
||||||
|
Artist(id = 362L, name = "AC/DC", coverArt = "ar-362", albumCount = 2),
|
||||||
|
Artist(id = 254L, name = "Acceptance", coverArt = "ar-254", albumCount = 1)
|
||||||
|
)),
|
||||||
|
Index(name = "T", artists = listOf(
|
||||||
|
Artist(id = 516L, name = "Tangerine Dream", coverArt = "ar-516", albumCount = 1),
|
||||||
|
Artist(id = 242L, name = "Taproot", coverArt = "ar-242", albumCount = 2)
|
||||||
|
))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should pass param on query for get artists call`() {
|
||||||
|
mockWebServerRule.enqueueResponse("get_artists_ok.json")
|
||||||
|
val musicFolderId = 101L
|
||||||
|
client.api.getArtists(musicFolderId).execute()
|
||||||
|
|
||||||
|
val request = mockWebServerRule.mockWebServer.takeRequest()
|
||||||
|
|
||||||
|
request.requestLine `should contain` "musicFolderId=$musicFolderId"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
package org.moire.ultrasonic.api.subsonic
|
||||||
|
|
||||||
|
import org.amshove.kluent.`should contain`
|
||||||
|
import org.amshove.kluent.`should equal to`
|
||||||
|
import org.amshove.kluent.`should equal`
|
||||||
|
import org.amshove.kluent.`should not be`
|
||||||
|
import org.junit.Test
|
||||||
|
import org.moire.ultrasonic.api.subsonic.models.Artist
|
||||||
|
import org.moire.ultrasonic.api.subsonic.models.Index
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration test for [SubsonicAPIClient] for getIndexes() request.
|
||||||
|
*/
|
||||||
|
class SubsonicApiGetIndexesTest : SubsonicAPIClientTest() {
|
||||||
|
@Test
|
||||||
|
fun `Should parse get indexes ok response`() {
|
||||||
|
mockWebServerRule.enqueueResponse("get_indexes_ok.json")
|
||||||
|
|
||||||
|
val response = client.api.getIndexes(null, null).execute()
|
||||||
|
|
||||||
|
assertResponseSuccessful(response)
|
||||||
|
response.body().indexes `should not be` null
|
||||||
|
with(response.body().indexes) {
|
||||||
|
lastModified `should equal` 1491069027523
|
||||||
|
ignoredArticles `should equal` "The El La Los Las Le Les"
|
||||||
|
shortcutList `should equal` listOf(
|
||||||
|
Artist(id = 889L, name = "podcasts"),
|
||||||
|
Artist(id = 890L, name = "audiobooks")
|
||||||
|
)
|
||||||
|
indexList `should equal` mutableListOf(
|
||||||
|
Index("A", listOf(
|
||||||
|
Artist(id = 50L, name = "Ace Of Base",
|
||||||
|
starred = parseDate("2017-04-02T20:16:29.815Z")),
|
||||||
|
Artist(id = 379L, name = "A Perfect Circle")
|
||||||
|
)),
|
||||||
|
Index("H", listOf(
|
||||||
|
Artist(id = 299, name = "Haddaway"),
|
||||||
|
Artist(id = 297, name = "Halestorm")
|
||||||
|
))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should add music folder id as a query param for getIndexes api call`() {
|
||||||
|
mockWebServerRule.enqueueResponse("get_indexes_ok.json")
|
||||||
|
val musicFolderId = 9L
|
||||||
|
|
||||||
|
client.api.getIndexes(musicFolderId, null).execute()
|
||||||
|
|
||||||
|
with(mockWebServerRule.mockWebServer.takeRequest()) {
|
||||||
|
requestLine `should contain` "musicFolderId=$musicFolderId"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should add ifModifiedSince as a query param for getIndexes api call`() {
|
||||||
|
mockWebServerRule.enqueueResponse("get_indexes_ok.json")
|
||||||
|
val ifModifiedSince = System.currentTimeMillis()
|
||||||
|
|
||||||
|
client.api.getIndexes(null, ifModifiedSince).execute()
|
||||||
|
|
||||||
|
with(mockWebServerRule.mockWebServer.takeRequest()) {
|
||||||
|
requestLine `should contain` "ifModifiedSince=$ifModifiedSince"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should add both params to query for getIndexes api call`() {
|
||||||
|
mockWebServerRule.enqueueResponse("get_indexes_ok.json")
|
||||||
|
val musicFolderId = 110L
|
||||||
|
val ifModifiedSince = System.currentTimeMillis()
|
||||||
|
|
||||||
|
client.api.getIndexes(musicFolderId, ifModifiedSince).execute()
|
||||||
|
|
||||||
|
with(mockWebServerRule.mockWebServer.takeRequest()) {
|
||||||
|
requestLine `should contain` "musicFolderId=$musicFolderId"
|
||||||
|
requestLine `should contain` "ifModifiedSince=$ifModifiedSince"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should parse get indexes error response`() {
|
||||||
|
val response = checkErrorCallParsed(mockWebServerRule, {
|
||||||
|
client.api.getIndexes(null, null).execute()
|
||||||
|
})
|
||||||
|
|
||||||
|
response.indexes `should not be` null
|
||||||
|
with(response.indexes) {
|
||||||
|
lastModified `should equal to` 0
|
||||||
|
ignoredArticles `should equal to` ""
|
||||||
|
indexList.size `should equal to` 0
|
||||||
|
shortcutList.size `should equal to` 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package org.moire.ultrasonic.api.subsonic
|
||||||
|
|
||||||
|
import org.amshove.kluent.`should equal to`
|
||||||
|
import org.amshove.kluent.`should equal`
|
||||||
|
import org.amshove.kluent.`should not be`
|
||||||
|
import org.junit.Test
|
||||||
|
import org.moire.ultrasonic.api.subsonic.models.License
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration test [SubsonicAPIClient] for getLicense() request.
|
||||||
|
*/
|
||||||
|
class SubsonicApiGetLicenseTest : SubsonicAPIClientTest() {
|
||||||
|
@Test
|
||||||
|
fun `Should parse get license ok response`() {
|
||||||
|
mockWebServerRule.enqueueResponse("license_ok.json")
|
||||||
|
|
||||||
|
val response = client.api.getLicense().execute()
|
||||||
|
|
||||||
|
assertResponseSuccessful(response)
|
||||||
|
with(response.body()) {
|
||||||
|
assertBaseResponseOk()
|
||||||
|
license `should equal` License(valid = true,
|
||||||
|
trialExpires = parseDate("2016-11-23T20:17:15.206Z"),
|
||||||
|
email = "someone@example.net",
|
||||||
|
licenseExpires = parseDate("8994-08-17T07:12:55.807Z"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should parse get license error response`() {
|
||||||
|
val response = checkErrorCallParsed(mockWebServerRule, {
|
||||||
|
client.api.getLicense().execute()
|
||||||
|
})
|
||||||
|
|
||||||
|
response.license `should not be` null
|
||||||
|
with(response.license) {
|
||||||
|
email `should equal to` ""
|
||||||
|
valid `should equal to` false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package org.moire.ultrasonic.api.subsonic
|
||||||
|
|
||||||
|
import org.amshove.kluent.`should be`
|
||||||
|
import org.amshove.kluent.`should contain`
|
||||||
|
import org.amshove.kluent.`should equal`
|
||||||
|
import org.amshove.kluent.`should not be`
|
||||||
|
import org.junit.Test
|
||||||
|
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration test for [SubsonicAPIClient] for getMusicDirectory request.
|
||||||
|
*/
|
||||||
|
class SubsonicApiGetMusicDirectoryTest : SubsonicAPIClientTest() {
|
||||||
|
@Test
|
||||||
|
fun `Should parse getMusicDirectory error response`() {
|
||||||
|
val response = checkErrorCallParsed(mockWebServerRule, {
|
||||||
|
client.api.getMusicDirectory(1).execute()
|
||||||
|
})
|
||||||
|
|
||||||
|
response.musicDirectory `should be` null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GetMusicDirectory should add directory id to query params`() {
|
||||||
|
mockWebServerRule.enqueueResponse("get_music_directory_ok.json")
|
||||||
|
val directoryId = 124L
|
||||||
|
|
||||||
|
client.api.getMusicDirectory(directoryId).execute()
|
||||||
|
|
||||||
|
mockWebServerRule.mockWebServer.takeRequest().requestLine `should contain` "id=$directoryId"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should parse get music directory ok response`() {
|
||||||
|
mockWebServerRule.enqueueResponse("get_music_directory_ok.json")
|
||||||
|
|
||||||
|
val response = client.api.getMusicDirectory(1).execute()
|
||||||
|
|
||||||
|
assertResponseSuccessful(response)
|
||||||
|
|
||||||
|
response.body().musicDirectory `should not be` null
|
||||||
|
with(response.body().musicDirectory!!) {
|
||||||
|
id `should equal` 382L
|
||||||
|
name `should equal` "AC_DC"
|
||||||
|
starred `should equal` parseDate("2017-04-02T20:16:29.815Z")
|
||||||
|
childList.size `should be` 2
|
||||||
|
childList[0] `should equal` MusicDirectoryChild(583L, 382L, true, "Black Ice",
|
||||||
|
"Black Ice", "AC/DC", 2008, "Hard Rock", 583L,
|
||||||
|
parseDate("2016-10-23T15:31:22.000Z"), parseDate("2017-04-02T20:16:15.724Z"))
|
||||||
|
childList[1] `should equal` MusicDirectoryChild(582L, 382L, true, "Rock or Bust",
|
||||||
|
"Rock or Bust", "AC/DC", 2014, "Hard Rock", 582L,
|
||||||
|
parseDate("2016-10-23T15:31:24.000Z"), null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package org.moire.ultrasonic.api.subsonic
|
||||||
|
|
||||||
|
import org.amshove.kluent.`should equal`
|
||||||
|
import org.junit.Test
|
||||||
|
import org.moire.ultrasonic.api.subsonic.models.MusicFolder
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration test for [SubsonicAPIClient] for getMusicFolders() request.
|
||||||
|
*/
|
||||||
|
class SubsonicApiGetMusicFoldersTest : SubsonicAPIClientTest() {
|
||||||
|
@Test
|
||||||
|
fun `Should parse get music folders ok response`() {
|
||||||
|
mockWebServerRule.enqueueResponse("get_music_folders_ok.json")
|
||||||
|
|
||||||
|
val response = client.api.getMusicFolders().execute()
|
||||||
|
|
||||||
|
assertResponseSuccessful(response)
|
||||||
|
with(response.body()) {
|
||||||
|
assertBaseResponseOk()
|
||||||
|
musicFolders `should equal` listOf(MusicFolder(0, "Music"), MusicFolder(2, "Test"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should parse get music folders error response`() {
|
||||||
|
val response = checkErrorCallParsed(mockWebServerRule, {
|
||||||
|
client.api.getMusicFolders().execute()
|
||||||
|
})
|
||||||
|
|
||||||
|
response.musicFolders `should equal` emptyList()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package org.moire.ultrasonic.api.subsonic
|
||||||
|
|
||||||
|
import org.amshove.kluent.`should contain`
|
||||||
|
import org.amshove.kluent.`should equal`
|
||||||
|
import org.amshove.kluent.`should not contain`
|
||||||
|
import org.apache.commons.codec.binary.Hex
|
||||||
|
import org.junit.Test
|
||||||
|
import java.security.MessageDigest
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration test for [SubsonicAPIClient] that checks proper user password handling.
|
||||||
|
*/
|
||||||
|
class SubsonicApiPasswordTest : SubsonicAPIClientTest() {
|
||||||
|
@Test
|
||||||
|
fun `Should pass password hash and salt in query params for api version 1 13 0`() {
|
||||||
|
val clientV12 = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(), USERNAME,
|
||||||
|
PASSWORD, SubsonicAPIVersions.V1_14_0, CLIENT_ID)
|
||||||
|
mockWebServerRule.enqueueResponse("ping_ok.json")
|
||||||
|
|
||||||
|
clientV12.api.ping().execute()
|
||||||
|
|
||||||
|
with(mockWebServerRule.mockWebServer.takeRequest()) {
|
||||||
|
requestLine `should contain` "&s="
|
||||||
|
requestLine `should contain` "&t="
|
||||||
|
requestLine `should not contain` "&p=enc:"
|
||||||
|
|
||||||
|
val salt = requestLine.split('&').find { it.startsWith("s=") }?.substringAfter('=')
|
||||||
|
val token = requestLine.split('&').find { it.startsWith("t=") }?.substringAfter('=')
|
||||||
|
val expectedToken = String(Hex.encodeHex(MessageDigest.getInstance("MD5")
|
||||||
|
.digest("$PASSWORD$salt".toByteArray()), false))
|
||||||
|
token!! `should equal` expectedToken
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should pass hex encoded password in query params for api version 1 12 0`() {
|
||||||
|
val clientV11 = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(), USERNAME,
|
||||||
|
PASSWORD, SubsonicAPIVersions.V1_12_0, CLIENT_ID)
|
||||||
|
mockWebServerRule.enqueueResponse("ping_ok.json")
|
||||||
|
|
||||||
|
clientV11.api.ping().execute()
|
||||||
|
|
||||||
|
with(mockWebServerRule.mockWebServer.takeRequest()) {
|
||||||
|
requestLine `should not contain` "&s="
|
||||||
|
requestLine `should not contain` "&t="
|
||||||
|
requestLine `should contain` "&p=enc:"
|
||||||
|
val passParam = requestLine.split('&').find { it.startsWith("p=enc:") }
|
||||||
|
val encodedPassword = String(Hex.encodeHex(PASSWORD.toByteArray(), false))
|
||||||
|
passParam `should equal` "p=enc:$encodedPassword"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package org.moire.ultrasonic.api.subsonic
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration test for [SubsonicAPIClient] that checks ping api call.
|
||||||
|
*/
|
||||||
|
class SubsonicApiPingRequestTest : SubsonicAPIClientTest() {
|
||||||
|
@Test
|
||||||
|
fun `Should parse ping ok response`() {
|
||||||
|
mockWebServerRule.enqueueResponse("ping_ok.json")
|
||||||
|
|
||||||
|
val response = client.api.ping().execute()
|
||||||
|
|
||||||
|
assertResponseSuccessful(response)
|
||||||
|
with(response.body()) {
|
||||||
|
assertBaseResponseOk()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should parse ping error response`() {
|
||||||
|
checkErrorCallParsed(mockWebServerRule, {
|
||||||
|
client.api.ping().execute()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user