Switched from Gradle to bld
This commit is contained in:
parent
4c031d7a61
commit
f613b8cdfc
58 changed files with 2344 additions and 760 deletions
318
bin/main/net/thauvin/erik/jokeapi/JokeApi.kt
Normal file
318
bin/main/net/thauvin/erik/jokeapi/JokeApi.kt
Normal file
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* JokeApi.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi
|
||||
|
||||
import net.thauvin.erik.jokeapi.exceptions.HttpErrorException
|
||||
import net.thauvin.erik.jokeapi.exceptions.JokeException
|
||||
import net.thauvin.erik.jokeapi.models.*
|
||||
import net.thauvin.erik.urlencoder.UrlEncoderUtil
|
||||
import org.json.JSONObject
|
||||
import java.util.logging.Logger
|
||||
import java.util.stream.Collectors
|
||||
|
||||
/**
|
||||
* Implements the [Sv443's JokeAPI](https://jokeapi.dev/).
|
||||
*/
|
||||
object JokeApi {
|
||||
private const val API_URL = "https://v2.jokeapi.dev/"
|
||||
|
||||
@JvmStatic
|
||||
val logger: Logger by lazy { Logger.getLogger(JokeApi::class.java.simpleName) }
|
||||
|
||||
/**
|
||||
* Makes a direct API call.
|
||||
*
|
||||
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#endpoints) for more details.
|
||||
*/
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@Throws(HttpErrorException::class)
|
||||
fun apiCall(
|
||||
endPoint: String,
|
||||
path: String = "",
|
||||
params: Map<String, String> = emptyMap(),
|
||||
auth: String = ""
|
||||
): String {
|
||||
val urlBuilder = StringBuilder("$API_URL$endPoint")
|
||||
|
||||
if (path.isNotEmpty()) {
|
||||
if (!urlBuilder.endsWith(('/'))) {
|
||||
urlBuilder.append('/')
|
||||
}
|
||||
urlBuilder.append(path)
|
||||
}
|
||||
|
||||
if (params.isNotEmpty()) {
|
||||
urlBuilder.append('?')
|
||||
val it = params.iterator()
|
||||
while (it.hasNext()) {
|
||||
val param = it.next()
|
||||
urlBuilder.append(param.key)
|
||||
if (param.value.isNotEmpty()) {
|
||||
urlBuilder.append("=").append(UrlEncoderUtil.encode(param.value))
|
||||
}
|
||||
if (it.hasNext()) {
|
||||
urlBuilder.append("&")
|
||||
}
|
||||
}
|
||||
}
|
||||
return fetchUrl(urlBuilder.toString(), auth)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns one or more jokes using a [configuration][JokeConfig].
|
||||
*
|
||||
* See the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details.
|
||||
*/
|
||||
@JvmStatic
|
||||
@Throws(HttpErrorException::class)
|
||||
fun getRawJokes(config: JokeConfig): String {
|
||||
return rawJokes(
|
||||
categories = config.categories,
|
||||
lang = config.language,
|
||||
blacklistFlags = config.flags,
|
||||
type = config.type,
|
||||
format = config.format,
|
||||
contains = config.contains,
|
||||
idRange = config.idRange,
|
||||
amount = config.amount,
|
||||
safe = config.safe,
|
||||
auth = config.auth
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a [Joke] instance using a [configuration][JokeConfig].
|
||||
*
|
||||
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details.
|
||||
*/
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@Throws(HttpErrorException::class, JokeException::class)
|
||||
fun joke(config: JokeConfig = JokeConfig.Builder().build()): Joke {
|
||||
return joke(
|
||||
categories = config.categories,
|
||||
lang = config.language,
|
||||
blacklistFlags = config.flags,
|
||||
type = config.type,
|
||||
contains = config.contains,
|
||||
idRange = config.idRange,
|
||||
safe = config.safe,
|
||||
auth = config.auth,
|
||||
splitNewLine = config.splitNewLine
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of [Joke] instances using a [configuration][JokeConfig].
|
||||
*
|
||||
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details.
|
||||
*/
|
||||
@JvmStatic
|
||||
@Throws(HttpErrorException::class, JokeException::class)
|
||||
fun jokes(config: JokeConfig): Array<Joke> {
|
||||
return jokes(
|
||||
categories = config.categories,
|
||||
lang = config.language,
|
||||
blacklistFlags = config.flags,
|
||||
type = config.type,
|
||||
contains = config.contains,
|
||||
idRange = config.idRange,
|
||||
amount = config.amount,
|
||||
safe = config.safe,
|
||||
auth = config.auth,
|
||||
splitNewLine = config.splitNewLine
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a [Joke] instance.
|
||||
*
|
||||
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details.
|
||||
*
|
||||
* @param splitNewLine Split newline within [Type.SINGLE] joke.
|
||||
*/
|
||||
fun joke(
|
||||
categories: Set<Category> = setOf(Category.ANY),
|
||||
lang: Language = Language.EN,
|
||||
blacklistFlags: Set<Flag> = emptySet(),
|
||||
type: Type = Type.ALL,
|
||||
contains: String = "",
|
||||
idRange: IdRange = IdRange(),
|
||||
safe: Boolean = false,
|
||||
auth: String = "",
|
||||
splitNewLine: Boolean = false
|
||||
): Joke {
|
||||
val json = JSONObject(
|
||||
rawJokes(
|
||||
categories = categories,
|
||||
lang = lang,
|
||||
blacklistFlags = blacklistFlags,
|
||||
type = type,
|
||||
contains = contains,
|
||||
idRange = idRange,
|
||||
safe = safe,
|
||||
auth = auth
|
||||
)
|
||||
)
|
||||
if (json.getBoolean("error")) {
|
||||
throw parseError(json)
|
||||
} else {
|
||||
return parseJoke(json, splitNewLine)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of [Joke] instances.
|
||||
*
|
||||
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details.
|
||||
*
|
||||
* @param amount The required amount of jokes to return.
|
||||
* @param splitNewLine Split newline within [Type.SINGLE] joke.
|
||||
*/
|
||||
fun jokes(
|
||||
amount: Int,
|
||||
categories: Set<Category> = setOf(Category.ANY),
|
||||
lang: Language = Language.EN,
|
||||
blacklistFlags: Set<Flag> = emptySet(),
|
||||
type: Type = Type.ALL,
|
||||
contains: String = "",
|
||||
idRange: IdRange = IdRange(),
|
||||
safe: Boolean = false,
|
||||
auth: String = "",
|
||||
splitNewLine: Boolean = false
|
||||
): Array<Joke> {
|
||||
val json = JSONObject(
|
||||
rawJokes(
|
||||
categories = categories,
|
||||
lang = lang,
|
||||
blacklistFlags = blacklistFlags,
|
||||
type = type,
|
||||
contains = contains,
|
||||
idRange = idRange,
|
||||
amount = amount,
|
||||
safe = safe,
|
||||
auth = auth
|
||||
)
|
||||
)
|
||||
if (json.getBoolean("error")) {
|
||||
throw parseError(json)
|
||||
} else {
|
||||
return if (json.has("amount")) {
|
||||
val jokes = json.getJSONArray("jokes")
|
||||
Array(jokes.length()) { i -> parseJoke(jokes.getJSONObject(i), splitNewLine) }
|
||||
} else {
|
||||
arrayOf(parseJoke(json, splitNewLine))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns one or more jokes.
|
||||
*
|
||||
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details.
|
||||
*/
|
||||
fun rawJokes(
|
||||
categories: Set<Category> = setOf(Category.ANY),
|
||||
lang: Language = Language.EN,
|
||||
blacklistFlags: Set<Flag> = emptySet(),
|
||||
type: Type = Type.ALL,
|
||||
format: Format = Format.JSON,
|
||||
contains: String = "",
|
||||
idRange: IdRange = IdRange(),
|
||||
amount: Int = 1,
|
||||
safe: Boolean = false,
|
||||
auth: String = ""
|
||||
): String {
|
||||
val params = mutableMapOf<String, String>()
|
||||
|
||||
// Categories
|
||||
val path = if (categories.isEmpty() || categories.contains(Category.ANY)) {
|
||||
Category.ANY.value
|
||||
} else {
|
||||
categories.stream().map(Category::value).collect(Collectors.joining(","))
|
||||
}
|
||||
|
||||
// Language
|
||||
if (lang != Language.EN) {
|
||||
params[Parameter.LANG] = lang.value
|
||||
}
|
||||
|
||||
// Flags
|
||||
if (blacklistFlags.isNotEmpty()) {
|
||||
if (blacklistFlags.contains(Flag.ALL)) {
|
||||
params[Parameter.FLAGS] = Flag.ALL.value
|
||||
} else {
|
||||
params[Parameter.FLAGS] = blacklistFlags.stream().map(Flag::value).collect(Collectors.joining(","))
|
||||
}
|
||||
}
|
||||
|
||||
// Type
|
||||
if (type != Type.ALL) {
|
||||
params[Parameter.TYPE] = type.value
|
||||
}
|
||||
|
||||
// Format
|
||||
if (format != Format.JSON) {
|
||||
params[Parameter.FORMAT] = format.value
|
||||
}
|
||||
|
||||
// Contains
|
||||
if (contains.isNotBlank()) {
|
||||
params[Parameter.CONTAINS] = contains
|
||||
}
|
||||
|
||||
// Range
|
||||
if (idRange.start >= 0) {
|
||||
if (idRange.end == -1 || idRange.start == idRange.end) {
|
||||
params[Parameter.RANGE] = idRange.start.toString()
|
||||
} else {
|
||||
require(idRange.end > idRange.start) { "Invalid ID Range: ${idRange.start}, ${idRange.end}" }
|
||||
params[Parameter.RANGE] = "${idRange.start}-${idRange.end}"
|
||||
}
|
||||
}
|
||||
|
||||
// Amount
|
||||
require(amount > 0) { "Invalid Amount: $amount" }
|
||||
if (amount > 1) {
|
||||
params[Parameter.AMOUNT] = amount.toString()
|
||||
}
|
||||
|
||||
// Safe
|
||||
if (safe) {
|
||||
params[Parameter.SAFE] = ""
|
||||
}
|
||||
|
||||
return JokeApi.apiCall("joke", path, params, auth)
|
||||
}
|
96
bin/main/net/thauvin/erik/jokeapi/JokeConfig.kt
Normal file
96
bin/main/net/thauvin/erik/jokeapi/JokeConfig.kt
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* JokeConfig.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi
|
||||
|
||||
import net.thauvin.erik.jokeapi.JokeConfig.Builder
|
||||
import net.thauvin.erik.jokeapi.models.Category
|
||||
import net.thauvin.erik.jokeapi.models.Flag
|
||||
import net.thauvin.erik.jokeapi.models.Format
|
||||
import net.thauvin.erik.jokeapi.models.IdRange
|
||||
import net.thauvin.erik.jokeapi.models.Language
|
||||
import net.thauvin.erik.jokeapi.models.Type
|
||||
|
||||
/**
|
||||
* Joke Configuration.
|
||||
*
|
||||
* Use the [Builder] to create a new configuration.
|
||||
*/
|
||||
class JokeConfig private constructor(
|
||||
val categories: Set<Category>,
|
||||
val language: Language,
|
||||
val flags: Set<Flag>,
|
||||
val type: Type,
|
||||
val format: Format,
|
||||
val contains: String,
|
||||
val idRange: IdRange,
|
||||
val amount: Int,
|
||||
val safe: Boolean,
|
||||
val splitNewLine: Boolean,
|
||||
val auth: String
|
||||
) {
|
||||
/**
|
||||
* [Builds][build] a new configuration.
|
||||
*
|
||||
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details.
|
||||
*
|
||||
* @param splitNewLine Split newline within [Type.SINGLE] joke.
|
||||
*/
|
||||
data class Builder(
|
||||
var categories: Set<Category> = setOf(Category.ANY),
|
||||
var lang: Language = Language.EN,
|
||||
var blacklistFlags: Set<Flag> = emptySet(),
|
||||
var type: Type = Type.ALL,
|
||||
var format: Format = Format.JSON,
|
||||
var contains: String = "",
|
||||
var idRange: IdRange = IdRange(),
|
||||
var amount: Int = 1,
|
||||
var safe: Boolean = false,
|
||||
var splitNewLine: Boolean = false,
|
||||
var auth: String = ""
|
||||
) {
|
||||
fun categories(categories: Set<Category>) = apply { this.categories = categories }
|
||||
fun lang(language: Language) = apply { lang = language }
|
||||
fun blacklistFlags(flags: Set<Flag>) = apply { blacklistFlags = flags }
|
||||
fun type(type: Type) = apply { this.type = type }
|
||||
fun format(format: Format) = apply { this.format = format }
|
||||
fun contains(search: String) = apply { contains = search }
|
||||
fun idRange(idRange: IdRange) = apply { this.idRange = idRange }
|
||||
fun amount(amount: Int) = apply { this.amount = amount }
|
||||
fun safe(safe: Boolean) = apply { this.safe = safe }
|
||||
fun splitNewLine(splitNewLine: Boolean) = apply { this.splitNewLine = splitNewLine }
|
||||
fun auth(auth: String) = apply { this.auth = auth }
|
||||
|
||||
fun build() = JokeConfig(
|
||||
categories, lang, blacklistFlags, type, format, contains, idRange, amount, safe, splitNewLine, auth
|
||||
)
|
||||
}
|
||||
}
|
173
bin/main/net/thauvin/erik/jokeapi/JokeUtil.kt
Normal file
173
bin/main/net/thauvin/erik/jokeapi/JokeUtil.kt
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* JokeUtil.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@file:JvmName("JokeUtil")
|
||||
|
||||
package net.thauvin.erik.jokeapi
|
||||
|
||||
import net.thauvin.erik.jokeapi.exceptions.HttpErrorException
|
||||
import net.thauvin.erik.jokeapi.exceptions.JokeException
|
||||
import net.thauvin.erik.jokeapi.models.Category
|
||||
import net.thauvin.erik.jokeapi.models.Flag
|
||||
import net.thauvin.erik.jokeapi.models.Joke
|
||||
import net.thauvin.erik.jokeapi.models.Language
|
||||
import net.thauvin.erik.jokeapi.models.Parameter
|
||||
import net.thauvin.erik.jokeapi.models.Type
|
||||
import org.json.JSONObject
|
||||
import java.io.IOException
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.util.logging.Level
|
||||
|
||||
internal fun fetchUrl(url: String, auth: String = ""): String {
|
||||
if (JokeApi.logger.isLoggable(Level.FINE)) {
|
||||
JokeApi.logger.fine(url)
|
||||
}
|
||||
|
||||
val connection = URL(url).openConnection() as HttpURLConnection
|
||||
connection.setRequestProperty(
|
||||
"User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0"
|
||||
)
|
||||
if (auth.isNotEmpty()) {
|
||||
connection.setRequestProperty("Authentication", auth)
|
||||
}
|
||||
|
||||
if (connection.responseCode in 200..399) {
|
||||
val body = connection.inputStream.bufferedReader().use { it.readText() }
|
||||
if (JokeApi.logger.isLoggable(Level.FINE)) {
|
||||
JokeApi.logger.fine(body)
|
||||
}
|
||||
return body
|
||||
} else {
|
||||
throw httpError(connection.responseCode)
|
||||
}
|
||||
}
|
||||
|
||||
private fun httpError(responseCode: Int): HttpErrorException {
|
||||
val httpException: HttpErrorException
|
||||
when (responseCode) {
|
||||
400 -> httpException = HttpErrorException(
|
||||
responseCode, "Bad Request", IOException(
|
||||
"The request you have sent to JokeAPI is formatted incorrectly and cannot be processed."
|
||||
)
|
||||
)
|
||||
|
||||
403 -> httpException = HttpErrorException(
|
||||
responseCode, "Forbidden", IOException(
|
||||
"You have been added to the blacklist due to malicious behavior and are not allowed"
|
||||
+ " to send requests to JokeAPI anymore."
|
||||
)
|
||||
)
|
||||
|
||||
404 -> httpException = HttpErrorException(
|
||||
responseCode, "Not Found", IOException("The URL you have requested couldn't be found.")
|
||||
)
|
||||
|
||||
413 -> httpException = HttpErrorException(
|
||||
responseCode, "URI Too Long", IOException("The URL exceeds the maximum length of 250 characters.")
|
||||
)
|
||||
|
||||
414 -> httpException = HttpErrorException(
|
||||
responseCode,
|
||||
"Payload Too Large",
|
||||
IOException("The payload data sent to the server exceeds the maximum size of 5120 bytes.")
|
||||
)
|
||||
|
||||
429 -> httpException = HttpErrorException(
|
||||
responseCode, "Too Many Requests", IOException(
|
||||
"You have exceeded the limit of 120 requests per minute and have to wait a bit"
|
||||
+ " until you are allowed to send requests again."
|
||||
)
|
||||
)
|
||||
|
||||
500 -> httpException = HttpErrorException(
|
||||
responseCode, "Internal Server Error", IOException(
|
||||
"There was a general internal error within JokeAPI. You can get more info from"
|
||||
+ " the properties in the response text."
|
||||
)
|
||||
)
|
||||
|
||||
523 -> httpException = HttpErrorException(
|
||||
responseCode, "Origin Unreachable", IOException(
|
||||
"The server is temporarily offline due to maintenance or a dynamic IP update."
|
||||
+ " Please be patient in this case."
|
||||
)
|
||||
)
|
||||
|
||||
else -> httpException = HttpErrorException(responseCode, "Unknown HTTP Error")
|
||||
}
|
||||
|
||||
return httpException
|
||||
}
|
||||
|
||||
internal fun parseError(json: JSONObject): JokeException {
|
||||
val causedBy = json.getJSONArray("causedBy")
|
||||
val causes = List<String>(causedBy.length()) { i -> causedBy.getString(i) }
|
||||
return JokeException(
|
||||
internalError = json.getBoolean("internalError"),
|
||||
code = json.getInt("code"),
|
||||
message = json.getString("message"),
|
||||
causedBy = causes,
|
||||
additionalInfo = json.getString("additionalInfo"),
|
||||
timestamp = json.getLong("timestamp")
|
||||
)
|
||||
}
|
||||
|
||||
internal fun parseJoke(json: JSONObject, splitNewLine: Boolean): Joke {
|
||||
val jokes = mutableListOf<String>()
|
||||
if (json.has("setup")) {
|
||||
jokes.add(json.getString("setup"))
|
||||
jokes.add(json.getString(("delivery")))
|
||||
} else {
|
||||
if (splitNewLine) {
|
||||
jokes.addAll(json.getString("joke").split("\n"))
|
||||
} else {
|
||||
jokes.add(json.getString("joke"))
|
||||
}
|
||||
}
|
||||
val enabledFlags = mutableSetOf<Flag>()
|
||||
val jsonFlags = json.getJSONObject("flags")
|
||||
Flag.values().filter { it != Flag.ALL }.forEach {
|
||||
if (jsonFlags.has(it.value) && jsonFlags.getBoolean(it.value)) {
|
||||
enabledFlags.add(it)
|
||||
}
|
||||
}
|
||||
return Joke(
|
||||
category = Category.valueOf(json.getString("category").uppercase()),
|
||||
type = Type.valueOf(json.getString(Parameter.TYPE).uppercase()),
|
||||
joke = jokes,
|
||||
flags = enabledFlags,
|
||||
safe = json.getBoolean("safe"),
|
||||
id = json.getInt("id"),
|
||||
lang = Language.valueOf(json.getString(Parameter.LANG).uppercase())
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* HttpErrorException.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi.exceptions
|
||||
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
* Signals that a server error has occurred.
|
||||
*
|
||||
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#status-codes) for more details.
|
||||
*/
|
||||
class HttpErrorException @JvmOverloads constructor(
|
||||
val statusCode: Int,
|
||||
message: String,
|
||||
cause: Throwable? = null
|
||||
) : IOException(message, cause) {
|
||||
companion object {
|
||||
private const val serialVersionUID = 1L
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* JokeException.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi.exceptions
|
||||
|
||||
/**
|
||||
* Signals that an error has occurred.
|
||||
*
|
||||
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#errors) for more details.
|
||||
*/
|
||||
class JokeException @JvmOverloads constructor(
|
||||
val internalError: Boolean,
|
||||
val code: Int,
|
||||
message: String,
|
||||
val causedBy: List<String>,
|
||||
val additionalInfo: String,
|
||||
val timestamp: Long,
|
||||
cause: Throwable? = null
|
||||
) : RuntimeException(message, cause) {
|
||||
companion object {
|
||||
private const val serialVersionUID = 1L
|
||||
}
|
||||
|
||||
fun debug(): String {
|
||||
return "JokeException(message=$message, internalError=$internalError, code=$code," +
|
||||
" causedBy=$causedBy, additionalInfo='$additionalInfo', timestamp=$timestamp)"
|
||||
}
|
||||
}
|
45
bin/main/net/thauvin/erik/jokeapi/models/Category.kt
Normal file
45
bin/main/net/thauvin/erik/jokeapi/models/Category.kt
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Category.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi.models
|
||||
|
||||
/**
|
||||
* The supported [categories](https://jokeapi.dev/#categories), use [ANY] for all.
|
||||
*/
|
||||
enum class Category(val value: String) {
|
||||
ANY("Any"),
|
||||
CHRISTMAS("Christmas"),
|
||||
DARK("Dark"),
|
||||
MISC("Misc"),
|
||||
PROGRAMMING("Programming"),
|
||||
PUN("Pun"),
|
||||
SPOOKY("Spooky")
|
||||
}
|
45
bin/main/net/thauvin/erik/jokeapi/models/Flag.kt
Normal file
45
bin/main/net/thauvin/erik/jokeapi/models/Flag.kt
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Flag.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi.models
|
||||
|
||||
/**
|
||||
* The supported [blacklist flags](https://jokeapi.dev/#flags-param), use [ALL] to prevent all.
|
||||
*/
|
||||
enum class Flag(val value: String) {
|
||||
EXPLICIT("explicit"),
|
||||
NSFW("nsfw"),
|
||||
POLITICAL("political"),
|
||||
RACIST("racist"),
|
||||
RELIGIOUS("religious"),
|
||||
SEXIST("sexist"),
|
||||
ALL("${NSFW.value},${RELIGIOUS.value},${POLITICAL.value},${RACIST.value},${SEXIST.value},${EXPLICIT.value}")
|
||||
}
|
44
bin/main/net/thauvin/erik/jokeapi/models/Format.kt
Normal file
44
bin/main/net/thauvin/erik/jokeapi/models/Format.kt
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Format.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi.models
|
||||
|
||||
/**
|
||||
* The supported response [formats](https://jokeapi.dev/#format-param).
|
||||
*/
|
||||
enum class Format(val value: String) {
|
||||
JSON("json"),
|
||||
|
||||
/** Plain Text */
|
||||
TXT("txt"),
|
||||
XML("xml"),
|
||||
YAML("yaml")
|
||||
}
|
37
bin/main/net/thauvin/erik/jokeapi/models/IdRange.kt
Normal file
37
bin/main/net/thauvin/erik/jokeapi/models/IdRange.kt
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* IdRange.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi.models
|
||||
|
||||
/**
|
||||
* Specifies a joke [ID or range of IDs](https://jokeapi.dev/#idrange-param).
|
||||
*/
|
||||
data class IdRange(val start: Int = -1, val end: Int = -1)
|
45
bin/main/net/thauvin/erik/jokeapi/models/Joke.kt
Normal file
45
bin/main/net/thauvin/erik/jokeapi/models/Joke.kt
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Joke.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi.models
|
||||
|
||||
/**
|
||||
* Stores a joke's data.
|
||||
*/
|
||||
data class Joke(
|
||||
val category: Category,
|
||||
val type: Type,
|
||||
val joke: List<String>,
|
||||
val flags: Set<Flag>,
|
||||
val id: Int,
|
||||
val safe: Boolean,
|
||||
val lang: Language
|
||||
)
|
55
bin/main/net/thauvin/erik/jokeapi/models/Language.kt
Normal file
55
bin/main/net/thauvin/erik/jokeapi/models/Language.kt
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Language.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi.models
|
||||
|
||||
/**
|
||||
* The supported [languages](https://jokeapi.dev/#lang).
|
||||
*/
|
||||
enum class Language(val value: String) {
|
||||
/** Czech */
|
||||
CS("cs"),
|
||||
|
||||
/** German */
|
||||
DE("de"),
|
||||
|
||||
/** English */
|
||||
EN("en"),
|
||||
|
||||
/** Spanish */
|
||||
ES("es"),
|
||||
|
||||
/** French */
|
||||
FR("fr"),
|
||||
|
||||
/** Portuguese */
|
||||
PT("pt")
|
||||
}
|
51
bin/main/net/thauvin/erik/jokeapi/models/Parameter.kt
Normal file
51
bin/main/net/thauvin/erik/jokeapi/models/Parameter.kt
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Parameter.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi.models
|
||||
|
||||
/**
|
||||
* The available [URL Parameters](https://jokeapi.dev/#url-parameters).
|
||||
*/
|
||||
object Parameter {
|
||||
const val AMOUNT = "amount"
|
||||
const val CONTAINS = "contains"
|
||||
const val FLAGS = "blacklistFlags"
|
||||
const val FORMAT = "format"
|
||||
const val RANGE = "idRange"
|
||||
const val LANG = "lang"
|
||||
const val SAFE = "safe-mode"
|
||||
const val TYPE = "type"
|
||||
|
||||
const val BLACKLIST_FLAGS = FLAGS
|
||||
const val ID_RANGE = RANGE
|
||||
const val SAFE_MODE = SAFE
|
||||
const val SEARCH = CONTAINS
|
||||
}
|
41
bin/main/net/thauvin/erik/jokeapi/models/Type.kt
Normal file
41
bin/main/net/thauvin/erik/jokeapi/models/Type.kt
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Type.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi.models
|
||||
|
||||
/**
|
||||
* The supported [types](https://jokeapi.dev/#type-param), use [ALL] for all.
|
||||
*/
|
||||
enum class Type(val value: String) {
|
||||
SINGLE("single"),
|
||||
TWOPART("twopart"),
|
||||
ALL("${SINGLE.value},${TWOPART.value}")
|
||||
}
|
87
bin/test/net/thauvin/erik/jokeapi/ApiCallTest.kt
Normal file
87
bin/test/net/thauvin/erik/jokeapi/ApiCallTest.kt
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* ApiCallTest.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi
|
||||
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isGreaterThan
|
||||
import assertk.assertions.startsWith
|
||||
import net.thauvin.erik.jokeapi.JokeApi.apiCall
|
||||
import net.thauvin.erik.jokeapi.models.Format
|
||||
import net.thauvin.erik.jokeapi.models.Language
|
||||
import net.thauvin.erik.jokeapi.models.Parameter
|
||||
import org.json.JSONObject
|
||||
import org.junit.jupiter.api.Assertions.assertFalse
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertAll
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import kotlin.test.assertContains
|
||||
|
||||
@ExtendWith(BeforeAllTests::class)
|
||||
internal class ApiCallTest {
|
||||
@Test
|
||||
fun `Get Flags`() {
|
||||
// See https://v2.jokeapi.dev/#flags-endpoint
|
||||
val response = apiCall(endPoint = "flags")
|
||||
val json = JSONObject(response)
|
||||
assertAll("Validate JSON",
|
||||
{ assertFalse(json.getBoolean("error"), "apiCall(flags).error") },
|
||||
{ assertThat(json.getJSONArray("flags").length(), "apiCall(flags).flags").isGreaterThan(0) },
|
||||
{ assertThat(json.getLong("timestamp"), "apiCall(flags).timestamp").isGreaterThan(0) })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Language Code`() {
|
||||
// See https://v2.jokeapi.dev/#langcode-endpoint
|
||||
val lang = apiCall(
|
||||
endPoint = "langcode", path = "french",
|
||||
params = mapOf(Parameter.FORMAT to Format.YAML.value)
|
||||
)
|
||||
assertContains(lang, "code: \"fr\"", false, "apiCall(langcode, french, yaml)")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Ping Response`() {
|
||||
// See https://v2.jokeapi.dev/#ping-endpoint
|
||||
val ping = apiCall(endPoint = "ping", params = mapOf(Parameter.FORMAT to Format.TXT.value))
|
||||
assertThat(ping, "apiCall(ping, txt)").startsWith("Pong!")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Supported Language`() {
|
||||
// See https://v2.jokeapi.dev/languages
|
||||
val lang = apiCall(
|
||||
endPoint = "languages",
|
||||
params = mapOf(Parameter.FORMAT to Format.XML.value, Parameter.LANG to Language.FR.value)
|
||||
)
|
||||
assertThat(lang).startsWith("<?xml version='1.0'?>")
|
||||
}
|
||||
}
|
47
bin/test/net/thauvin/erik/jokeapi/BeforeAllTests.kt
Normal file
47
bin/test/net/thauvin/erik/jokeapi/BeforeAllTests.kt
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* BeforeAllTests.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi
|
||||
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback
|
||||
import org.junit.jupiter.api.extension.ExtensionContext
|
||||
import java.util.logging.ConsoleHandler
|
||||
import java.util.logging.Level
|
||||
|
||||
class BeforeAllTests : BeforeAllCallback {
|
||||
override fun beforeAll(context: ExtensionContext?) {
|
||||
with(JokeApi.logger) {
|
||||
addHandler(ConsoleHandler().apply { level = Level.FINE })
|
||||
level = Level.FINE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
90
bin/test/net/thauvin/erik/jokeapi/ExceptionsTest.kt
Normal file
90
bin/test/net/thauvin/erik/jokeapi/ExceptionsTest.kt
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* ExceptionsTest.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi
|
||||
|
||||
import assertk.all
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.index
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isFalse
|
||||
import assertk.assertions.isGreaterThan
|
||||
import assertk.assertions.isNotEmpty
|
||||
import assertk.assertions.isNotNull
|
||||
import assertk.assertions.isNull
|
||||
import assertk.assertions.prop
|
||||
import assertk.assertions.size
|
||||
import assertk.assertions.startsWith
|
||||
import net.thauvin.erik.jokeapi.JokeApi.logger
|
||||
import net.thauvin.erik.jokeapi.exceptions.HttpErrorException
|
||||
import net.thauvin.erik.jokeapi.exceptions.JokeException
|
||||
import net.thauvin.erik.jokeapi.models.Category
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.ValueSource
|
||||
|
||||
@ExtendWith(BeforeAllTests::class)
|
||||
internal class ExceptionsTest {
|
||||
@Test
|
||||
fun `Validate Joke Exception`() {
|
||||
val e = assertThrows<JokeException> {
|
||||
joke(categories = setOf(Category.CHRISTMAS), contains = "foo")
|
||||
}
|
||||
logger.fine(e.debug())
|
||||
assertThat(e, "joke(${Category.CHRISTMAS},foo)").all {
|
||||
prop(JokeException::code).isEqualTo(106)
|
||||
prop(JokeException::internalError).isFalse()
|
||||
prop(JokeException::message).isEqualTo("No matching joke found")
|
||||
prop(JokeException::causedBy).size().isEqualTo(1)
|
||||
prop(JokeException::causedBy).index(0).startsWith("No jokes")
|
||||
prop(JokeException::additionalInfo).isNotEmpty()
|
||||
prop(JokeException::timestamp).isGreaterThan(0)
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = [400, 404, 403, 413, 414, 429, 500, 523, 666])
|
||||
fun `Validate HTTP Exceptions`(code: Int) {
|
||||
val e = assertThrows<HttpErrorException> {
|
||||
fetchUrl("https://httpstat.us/$code")
|
||||
}
|
||||
assertThat(e, "fetchUrl($code)").all {
|
||||
prop(HttpErrorException::statusCode).isEqualTo(code)
|
||||
prop(HttpErrorException::message).isNotNull().isNotEmpty()
|
||||
if (code < 600)
|
||||
prop(HttpErrorException::cause).isNotNull().assertThat(Throwable::message).isNotNull()
|
||||
else
|
||||
prop(HttpErrorException::cause).isNull()
|
||||
}
|
||||
}
|
||||
}
|
211
bin/test/net/thauvin/erik/jokeapi/GetJokeTest.kt
Normal file
211
bin/test/net/thauvin/erik/jokeapi/GetJokeTest.kt
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* GetJokeTest.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi
|
||||
|
||||
import assertk.all
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.any
|
||||
import assertk.assertions.contains
|
||||
import assertk.assertions.containsNone
|
||||
import assertk.assertions.each
|
||||
import assertk.assertions.isBetween
|
||||
import assertk.assertions.isEmpty
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isGreaterThan
|
||||
import assertk.assertions.isGreaterThanOrEqualTo
|
||||
import assertk.assertions.isIn
|
||||
import assertk.assertions.isNotEmpty
|
||||
import assertk.assertions.isNotNull
|
||||
import assertk.assertions.isTrue
|
||||
import assertk.assertions.prop
|
||||
import assertk.assertions.size
|
||||
import net.thauvin.erik.jokeapi.JokeApi.logger
|
||||
import net.thauvin.erik.jokeapi.exceptions.JokeException
|
||||
import net.thauvin.erik.jokeapi.models.Category
|
||||
import net.thauvin.erik.jokeapi.models.Flag
|
||||
import net.thauvin.erik.jokeapi.models.IdRange
|
||||
import net.thauvin.erik.jokeapi.models.Joke
|
||||
import net.thauvin.erik.jokeapi.models.Language
|
||||
import net.thauvin.erik.jokeapi.models.Type
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
|
||||
@ExtendWith(BeforeAllTests::class)
|
||||
internal class GetJokeTest {
|
||||
@Test
|
||||
fun `Get Joke`() {
|
||||
val joke = joke()
|
||||
logger.fine(joke.toString())
|
||||
assertThat(joke, "joke()").all {
|
||||
prop(Joke::joke).isNotEmpty()
|
||||
prop(Joke::type).isIn(Type.SINGLE, Type.TWOPART)
|
||||
prop(Joke::id).isGreaterThanOrEqualTo(0)
|
||||
prop(Joke::lang).isEqualTo(Language.EN)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Joke without Blacklist Flags`() {
|
||||
val joke = joke(blacklistFlags = setOf(Flag.ALL))
|
||||
assertThat(joke::flags).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Joke without any Blacklist Flags`() {
|
||||
val allFlags = Flag.values().filter { it != Flag.ALL }.toSet()
|
||||
val joke = joke(blacklistFlags = allFlags)
|
||||
assertThat(joke::flags).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Joke with ID`() {
|
||||
val id = 172
|
||||
val joke = joke(idRange = IdRange(id))
|
||||
logger.fine(joke.toString())
|
||||
assertThat(joke, "joke($id)").all {
|
||||
prop(Joke::flags).all {
|
||||
contains(Flag.EXPLICIT)
|
||||
contains(Flag.NSFW)
|
||||
}
|
||||
prop(Joke::id).isEqualTo(172)
|
||||
prop(Joke::category).isEqualTo(Category.PUN)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Joke with ID Range`() {
|
||||
val idRange = IdRange(1, 100)
|
||||
val joke = joke(idRange = idRange)
|
||||
logger.fine(joke.toString())
|
||||
assertThat(joke::id).isBetween(idRange.start, idRange.end)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Joke with invalid ID Range`() {
|
||||
val idRange = IdRange(100, 1)
|
||||
val e = assertThrows<IllegalArgumentException> { joke(idRange = idRange, lang = Language.DE) }
|
||||
assertThat(e::message).isNotNull().contains("100, 1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Joke with max ID Range`() {
|
||||
val idRange = IdRange(1, 30000)
|
||||
val e = assertThrows<JokeException> { joke(idRange = idRange) }
|
||||
assertThat(e, "joke{${idRange})").all {
|
||||
prop(JokeException::additionalInfo).contains("ID range")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Joke with two Categories`() {
|
||||
val joke = joke(categories = setOf(Category.PROGRAMMING, Category.MISC))
|
||||
logger.fine(joke.toString())
|
||||
assertThat(joke.category, "joke(${Category.PROGRAMMING},${Category.MISC})").isIn(
|
||||
Category.PROGRAMMING,
|
||||
Category.MISC
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Joke with each Categories`() {
|
||||
Category.values().filter { it != Category.ANY }.forEach {
|
||||
val joke = joke(categories = setOf(it))
|
||||
logger.fine(joke.toString())
|
||||
assertThat(joke::category, "joke($it)").prop(Category::value).isEqualTo(it.value)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Joke with each Languages`() {
|
||||
Language.values().forEach {
|
||||
val joke = joke(lang = it)
|
||||
logger.fine(joke.toString())
|
||||
assertThat(joke::lang, "joke($it)").prop(Language::value).isEqualTo(it.value)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Joke with Split Newline`() {
|
||||
val joke = joke(
|
||||
categories = setOf(Category.DARK), type = Type.SINGLE, idRange = IdRange(178), splitNewLine = true
|
||||
)
|
||||
logger.fine(joke.toString())
|
||||
assertThat(joke::joke, "joke(splitNewLine=true)").all {
|
||||
size().isEqualTo(2)
|
||||
each {
|
||||
containsNone("\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Safe Joke`() {
|
||||
val joke = joke(safe = true)
|
||||
logger.fine(joke.toString())
|
||||
assertThat(joke, "joke(safe)").all {
|
||||
prop(Joke::safe).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Single Joke`() {
|
||||
val joke = joke(type = Type.SINGLE)
|
||||
logger.fine(joke.toString())
|
||||
assertThat(joke::type).assertThat(Type.SINGLE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Two-Parts Joke`() {
|
||||
val joke = joke(type = Type.TWOPART)
|
||||
logger.fine(joke.toString())
|
||||
assertThat(joke, "joke(${Type.TWOPART})").all {
|
||||
prop(Joke::type).isEqualTo(Type.TWOPART)
|
||||
prop(Joke::joke).size().isGreaterThan(1)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Joke using Search`() {
|
||||
val id = 265
|
||||
val search = "his wife"
|
||||
val joke =
|
||||
joke(contains = search, categories = setOf(Category.PROGRAMMING), idRange = IdRange(id), safe = true)
|
||||
logger.fine(joke.toString())
|
||||
assertThat(joke, "joke($search)").all {
|
||||
prop(Joke::id).isEqualTo(id)
|
||||
prop(Joke::joke).any {
|
||||
it.contains(search)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
84
bin/test/net/thauvin/erik/jokeapi/GetJokesTest.kt
Normal file
84
bin/test/net/thauvin/erik/jokeapi/GetJokesTest.kt
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* GetJokesTest.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi
|
||||
|
||||
import assertk.all
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.contains
|
||||
import assertk.assertions.each
|
||||
import assertk.assertions.index
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isGreaterThanOrEqualTo
|
||||
import assertk.assertions.isNotNull
|
||||
import assertk.assertions.isTrue
|
||||
import assertk.assertions.prop
|
||||
import assertk.assertions.size
|
||||
import net.thauvin.erik.jokeapi.models.Joke
|
||||
import net.thauvin.erik.jokeapi.models.Language
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
|
||||
@ExtendWith(BeforeAllTests::class)
|
||||
internal class GetJokesTest {
|
||||
@Test
|
||||
fun `Get Multiple Jokes`() {
|
||||
val amount = 2
|
||||
val jokes = jokes(amount = amount, safe = true, lang = Language.FR)
|
||||
assertThat(jokes, "jokes").all {
|
||||
size().isEqualTo(amount)
|
||||
each {
|
||||
it.prop(Joke::id).isGreaterThanOrEqualTo(0)
|
||||
it.prop(Joke::safe).isTrue()
|
||||
it.prop(Joke::lang).isEqualTo(Language.FR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Jokes with Invalid Amount`() {
|
||||
val e = assertThrows<IllegalArgumentException> { jokes(amount = -1) }
|
||||
assertThat(e::message).isNotNull().contains("-1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get One Joke as Multiple`() {
|
||||
val jokes = jokes(amount = 1, safe = true)
|
||||
assertThat(jokes, "jokes").all {
|
||||
size().isEqualTo(1)
|
||||
index(0).all {
|
||||
prop(Joke::id).isGreaterThanOrEqualTo(0)
|
||||
prop(Joke::safe).isTrue()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
79
bin/test/net/thauvin/erik/jokeapi/GetRawJokesTest.kt
Normal file
79
bin/test/net/thauvin/erik/jokeapi/GetRawJokesTest.kt
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* GetRawJokesTest.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi
|
||||
|
||||
import assertk.all
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.doesNotContain
|
||||
import assertk.assertions.isNotEmpty
|
||||
import assertk.assertions.startsWith
|
||||
import net.thauvin.erik.jokeapi.models.Format
|
||||
import net.thauvin.erik.jokeapi.models.IdRange
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import kotlin.test.assertContains
|
||||
|
||||
@ExtendWith(BeforeAllTests::class)
|
||||
internal class GetRawJokesTest {
|
||||
@Test
|
||||
fun `Get Raw Joke with TXT`() {
|
||||
val response = rawJokes(format = Format.TXT)
|
||||
assertThat(response, "rawJoke(txt)").all {
|
||||
isNotEmpty()
|
||||
doesNotContain("Error")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Raw Joke with XML`() {
|
||||
val response = rawJokes(format = Format.XML)
|
||||
assertThat(response, "rawJoke(xml)").startsWith("<?xml version='1.0'?>\n<data>\n <error>false</error>")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Raw Joke with YAML`() {
|
||||
val response = rawJokes(format = Format.YAML)
|
||||
assertThat(response, "rawJoke(yaml)").startsWith("error: false")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Raw Jokes`() {
|
||||
val response = rawJokes(amount = 2)
|
||||
assertContains(response, "\"amount\": 2", false, "rawJoke(2)")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Raw Invalid Jokes`() {
|
||||
val response = rawJokes(contains = "foo", safe = true, amount = 2, idRange = IdRange(160, 161))
|
||||
assertContains(response, "\"error\": true", false, "getRawJokes(foo)")
|
||||
}
|
||||
}
|
182
bin/test/net/thauvin/erik/jokeapi/JokeConfigTest.kt
Normal file
182
bin/test/net/thauvin/erik/jokeapi/JokeConfigTest.kt
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* JokeConfigTest.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi
|
||||
|
||||
import assertk.all
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.each
|
||||
import assertk.assertions.isBetween
|
||||
import assertk.assertions.isEmpty
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isGreaterThanOrEqualTo
|
||||
import assertk.assertions.isTrue
|
||||
import assertk.assertions.prop
|
||||
import assertk.assertions.size
|
||||
import net.thauvin.erik.jokeapi.JokeApi.joke
|
||||
import net.thauvin.erik.jokeapi.JokeApi.jokes
|
||||
import net.thauvin.erik.jokeapi.JokeApi.getRawJokes
|
||||
import net.thauvin.erik.jokeapi.JokeApi.logger
|
||||
import net.thauvin.erik.jokeapi.models.Category
|
||||
import net.thauvin.erik.jokeapi.models.Flag
|
||||
import net.thauvin.erik.jokeapi.models.Format
|
||||
import net.thauvin.erik.jokeapi.models.IdRange
|
||||
import net.thauvin.erik.jokeapi.models.Joke
|
||||
import net.thauvin.erik.jokeapi.models.Language
|
||||
import net.thauvin.erik.jokeapi.models.Type
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import kotlin.test.assertContains
|
||||
|
||||
@ExtendWith(BeforeAllTests::class)
|
||||
internal class JokeConfigTest {
|
||||
@Test
|
||||
fun `Get Joke with Default Builder`() {
|
||||
val joke = joke()
|
||||
assertThat(joke, "joke").all {
|
||||
prop(Joke::id).isGreaterThanOrEqualTo(0)
|
||||
prop(Joke::lang).isEqualTo(Language.EN)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Joke with Builder`() {
|
||||
val id = 266
|
||||
val config = JokeConfig.Builder().apply {
|
||||
categories(setOf(Category.PROGRAMMING))
|
||||
lang(Language.EN)
|
||||
blacklistFlags(setOf(Flag.ALL))
|
||||
type(Type.TWOPART)
|
||||
idRange(IdRange(id - 2, id + 2))
|
||||
safe(true)
|
||||
}.build()
|
||||
val joke = joke(config)
|
||||
logger.fine(joke.toString())
|
||||
assertThat(joke, "config").all {
|
||||
prop(Joke::type).isEqualTo(Type.TWOPART)
|
||||
prop(Joke::category).isEqualTo(Category.PROGRAMMING)
|
||||
prop(Joke::joke).size().isEqualTo(2)
|
||||
prop(Joke::lang).isEqualTo(Language.EN)
|
||||
prop(Joke::flags).isEmpty()
|
||||
prop(Joke::id).isBetween(id - 2, id + 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get joke with Builder and Split Newline`() {
|
||||
val id = 5
|
||||
val config = JokeConfig.Builder().apply {
|
||||
categories(setOf(Category.PROGRAMMING))
|
||||
idRange(IdRange(id))
|
||||
splitNewLine(true)
|
||||
}.build()
|
||||
val joke = joke(config)
|
||||
logger.fine(joke.toString())
|
||||
assertThat(joke, "config").all {
|
||||
prop(Joke::id).isEqualTo(id)
|
||||
prop(Joke::joke).size().isEqualTo(2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Raw Joke with Builder`() {
|
||||
val config = JokeConfig.Builder().apply {
|
||||
categories(setOf(Category.PROGRAMMING))
|
||||
format(Format.TXT)
|
||||
contains("bar")
|
||||
amount(2)
|
||||
safe(true)
|
||||
}.build()
|
||||
val joke = getRawJokes(config)
|
||||
assertContains(joke, "----------------------------------------------", false, "config.amount(2)")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Multiple Jokes with Builder`() {
|
||||
val amount = 2
|
||||
val config = JokeConfig.Builder().apply {
|
||||
amount(amount)
|
||||
safe(true)
|
||||
lang(Language.FR)
|
||||
}.build()
|
||||
val jokes = jokes(config)
|
||||
assertThat(jokes, "jokes").all {
|
||||
size().isEqualTo(amount)
|
||||
each {
|
||||
it.prop(Joke::id).isGreaterThanOrEqualTo(0)
|
||||
it.prop(Joke::safe).isTrue()
|
||||
it.prop(Joke::flags).isEmpty()
|
||||
it.prop(Joke::lang).isEqualTo(Language.FR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Validate Config`() {
|
||||
val categories = setOf(Category.ANY)
|
||||
val language = Language.CS
|
||||
val flags = setOf(Flag.POLITICAL, Flag.RELIGIOUS)
|
||||
val type = Type.TWOPART
|
||||
val format = Format.XML
|
||||
val search = "foo"
|
||||
val idRange = IdRange(1, 20)
|
||||
val amount = 10
|
||||
val safe = true
|
||||
val splitNewLine = true
|
||||
val auth = "token"
|
||||
val config = JokeConfig.Builder().apply {
|
||||
categories(categories)
|
||||
lang(language)
|
||||
blacklistFlags(flags)
|
||||
type(type)
|
||||
format(format)
|
||||
contains(search)
|
||||
idRange(idRange)
|
||||
amount(amount)
|
||||
safe(safe)
|
||||
splitNewLine(splitNewLine)
|
||||
auth(auth)
|
||||
}.build()
|
||||
assertThat(config, "config").all {
|
||||
prop(JokeConfig::categories).isEqualTo(categories)
|
||||
prop(JokeConfig::language).isEqualTo(language)
|
||||
prop(JokeConfig::flags).isEqualTo(flags)
|
||||
prop(JokeConfig::type).isEqualTo(type)
|
||||
prop(JokeConfig::format).isEqualTo(format)
|
||||
prop(JokeConfig::contains).isEqualTo(search)
|
||||
prop(JokeConfig::idRange).isEqualTo(idRange)
|
||||
prop(JokeConfig::amount).isEqualTo(amount)
|
||||
prop(JokeConfig::safe).isEqualTo(safe)
|
||||
prop(JokeConfig::splitNewLine).isEqualTo(splitNewLine)
|
||||
prop(JokeConfig::auth).isEqualTo(auth)
|
||||
}
|
||||
}
|
||||
}
|
60
bin/test/net/thauvin/erik/jokeapi/JokeUtilTest.kt
Normal file
60
bin/test/net/thauvin/erik/jokeapi/JokeUtilTest.kt
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* UtilTest.kt
|
||||
*
|
||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.jokeapi
|
||||
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.contains
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
|
||||
@ExtendWith(BeforeAllTests::class)
|
||||
internal class JokeUtilTest {
|
||||
@Test
|
||||
fun `Invalid JSON Error`() {
|
||||
assertThrows<JSONException> { parseError(JSONObject("{}")) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Invalid JSON Joke`() {
|
||||
assertThrows<JSONException> { parseJoke(JSONObject("{}"), false) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Validate Authentication Header`() {
|
||||
val token = "AUTH-TOKEN"
|
||||
val body = fetchUrl("https://postman-echo.com/get", token)
|
||||
assertThat(body, "body").contains("\"authentication\": \"$token\"")
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue