Split tests

This commit is contained in:
Erik C. Thauvin 2022-09-23 23:18:26 -07:00
parent 9b5047e5fa
commit a41119d195
5 changed files with 478 additions and 265 deletions

View file

@ -0,0 +1,88 @@
/*
* ApiCallTest.kt
*
* Copyright (c) 2022, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* 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.JokeApi.Companion.apiCall
import net.thauvin.erik.jokeapi.JokeApi.Companion.logger
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.Assertions.assertTrue
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertAll
import java.util.logging.ConsoleHandler
import java.util.logging.Level
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"), "should not be an error") },
{ assertTrue(json.getJSONArray("flags").length() > 0, "should have flags") },
{ assertTrue(json.getLong("timestamp") > 0, "should have a timestamp") })
}
@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)
)
assertTrue(lang.contains("code: \"fr\"")) { "should contain ${Language.FR.value}" }
}
@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))
assertTrue(ping.startsWith("Pong!"), "should return pong")
}
companion object {
@JvmStatic
@BeforeAll
fun beforeAll() {
with(logger) {
addHandler(ConsoleHandler().apply { level = Level.FINE })
level = Level.FINE
}
}
}
}

View file

@ -0,0 +1,106 @@
/*
* ExceptionsTest.kt
*
* Copyright (c) 2022, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* 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.JokeApi.Companion.fetchUrl
import net.thauvin.erik.jokeapi.JokeApi.Companion.getJoke
import net.thauvin.erik.jokeapi.JokeApi.Companion.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.Assertions
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertAll
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
import java.util.logging.ConsoleHandler
import java.util.logging.Level
internal class ExceptionsTest {
@Test
fun `Validate Joke Exception`() {
val e = assertThrows<JokeException> {
getJoke(categories = setOf(Category.CHRISTMAS), search = "foo")
}
logger.fine(e.debug())
assertAll("JokeException Validation",
{ assertEquals(106, e.code, "code should be valid") },
{ assertTrue(e.error, "should be an error") },
{ assertFalse(e.internalError, "should not be internal error") },
{ assertEquals("No matching joke found", e.message, "message should match") },
{ assertEquals(1, e.causedBy.size, "causedBy size should be 1") },
{ assertTrue(e.causedBy[0].startsWith("No jokes"), "causedBy should start with no jokes") },
{ assertTrue(e.additionalInfo.isNotEmpty(), "additional info should not be empty") },
{ assertTrue(e.timestamp > 0, "timestamp should be > 0") })
}
@ParameterizedTest(name = "HTTP Status Code: {0}")
@ValueSource(ints = [400, 404, 403, 413, 414, 429, 500, 523])
fun `Validate HTTP Error Exceptions`(input: Int) {
val e = assertThrows<HttpErrorException> {
fetchUrl("https://httpstat.us/$input")
}
assertAll("HttpErrorException Validation",
{ assertEquals(input, e.statusCode) { "status code should be $input" } },
{ assertTrue(e.message!!.isNotEmpty()) { "message for $input should not be empty" } },
{ assertTrue(e.cause!!.message!!.isNotEmpty()) { "cause of $input should not be empty" } })
}
@Test
fun `Fetch Invalid URL`() {
val statusCode = 999
val e = assertThrows<HttpErrorException> {
fetchUrl("https://httpstat.us/$statusCode")
}
Assertions.assertAll("JokeException Validation",
{ assertEquals(statusCode, e.statusCode) { "status code should be $statusCode" } },
{ assertTrue(e.message!!.isNotEmpty(), "message should not be empty") },
{ assertTrue(e.cause == null, "cause should be null") })
}
companion object {
@JvmStatic
@BeforeAll
fun beforeAll() {
with(logger) {
addHandler(ConsoleHandler().apply { level = Level.FINE })
level = Level.FINE
}
}
}
}

View file

@ -0,0 +1,193 @@
/*
* JokeApiTest.kt
*
* Copyright (c) 2022, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* 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.JokeApi.Companion.fetchUrl
import net.thauvin.erik.jokeapi.JokeApi.Companion.getJoke
import net.thauvin.erik.jokeapi.JokeApi.Companion.logger
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.IdRange
import net.thauvin.erik.jokeapi.models.Language
import net.thauvin.erik.jokeapi.models.Type
import org.junit.jupiter.api.Assertions.assertAll
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import java.util.logging.ConsoleHandler
import java.util.logging.Level
internal class GetJokeTest {
@Test
fun `Get Joke`() {
val joke = getJoke()
logger.fine(joke.toString())
assertAll("No Param Joke",
{ assertFalse(joke.error, "error should be false") },
{ assertTrue(joke.joke.isNotEmpty(), "joke should not be empty") },
{ assertTrue(joke.type == Type.TWOPART || joke.type == Type.SINGLE, "type should validate") },
{ assertTrue(joke.id >= 0, "id should be >= 0") },
{ assertEquals(Language.EN, joke.language, "language should be english") })
}
@Test
fun `Get Joke without Blacklist Flags`() {
val joke = getJoke(flags = setOf(Flag.ALL))
assertTrue(joke.flags.isEmpty(), "flags should be empty.")
}
@Test
fun `Get Joke without any Blacklist Flags`() {
val allFlags = Flag.values().filter { it != Flag.ALL }.toSet()
val joke = getJoke(flags = allFlags)
assertTrue(joke.flags.isEmpty(), "flags should be empty.")
}
@Test
fun `Get Joke with ID`() {
val id = 172
val joke = getJoke(idRange = IdRange(id))
logger.fine(joke.toString())
assertAll("Joke by ID",
{ assertTrue(joke.flags.contains(Flag.NSFW) && joke.flags.contains(Flag.EXPLICIT), "nsfw & explicit") },
{ assertEquals(172, joke.id) { "id is $id" } },
{ assertEquals(Category.PUN, joke.category, "category should be pun") })
}
@Test
fun `Get Joke with ID Range`() {
val idRange = IdRange(1, 100)
val joke = getJoke(idRange = idRange)
logger.fine(joke.toString())
assertTrue(joke.id >= idRange.start && joke.id <= idRange.end, "id should be in range")
}
@Test
fun `Get Joke with invalid ID Range`() {
val joke = getJoke(idRange = IdRange(100, 1))
logger.fine(joke.toString())
assertFalse(joke.error, "should not be an error")
}
@Test
fun `Get Joke with max ID Range`() {
val e = assertThrows<JokeException> { getJoke(idRange = IdRange(1, 30000)) }
assertAll("Joke w/ max ID Range",
{ assertTrue(e.error, "should be an error") },
{ assertTrue(e.additionalInfo.contains("ID range"), "should contain ID range") })
}
@Test
fun `Get Joke with two Categories`() {
val joke = getJoke(categories = setOf(Category.PROGRAMMING, Category.MISC))
logger.fine(joke.toString())
assertTrue(joke.category == Category.PROGRAMMING || joke.category == Category.MISC) {
"category should be ${Category.PROGRAMMING.value} or ${Category.MISC.value}"
}
}
@Test
fun `Get Joke with each Categories`() {
Category.values().filter { it != Category.ANY }.forEach {
val joke = getJoke(categories = setOf(it))
logger.fine(joke.toString())
assertEquals(it.value, joke.category.value) { "category should be ${it.value}" }
}
}
@Test
fun `Get Joke with each Languages`() {
Language.values().forEach {
val joke = getJoke(language = it)
assertEquals(it.value, joke.language.value) { "language should be ${it.value}" }
}
}
@Test
fun `Get Joke with Newline`() {
val joke = getJoke(
categories = setOf(Category.DARK), type = Type.SINGLE, idRange = IdRange(178), splitNewLine = false
)
assertTrue(joke.joke.toString().contains("\n"), "should contain newline")
}
@Test
fun `Get Safe Joke`() {
val joke = getJoke(safe = true)
logger.fine(joke.toString())
assertAll("Safe Joke",
{ assertTrue(joke.safe, "should be safe") },
{ assertTrue(joke.flags.isEmpty(), "flags should be empty") })
}
@Test
fun `Get Single Joke`() {
val joke = getJoke(type = Type.SINGLE)
logger.fine(joke.toString())
assertEquals(Type.SINGLE, joke.type, "type should be single")
}
@Test
fun `Get Two-Parts Joke`() {
val joke = getJoke(type = Type.TWOPART)
logger.fine(joke.toString())
assertAll("Two-Parts Joke",
{ assertEquals(Type.TWOPART, joke.type, "type should be two-part") },
{ assertTrue(joke.joke.size > 1, "should have multiple lines") })
}
@Test
fun `Get Joke using Search`() {
val id = 265
val joke =
getJoke(search = "his wife", categories = setOf(Category.PROGRAMMING), idRange = IdRange(id), safe = true)
logger.fine(joke.toString())
assertEquals(id, joke.id) { "id should be $id" }
}
companion object {
@JvmStatic
@BeforeAll
fun beforeAll() {
with(logger) {
addHandler(ConsoleHandler().apply { level = Level.FINE })
level = Level.FINE
}
}
}
}

View file

@ -0,0 +1,91 @@
/*
* GetRawJokeTest.kt
*
* Copyright (c) 2022, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* 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.JokeApi.Companion.getRawJoke
import net.thauvin.erik.jokeapi.JokeApi.Companion.logger
import net.thauvin.erik.jokeapi.models.Format
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertAll
import java.util.logging.ConsoleHandler
import java.util.logging.Level
internal class GetRawJokeTest {
@Test
fun `Get Raw Joke with TXT`() {
val response = getRawJoke(format = Format.TEXT)
assertAll("Plain Text",
{ assertTrue(response.isNotEmpty(), "should be not empty") },
{ assertFalse(response.startsWith("Error "), "should not be an error") })
}
@Test
fun `Get Raw Joke with invalid Amount`() {
val response = getRawJoke(amount = 100)
assertFalse(response.contains("\"amount\":"), "should not have amount")
}
@Test
fun `Get Raw Joke with XML`() {
val response = getRawJoke(format = Format.XML)
assertTrue(
response.startsWith("<?xml version='1.0'?>\n<data>\n <error>false</error>"), "should be xml"
)
}
@Test
fun `Get Raw Joke with YAML`() {
val response = getRawJoke(format = Format.YAML)
assertTrue(response.startsWith("error: false"), "should be yaml")
}
@Test
fun `Get Raw Jokes`() {
val response = getRawJoke(amount = 2)
assertTrue(response.contains("\"amount\": 2"), "amount should be 2")
}
companion object {
@JvmStatic
@BeforeAll
fun beforeAll() {
with(logger) {
addHandler(ConsoleHandler().apply { level = Level.FINE })
level = Level.FINE
}
}
}
}

View file

@ -1,265 +0,0 @@
/*
* JokeApiTest.kt
*
* Copyright (c) 2022, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* 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.JokeApi.Companion.fetchUrl
import net.thauvin.erik.jokeapi.JokeApi.Companion.getJoke
import net.thauvin.erik.jokeapi.JokeApi.Companion.getRawJoke
import net.thauvin.erik.jokeapi.JokeApi.Companion.logger
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.Format
import net.thauvin.erik.jokeapi.models.IdRange
import net.thauvin.erik.jokeapi.models.Language
import net.thauvin.erik.jokeapi.models.Type
import org.junit.jupiter.api.Assertions.assertAll
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
import java.util.logging.ConsoleHandler
import java.util.logging.Level
internal class JokeApiTest {
@Test
fun `Get Joke`() {
val joke = getJoke()
logger.fine(joke.toString())
assertAll("no param",
{ assertFalse(joke.error) { "error should be false" } },
{ assertTrue(joke.joke.isNotEmpty()) { "joke should not be empty" } },
{ assertTrue(joke.type == Type.TWOPART || joke.type == Type.SINGLE) { "type should validate" } },
{ assertTrue(joke.id >= 0) { "id should be >= 0" } },
{ assertEquals(Language.EN, joke.language) { "language should be english" } })
}
@Test
fun `Get Joke with all Blacklist Flags`() {
val joke = getJoke(flags = setOf(Flag.ALL))
assertAll("joke with all flags", { assertTrue(joke.flags.isEmpty()) { "flags should be empty." } })
}
@Test
fun `Get Joke with no Blacklist Flags`() {
val noFlags = Flag.values().filter { it != Flag.ALL }.toSet()
val joke = getJoke(flags = noFlags)
assertAll("joke with no flags", { assertTrue(joke.flags.isEmpty()) { "flags should be empty." } })
}
@Test
fun `Get Joke with ID`() {
val id = 172
val joke = getJoke(idRange = IdRange(id))
logger.fine(joke.toString())
assertAll("joke by id",
{ assertTrue(joke.flags.contains(Flag.NSFW) && joke.flags.contains(Flag.EXPLICIT)) { "nsfw & explicit" } },
{ assertEquals(172, joke.id) { "id is $id" } },
{ assertEquals(Category.PUN, joke.category) { "category should be pun" } })
}
@Test
fun `Get Joke with ID Range`() {
val idRange = IdRange(1, 100)
val joke = getJoke(idRange = idRange)
logger.fine(joke.toString())
assertTrue(joke.id >= idRange.start && joke.id <= idRange.end) { "id should be in range" }
}
@Test
fun `Get Joke with invalid ID Range`() {
val joke = getJoke(idRange = IdRange(100, 1))
logger.fine(joke.toString())
assertFalse(joke.error) { "should not be an error" }
}
@Test
fun `Get Joke with max ID Range`() {
val e = assertThrows<JokeException> { getJoke(idRange = IdRange(1, 30000)) }
assertAll("joke with max ID range",
{ assertTrue(e.error) { "should be an error" } },
{ assertTrue(e.additionalInfo.contains("ID range")) { "should contain ID range" } }
)
}
@Test
fun `Get Joke with each Categories`() {
Category.values().filter { it != Category.ANY }.forEach {
val joke = getJoke(categories = setOf(it))
assertEquals(it.value, joke.category.value) { "category should be ${it.value}" }
}
}
@Test
fun `Get Joke with each Languages`() {
Language.values().forEach {
val joke = getJoke(language = it)
assertEquals(it.value, joke.language.value) { "language should be ${it.value}" }
}
}
@Test
fun `Get Joke with Newline`() {
val joke = getJoke(
categories = setOf(Category.DARK),
type = Type.SINGLE,
idRange = IdRange(178),
splitNewLine = false
)
assertTrue(joke.joke.toString().contains("\n")) { "should contain newline" }
}
@Test
fun `Get Safe Joke`() {
val joke = getJoke(safe = true)
logger.fine(joke.toString())
assertAll("safe joke",
{ assertTrue(joke.safe) { "should be safe" } },
{ assertTrue(joke.flags.isEmpty()) { "flags should be empty" } })
}
@Test
fun `Get Single Joke`() {
val joke = getJoke(type = Type.SINGLE)
logger.fine(joke.toString())
assertEquals(Type.SINGLE, joke.type) { "type should be single" }
}
@Test
fun `Get Two-Parts Joke`() {
val joke = getJoke(type = Type.TWOPART)
logger.fine(joke.toString())
assertAll("two-part joke",
{ assertEquals(Type.TWOPART, joke.type) { "type should be two-part" } },
{ assertTrue(joke.joke.size > 1) { "should have multiple lines" } })
}
@Test
fun `Get Joke using Search`() {
val id = 1
val joke = getJoke(search = "man", categories = setOf(Category.PROGRAMMING), idRange = IdRange(id), safe = true)
logger.fine(joke.toString())
assertEquals(id, joke.id) { "id should be $id" }
}
@Test
fun `Get Raw Joke with TXT`() {
val response = getRawJoke(format = Format.TEXT)
assertAll("plain text",
{ assertTrue(response.isNotEmpty()) { "should be not empty" } },
{ assertFalse(response.startsWith("Error ")) { "should not be an error" } })
}
@Test
fun `Get Raw Joke with invalid Amount`() {
val response = getRawJoke(amount = 100)
assertFalse(response.contains("\"amount\":")) { "should not have amount" }
}
@Test
fun `Get Raw Joke with XML`() {
val response = getRawJoke(format = Format.XML)
assertTrue(response.startsWith("<?xml version='1.0'?>\n<data>\n <error>false</error>")) { "should be xml" }
}
@Test
fun `Get Raw Joke with YAML`() {
val response = getRawJoke(format = Format.YAML)
assertTrue(response.startsWith("error: false")) { "should be yaml" }
}
@Test
fun `Get Raw Jokes`() {
val response = getRawJoke(amount = 2)
assertTrue(response.contains("\"amount\": 2")) { "amount should be 2" }
}
@Test
fun `Fetch Invalid URL`() {
val statusCode = 999
val e = assertThrows<HttpErrorException> {
fetchUrl("https://httpstat.us/$statusCode")
}
assertAll("JokeException validation",
{ assertEquals(statusCode, e.statusCode) { "status code should be $statusCode" } },
{ assertTrue(e.message!!.isNotEmpty()) { "message should not be empty" } },
{ assertTrue(e.cause == null) { "cause should be null" } })
}
@Test
fun `Validate Joke Exception`() {
val e = assertThrows<JokeException> {
getJoke(categories = setOf(Category.CHRISTMAS), search = "foo")
}
logger.fine(e.debug())
assertAll("JokeException validation",
{ assertEquals(106, e.code) { "code should be valid" } },
{ assertTrue(e.error) { "should be an error" } },
{ assertFalse(e.internalError) { "should not be internal error" } },
{ assertEquals("No matching joke found", e.message) { "message should match" } },
{ assertEquals(1, e.causedBy.size) { "causedBy size should be 1" } },
{ assertTrue(e.causedBy[0].startsWith("No jokes")) { "causedBy should start with no jokes" } },
{ assertTrue(e.additionalInfo.isNotEmpty()) { "additional info should not be empty" } },
{ assertTrue(e.timestamp > 0) { "timestamp should be > 0" } })
}
@ParameterizedTest
@ValueSource(ints = [400, 404, 403, 413, 414, 429, 500, 523])
fun `Validate HTTP Error Exceptions`(input: Int) {
val e = assertThrows<HttpErrorException> {
fetchUrl("https://httpstat.us/$input")
}
assertAll("HttpErrorException validation",
{ assertEquals(input, e.statusCode) { "status code should be $input" } },
{ assertTrue(e.message!!.isNotEmpty()) { "message for $input should not be empty" } },
{ assertTrue(e.cause!!.message!!.isNotEmpty()) { "cause of $input should not be empty" } })
}
companion object {
@JvmStatic
@BeforeAll
fun beforeAll() {
with(logger) {
addHandler(ConsoleHandler().apply { level = Level.FINE })
level = Level.FINE
}
}
}
}