diff --git a/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/CommonFunctions.kt b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/CommonFunctions.kt index 5efa0bf3..e984c6c0 100644 --- a/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/CommonFunctions.kt +++ b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/CommonFunctions.kt @@ -66,7 +66,7 @@ fun SubsonicResponse.assertBaseResponseOk() { error `should be` null } -fun MockWebServerRule.assertRequestParam(responseResourceName: String, +fun MockWebServerRule.assertRequestParam(responseResourceName: String = "ping_ok.json", expectedParam: String, apiRequest: () -> Response) { this.enqueueResponse(responseResourceName) diff --git a/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiJukeboxControlTest.kt b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiJukeboxControlTest.kt new file mode 100644 index 00000000..be4a96de --- /dev/null +++ b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiJukeboxControlTest.kt @@ -0,0 +1,110 @@ +package org.moire.ultrasonic.api.subsonic + +import org.amshove.kluent.`should equal to` +import org.amshove.kluent.`should equal` +import org.junit.Test +import org.moire.ultrasonic.api.subsonic.models.JukeboxAction +import org.moire.ultrasonic.api.subsonic.models.JukeboxAction.GET +import org.moire.ultrasonic.api.subsonic.models.JukeboxAction.STATUS +import org.moire.ultrasonic.api.subsonic.models.JukeboxStatus +import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild + +/** + * Integration test for [SubsonicAPIDefinition.jukeboxControl] call. + */ +class SubsonicApiJukeboxControlTest : SubsonicAPIClientTest() { + @Test + fun `Should handle error response`() { + val response = checkErrorCallParsed(mockWebServerRule) { + client.api.jukeboxControl(GET).execute() + } + + response.jukebox `should equal` JukeboxStatus() + } + + @Test + fun `Should handle ok response with jukebox status`() { + mockWebServerRule.enqueueResponse("jukebox_control_status_ok.json") + + val response = client.api.jukeboxControl(STATUS).execute() + + assertResponseSuccessful(response) + with(response.body().jukebox) { + currentIndex `should equal to` 94 + playing `should equal to` true + gain `should equal to` 0.32f + position `should equal to` 3 + playlistEntries `should equal` emptyList() + } + } + + @Test + fun `Should handle ok response with jukebox playlist`() { + mockWebServerRule.enqueueResponse("jukebox_control_playlist_ok.json") + + val response = client.api.jukeboxControl(GET).execute() + + assertResponseSuccessful(response) + with(response.body().jukebox) { + currentIndex `should equal to` 887 + playing `should equal to` false + gain `should equal to` 0.88f + position `should equal to` 2 + playlistEntries.size `should equal to` 2 + playlistEntries[1] `should equal` MusicDirectoryChild(id = 4215L, parent = 4186L, + isDir = false, title = "Going to Hell", album = "Going to Hell", + artist = "The Pretty Reckless", track = 2, year = 2014, genre = "Hard Rock", + coverArt = "4186", size = 11089627, contentType = "audio/mpeg", + suffix = "mp3", duration = 277, bitRate = 320, + path = "The Pretty Reckless/Going to Hell/02 Going to Hell.mp3", isVideo = false, + playCount = 0, discNumber = 1, + created = parseDate("2016-10-23T21:30:41.000Z"), albumId = 388, + artistId = 238, type = "music") + } + } + + @Test + fun `Should pass action in request params`() { + val action = JukeboxAction.SET_GAIN + + mockWebServerRule.assertRequestParam(expectedParam = "action=$action") { + client.api.jukeboxControl(action).execute() + } + } + + @Test + fun `Should pass index in request params`() { + val index = 440 + + mockWebServerRule.assertRequestParam(expectedParam = "index=$index") { + client.api.jukeboxControl(GET, index = index).execute() + } + } + + @Test + fun `Should pass offset in request params`() { + val offset = 58223 + + mockWebServerRule.assertRequestParam(expectedParam = "offset=$offset") { + client.api.jukeboxControl(GET, offset = offset).execute() + } + } + + @Test + fun `Should pass ids in request params`() { + val id = listOf("some-id1", "some-id2") + + mockWebServerRule.assertRequestParam(expectedParam = "id=${id[0]}&id=${id[1]}") { + client.api.jukeboxControl(GET, ids = id).execute() + } + } + + @Test + fun `Should pass gain in request params`() { + val gain = 0.73f + + mockWebServerRule.assertRequestParam(expectedParam = "gain=$gain") { + client.api.jukeboxControl(GET, gain = gain).execute() + } + } +} diff --git a/subsonic-api/src/integrationTest/resources/jukebox_control_playlist_ok.json b/subsonic-api/src/integrationTest/resources/jukebox_control_playlist_ok.json new file mode 100644 index 00000000..9329535f --- /dev/null +++ b/subsonic-api/src/integrationTest/resources/jukebox_control_playlist_ok.json @@ -0,0 +1,61 @@ +{ + "subsonic-response" : { + "status" : "ok", + "version" : "1.15.0", + "jukeboxPlaylist" : { + "currentIndex" : 887, + "playing" : false, + "gain" : 0.88, + "position" : 2, + "entry" : [ { + "id" : "4209", + "parent" : "4186", + "isDir" : false, + "title" : "Follow Me Down", + "album" : "Going to Hell", + "artist" : "The Pretty Reckless", + "track" : 1, + "year" : 2014, + "genre" : "Hard Rock", + "coverArt" : "4186", + "size" : 11229681, + "contentType" : "audio/mpeg", + "suffix" : "mp3", + "duration" : 280, + "bitRate" : 320, + "path" : "The Pretty Reckless/Going to Hell/01 Follow Me Down.mp3", + "isVideo" : false, + "playCount" : 1, + "discNumber" : 1, + "created" : "2016-10-23T21:30:43.000Z", + "albumId" : "388", + "artistId" : "238", + "type" : "music" + }, { + "id" : "4215", + "parent" : "4186", + "isDir" : false, + "title" : "Going to Hell", + "album" : "Going to Hell", + "artist" : "The Pretty Reckless", + "track" : 2, + "year" : 2014, + "genre" : "Hard Rock", + "coverArt" : "4186", + "size" : 11089627, + "contentType" : "audio/mpeg", + "suffix" : "mp3", + "duration" : 277, + "bitRate" : 320, + "path" : "The Pretty Reckless/Going to Hell/02 Going to Hell.mp3", + "isVideo" : false, + "playCount" : 0, + "discNumber" : 1, + "created" : "2016-10-23T21:30:41.000Z", + "albumId" : "388", + "artistId" : "238", + "type" : "music" + } ] + } + } +} \ No newline at end of file diff --git a/subsonic-api/src/integrationTest/resources/jukebox_control_status_ok.json b/subsonic-api/src/integrationTest/resources/jukebox_control_status_ok.json new file mode 100644 index 00000000..47dfde8a --- /dev/null +++ b/subsonic-api/src/integrationTest/resources/jukebox_control_status_ok.json @@ -0,0 +1,12 @@ +{ + "subsonic-response" : { + "status" : "ok", + "version" : "1.15.0", + "jukeboxStatus" : { + "currentIndex" : 94, + "playing" : true, + "gain" : 0.32, + "position" : 3 + } + } +} \ No newline at end of file diff --git a/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIDefinition.kt b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIDefinition.kt index d5a778e1..0f760389 100644 --- a/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIDefinition.kt +++ b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIDefinition.kt @@ -2,6 +2,7 @@ package org.moire.ultrasonic.api.subsonic import okhttp3.ResponseBody import org.moire.ultrasonic.api.subsonic.models.AlbumListType +import org.moire.ultrasonic.api.subsonic.models.JukeboxAction import org.moire.ultrasonic.api.subsonic.response.GetAlbumList2Response import org.moire.ultrasonic.api.subsonic.response.GetAlbumListResponse import org.moire.ultrasonic.api.subsonic.response.GetAlbumResponse @@ -16,6 +17,7 @@ import org.moire.ultrasonic.api.subsonic.response.GetPodcastsResponse import org.moire.ultrasonic.api.subsonic.response.GetRandomSongsResponse import org.moire.ultrasonic.api.subsonic.response.GetStarredResponse import org.moire.ultrasonic.api.subsonic.response.GetStarredTwoResponse +import org.moire.ultrasonic.api.subsonic.response.JukeboxResponse import org.moire.ultrasonic.api.subsonic.response.LicenseResponse import org.moire.ultrasonic.api.subsonic.response.MusicFoldersResponse import org.moire.ultrasonic.api.subsonic.response.SearchResponse @@ -179,4 +181,11 @@ interface SubsonicAPIDefinition { @Query("estimateContentLength") estimateContentLength: Boolean? = null, @Query("converted") converted: Boolean? = null, @Header("Range") offset: Long? = null): Call + + @GET("jukeboxControl.view") + fun jukeboxControl(@Query("action") action: JukeboxAction, + @Query("index") index: Int? = null, + @Query("offset") offset: Int? = null, + @Query("id") ids: List? = null, + @Query("gain") gain: Float? = null): Call } diff --git a/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/models/JukeboxAction.kt b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/models/JukeboxAction.kt new file mode 100644 index 00000000..19502d02 --- /dev/null +++ b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/models/JukeboxAction.kt @@ -0,0 +1,24 @@ +package org.moire.ultrasonic.api.subsonic.models + +/** + * Supported jukebox commands. + * + * It is used in [org.moire.ultrasonic.api.subsonic.SubsonicAPIDefinition.jukeboxControl] call. + */ +enum class JukeboxAction(val action: String) { + GET("get"), + STATUS("status"), + SET("set"), + START("start"), + STOP("stop"), + SKIP("skip"), + ADD("add"), + CLEAR("clear"), + REMOVE("remove"), + SHUFFLE("shuffle"), + SET_GAIN("setGain"); + + override fun toString(): String { + return action + } +} diff --git a/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/models/JukeboxStatus.kt b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/models/JukeboxStatus.kt new file mode 100644 index 00000000..c52fc1cf --- /dev/null +++ b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/models/JukeboxStatus.kt @@ -0,0 +1,10 @@ +package org.moire.ultrasonic.api.subsonic.models + +import com.fasterxml.jackson.annotation.JsonProperty + +data class JukeboxStatus( + val currentIndex: Int = -1, + val playing: Boolean = false, + val gain: Float = 0.0f, + val position: Int = 0, + @JsonProperty("entry") val playlistEntries: List = emptyList()) diff --git a/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/response/JukeboxResponse.kt b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/response/JukeboxResponse.kt new file mode 100644 index 00000000..be2d6f74 --- /dev/null +++ b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/response/JukeboxResponse.kt @@ -0,0 +1,20 @@ +package org.moire.ultrasonic.api.subsonic.response + +import com.fasterxml.jackson.annotation.JsonSetter +import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions +import org.moire.ultrasonic.api.subsonic.SubsonicError +import org.moire.ultrasonic.api.subsonic.models.JukeboxStatus + +class JukeboxResponse(status: Status, + version: SubsonicAPIVersions, + error: SubsonicError?, + var jukebox: JukeboxStatus = JukeboxStatus()) + : SubsonicResponse(status, version, error) { + @JsonSetter("jukeboxStatus") fun setJukeboxStatus(jukebox: JukeboxStatus) { + this.jukebox = jukebox + } + + @JsonSetter("jukeboxPlaylist") fun setJukeboxPlaylist(jukebox: JukeboxStatus) { + this.jukebox = jukebox + } +} diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/RESTMusicService.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/RESTMusicService.java index 7de681be..7133a0ce 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/RESTMusicService.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/RESTMusicService.java @@ -56,6 +56,7 @@ import org.apache.http.protocol.HttpContext; import org.moire.ultrasonic.R; import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient; import org.moire.ultrasonic.api.subsonic.models.AlbumListType; +import org.moire.ultrasonic.api.subsonic.models.JukeboxAction; import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild; import org.moire.ultrasonic.api.subsonic.response.GetAlbumList2Response; import org.moire.ultrasonic.api.subsonic.response.GetAlbumListResponse; @@ -71,6 +72,7 @@ import org.moire.ultrasonic.api.subsonic.response.GetPodcastsResponse; import org.moire.ultrasonic.api.subsonic.response.GetRandomSongsResponse; import org.moire.ultrasonic.api.subsonic.response.GetStarredResponse; import org.moire.ultrasonic.api.subsonic.response.GetStarredTwoResponse; +import org.moire.ultrasonic.api.subsonic.response.JukeboxResponse; import org.moire.ultrasonic.api.subsonic.response.LicenseResponse; import org.moire.ultrasonic.api.subsonic.response.MusicFoldersResponse; import org.moire.ultrasonic.api.subsonic.response.SearchResponse; @@ -81,6 +83,7 @@ import org.moire.ultrasonic.api.subsonic.response.SubsonicResponse; import org.moire.ultrasonic.data.APIAlbumConverter; import org.moire.ultrasonic.data.APIArtistConverter; import org.moire.ultrasonic.data.APIIndexesConverter; +import org.moire.ultrasonic.data.APIJukeboxConverter; import org.moire.ultrasonic.data.APILyricsConverter; import org.moire.ultrasonic.data.APIMusicDirectoryConverter; import org.moire.ultrasonic.data.APIMusicFolderConverter; @@ -106,7 +109,6 @@ import org.moire.ultrasonic.service.parser.BookmarkParser; import org.moire.ultrasonic.service.parser.ChatMessageParser; import org.moire.ultrasonic.service.parser.ErrorParser; import org.moire.ultrasonic.service.parser.GenreParser; -import org.moire.ultrasonic.service.parser.JukeboxStatusParser; import org.moire.ultrasonic.service.parser.MusicDirectoryParser; import org.moire.ultrasonic.service.parser.RandomSongsParser; import org.moire.ultrasonic.service.parser.ShareParser; @@ -141,8 +143,6 @@ import java.util.concurrent.atomic.AtomicReference; import kotlin.Pair; import retrofit2.Response; -import static java.util.Arrays.asList; - /** * @author Sindre Mehus */ @@ -872,58 +872,80 @@ public class RESTMusicService implements MusicService return url; } - @Override - public JukeboxStatus updateJukeboxPlaylist(List ids, Context context, ProgressListener progressListener) throws Exception - { - int n = ids.size(); - List parameterNames = new ArrayList(n + 1); - parameterNames.add("action"); + @Override + public JukeboxStatus updateJukeboxPlaylist(List ids, + Context context, + ProgressListener progressListener) throws Exception { + updateProgressListener(progressListener, R.string.parser_reading); + Response response = subsonicAPIClient.getApi() + .jukeboxControl(JukeboxAction.SET, null, null, ids, null) + .execute(); + checkResponseSuccessful(response); - for (String ignored : ids) - { - parameterNames.add("id"); - } + return APIJukeboxConverter.toDomainEntity(response.body().getJukebox()); + } - List parameterValues = new ArrayList(); - parameterValues.add("set"); - parameterValues.addAll(ids); + @Override + public JukeboxStatus skipJukebox(int index, + int offsetSeconds, + Context context, + ProgressListener progressListener) throws Exception { + updateProgressListener(progressListener, R.string.parser_reading); + Response response = subsonicAPIClient.getApi() + .jukeboxControl(JukeboxAction.SKIP, index, offsetSeconds, null, null) + .execute(); + checkResponseSuccessful(response); - return executeJukeboxCommand(context, progressListener, parameterNames, parameterValues); - } + return APIJukeboxConverter.toDomainEntity(response.body().getJukebox()); + } - @Override - public JukeboxStatus skipJukebox(int index, int offsetSeconds, Context context, ProgressListener progressListener) throws Exception - { - List parameterNames = asList("action", "index", "offset"); - List parameterValues = Arrays.asList("skip", index, offsetSeconds); - return executeJukeboxCommand(context, progressListener, parameterNames, parameterValues); - } + @Override + public JukeboxStatus stopJukebox(Context context, + ProgressListener progressListener) throws Exception { + updateProgressListener(progressListener, R.string.parser_reading); + Response response = subsonicAPIClient.getApi() + .jukeboxControl(JukeboxAction.STOP, null, null, null, null) + .execute(); + checkResponseSuccessful(response); - @Override - public JukeboxStatus stopJukebox(Context context, ProgressListener progressListener) throws Exception - { - return executeJukeboxCommand(context, progressListener, Collections.singletonList("action"), Arrays.asList("stop")); - } + return APIJukeboxConverter.toDomainEntity(response.body().getJukebox()); + } - @Override - public JukeboxStatus startJukebox(Context context, ProgressListener progressListener) throws Exception - { - return executeJukeboxCommand(context, progressListener, Collections.singletonList("action"), Arrays.asList("start")); - } + @Override + public JukeboxStatus startJukebox(Context context, + ProgressListener progressListener) throws Exception { + updateProgressListener(progressListener, R.string.parser_reading); + Response response = subsonicAPIClient.getApi() + .jukeboxControl(JukeboxAction.START, null, null, null, null) + .execute(); + checkResponseSuccessful(response); - @Override - public JukeboxStatus getJukeboxStatus(Context context, ProgressListener progressListener) throws Exception - { - return executeJukeboxCommand(context, progressListener, Collections.singletonList("action"), Arrays.asList("status")); - } + return APIJukeboxConverter.toDomainEntity(response.body().getJukebox()); + } - @Override - public JukeboxStatus setJukeboxGain(float gain, Context context, ProgressListener progressListener) throws Exception - { - List parameterNames = asList("action", "gain"); - List parameterValues = Arrays.asList("setGain", gain); - return executeJukeboxCommand(context, progressListener, parameterNames, parameterValues); - } + @Override + public JukeboxStatus getJukeboxStatus(Context context, + ProgressListener progressListener) throws Exception { + updateProgressListener(progressListener, R.string.parser_reading); + Response response = subsonicAPIClient.getApi() + .jukeboxControl(JukeboxAction.STATUS, null, null, null, null) + .execute(); + checkResponseSuccessful(response); + + return APIJukeboxConverter.toDomainEntity(response.body().getJukebox()); + } + + @Override + public JukeboxStatus setJukeboxGain(float gain, Context context, + ProgressListener progressListener) throws Exception { + updateProgressListener(progressListener, R.string.parser_reading); + Response response = subsonicAPIClient.getApi() + .jukeboxControl(JukeboxAction.SET_GAIN, null, null, null, gain) + .execute(); + checkResponseSuccessful(response); + + return APIJukeboxConverter.toDomainEntity(response.body().getJukebox()); + } @Override public List getShares(boolean refresh, Context context, ProgressListener progressListener) throws Exception @@ -940,20 +962,6 @@ public class RESTMusicService implements MusicService } } - private JukeboxStatus executeJukeboxCommand(Context context, ProgressListener progressListener, List parameterNames, List parameterValues) throws Exception - { - checkServerVersion(context, "1.7", "Jukebox not supported."); - Reader reader = getReader(context, progressListener, "jukeboxControl", null, parameterNames, parameterValues); - try - { - return new JukeboxStatusParser(context).parse(reader); - } - finally - { - Util.close(reader); - } - } - private Reader getReader(Context context, ProgressListener progressListener, String method, HttpParams requestParams) throws Exception { return getReader(context, progressListener, method, requestParams, Collections.emptyList(), Collections.emptyList()); diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/parser/JukeboxStatusParser.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/parser/JukeboxStatusParser.java deleted file mode 100644 index a875e073..00000000 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/parser/JukeboxStatusParser.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Subsonic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package org.moire.ultrasonic.service.parser; - -import android.content.Context; - -import org.moire.ultrasonic.domain.JukeboxStatus; - -import org.xmlpull.v1.XmlPullParser; - -import java.io.Reader; - -/** - * @author Sindre Mehus - */ -public class JukeboxStatusParser extends AbstractParser -{ - - public JukeboxStatusParser(Context context) - { - super(context); - } - - public JukeboxStatus parse(Reader reader) throws Exception - { - - init(reader); - - JukeboxStatus jukeboxStatus = new JukeboxStatus(); - int eventType; - do - { - eventType = nextParseEvent(); - if (eventType == XmlPullParser.START_TAG) - { - String name = getElementName(); - if ("jukeboxPlaylist".equals(name) || "jukeboxStatus".equals(name)) - { - jukeboxStatus.setPositionSeconds(getInteger("position")); - jukeboxStatus.setCurrentIndex(getInteger("currentIndex")); - jukeboxStatus.setPlaying(getBoolean("playing")); - jukeboxStatus.setGain(getFloat("gain")); - } - else if ("error".equals(name)) - { - handleError(); - } - } - } while (eventType != XmlPullParser.END_DOCUMENT); - - validate(); - - return jukeboxStatus; - } -} \ No newline at end of file diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/APIJukeboxCoverter.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/APIJukeboxCoverter.kt new file mode 100644 index 00000000..bb4fe9a1 --- /dev/null +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/APIJukeboxCoverter.kt @@ -0,0 +1,13 @@ +// Collection of function to convert subsonic api jukebox responses to app entities +@file:JvmName("APIJukeboxConverter") +package org.moire.ultrasonic.data + +import org.moire.ultrasonic.domain.JukeboxStatus +import org.moire.ultrasonic.api.subsonic.models.JukeboxStatus as ApiJukeboxStatus + +fun ApiJukeboxStatus.toDomainEntity(): JukeboxStatus = JukeboxStatus().apply { + positionSeconds = this@toDomainEntity.position + setCurrentIndex(this@toDomainEntity.currentIndex) + isPlaying = this@toDomainEntity.playing + gain = this@toDomainEntity.gain +} diff --git a/ultrasonic/src/test/kotlin/org/moire/ultrasonic/data/APIJukeboxConverterTest.kt b/ultrasonic/src/test/kotlin/org/moire/ultrasonic/data/APIJukeboxConverterTest.kt new file mode 100644 index 00000000..846970a6 --- /dev/null +++ b/ultrasonic/src/test/kotlin/org/moire/ultrasonic/data/APIJukeboxConverterTest.kt @@ -0,0 +1,26 @@ +@file:Suppress("IllegalIdentifier") + +package org.moire.ultrasonic.data + +import org.amshove.kluent.`should equal to` +import org.junit.Test +import org.moire.ultrasonic.api.subsonic.models.JukeboxStatus + +/** + * Unit test for functions in [APIJukeboxConverter.kt] file. + */ +class APIJukeboxConverterTest { + @Test + fun `Should convert JukeboxStatus to domain entity`() { + val entity = JukeboxStatus(45, true, 0.11f, 442) + + val convertedEntity = entity.toDomainEntity() + + with(convertedEntity) { + currentPlayingIndex `should equal to` entity.currentIndex + gain `should equal to` entity.gain + isPlaying `should equal to` entity.playing + positionSeconds `should equal to` entity.position + } + } +}