Change Array to List whenever applicable

This commit is contained in:
Erik C. Thauvin 2025-07-04 18:22:53 -07:00
parent 042479e989
commit 53151d868a
Signed by: erik
GPG key ID: 776702A6A2DA330E
8 changed files with 159 additions and 40 deletions

View file

@ -19,8 +19,8 @@
<ID>FunctionParameterNaming:UpdateDeeplinks.kt$UpdateDeeplinks$brand_guid: String</ID> <ID>FunctionParameterNaming:UpdateDeeplinks.kt$UpdateDeeplinks$brand_guid: String</ID>
<ID>FunctionParameterNaming:UpdateDeeplinks.kt$UpdateDeeplinks$install_type: InstallType</ID> <ID>FunctionParameterNaming:UpdateDeeplinks.kt$UpdateDeeplinks$install_type: InstallType</ID>
<ID>FunctionParameterNaming:UpdateDeeplinks.kt$UpdateDeeplinks$install_url: String</ID> <ID>FunctionParameterNaming:UpdateDeeplinks.kt$UpdateDeeplinks$install_url: String</ID>
<ID>LongParameterList:Bitlinks.kt$Bitlinks$( bitlink: String, title: String = Constants.EMPTY, archived: Boolean = false, tags: Array&lt;String&gt; = emptyArray(), deeplinks: UpdateDeeplinks = UpdateDeeplinks(), toJson: Boolean = false )</ID> <ID>LongParameterList:Bitlinks.kt$Bitlinks$( bitlink: String, title: String = Constants.EMPTY, archived: Boolean = false, tags: List&lt;String&gt; = emptyList(), deeplinks: UpdateDeeplinks = UpdateDeeplinks(), toJson: Boolean = false )</ID>
<ID>LongParameterList:Bitlinks.kt$Bitlinks$( long_url: String, domain: String = Constants.EMPTY, group_guid: String = Constants.EMPTY, title: String = Constants.EMPTY, tags: Array&lt;String&gt; = emptyArray(), deeplinks: CreateDeeplinks = CreateDeeplinks(), toJson: Boolean = false )</ID> <ID>LongParameterList:Bitlinks.kt$Bitlinks$( long_url: String, domain: String = Constants.EMPTY, group_guid: String = Constants.EMPTY, title: String = Constants.EMPTY, tags: List&lt;String&gt; = emptyList(), deeplinks: CreateDeeplinks = CreateDeeplinks(), toJson: Boolean = false )</ID>
<ID>MagicNumber:CallResponse.kt$CallResponse$200</ID> <ID>MagicNumber:CallResponse.kt$CallResponse$200</ID>
<ID>MagicNumber:CallResponse.kt$CallResponse$201</ID> <ID>MagicNumber:CallResponse.kt$CallResponse$201</ID>
<ID>MagicNumber:CallResponse.kt$CallResponse$299</ID> <ID>MagicNumber:CallResponse.kt$CallResponse$299</ID>

View file

@ -136,7 +136,7 @@ open class Bitlinks(private val accessToken: String) {
domain: String = Constants.EMPTY, domain: String = Constants.EMPTY,
group_guid: String = Constants.EMPTY, group_guid: String = Constants.EMPTY,
title: String = Constants.EMPTY, title: String = Constants.EMPTY,
tags: Array<String> = emptyArray(), tags: List<String> = emptyList(),
deeplinks: CreateDeeplinks = CreateDeeplinks(), deeplinks: CreateDeeplinks = CreateDeeplinks(),
toJson: Boolean = false toJson: Boolean = false
): String { ): String {
@ -282,7 +282,7 @@ open class Bitlinks(private val accessToken: String) {
bitlink: String, bitlink: String,
title: String = Constants.EMPTY, title: String = Constants.EMPTY,
archived: Boolean = false, archived: Boolean = false,
tags: Array<String> = emptyArray(), tags: List<String> = emptyList(),
deeplinks: UpdateDeeplinks = UpdateDeeplinks(), deeplinks: UpdateDeeplinks = UpdateDeeplinks(),
toJson: Boolean = false toJson: Boolean = false
): String { ): String {

View file

@ -124,7 +124,7 @@ object Utils {
var message = response.message var message = response.message
var description = "" var description = ""
var json = Constants.EMPTY_JSON var json = Constants.EMPTY_JSON
response.body?.string()?.let { body -> response.body.string().let { body ->
json = body json = body
if (!response.isSuccessful && body.isNotEmpty()) { if (!response.isSuccessful && body.isNotEmpty()) {
try { try {

View file

@ -60,7 +60,7 @@ class CreateConfig private constructor(builder: Builder) {
var domain: String = Constants.EMPTY var domain: String = Constants.EMPTY
var group_guid: String = Constants.EMPTY var group_guid: String = Constants.EMPTY
var title: String = Constants.EMPTY var title: String = Constants.EMPTY
var tags: Array<String> = emptyArray() var tags: List<String> = emptyList()
var deeplinks: CreateDeeplinks = CreateDeeplinks() var deeplinks: CreateDeeplinks = CreateDeeplinks()
var toJson: Boolean = false var toJson: Boolean = false
@ -76,7 +76,7 @@ class CreateConfig private constructor(builder: Builder) {
fun title(title: String): Builder = apply { this.title = title } fun title(title: String): Builder = apply { this.title = title }
fun tags(tags: Array<String>): Builder = apply { this.tags = tags } fun tags(tags: List<String>): Builder = apply { this.tags = tags }
fun deeplinks(deeplinks: CreateDeeplinks): Builder = apply { this.deeplinks = deeplinks } fun deeplinks(deeplinks: CreateDeeplinks): Builder = apply { this.deeplinks = deeplinks }

View file

@ -57,7 +57,7 @@ class UpdateConfig private constructor(builder: Builder) {
data class Builder(var bitlink: String) { data class Builder(var bitlink: String) {
var title: String = Constants.EMPTY var title: String = Constants.EMPTY
var archived: Boolean = false var archived: Boolean = false
var tags: Array<String> = emptyArray() var tags: List<String> = emptyList()
var deeplinks: UpdateDeeplinks = UpdateDeeplinks() var deeplinks: UpdateDeeplinks = UpdateDeeplinks()
var toJson: Boolean = false var toJson: Boolean = false
@ -68,7 +68,7 @@ class UpdateConfig private constructor(builder: Builder) {
fun title(title: String): Builder = apply { this.title = title } fun title(title: String): Builder = apply { this.title = title }
fun archived(archived: Boolean): Builder = apply { this.archived = archived } fun archived(archived: Boolean): Builder = apply { this.archived = archived }
fun tags(tags: Array<String>): Builder = apply { this.tags = tags } fun tags(tags: List<String>): Builder = apply { this.tags = tags }
fun deeplinks(deeplinks: UpdateDeeplinks): Builder = apply { this.deeplinks = deeplinks } fun deeplinks(deeplinks: UpdateDeeplinks): Builder = apply { this.deeplinks = deeplinks }
/** /**

View file

@ -47,10 +47,12 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable
import org.junit.jupiter.api.extension.ExtendWith import org.junit.jupiter.api.extension.ExtendWith
import java.io.File import java.io.File
import java.util.*
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ExtendWith(BeforeAllTests::class) @ExtendWith(BeforeAllTests::class)
class BitlinksTests { class BitlinksTests {
private val bitly = with(File("local.properties")) { private val bitly = with(File("local.properties")) {
@ -91,9 +93,113 @@ class BitlinksTests {
} }
} }
@Nested
@DisplayName("Constructor Tests")
inner class ConstructorTests {
@Test
fun `Constructor with access token string should set the token correctly`() {
// Arrange
val expectedToken = "my-secret-token"
// Act
val bitly = Bitly(expectedToken)
// Assert
assertThat(bitly.accessToken).isEqualTo(expectedToken)
}
@Test
fun `Constructor with Path should not change token if file does not exist`() {
// Arrange
val nonExistentPath = File("non/existent/path/file.properties").toPath()
val bitlyWithDefaultToken = Bitly()
val initialToken = bitlyWithDefaultToken.accessToken
// Act
val bitly = Bitly(nonExistentPath)
// Assert
assertThat(bitly.accessToken).isEqualTo(initialToken)
}
@Test
fun `Constructor with Properties and custom key should set token correctly`() {
// Arrange
val customKey = "MY_CUSTOM_BITLY_KEY"
val expectedToken = "token-from-custom-key"
val properties = Properties().apply {
setProperty(customKey, expectedToken)
}
// Act
val bitly = Bitly(properties, customKey)
// Assert
assertThat(bitly.accessToken).isEqualTo(expectedToken)
}
@Test
fun `Constructor with Properties should keep default token if key not found`() {
// Arrange
val properties = Properties() // Empty properties
val bitlyWithDefaultToken = Bitly() // Has "" as token by default
val initialToken = bitlyWithDefaultToken.accessToken
// Act
val bitly = Bitly(properties, "non-existent-key")
// Assert
// The token should remain the default empty string
assertThat(bitly.accessToken).isEqualTo(initialToken)
}
@Test
fun `Constructor with Properties should set token using default key`() {
// Arrange
val expectedToken = "token-from-props"
val properties = Properties().apply {
setProperty(Constants.ENV_ACCESS_TOKEN, expectedToken)
}
// Act
val bitly = Bitly(properties)
// Assert
assertThat(bitly.accessToken).isEqualTo(expectedToken)
}
@Test
fun `Default constructor should default to empty string if no token is provided`() {
// Arrange: Ensure no env var or system property is set
System.clearProperty(Constants.ENV_ACCESS_TOKEN)
// Note: Testing environment variables directly is often avoided in unit tests.
// This test verifies the fallback mechanism.
// Act
val bitly = Bitly()
// Assert
assertThat(bitly.accessToken).isEmpty()
}
@Test
fun `Default constructor should use system property if env var is not set`() {
// Arrange
val expectedToken = "token-from-property"
System.setProperty(Constants.ENV_ACCESS_TOKEN, expectedToken)
// Act
val bitly = Bitly()
// Assert
assertThat(bitly.accessToken).isEqualTo(expectedToken)
}
}
@Nested @Nested
@DisplayName("Create Bitlink Tests") @DisplayName("Create Bitlink Tests")
inner class CreateBitlinkTests { inner class CreateBitlinkTests {
@Test @Test
fun `Create bitlink`() { fun `Create bitlink`() {
assertThat(bitly.bitlinks().create(long_url = longUrl), "create(longUrl)") assertThat(bitly.bitlinks().create(long_url = longUrl), "create(longUrl)")
@ -103,7 +209,7 @@ class BitlinksTests {
bitly.bitlinks().create( bitly.bitlinks().create(
domain = "bit.ly", domain = "bit.ly",
title = "Erik's Blog", title = "Erik's Blog",
tags = arrayOf("erik", "thauvin", "blog", "weblog"), tags = listOf("erik", "thauvin", "blog", "weblog"),
long_url = longUrl long_url = longUrl
) )
) )
@ -118,7 +224,7 @@ class BitlinksTests {
config = CreateConfig.Builder(longUrl) config = CreateConfig.Builder(longUrl)
.domain("bit.ly") .domain("bit.ly")
.title("Erik's Blog") .title("Erik's Blog")
.tags(arrayOf("erik", "thauvin", "blog", "weblog")) .tags(listOf("erik", "thauvin", "blog", "weblog"))
.build() .build()
assertEquals( assertEquals(
shortUrl, shortUrl,
@ -148,6 +254,7 @@ class BitlinksTests {
@Nested @Nested
@DisplayName("Expand Test") @DisplayName("Expand Test")
inner class ExpandTests { inner class ExpandTests {
@Test @Test
fun `Expand as json`() { fun `Expand as json`() {
assertTrue( assertTrue(
@ -165,6 +272,7 @@ class BitlinksTests {
@Nested @Nested
@DisplayName("Shorten Tests") @DisplayName("Shorten Tests")
inner class ShortenTests { inner class ShortenTests {
@Test @Test
fun `Shorten as json`() { fun `Shorten as json`() {
assertTrue( assertTrue(
@ -218,17 +326,18 @@ class BitlinksTests {
@Nested @Nested
@DisplayName("Update Bitlink Tests") @DisplayName("Update Bitlink Tests")
inner class UpdateBitlinkTests { inner class UpdateBitlinkTests {
@Test @Test
fun `Update bitlink`() { fun `Update bitlink`() {
val bl = bitly.bitlinks() val bl = bitly.bitlinks()
assertEquals( assertEquals(
Constants.TRUE, Constants.TRUE,
bl.update( bl.update(
shortUrl, title = "Erik's Weblog", tags = arrayOf("blog", "weblog"), archived = true shortUrl, title = "Erik's Weblog", tags = listOf("blog", "weblog"), archived = true
) )
) )
assertThat(bl.update(shortUrl, tags = emptyArray(), toJson = true), "update(tags)") assertThat(bl.update(shortUrl, tags = emptyList(), toJson = true), "update(tags)")
.contains("\"tags\":[]") .contains("\"tags\":[]")
} }
@ -237,7 +346,7 @@ class BitlinksTests {
val bl = bitly.bitlinks() val bl = bitly.bitlinks()
var config = UpdateConfig.Builder(shortUrl) var config = UpdateConfig.Builder(shortUrl)
.archived(true) .archived(true)
.tags(arrayOf("blog", "weblog")) .tags(listOf("blog", "weblog"))
.title("Erik's Weblog") .title("Erik's Weblog")
.build() .build()
@ -279,6 +388,7 @@ class BitlinksTests {
@Nested @Nested
@DisplayName("Validation Tests") @DisplayName("Validation Tests")
inner class ValidationTests { inner class ValidationTests {
@Test @Test
fun `Empty URL should not shorten`() { fun `Empty URL should not shorten`() {
assertEquals(Constants.EMPTY, bitly.bitlinks().shorten(Constants.EMPTY)) assertEquals(Constants.EMPTY, bitly.bitlinks().shorten(Constants.EMPTY))
@ -289,13 +399,6 @@ class BitlinksTests {
assertEquals(shortUrl, bitly.bitlinks().shorten(shortUrl)) assertEquals(shortUrl, bitly.bitlinks().shorten(shortUrl))
} }
@Test
fun `Token not specified with API call`() {
assertFailsWith(IllegalArgumentException::class, "Utils.call()") {
Utils.call("", "foo")
}
}
@Test @Test
@DisableOnCi @DisableOnCi
fun `Token not specified`() { fun `Token not specified`() {
@ -316,6 +419,13 @@ class BitlinksTests {
} }
} }
@Test
fun `Token not specified with API call`() {
assertFailsWith(IllegalArgumentException::class, "Utils.call()") {
Utils.call("", "foo")
}
}
@Test @Test
fun `Token should be valid`() { fun `Token should be valid`() {
val test = Bitly().apply { accessToken = "12345679" } val test = Bitly().apply { accessToken = "12345679" }

View file

@ -51,6 +51,11 @@ class UtilsTests {
assertThat("".toEndPoint()).isEqualTo("") assertThat("".toEndPoint()).isEqualTo("")
} }
@Test
fun `Convert endpoint with blank string`() {
assertThat(" ".toEndPoint()).isEqualTo(" ")
}
@Test @Test
fun `Convert endpoint with full URL`() { fun `Convert endpoint with full URL`() {
assertThat("https://example.com/path".toEndPoint()).isEqualTo("https://example.com/path") assertThat("https://example.com/path".toEndPoint()).isEqualTo("https://example.com/path")
@ -102,13 +107,17 @@ class UtilsTests {
} }
} }
@Test @Nested
fun `Validate invalid URL`() { @DisplayName("URL Validation Tests")
assertFalse("this is a test".isValidUrl(), "invalid url") inner class URLValidationTests {
} @Test
fun `Validate invalid URL`() {
assertFalse("this is a test".isValidUrl(), "invalid url")
}
@Test @Test
fun `Validate URL`() { fun `Validate URL`() {
assertTrue("https://www.example.com".isValidUrl(), "valid url") assertTrue("https://www.example.com".isValidUrl(), "valid url")
}
} }
} }

View file

@ -61,7 +61,7 @@ class ConfigTests {
.deeplinks(deeplinks) .deeplinks(deeplinks)
.domain("domain") .domain("domain")
.groupGuid("group_guid") .groupGuid("group_guid")
.tags(arrayOf("tag", "tag2")) .tags(listOf("tag", "tag2"))
.title("title") .title("title")
.build() .build()
@ -70,13 +70,13 @@ class ConfigTests {
prop(CreateConfig::domain).isEqualTo("domain") prop(CreateConfig::domain).isEqualTo("domain")
prop(CreateConfig::group_guid).isEqualTo("group_guid") prop(CreateConfig::group_guid).isEqualTo("group_guid")
prop(CreateConfig::long_url).isEqualTo("long_url") prop(CreateConfig::long_url).isEqualTo("long_url")
prop(CreateConfig::tags).isEqualTo(arrayOf("tag", "tag2")) prop(CreateConfig::tags).isEqualTo(listOf("tag", "tag2"))
prop(CreateConfig::title).isEqualTo("title") prop(CreateConfig::title).isEqualTo("title")
prop(CreateConfig::toJson).isEqualTo(false) prop(CreateConfig::toJson).isEqualTo(false)
} }
val map = mapOf( val map = mapOf(
"deeplinks" to arrayOf(deeplinks.links()), "deeplinks" to listOf(deeplinks.links()),
"domain" to config.domain, "domain" to config.domain,
"group_guid" to config.group_guid, "group_guid" to config.group_guid,
"long_url" to config.long_url, "long_url" to config.long_url,
@ -103,7 +103,7 @@ class ConfigTests {
val config = UpdateConfig.Builder("blink") val config = UpdateConfig.Builder("blink")
.archived(true) .archived(true)
.deeplinks(deeplinks) .deeplinks(deeplinks)
.tags(arrayOf("tag", "tag2")) .tags(listOf("tag", "tag2"))
.title("title") .title("title")
.build() .build()
@ -111,7 +111,7 @@ class ConfigTests {
prop(UpdateConfig::archived).isTrue() prop(UpdateConfig::archived).isTrue()
prop(UpdateConfig::bitlink).isEqualTo("blink") prop(UpdateConfig::bitlink).isEqualTo("blink")
prop(UpdateConfig::deeplinks).isEqualTo(deeplinks) prop(UpdateConfig::deeplinks).isEqualTo(deeplinks)
prop(UpdateConfig::tags).isEqualTo(arrayOf("tag", "tag2")) prop(UpdateConfig::tags).isEqualTo(listOf("tag", "tag2"))
prop(UpdateConfig::title).isEqualTo("title") prop(UpdateConfig::title).isEqualTo("title")
prop(UpdateConfig::toJson).isEqualTo(false) prop(UpdateConfig::toJson).isEqualTo(false)
} }
@ -119,7 +119,7 @@ class ConfigTests {
val map = mapOf( val map = mapOf(
"archived" to config.archived, "archived" to config.archived,
"bitlink" to config.bitlink, "bitlink" to config.bitlink,
"deeplinks" to arrayOf(deeplinks.links()), "deeplinks" to listOf(deeplinks.links()),
"tags" to config.tags, "tags" to config.tags,
"title" to config.title "title" to config.title
) )
@ -145,7 +145,7 @@ class ConfigTests {
.deeplinks(deeplinks) .deeplinks(deeplinks)
.domain("domain") .domain("domain")
.groupGuid("group_guid") .groupGuid("group_guid")
.tags(arrayOf("tag", "tag2")) .tags(listOf("tag", "tag2"))
.title("title") .title("title")
.toJson(true) .toJson(true)
@ -154,7 +154,7 @@ class ConfigTests {
prop(CreateConfig.Builder::domain).isEqualTo("domain") prop(CreateConfig.Builder::domain).isEqualTo("domain")
prop(CreateConfig.Builder::group_guid).isEqualTo("group_guid") prop(CreateConfig.Builder::group_guid).isEqualTo("group_guid")
prop(CreateConfig.Builder::long_url).isEqualTo("long_url") prop(CreateConfig.Builder::long_url).isEqualTo("long_url")
prop(CreateConfig.Builder::tags).isEqualTo(arrayOf("tag", "tag2")) prop(CreateConfig.Builder::tags).isEqualTo(listOf("tag", "tag2"))
prop(CreateConfig.Builder::title).isEqualTo("title") prop(CreateConfig.Builder::title).isEqualTo("title")
prop(CreateConfig.Builder::toJson).isTrue() prop(CreateConfig.Builder::toJson).isTrue()
} }
@ -172,7 +172,7 @@ class ConfigTests {
prop(CreateConfig.Builder::domain).isEqualTo(Constants.EMPTY) prop(CreateConfig.Builder::domain).isEqualTo(Constants.EMPTY)
prop(CreateConfig.Builder::group_guid).isEqualTo(Constants.EMPTY) prop(CreateConfig.Builder::group_guid).isEqualTo(Constants.EMPTY)
prop(CreateConfig.Builder::title).isEqualTo(Constants.EMPTY) prop(CreateConfig.Builder::title).isEqualTo(Constants.EMPTY)
prop(CreateConfig.Builder::tags).isEqualTo(emptyArray()) prop(CreateConfig.Builder::tags).isEqualTo(emptyList())
prop(CreateConfig.Builder::deeplinks).prop(CreateDeeplinks::links).isEqualTo(CreateDeeplinks().links()) prop(CreateConfig.Builder::deeplinks).prop(CreateDeeplinks::links).isEqualTo(CreateDeeplinks().links())
prop(CreateConfig.Builder::toJson).isEqualTo(false) prop(CreateConfig.Builder::toJson).isEqualTo(false)
} }
@ -189,7 +189,7 @@ class ConfigTests {
val config = UpdateConfig.Builder("bitlink") val config = UpdateConfig.Builder("bitlink")
.title("title") .title("title")
.archived(true) .archived(true)
.tags(arrayOf("tag", "tag2")) .tags(listOf("tag", "tag2"))
.deeplinks(deeplinks) .deeplinks(deeplinks)
.toJson(true) .toJson(true)
@ -197,7 +197,7 @@ class ConfigTests {
prop(UpdateConfig.Builder::bitlink).isEqualTo("bitlink") prop(UpdateConfig.Builder::bitlink).isEqualTo("bitlink")
prop(UpdateConfig.Builder::title).isEqualTo("title") prop(UpdateConfig.Builder::title).isEqualTo("title")
prop(UpdateConfig.Builder::archived).isTrue() prop(UpdateConfig.Builder::archived).isTrue()
prop(UpdateConfig.Builder::tags).isEqualTo(arrayOf("tag", "tag2")) prop(UpdateConfig.Builder::tags).isEqualTo(listOf("tag", "tag2"))
prop(UpdateConfig.Builder::deeplinks).isEqualTo(deeplinks) prop(UpdateConfig.Builder::deeplinks).isEqualTo(deeplinks)
prop(UpdateConfig.Builder::toJson).isTrue() prop(UpdateConfig.Builder::toJson).isTrue()
} }
@ -214,7 +214,7 @@ class ConfigTests {
prop(UpdateConfig.Builder::bitlink).isEqualTo("bitlink") prop(UpdateConfig.Builder::bitlink).isEqualTo("bitlink")
prop(UpdateConfig.Builder::title).isEqualTo(Constants.EMPTY) prop(UpdateConfig.Builder::title).isEqualTo(Constants.EMPTY)
prop(UpdateConfig.Builder::archived).isEqualTo(false) prop(UpdateConfig.Builder::archived).isEqualTo(false)
prop(UpdateConfig.Builder::tags).isEqualTo(emptyArray()) prop(UpdateConfig.Builder::tags).isEqualTo(emptyList())
prop(UpdateConfig.Builder::deeplinks).prop(UpdateDeeplinks::links).isEqualTo(UpdateDeeplinks().links()) prop(UpdateConfig.Builder::deeplinks).prop(UpdateDeeplinks::links).isEqualTo(UpdateDeeplinks().links())
prop(UpdateConfig.Builder::toJson).isEqualTo(false) prop(UpdateConfig.Builder::toJson).isEqualTo(false)
} }