diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6907c40f..6faa4f34 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,11 @@ jobs: steps: - name: Check out repo uses: actions/checkout@v2 + - name: Install java 11 + uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: '11' - name: Install curl run: sudo apt-get install -y curl libcurl4-openssl-dev - name: Test secret @@ -44,6 +49,11 @@ jobs: steps: - name: Check out repo uses: actions/checkout@v2 + - name: Install java 11 + uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: '11' - name: Test mac run: gradle macosX64Test - name: Archive test results @@ -51,22 +61,4 @@ jobs: with: name: code-coverage-report path: build/reports - if: always() - test_windows: - runs-on: windows-latest - environment: testing - env: - SPOTIFY_CLIENT_ID: ${{ secrets.SPOTIFY_CLIENT_ID }} - SPOTIFY_CLIENT_SECRET: ${{ secrets.SPOTIFY_CLIENT_SECRET }} - steps: - - name: Check out repo - uses: actions/checkout@v2 - - name: Test windows - run: gradle mingwX64Test - - name: Archive test results - uses: actions/upload-artifact@v2 - with: - name: code-coverage-report - path: build/reports - if: always() - + if: always() \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4aedba7a..b22d80ed 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,6 +28,11 @@ jobs: steps: - name: Check out repo uses: actions/checkout@v2 + - name: Install java 11 + uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: '11' - name: Install curl run: sudo apt-get install -y curl libcurl4-openssl-dev - name: Verify Android @@ -49,6 +54,11 @@ jobs: steps: - name: Check out repo uses: actions/checkout@v2 + - name: Install java 11 + uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: '11' - name: Publish macOS/tvOS/iOS run: gradle publishMacosX64PublicationToNexusRepository publishIosX64PublicationToNexusRepository publishTvosX64PublicationToNexusRepository release_windows: @@ -58,6 +68,12 @@ jobs: steps: - name: Check out repo uses: actions/checkout@v2 + - name: Install java 11 + uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: '11' + - run: choco install curl - name: Publish windows run: gradle publishMingwX64PublicationToNexusRepository release_docs: @@ -66,6 +82,11 @@ jobs: steps: - name: Check out repo uses: actions/checkout@v2 + - name: Install java 11 + uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: '11' - name: Build docs run: gradle dokkaHtml - name: Push docs to docs repo diff --git a/build.gradle.kts b/build.gradle.kts index 6019839e..3fd2595a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,15 +5,15 @@ import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackOutput.Target plugins { id("lt.petuska.npm.publish") version "1.1.2" - kotlin("multiplatform") version "1.5.31" + kotlin("multiplatform") `maven-publish` signing id("io.codearte.nexus-staging") version "0.30.0" id("com.android.library") - kotlin("plugin.serialization") version "1.5.31" - id("com.diffplug.spotless") version "5.14.2" + kotlin("plugin.serialization") + id("com.diffplug.spotless") version "6.3.0" id("com.moowork.node") version "1.3.1" - id("org.jetbrains.dokka") version "1.5.0" + id("org.jetbrains.dokka") } repositories { @@ -27,8 +27,8 @@ buildscript { mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:4.1.3") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31") + classpath("com.android.tools.build:gradle:") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:") } } @@ -68,8 +68,9 @@ android { testOptions { this.unitTests.isReturnDefaultValues = true } - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") - + //sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") + sourceSets["main"].setRoot("src/androidMain") + sourceSets["test"].setRoot("src/androidTest") /*sourceSets { getByName("main") { manifest.srcFile("src/androidMain/AndroidManifest.xml") @@ -121,8 +122,7 @@ kotlin { } - val irOnlyJs = project.hasProperty("irOnly") - js(if (irOnlyJs) KotlinJsCompilerType.IR else KotlinJsCompilerType.BOTH) { + js(KotlinJsCompilerType.IR) { mavenPublication { setupPom(artifactId) @@ -151,7 +151,7 @@ kotlin { } }*/ - if (irOnlyJs) binaries.executable() + binaries.executable() } // val hostOs = System.getProperty("os.name") @@ -217,13 +217,13 @@ kotlin { val kotlinxDatetimeVersion = "0.3.1" sourceSets { - val serializationVersion = "1.3.0" - val ktorVersion = "1.6.3" + val serializationVersion = "1.3.2" + val ktorVersion = "1.6.8" val korlibsVersion = "2.2.0" val sparkVersion = "2.9.3" - val androidSpotifyAuthVersion = "1.2.3" + val androidSpotifyAuthVersion = "1.2.5" val androidCryptoVersion = "1.0.0" - val coroutineMTVersion = "1.5.2-native-mt" + val coroutineMTVersion = "1.6.0-native-mt" val commonMain by getting { dependencies { diff --git a/gradle.properties b/gradle.properties index cab820ff..9aa540ff 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,4 +18,6 @@ org.gradle.jvmargs=-Xmx8000m kotlin.native.enableDependencyPropagation=false android.useAndroidX=true android.enableJetifier=true -kotlin.mpp.enableGranularSourceSetsMetadata=true \ No newline at end of file +kotlin.mpp.enableGranularSourceSetsMetadata=true +kotlinVersion=1.6.10 +androidBuildToolsVersion=7.0.0 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a0f7639f..00e33ede 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index b6af7ec6..a5da4b20 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,20 +1,27 @@ pluginManagement { - val mainKotlinVersion = "1.5.0" + val kotlinVersion: String by settings + val androidBuildToolsVersion: String by settings + + plugins { + id("org.jetbrains.kotlin.multiplatform").version(kotlinVersion) + id("org.jetbrains.kotlin.plugin.serialization").version(kotlinVersion) + id("org.jetbrains.dokka").version(kotlinVersion) + } resolutionStrategy { eachPlugin { if (requested.id.id == "kotlin-multiplatform") { - useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:$mainKotlinVersion") + useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") } if (requested.id.id == "org.jetbrains.kotlin.jvm") { - useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:$mainKotlinVersion") + useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") } if (requested.id.id == "kotlinx-serialization") { - useModule("org.jetbrains.kotlin:kotlin-serialization:$mainKotlinVersion") - } else if (requested.id.namespace == "com.android") { - useModule("com.android.tools.build:gradle:3.5.4") + useModule("org.jetbrains.kotlin:kotlin-serialization:$kotlinVersion") + } else if (requested.id.id == "com.android.library") { + useModule("com.android.tools.build:gradle:$androidBuildToolsVersion") } else if (requested.id.id == "kotlin-android-extensions") { - useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:$mainKotlinVersion") + useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") } } } @@ -27,7 +34,4 @@ pluginManagement { } } -rootProject.name = "spotify-web-api-kotlin" -include("java-interop-basic-sample") -findProject(":java-interop-basic-sample")?.name = "java-interop-basic" -include("java-interop-sample") +rootProject.name = "spotify-web-api-kotlin" \ No newline at end of file diff --git a/src/commonMain/kotlin/com.adamratzman.spotify/endpoints/client/ClientPlayerApi.kt b/src/commonMain/kotlin/com.adamratzman.spotify/endpoints/client/ClientPlayerApi.kt index 15e669b4..bd463ca3 100644 --- a/src/commonMain/kotlin/com.adamratzman.spotify/endpoints/client/ClientPlayerApi.kt +++ b/src/commonMain/kotlin/com.adamratzman.spotify/endpoints/client/ClientPlayerApi.kt @@ -93,13 +93,12 @@ public class ClientPlayerApi(api: GenericSpotifyApi) : SpotifyEndpoint(api) { requireScopes(SpotifyScope.USER_READ_PLAYBACK_STATE) val obj = catch { - get( + getNullable( endpointBuilder("/me/player") .with("additional_types", additionalTypes.joinToString(",") { it.identifier }) .with("market", market?.name) .toString() - ) - .toObject(CurrentlyPlayingContext.serializer(), api, json) + )?.toObject(CurrentlyPlayingContext.serializer(), api, json) } return if (obj?.timestamp == null) null else obj } diff --git a/src/commonMain/kotlin/com.adamratzman.spotify/endpoints/pub/SearchApi.kt b/src/commonMain/kotlin/com.adamratzman.spotify/endpoints/pub/SearchApi.kt index 869740a4..54dd1216 100644 --- a/src/commonMain/kotlin/com.adamratzman.spotify/endpoints/pub/SearchApi.kt +++ b/src/commonMain/kotlin/com.adamratzman.spotify/endpoints/pub/SearchApi.kt @@ -87,7 +87,18 @@ public open class SearchApi(api: GenericSpotifyApi) : SpotifyEndpoint(api) { * * **[Api Reference](https://developer.spotify.com/documentation/web-api/reference/search/search/)** * - * @param query Search query keywords and optional field filters and operators. + * @param query Search query keywords and optional field filters and operators. You can narrow down your search using field filters. The available filters are album, artist, track, year, upc, tag:hipster, tag:new, isrc, and genre. Each field filter only applies to certain result types. + + The artist filter can be used while searching albums, artists or tracks. + The album and year filters can be used while searching albums or tracks. You can filter on a single year or a range (e.g. 1955-1960). + The genre filter can be use while searching tracks and artists. + The isrc and track filters can be used while searching tracks. + The upc, tag:new and tag:hipster filters can only be used while searching albums. The tag:new filter will return albums released in the past two weeks and tag:hipster can be used to return only albums with the lowest 10% popularity. + + You can also use the NOT operator to exclude keywords from your search. + + Example value: + "remaster%20track:Doxy+artist:Miles%20Davis" * @param searchTypes A list of item types to search across. Search results include hits from all the specified item types. * @param limit Maximum number of results to return. Default: 20 @@ -103,7 +114,10 @@ public open class SearchApi(api: GenericSpotifyApi) : SpotifyEndpoint(api) { - Playlist results are not affected by the market parameter. - If market is set to from_token, and a valid access token is specified in the request header, only content playable in the country associated with the user account, is returned. - Users can view the country that is associated with their account in the account settings. A user must grant access to the [SpotifyScope.USER_READ_PRIVATE] scope prior to when the access token is issued. + **Note**: episodes will not be returned if this is NOT specified * @param includeExternal If true, the response will include any relevant audio content that is hosted externally. By default external content is filtered out from responses. + * + * @throws IllegalArgumentException if no search types are provided, or if [SearchType.EPISODE] is provided but [market] is not */ public suspend fun search( query: String, @@ -114,6 +128,10 @@ public open class SearchApi(api: GenericSpotifyApi) : SpotifyEndpoint(api) { includeExternal: Boolean? = null ): SpotifySearchResult { require(searchTypes.isNotEmpty()) { "At least one search type must be provided" } + if (SearchType.EPISODE in searchTypes) { + requireNotNull(market) { "Market must be provided when SearchType.EPISODE is requested"} + } + val jsonString = get(build(query, market, limit, offset, *searchTypes, includeExternal = includeExternal)) val map = json.decodeFromString(MapSerializer(String.serializer(), JsonObject.serializer()), jsonString) @@ -184,6 +202,8 @@ public open class SearchApi(api: GenericSpotifyApi) : SpotifyEndpoint(api) { - Playlist results are not affected by the market parameter. - If market is set to from_token, and a valid access token is specified in the request header, only content playable in the country associated with the user account, is returned. - Users can view the country that is associated with their account in the account settings. A user must grant access to the [SpotifyScope.USER_READ_PRIVATE] scope prior to when the access token is issued. + + **Note**: episodes will not be returned if this is NOT specified * @param includeExternal If true, the response will include any relevant audio content that is hosted externally. By default external content is filtered out from responses. */ public fun searchRestAction( diff --git a/src/commonMain/kotlin/com.adamratzman.spotify/http/Endpoints.kt b/src/commonMain/kotlin/com.adamratzman.spotify/http/Endpoints.kt index 754e1b30..358b4dff 100644 --- a/src/commonMain/kotlin/com.adamratzman.spotify/http/Endpoints.kt +++ b/src/commonMain/kotlin/com.adamratzman.spotify/http/Endpoints.kt @@ -11,6 +11,7 @@ import com.adamratzman.spotify.models.ErrorResponse import com.adamratzman.spotify.models.serialization.toObject import com.adamratzman.spotify.utils.ConcurrentHashMap import com.adamratzman.spotify.utils.getCurrentTimeMs +import io.ktor.http.HttpStatusCode import kotlin.math.ceil import kotlinx.coroutines.CancellationException import kotlinx.coroutines.async @@ -76,15 +77,19 @@ public abstract class SpotifyEndpoint(public val api: GenericSpotifyApi) { internal suspend fun get(url: String): String { - return execute(url) + return execute(url) + } + + internal suspend fun getNullable(url: String): String? { + return execute(url) } internal suspend fun post(url: String, body: String? = null, contentType: String? = null): String { - return execute(url, body, HttpRequestMethod.POST, contentType = contentType) + return execute(url, body, HttpRequestMethod.POST, contentType = contentType) } internal suspend fun put(url: String, body: String? = null, contentType: String? = null): String { - return execute(url, body, HttpRequestMethod.PUT, contentType = contentType) + return execute(url, body, HttpRequestMethod.PUT, contentType = contentType) } internal suspend fun delete( @@ -92,10 +97,10 @@ public abstract class SpotifyEndpoint(public val api: GenericSpotifyApi) { body: String? = null, contentType: String? = null ): String { - return execute(url, body, HttpRequestMethod.DELETE, contentType = contentType) + return execute(url, body, HttpRequestMethod.DELETE, contentType = contentType) } - private suspend fun execute( + private suspend fun execute( url: String, body: String? = null, method: HttpRequestMethod = HttpRequestMethod.GET, @@ -117,7 +122,7 @@ public abstract class SpotifyEndpoint(public val api: GenericSpotifyApi) { } try { - return withTimeout(api.spotifyApiOptions.requestTimeoutMillis ?: 100 * 1000L) { + return withTimeout(api.spotifyApiOptions.requestTimeoutMillis ?: (100 * 1000L)) { try { val document = createConnection(url, body, method, contentType).execute( additionalHeaders = cacheState?.eTag?.let { @@ -126,7 +131,7 @@ public abstract class SpotifyEndpoint(public val api: GenericSpotifyApi) { retryIfInternalServerErrorLeft = api.spotifyApiOptions.retryOnInternalServerErrorTimes ) - handleResponse(document, cacheState, spotifyRequest, retry202) ?: execute( + handleResponse(document, cacheState, spotifyRequest, retry202) ?: execute( url, body, method, @@ -137,7 +142,7 @@ public abstract class SpotifyEndpoint(public val api: GenericSpotifyApi) { if (e.statusCode == 401 && !attemptedRefresh) { api.refreshToken() - execute( + execute( url, body, method, @@ -165,10 +170,13 @@ public abstract class SpotifyEndpoint(public val api: GenericSpotifyApi) { ): String? { val statusCode = document.responseCode - if (statusCode == HttpConnectionStatus.HTTP_NOT_MODIFIED.code) { + if (statusCode == HttpStatusCode.NotModified.value) { requireNotNull(cacheState?.eTag) { "304 status only allowed on Etag-able endpoints" } return cacheState?.data } + else if (statusCode == HttpStatusCode.NoContent.value) { + return null + } val responseBody = document.body diff --git a/src/commonMain/kotlin/com.adamratzman.spotify/http/HttpConnection.kt b/src/commonMain/kotlin/com.adamratzman.spotify/http/HttpConnection.kt index 5b5fcfcc..6c99c703 100644 --- a/src/commonMain/kotlin/com.adamratzman.spotify/http/HttpConnection.kt +++ b/src/commonMain/kotlin/com.adamratzman.spotify/http/HttpConnection.kt @@ -11,6 +11,7 @@ import com.adamratzman.spotify.models.ErrorResponse import com.adamratzman.spotify.models.SpotifyRatelimitedException import com.adamratzman.spotify.models.serialization.nonstrictJson import com.adamratzman.spotify.models.serialization.toObject +import com.soywiz.korio.dynamic.KDynamic.Companion.toLong import io.ktor.client.HttpClient import io.ktor.client.features.ResponseException import io.ktor.client.request.HttpRequestBuilder @@ -115,12 +116,10 @@ public class HttpConnection constructor( } else throw SpotifyRatelimitedException(ratelimit) } - val body = response.readText() + val body: String = response.readText() if (api?.spotifyApiOptions?.enableDebugMode == true) println("DEBUG MODE: $body") - if (respCode == 401 && body.contains("access token") && - api != null && api.spotifyApiOptions.automaticRefresh - ) { + if (respCode == 401 && body.contains("access token") && api?.spotifyApiOptions?.automaticRefresh == true) { api.refreshToken() val newAdditionalHeaders = additionalHeaders?.toMutableList()?.filter { it.key != "Authorization" }?.toMutableList() @@ -222,8 +221,4 @@ public class HttpConnection constructor( expectSuccess = false } } -} - -public enum class HttpConnectionStatus(public val code: Int) { - HTTP_NOT_MODIFIED(304); -} +} \ No newline at end of file diff --git a/src/commonMain/kotlin/com.adamratzman.spotify/utils/Market.kt b/src/commonMain/kotlin/com.adamratzman.spotify/utils/Market.kt index d701f64d..971450dc 100644 --- a/src/commonMain/kotlin/com.adamratzman.spotify/utils/Market.kt +++ b/src/commonMain/kotlin/com.adamratzman.spotify/utils/Market.kt @@ -1,6 +1,8 @@ /* Spotify Web API, Kotlin Wrapper; MIT License, 2017-2021; Original author: Adam Ratzman */ package com.adamratzman.spotify.utils +import com.adamratzman.spotify.SpotifyAppApi + /* * Copyright (C) 2012-2019 Neo Visionaries Inc. * @@ -20,81 +22,7 @@ package com.adamratzman.spotify.utils /** * [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1) country code. * - * - * - * Enum names of this enum themselves are represented by - * [ISO 3166-1 alpha-2](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) - * code (2-letter upper-case alphabets). There are instance methods to get the - * country name ([.getName]), the - * [ISO 3166-1 alpha-3](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) - * code ([.getAlpha3]) and the - * [ISO 3166-1 numeric](http://en.wikipedia.org/wiki/ISO_3166-1_numeric) - * code ([.getNumeric]). - * In addition, there are static methods to get a `Market` instance that - * corresponds to a given alpha-2/alpha-3/numeric code ([.getByCode], - * [.getByCode]). - * - * - *
- * // List all the country codes.
- * for (Market code : Market.values())
- * {
- * // For example, "[US] United States" is printed.
- * System.out.format("[%s] %s\n", code, code.[.getName]);
- * }
- *
- * // Get a Market instance by ISO 3166-1 code.
- * Market code = Market.[getByCode][.getByCode]("JP");
- *
- * // Print all the information. Output will be:
- * //
- * //     Country name            = Japan
- * //     ISO 3166-1 alpha-2 code = JP
- * //     ISO 3166-1 alpha-3 code = JPN
- * //     ISO 3166-1 numeric code = 392
- * //     Assignment state        = OFFICIALLY_ASSIGNED
- * //
- * System.out.println("Country name            = " + code.[.getName]);
- * System.out.println("ISO 3166-1 alpha-2 code = " + code.[.getAlpha2]);
- * System.out.println("ISO 3166-1 alpha-3 code = " + code.[.getAlpha3]);
- * System.out.println("ISO 3166-1 numeric code = " + code.[.getNumeric]);
- * System.out.println("Assignment state        = " + code.[.getAssignment]);
- *
- * // Convert to a Locale instance.
- *
- * // Get a Market by a Locale instance.
- * code = Market.[getByLocale][.getByLocale](locale);
- *
- * // Get the currency of the country.
- *
- * // Get a list by a regular expression for names.
- * //
- * // The list will contain:
- * //
- * //     Market.AE ed Arab Emirates
- * //     Market.GB ed Kingdom
- * //     Market.TZ : Tanzania, United Republic of
- * //     Market.UK ed Kingdom
- * //     Market.UM ed States Minor Outlying Islands
- * //     Market.US ed States
- * //
- * List<Market> list = Market.[findByName][.findByName](".*United.*");
- *
- * 
- * // For backward compatibility for older versions than 1.16, some
- * // 4-letter ISO 3166-3 codes are accepted by getByCode(String, boolean)
- * // and its variants. To be concrete:
- * //
- * //     [ANHH](https://en.wikipedia.org/wiki/ISO_3166-3#ANHH) : Market.AN
- * //     [BUMM](https://en.wikipedia.org/wiki/ISO_3166-3#BUMM) : Market.BU
- * //     [CSXX](https://en.wikipedia.org/wiki/ISO_3166-3#CSXX) : Market.CS
- * //     [NTHH](https://en.wikipedia.org/wiki/ISO_3166-3#NTHH) : Market.NT
- * //     [TPTL](https://en.wikipedia.org/wiki/ISO_3166-3#TPTL) : Market.TP
- * //     [YUCS](https://en.wikipedia.org/wiki/ISO_3166-3#YUCS) : Market.YU
- * //     [ZRCD](https://en.wikipedia.org/wiki/ISO_3166-3#ZRCD) : Market.ZR
- * //
- * code = Market.[getByCode][.getByCode]("ANHH");
-
* + * **Note**: Use [Market.FROM_TOKEN] if you want to use the client's locale. This should not be used with [SpotifyAppApi] * * @author Takahiko Kawasaki (https://github.com/TakahikoKawasaki/nv-i18n) */ diff --git a/src/commonTest/kotlin/com.adamratzman/spotify/pub/PublicPlaylistsApiTest.kt b/src/commonTest/kotlin/com.adamratzman/spotify/pub/PublicPlaylistsApiTest.kt index e076d82f..c5736a16 100644 --- a/src/commonTest/kotlin/com.adamratzman/spotify/pub/PublicPlaylistsApiTest.kt +++ b/src/commonTest/kotlin/com.adamratzman/spotify/pub/PublicPlaylistsApiTest.kt @@ -39,7 +39,7 @@ class PublicPlaylistsApiTest : AbstractTest() { assertEquals("run2", api!!.playlists.getPlaylist("78eWnYKwDksmCHAjOUNPEj")?.name) assertNull(api!!.playlists.getPlaylist("nope")) assertTrue(api!!.playlists.getPlaylist("78eWnYKwDksmCHAjOUNPEj")!!.tracks.isNotEmpty()) - val playlistWithLocalAndNonLocalTracks = api!!.playlists.getPlaylist("0vzdw0N41qZLbRDqyx2cE0")!!.tracks + val playlistWithLocalAndNonLocalTracks = api!!.playlists.getPlaylist("627gNjNzj3sOrSiDm5acc2")!!.tracks assertEquals(LocalTrack::class, playlistWithLocalAndNonLocalTracks[0].track!!::class) assertEquals(Track::class, playlistWithLocalAndNonLocalTracks[1].track!!::class) @@ -57,7 +57,7 @@ class PublicPlaylistsApiTest : AbstractTest() { if (!testPrereq()) return@runBlockingTest else api!! assertTrue(api!!.playlists.getPlaylistTracks("78eWnYKwDksmCHAjOUNPEj").items.isNotEmpty()) - val playlist = api!!.playlists.getPlaylistTracks("0vzdw0N41qZLbRDqyx2cE0") + val playlist = api!!.playlists.getPlaylistTracks("627gNjNzj3sOrSiDm5acc2") assertEquals(LocalTrack::class, playlist[0].track!!::class) assertEquals(Track::class, playlist[1].track!!::class) assertFailsWith { api!!.playlists.getPlaylistTracks("adskjfjkasdf") } diff --git a/src/commonTest/kotlin/com.adamratzman/spotify/pub/SearchApiTest.kt b/src/commonTest/kotlin/com.adamratzman/spotify/pub/SearchApiTest.kt index beb871d5..7510a789 100644 --- a/src/commonTest/kotlin/com.adamratzman/spotify/pub/SearchApiTest.kt +++ b/src/commonTest/kotlin/com.adamratzman/spotify/pub/SearchApiTest.kt @@ -18,7 +18,7 @@ class SearchApiTest : AbstractTest() { return runBlockingTest { super.build() if (!testPrereq()) return@runBlockingTest else api!! - val query = api!!.search.search("lo", *SearchApi.SearchType.values()) + val query = api!!.search.search("lo", *SearchApi.SearchType.values(), market = Market.US) assertTrue( query.albums?.items?.isNotEmpty() == true && query.tracks?.items?.isNotEmpty() == true && query.artists?.items?.isNotEmpty() == true && query.playlists?.items?.isNotEmpty() == true && query.shows?.items?.isNotEmpty() == true && query.episodes?.items?.isNotEmpty() == true @@ -28,7 +28,7 @@ class SearchApiTest : AbstractTest() { query2.albums == null && query2.tracks == null && query2.shows == null && query2.episodes == null && query2.artists?.items?.isNotEmpty() == true && query2.playlists?.items?.isNotEmpty() == true ) - val query3 = api!!.search.search("lo", SearchApi.SearchType.SHOW, SearchApi.SearchType.EPISODE) + val query3 = api!!.search.search("lo", SearchApi.SearchType.SHOW, SearchApi.SearchType.EPISODE, market = Market.US) assertTrue(query3.episodes?.items?.isNotEmpty() == true && query3.shows?.items?.isNotEmpty() == true) } } diff --git a/src/commonTest/kotlin/com.adamratzman/spotify/utilities/UtilityTests.kt b/src/commonTest/kotlin/com.adamratzman/spotify/utilities/UtilityTests.kt index b252f634..84d0a4dd 100644 --- a/src/commonTest/kotlin/com.adamratzman/spotify/utilities/UtilityTests.kt +++ b/src/commonTest/kotlin/com.adamratzman/spotify/utilities/UtilityTests.kt @@ -32,7 +32,7 @@ class UtilityTests { if (!testPrereq()) return runBlockingTest { - val spotifyWfhPlaylist = api!!.playlists.getPlaylist("spotify:playlist:37i9dQZF1DWTLSN7iG21yC")!! + val spotifyWfhPlaylist = api!!.playlists.getPlaylist("37i9dQZF1DWTLSN7iG21yC")!! val totalTracks = spotifyWfhPlaylist.tracks.total val allTracks = spotifyWfhPlaylist.tracks.getAllItemsNotNull() assertEquals(totalTracks, allTracks.size)