From 8ff80449825ff8546179db984a0c6bb35f49b475 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Tue, 18 Mar 2025 04:25:26 -0700 Subject: [PATCH 01/28] Add Junit Platform Launcher dependency --- src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java index d007e1e..2db2158 100644 --- a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java +++ b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java @@ -84,6 +84,7 @@ public class BitlyShortenBuild extends Project { .include(dependency("org.jetbrains.kotlin", "kotlin-test-junit5", kotlin)) .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 1))) .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 1))) + .include(dependency("org.junit.platform", "junit-platform-launcher", version(1, 12, 1))) .include(dependency("com.willowtreeapps.assertk", "assertk-jvm", version(0, 28, 1))); publishOperation() From 8d5ac54078828f526406457fdf9d5aa1ef7b15a8 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Tue, 18 Mar 2025 23:49:18 -0700 Subject: [PATCH 02/28] JDK 24 --- .github/workflows/bld.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index 92c82da..9c848ce 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - java-version: [17, 21, 23] + java-version: [17, 21, 24] kotlin-version: [1.9.25, 2.1.10] steps: From 854ea4e43495e3ac9c6b8e21379f73b0cd477979 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Thu, 20 Mar 2025 09:31:52 -0700 Subject: [PATCH 03/28] Bump Kotlin to version 2.1.20 --- .github/workflows/bld.yml | 2 +- README.md | 2 +- examples/gradle/build.gradle.kts | 2 +- pom.xml | 6 +++--- src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index 9c848ce..2bf97e9 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: java-version: [17, 21, 24] - kotlin-version: [1.9.25, 2.1.10] + kotlin-version: [1.9.25, 2.1.20] steps: - name: Checkout source repository diff --git a/README.md b/README.md index 00001fc..02d7aae 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![License (3-Clause BSD)](https://img.shields.io/badge/license-BSD%203--Clause-blue.svg?style=flat-square)](https://opensource.org/licenses/BSD-3-Clause) -[![Kotlin](https://img.shields.io/badge/kotlin-2.1.10-7f52ff)](https://kotlinlang.org/) +[![Kotlin](https://img.shields.io/badge/kotlin-2.1.20-7f52ff)](https://kotlinlang.org/) [![bld](https://img.shields.io/badge/2.2.1-FA9052?label=bld&labelColor=2392FF)](https://rife2.com/bld) [![Release](https://img.shields.io/github/release/ethauvin/bitly-shorten.svg)](https://github.com/ethauvin/bitly-shorten/releases/latest) [![Maven Central](https://img.shields.io/maven-central/v/net.thauvin.erik/bitly-shorten.svg?color=blue)](https://central.sonatype.com/artifact/net.thauvin.erik/bitly-shorten) diff --git a/examples/gradle/build.gradle.kts b/examples/gradle/build.gradle.kts index e44fb22..15fd69d 100644 --- a/examples/gradle/build.gradle.kts +++ b/examples/gradle/build.gradle.kts @@ -1,7 +1,7 @@ plugins { id("application") id("com.github.ben-manes.versions") version "0.51.0" - kotlin("jvm") version "2.1.10" + kotlin("jvm") version "2.1.20" } repositories { diff --git a/pom.xml b/pom.xml index 7dfc770..6e21725 100644 --- a/pom.xml +++ b/pom.xml @@ -18,19 +18,19 @@ org.jetbrains.kotlin kotlin-stdlib - 2.1.10 + 2.1.20 compile org.jetbrains.kotlin kotlin-stdlib-common - 2.1.10 + 2.1.20 compile org.jetbrains.kotlin kotlin-stdlib-jdk8 - 2.1.10 + 2.1.20 compile diff --git a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java index 2db2158..7d5cd0e 100644 --- a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java +++ b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java @@ -69,7 +69,7 @@ public class BitlyShortenBuild extends Project { repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL); var okHttp = version(4, 12, 0); - final var kotlin = version(2, 1, 10); + final var kotlin = version(2, 1, 20); scope(compile) // Kotlin .include(dependency("org.jetbrains.kotlin", "kotlin-stdlib", kotlin)) From 2f974c46daa6fa1ed2e4ed2d4ac3f5ab3666dcd8 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Thu, 20 Mar 2025 09:32:15 -0700 Subject: [PATCH 04/28] 2.0.1-SNAPSHOT --- pom.xml | 2 +- src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 6e21725..75bbccc 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 net.thauvin.erik bitly-shorten - 2.0.0 + 2.0.1-SNAPSHOT bitly-shorten A simple implementation of the Bitly link shortening API v4 https://github.com/ethauvin/bitly-shorten diff --git a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java index 7d5cd0e..5b8cc59 100644 --- a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java +++ b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java @@ -61,7 +61,7 @@ public class BitlyShortenBuild extends Project { public BitlyShortenBuild() { pkg = "net.thauvin.erik"; name = "bitly-shorten"; - version = version(2, 0, 0); + version = version(2, 0, 1, "SNAPSHOT"); javaRelease = 11; downloadSources = true; From 735775666729d135049a2b7056212bf3e9f22ab2 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Thu, 20 Mar 2025 09:33:22 -0700 Subject: [PATCH 05/28] Add Kotlin compile options for JDK 24 --- src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java index 5b8cc59..85cf29e 100644 --- a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java +++ b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java @@ -40,6 +40,7 @@ import rife.bld.extension.JacocoReportOperation; import rife.bld.extension.dokka.LoggingLevel; import rife.bld.extension.dokka.OutputFormat; import rife.bld.extension.dokka.SourceSet; +import rife.bld.extension.kotlin.CompileOptions; import rife.bld.operations.exceptions.ExitStatusException; import rife.bld.publish.PomBuilder; import rife.bld.publish.PublishDeveloper; @@ -126,8 +127,11 @@ public class BitlyShortenBuild extends Project { @BuildCommand(summary = "Compiles the Kotlin project") @Override public void compile() throws Exception { + final var options = new CompileOptions(); + options.jvmOptions().add("--enable-native-access=ALL-UNNAMED"); new CompileKotlinOperation() .fromProject(this) + .compileOptions(options) .execute(); } From f6a1e7bc3d6f10649969cdc603377a1d423ab587 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Thu, 20 Mar 2025 20:39:41 -0700 Subject: [PATCH 06/28] Combine Kotlin compile options --- src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java index 85cf29e..77fd730 100644 --- a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java +++ b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java @@ -127,8 +127,7 @@ public class BitlyShortenBuild extends Project { @BuildCommand(summary = "Compiles the Kotlin project") @Override public void compile() throws Exception { - final var options = new CompileOptions(); - options.jvmOptions().add("--enable-native-access=ALL-UNNAMED"); + var options = new CompileOptions().jvmOptions("--enable-native-access=ALL-UNNAMED"); new CompileKotlinOperation() .fromProject(this) .compileOptions(options) From 6d8525c30c987dc80863143ffa48c43afa27085d Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 26 Mar 2025 11:36:02 -0700 Subject: [PATCH 07/28] Enable extensions logging --- .../thauvin/erik/bitly/BitlyShortenBuild.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java index 77fd730..648cce7 100644 --- a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java +++ b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java @@ -51,6 +51,9 @@ import rife.tools.exceptions.FileUtilsErrorException; import java.io.File; import java.io.IOException; import java.util.List; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; import static rife.bld.dependencies.Repository.*; import static rife.bld.dependencies.Scope.compile; @@ -121,16 +124,25 @@ public class BitlyShortenBuild extends Project { } public static void main(String[] args) { + // Enable detailed logging for the extensions + var level = Level.ALL; + var logger = Logger.getLogger("rife.bld.extension"); + var consoleHandler = new ConsoleHandler(); + + consoleHandler.setLevel(level); + logger.addHandler(consoleHandler); + logger.setLevel(level); + logger.setUseParentHandlers(false); + new BitlyShortenBuild().start(args); } @BuildCommand(summary = "Compiles the Kotlin project") @Override public void compile() throws Exception { - var options = new CompileOptions().jvmOptions("--enable-native-access=ALL-UNNAMED"); new CompileKotlinOperation() .fromProject(this) - .compileOptions(options) + .compileOptions(new CompileOptions().verbose(true)) .execute(); } From ed5dd2110a428d80d617ff3d0bb30caae5a461ec Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 26 Mar 2025 11:37:19 -0700 Subject: [PATCH 08/28] Update to the latest snapshots --- .idea/inspectionProfiles/Project_Default.xml | 1 + examples/bld/lib/bld/bld-wrapper.properties | 2 +- examples/bld/src/bld/java/com/example/ExampleBuild.java | 2 +- examples/gradle/build.gradle.kts | 2 +- lib/bld/bld-wrapper.properties | 8 ++++---- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 1e01b48..94f28ea 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -4,5 +4,6 @@ + \ No newline at end of file diff --git a/examples/bld/lib/bld/bld-wrapper.properties b/examples/bld/lib/bld/bld-wrapper.properties index 1ffe3ff..1f1009d 100644 --- a/examples/bld/lib/bld/bld-wrapper.properties +++ b/examples/bld/lib/bld/bld-wrapper.properties @@ -1,7 +1,7 @@ bld.downloadExtensionJavadoc=false bld.downloadExtensionSources=true bld.downloadLocation= -bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.0.4 +bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.1.0-SNAPSHOT bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES bld.sourceDirectories= bld.version=2.2.1 diff --git a/examples/bld/src/bld/java/com/example/ExampleBuild.java b/examples/bld/src/bld/java/com/example/ExampleBuild.java index b23667e..0a3eb7a 100644 --- a/examples/bld/src/bld/java/com/example/ExampleBuild.java +++ b/examples/bld/src/bld/java/com/example/ExampleBuild.java @@ -24,7 +24,7 @@ public class ExampleBuild extends BaseProject { repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL, SONATYPE_SNAPSHOTS_LEGACY); scope(compile) - .include(dependency("net.thauvin.erik:bitly-shorten:2.0.0")) + .include(dependency("net.thauvin.erik:bitly-shorten:2.0.1-SNAPSHOT")) .include(dependency("org.json:json:20250107")); } diff --git a/examples/gradle/build.gradle.kts b/examples/gradle/build.gradle.kts index 15fd69d..e265ddb 100644 --- a/examples/gradle/build.gradle.kts +++ b/examples/gradle/build.gradle.kts @@ -11,7 +11,7 @@ repositories { } dependencies { - implementation("net.thauvin.erik:bitly-shorten:2.0.0") + implementation("net.thauvin.erik:bitly-shorten:2.0.1-SNAPSHOT") implementation("org.json:json:20240303") } diff --git a/lib/bld/bld-wrapper.properties b/lib/bld/bld-wrapper.properties index 154abb0..fc9463a 100644 --- a/lib/bld/bld-wrapper.properties +++ b/lib/bld/bld-wrapper.properties @@ -1,10 +1,10 @@ bld.downloadExtensionJavadoc=false bld.downloadExtensionSources=true bld.downloadLocation= -bld.extension-detekt=com.uwyn.rife2:bld-detekt:0.9.9 -bld.extension-dokka=com.uwyn.rife2:bld-dokka:1.0.3 -bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.9 -bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.0.4 +bld.extension-detekt=com.uwyn.rife2:bld-detekt:0.9.10-SNAPSHOT +bld.extension-dokka=com.uwyn.rife2:bld-dokka:1.0.4-SNAPSHOT +bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.10-SNAPSHOT +bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.1.0-SNAPSHOT bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES bld.sourceDirectories= bld.version=2.2.1 From a8ce2a04b8e80fb61410093b16e500d7c8e3410e Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 26 Mar 2025 11:37:44 -0700 Subject: [PATCH 09/28] Add OS matrix for Ubuntu, Windows and macOS --- .github/workflows/bld.yml | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index 2bf97e9..795d0f2 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -1,21 +1,21 @@ name: bld-ci -on: [push, pull_request, workflow_dispatch] +on: [ push, pull_request, workflow_dispatch ] env: BITLY_ACCESS_TOKEN: ${{ secrets.BITLY_ACCESS_TOKEN }} COVERAGE_JDK: "21" - COVERAGE_KOTLIN: "2.0.0" - KOTLIN_HOME: /usr/share/kotlinc + COVERAGE_KOTLIN: "2.0.21" jobs: build-bld-project: - runs-on: ubuntu-latest - strategy: matrix: - java-version: [17, 21, 24] - kotlin-version: [1.9.25, 2.1.20] + java-version: [ 17, 21, 24 ] + kotlin-version: [ 1.9.25, 2.0.21, 2.1.20 ] + os: [ ubuntu-latest, windows-latest, macos-latest ] + + runs-on: ${{ matrix.os }} steps: - name: Checkout source repository @@ -29,6 +29,25 @@ jobs: distribution: "zulu" java-version: ${{ matrix.java-version }} + - name: Download dependencies [bld example] + working-directory: examples/bld + run: ./bld download + + - name: Compile and run examples [bld examples] + working-directory: examples/bld + run: | + ./bld run --args='https://erik.thauvin.net/ https://bit.ly/2PsNMAA' + ./bld run-retrieve + ./bld run-java --args='https://erik.thauvin.net/ https://bit.ly/2PsNMAA' + + - name: Run examples [gradle examples] + working-directory: examples/gradle + if: matrix.java-version != '24' + run: | + ./gradlew run --args='https://erik.thauvin.net/ https://bit.ly/2PsNMAA' + ./gradlew runRetrieve + ./gradlew runJava --args='https://erik.thauvin.net/ https://bit.ly/2PsNMAA' + - name: Download dependencies run: ./bld download @@ -40,11 +59,13 @@ jobs: - name: Remove pom.xml if: success() && matrix.java-version == env.COVERAGE_JDK && matrix.kotlin-version == env.COVERAGE_KOTLIN + && matrix.os == 'unbuntu-latest' run: rm -rf pom.xml - name: SonarCloud Scan uses: sonarsource/sonarcloud-github-action@master if: success() && matrix.java-version == env.COVERAGE_JDK && matrix.kotlin-version == env.COVERAGE_KOTLIN + && matrix.os == 'unbuntu-latest' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} From d79f225325d9e92ac86b6d5165346b4e22f2f83b Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 26 Mar 2025 11:41:26 -0700 Subject: [PATCH 10/28] Add bld example compile step --- .github/workflows/bld.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index 795d0f2..fa9f0bd 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -36,6 +36,7 @@ jobs: - name: Compile and run examples [bld examples] working-directory: examples/bld run: | + ./bld compile ./bld run --args='https://erik.thauvin.net/ https://bit.ly/2PsNMAA' ./bld run-retrieve ./bld run-java --args='https://erik.thauvin.net/ https://bit.ly/2PsNMAA' From 4dd96b7cdb320e0cafd8acbae639d934c1d28f4c Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 26 Mar 2025 12:38:39 -0700 Subject: [PATCH 11/28] Fix typo --- .github/workflows/bld.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index fa9f0bd..4ee117f 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -60,13 +60,13 @@ jobs: - name: Remove pom.xml if: success() && matrix.java-version == env.COVERAGE_JDK && matrix.kotlin-version == env.COVERAGE_KOTLIN - && matrix.os == 'unbuntu-latest' + && matrix.os == 'ubuntu-latest' run: rm -rf pom.xml - name: SonarCloud Scan uses: sonarsource/sonarcloud-github-action@master if: success() && matrix.java-version == env.COVERAGE_JDK && matrix.kotlin-version == env.COVERAGE_KOTLIN - && matrix.os == 'unbuntu-latest' + && matrix.os == 'ubuntu-latest' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} From 54b6a09572396d3cad57fe446cb0956d5b65f9e3 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sun, 13 Apr 2025 13:34:39 -0700 Subject: [PATCH 12/28] Bump JUnit to version 5.12.2 --- src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java index 648cce7..4465ac4 100644 --- a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java +++ b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java @@ -86,9 +86,9 @@ public class BitlyShortenBuild extends Project { .include(dependency("org.json", "json", "20250107")); scope(test) .include(dependency("org.jetbrains.kotlin", "kotlin-test-junit5", kotlin)) - .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 1))) - .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 1))) - .include(dependency("org.junit.platform", "junit-platform-launcher", version(1, 12, 1))) + .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 2))) + .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 2))) + .include(dependency("org.junit.platform", "junit-platform-launcher", version(1, 12, 2))) .include(dependency("com.willowtreeapps.assertk", "assertk-jvm", version(0, 28, 1))); publishOperation() From f57295637f6504b40e27706dabc815a397aadba7 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sun, 13 Apr 2025 13:34:54 -0700 Subject: [PATCH 13/28] Bump JaCoCo Report extension to version 0.9.10 --- lib/bld/bld-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bld/bld-wrapper.properties b/lib/bld/bld-wrapper.properties index fc9463a..751133d 100644 --- a/lib/bld/bld-wrapper.properties +++ b/lib/bld/bld-wrapper.properties @@ -3,7 +3,7 @@ bld.downloadExtensionSources=true bld.downloadLocation= bld.extension-detekt=com.uwyn.rife2:bld-detekt:0.9.10-SNAPSHOT bld.extension-dokka=com.uwyn.rife2:bld-dokka:1.0.4-SNAPSHOT -bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.10-SNAPSHOT +bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.10 bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.1.0-SNAPSHOT bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES bld.sourceDirectories= From a72af5cac65ac1c2b4abaff0bf00d2b3f4bf8c69 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 25 Apr 2025 09:28:04 -0700 Subject: [PATCH 14/28] Bump Gradle to version 8.14 --- .github/workflows/bld.yml | 5 ++--- .../gradle/gradle/wrapper/gradle-wrapper.jar | Bin 43705 -> 43764 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- examples/gradle/gradlew | 4 ++-- examples/gradle/gradlew.bat | 4 ++-- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index 4ee117f..2d75217 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -33,7 +33,7 @@ jobs: working-directory: examples/bld run: ./bld download - - name: Compile and run examples [bld examples] + - name: Compile and run examples [bld example] working-directory: examples/bld run: | ./bld compile @@ -41,9 +41,8 @@ jobs: ./bld run-retrieve ./bld run-java --args='https://erik.thauvin.net/ https://bit.ly/2PsNMAA' - - name: Run examples [gradle examples] + - name: Run examples [gradle example] working-directory: examples/gradle - if: matrix.java-version != '24' run: | ./gradlew run --args='https://erik.thauvin.net/ https://bit.ly/2PsNMAA' ./gradlew runRetrieve diff --git a/examples/gradle/gradle/wrapper/gradle-wrapper.jar b/examples/gradle/gradle/wrapper/gradle-wrapper.jar index 9bbc975c742b298b441bfb90dbc124400a3751b9..1b33c55baabb587c669f562ae36f953de2481846 100644 GIT binary patch delta 642 zcmdmamFde>rVZJA^}0Q$xegf!xPEW^+5YDM%iT2bEgct9o+jH~+sJas#HZ=szO|** z=Pj=X_vx?W&DSwKck|WWn~hffsvnQ+42*W$b7b0$SCcOoZ`{W{^$^pk;4>8-A*-)$ z?n(Po`1$6Jn_u?t-L+tsPyZ2#X}8T6OS8pAU;kdgd+_Hw4z4TW0p9E!T+=f7-c&O% zFic^X{7^$?^Ho04eona9n#mGMxKhA=~8B%JN`M zMhm5wc-2v)$``sY$!Q`9xiU@DhI73ZxiGEKg>yIPs)NmWwMdF-ngLXpZSqV5ez36n zVkxF2rjrjWR+_xr6e6@_u@s~2uv{9vi*1pj2)BjFD+-%@&pRVP1f{O1glxTOp2-62Ph;v z`N1+vCd)9ea)af*Ol1*JCfnp$%Uu}%OuoN7g2}3C@`L5FlP#(sA=|h@iixuZC?qp^ z=L$=v$ZoI}|87Wh=&h7udff{aieKr*l+zDp?pf)_bbRvUf>kn;HCDMXNlgbbo!QRK I1x7am0No)LiU0rr delta 584 zcmexzm1*ZyrVZJAexH5Moc8h7)w{^+t*dqJ%=yhh23L$9JpFV=_k`zJ-?Q4DI*eSe z+ES)HSrVnWLtJ&)lO%hRkV9zl5qqWRt0e;bb zPPo`)y?HTAyZI&u&X<|2$FDHCf4;!v8}p=?Tm`^F0`u(|1ttf~&t$qP3KUSD>@TJQ zRwJ}Pim6NzEc8KA6)e;S6gs8=7IIL8sQL*MYEuRYO;Uj<%3UbMbV&^&!Zvx+LKmjT z8Zch6rYP7Tw?$Hn(UTJwWiS=$f{lB(C=e*%usDV})0AQIK~sat=ND@+Gg*Pyij!rR z*fa02W|%BsV++>4W{DKDGSIUEHd2$P+8ct!RF+CHDowUuTEZOZ%rJSQv*qOXOSPDN zT|sP-$p*_3ncsWB*qoD7JQcyZ9xan%cJP6Tb4-?AZpr*F6v98hoNaPJm@HV`yya5N z))6pqFXn@}P(3T0nEzM8*c_9KtE9o|_pFd&K35GBXP^9Kg(b6GH-z8S4GDzIl~T+b zdLd#meKKHu$5u))8cu$=GKINkGDPOUD)!0$C(BH(U!}!-e;Q0ok8Sc?V1zRO04>ts AA^-pY diff --git a/examples/gradle/gradle/wrapper/gradle-wrapper.properties b/examples/gradle/gradle/wrapper/gradle-wrapper.properties index 37f853b..ca025c8 100644 --- a/examples/gradle/gradle/wrapper/gradle-wrapper.properties +++ b/examples/gradle/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/examples/gradle/gradlew b/examples/gradle/gradlew index faf9300..23d15a9 100755 --- a/examples/gradle/gradlew +++ b/examples/gradle/gradlew @@ -114,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/examples/gradle/gradlew.bat b/examples/gradle/gradlew.bat index 9d21a21..db3a6ac 100644 --- a/examples/gradle/gradlew.bat +++ b/examples/gradle/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell From cce4ddbcb97fc500d5d7686f99a10cc7e6a92196 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 3 May 2025 17:43:43 -0700 Subject: [PATCH 15/28] Cleanup tests --- config/detekt/baseline.xml | 5 +- .../kotlin/net/thauvin/erik/bitly/Utils.kt | 5 +- .../net/thauvin/erik/bitly/BitlinksTest.kt | 338 ++++++++++++++++++ .../net/thauvin/erik/bitly/BitlyTest.kt | 312 +++------------- .../net/thauvin/erik/bitly/UtilsTests.kt | 114 ++++++ .../thauvin/erik/bitly/config/ConfigTest.kt | 182 ++++++++-- .../bitly/config/deeplinks/DeeplinksTest.kt | 112 +++--- 7 files changed, 715 insertions(+), 353 deletions(-) create mode 100644 src/test/kotlin/net/thauvin/erik/bitly/BitlinksTest.kt create mode 100644 src/test/kotlin/net/thauvin/erik/bitly/UtilsTests.kt diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml index dc8efc2..c56ebfd 100644 --- a/config/detekt/baseline.xml +++ b/config/detekt/baseline.xml @@ -1,6 +1,6 @@ - + ConstructorParameterNaming:CreateConfig.kt$CreateConfig.Builder$var long_url: String FunctionParameterNaming:Bitlinks.kt$Bitlinks$bitlink_id: String @@ -42,7 +42,6 @@ VariableNaming:CreateConfig.kt$CreateConfig$val group_guid = builder.group_guid VariableNaming:CreateConfig.kt$CreateConfig$val long_url = builder.long_url VariableNaming:CreateConfig.kt$CreateConfig.Builder$var group_guid: String = Constants.EMPTY - WildcardImport:BitlyTest.kt$import assertk.assertions.* - WildcardImport:BitlyTest.kt$import kotlin.test.* + WildcardImport:BitlinksTest.kt$import assertk.assertions.* diff --git a/src/main/kotlin/net/thauvin/erik/bitly/Utils.kt b/src/main/kotlin/net/thauvin/erik/bitly/Utils.kt index 17441e0..dca27c2 100644 --- a/src/main/kotlin/net/thauvin/erik/bitly/Utils.kt +++ b/src/main/kotlin/net/thauvin/erik/bitly/Utils.kt @@ -174,8 +174,9 @@ object Utils { return false } + /** - * Removes http(s) scheme from string. + * Removes the `http` or `https` schemes from a string. */ @JvmStatic fun String.removeHttp(): String { @@ -183,7 +184,7 @@ object Utils { } /** - * Builds the full API endpoint URL using the [Constants.API_BASE_URL]. + * Converts a path to an API endpoint URL using the [Constants.API_BASE_URL], unless a URL is already specified. */ @JvmStatic fun String.toEndPoint(): String { diff --git a/src/test/kotlin/net/thauvin/erik/bitly/BitlinksTest.kt b/src/test/kotlin/net/thauvin/erik/bitly/BitlinksTest.kt new file mode 100644 index 0000000..66de791 --- /dev/null +++ b/src/test/kotlin/net/thauvin/erik/bitly/BitlinksTest.kt @@ -0,0 +1,338 @@ +/* + * BitlinksTest.kt + * + * Copyright 2020-2025 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.bitly + +import DisableOnCi +import assertk.all +import assertk.assertThat +import assertk.assertions.* +import net.thauvin.erik.bitly.config.CreateConfig +import net.thauvin.erik.bitly.config.UpdateConfig +import net.thauvin.erik.bitly.config.deeplinks.CreateDeeplinks +import net.thauvin.erik.bitly.config.deeplinks.UpdateDeeplinks +import net.thauvin.erik.bitly.config.deeplinks.enums.InstallType +import net.thauvin.erik.bitly.config.deeplinks.enums.Os +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable +import java.io.File +import java.util.logging.Level +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith +import kotlin.test.assertTrue + +class BitlinksTest { + private val bitly = with(File("local.properties")) { + if (exists()) { + Bitly(toPath()) + } else { + Bitly() + } + } + private val longUrl = "https://erik.thauvin.net/blog" + private val shortUrl = "https://bit.ly/380ojFd" + + companion object { + @JvmStatic + @BeforeAll + fun before() { + with(Utils.logger) { + level = Level.FINE + } + } + } + + @Nested + @DisplayName("Bitlinks Tests") + inner class BitlinksTests { + @Test + fun `Clicks summary`() { + val bl = bitly.bitlinks() + val clicks = bl.clicks(shortUrl, unit = Units.MONTH, units = 1) + assertThat(bl.lastCallResponse).all { + prop(CallResponse::description).isEmpty() + prop(CallResponse::isSuccessful).isTrue() + prop(CallResponse::statusCode).isEqualTo(200) + } + assertThat(clicks.toInt()).isGreaterThanOrEqualTo(0) + } + + @Test + fun `Clicks summary as json`() { + val bl = bitly.bitlinks() + val clicks = bl.clicks(shortUrl, toJson = true) + assertThat(bl.lastCallResponse).all { + prop(CallResponse::description).isEmpty() + prop(CallResponse::isSuccessful).isTrue() + prop(CallResponse::statusCode).isEqualTo(200) + } + assertThat(clicks).startsWith("{\"unit_reference\":") + } + } + + @Nested + @DisplayName("Create Bitlink Tests") + inner class CreateBitlinkTests { + @Test + fun `Create bitlink`() { + assertThat(bitly.bitlinks().create(long_url = longUrl), "create(longUrl)") + .matches("https://\\w+.\\w{2}/\\w{7}".toRegex()) + assertEquals( + shortUrl, + bitly.bitlinks().create( + domain = "bit.ly", + title = "Erik's Blog", + tags = arrayOf("erik", "thauvin", "blog", "weblog"), + long_url = longUrl + ) + ) + } + + @Test + fun `Create bitlink with config`() { + var config = CreateConfig.Builder(longUrl).build() + assertThat(bitly.bitlinks().create(config), "create(config)") + .matches("https://\\w+.\\w{2}/\\w{7}".toRegex()) + + config = CreateConfig.Builder(longUrl) + .domain("bit.ly") + .title("Erik's Blog") + .tags(arrayOf("erik", "thauvin", "blog", "weblog")) + .build() + assertEquals( + shortUrl, + bitly.bitlinks().create(config) + ) + } + + @Test + fun `Create bitlink with deep links`() { + val bl = bitly.bitlinks() + val dl = CreateDeeplinks().apply { + app_uri_path("/store?id=123456") + install_type(InstallType.NO_INSTALL) + install_url("https://play.google.com/store/apps/details?id=com.bitly.app&hl=en_US") + } + + val config = CreateConfig.Builder(longUrl) + .deeplinks(dl) + .domain("bit.ly") + .build() + + assertThat(bl.create(config)).isEqualTo(Constants.EMPTY) + assertThat(bl.lastCallResponse.isUpgradeRequired).isTrue() + } + } + + @Nested + @DisplayName("Expand Test") + inner class ExpandTests { + @Test + fun `Expand as json`() { + assertTrue( + bitly.bitlinks().expand(shortUrl, toJson = true) + .startsWith("{\"created_at\":") + ) + } + + @Test + fun `Expand link`() { + assertEquals(longUrl, Bitlinks(bitly.accessToken).expand(shortUrl)) + } + } + + @Nested + @DisplayName("Shorten Tests") + inner class ShortenTests { + @Test + fun `Shorten as json`() { + assertTrue( + bitly.bitlinks().shorten(longUrl, toJson = true) + .startsWith("{\"created_at\":") + ) + } + + @Test + fun `Shorten last call response`() { + val bl = Bitlinks(bitly.accessToken) + bl.shorten(longUrl, domain = "bit.ly") + assertThat(bl.lastCallResponse, "shorten(longUrl)").all { + prop(CallResponse::body).contains("\"link\":\"$shortUrl\"") + prop(CallResponse::isSuccessful).isTrue() + prop(CallResponse::message).isEmpty() + prop(CallResponse::statusCode).isEqualTo(200) + } + + bl.shorten(shortUrl) + assertThat(bl.lastCallResponse, "shorten(shortUrl)").all { + prop(CallResponse::description).isEqualTo("The value provided is invalid.") + prop(CallResponse::isBadRequest).isTrue() + prop(CallResponse::isSuccessful).isFalse() + prop(CallResponse::message).isEqualTo("ALREADY_A_BITLY_LINK") + prop(CallResponse::statusCode).isEqualTo(400) + } + } + + @Test + fun `Shorten link`() { + assertEquals( + shortUrl, Bitlinks(bitly.accessToken) + .shorten(longUrl, domain = "bit.ly") + ) + } + + @Test + fun `Shorten with invalid domain`() { + val bl = bitly.bitlinks() + bl.shorten("https://www.examples.com", domain = "foo.com") + assertThat(bl.lastCallResponse).all { + prop(CallResponse::description).contains("invalid") + prop(CallResponse::isBadRequest).isTrue() + prop(CallResponse::isSuccessful).isFalse() + prop(CallResponse::message).isEqualTo("INVALID_ARG_DOMAIN") + } + } + } + + @Nested + @DisplayName("Update Bitlink Tests") + inner class UpdateBitlinkTests { + @Test + fun `Update bitlink`() { + val bl = bitly.bitlinks() + assertEquals( + Constants.TRUE, + bl.update( + shortUrl, title = "Erik's Weblog", tags = arrayOf("blog", "weblog"), archived = true + ) + ) + + assertThat(bl.update(shortUrl, tags = emptyArray(), toJson = true), "update(tags)") + .contains("\"tags\":[]") + } + + @Test + fun `Update bitlink with config`() { + val bl = bitly.bitlinks() + var config = UpdateConfig.Builder(shortUrl) + .archived(true) + .tags(arrayOf("blog", "weblog")) + .title("Erik's Weblog") + .build() + + assertEquals(Constants.TRUE, bl.update(config)) + + config = UpdateConfig.Builder(shortUrl) + .toJson(true) + .build() + + assertThat(bl.update(config), "update(tags)").contains("\"tags\":[]") + } + + @Test + fun `Update bitlink with deep links`() { + val bl = bitly.bitlinks() + val dl = UpdateDeeplinks().apply { + os(Os.ANDROID) + brand_guid("Ba1bc23dE4F") + } + val config = UpdateConfig.Builder(shortUrl) + .deeplinks(dl) + .build() + + assertThat(bl.update(config)).isEqualTo(Constants.FALSE) + assertThat(bl.lastCallResponse.isUpgradeRequired).isTrue() + } + + @Test + @DisableOnCi + fun `Update custom bitlink`() { + val bl = bitly.bitlinks() + assertEquals( + Constants.TRUE, + bl.updateCustom("https://thauv.in/2NwtljT", "thauv.in/2NwtljT") + ) + } + } + + @Nested + @DisplayName("Validation Tests") + inner class ValidationTests { + @Test + fun `Empty URL should not shorten`() { + assertEquals(Constants.EMPTY, bitly.bitlinks().shorten(Constants.EMPTY)) + } + + @Test + fun `Short URL should not shorten`() { + assertEquals(shortUrl, bitly.bitlinks().shorten(shortUrl)) + } + + @Test + fun `Token not specified with API call`() { + assertFailsWith(IllegalArgumentException::class, "Utils.call()") { + Utils.call("", "foo") + } + } + + @Test + @DisableOnCi + fun `Token not specified`() { + val test = Bitly() + + assertFailsWith(IllegalArgumentException::class) { + test.bitlinks().shorten(longUrl) + } + } + + @Test + @EnabledIfEnvironmentVariable(named = "CI", matches = "true") + fun `Token not specified on CI`() { + val test = Bitly(Constants.EMPTY) // to void picking up the environment variable + + assertFailsWith(IllegalArgumentException::class) { + test.bitlinks().shorten(longUrl) + } + } + + @Test + fun `Token should be valid`() { + val test = Bitly().apply { accessToken = "12345679" } + assertEquals( + "{\"message\":\"FORBIDDEN\"}", + test.bitlinks().shorten("https://erik.thauvin.net/blog", toJson = true) + ) + } + } +} diff --git a/src/test/kotlin/net/thauvin/erik/bitly/BitlyTest.kt b/src/test/kotlin/net/thauvin/erik/bitly/BitlyTest.kt index 2af5f86..3ad00cf 100644 --- a/src/test/kotlin/net/thauvin/erik/bitly/BitlyTest.kt +++ b/src/test/kotlin/net/thauvin/erik/bitly/BitlyTest.kt @@ -31,24 +31,22 @@ package net.thauvin.erik.bitly -import DisableOnCi import assertk.all import assertk.assertThat -import assertk.assertions.* -import net.thauvin.erik.bitly.Utils.isValidUrl +import assertk.assertions.contains +import assertk.assertions.isTrue +import assertk.assertions.prop import net.thauvin.erik.bitly.Utils.removeHttp import net.thauvin.erik.bitly.Utils.toEndPoint -import net.thauvin.erik.bitly.config.CreateConfig -import net.thauvin.erik.bitly.config.UpdateConfig -import net.thauvin.erik.bitly.config.deeplinks.CreateDeeplinks -import net.thauvin.erik.bitly.config.deeplinks.UpdateDeeplinks -import net.thauvin.erik.bitly.config.deeplinks.enums.InstallType -import net.thauvin.erik.bitly.config.deeplinks.enums.Os import org.json.JSONObject import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested import java.io.File import java.util.logging.Level -import kotlin.test.* +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith class BitlyTest { private val bitly = with(File("local.properties")) { @@ -58,260 +56,8 @@ class BitlyTest { Bitly() } } - private val longUrl = "https://erik.thauvin.net/blog" private val shortUrl = "https://bit.ly/380ojFd" - @Test - fun `token should be specified`() { - val test = Bitly() - if (System.getenv("CI") == "true") { - test.accessToken = Constants.EMPTY - } - assertFailsWith(IllegalArgumentException::class) { - test.bitlinks().shorten(longUrl) - } - assertFailsWith(IllegalArgumentException::class, "Utils.call()") { - Utils.call("", "foo") - } - } - - @Test - fun `token should be valid`() { - val test = Bitly().apply { accessToken = "12345679" } - assertEquals( - "{\"message\":\"FORBIDDEN\"}", - test.bitlinks().shorten("https://erik.thauvin.net/blog", toJson = true) - ) - } - - @Test - fun `long url should be valid`() { - assertEquals(Constants.EMPTY, bitly.bitlinks().shorten(Constants.EMPTY)) - } - - @Test - fun `long url should not be short`() { - assertEquals(shortUrl, bitly.bitlinks().shorten(shortUrl)) - } - - @Test - fun `endPoint should be specified`() { - assertFailsWith(IllegalArgumentException::class, "bitly.call()") { - bitly.call("") - } - assertFailsWith(IllegalArgumentException::class, "Utils.call()") { - Utils.call("1234568", "") - } - } - - @Test - fun `endPoint conversion`() { - assertThat(Constants.API_BASE_URL.toEndPoint()).isEqualTo(Constants.API_BASE_URL) - assertThat("path".toEndPoint()).isEqualTo("${Constants.API_BASE_URL}/path") - assertThat("/path".toEndPoint()).isEqualTo("${Constants.API_BASE_URL}/path") - } - - @Test - fun `shorten = expand`() { - val shortUrl = bitly.bitlinks().shorten(longUrl, domain = "bit.ly") - assertEquals(longUrl, bitly.bitlinks().expand(shortUrl)) - } - - @Test - fun `shorten as json`() { - assertTrue(bitly.bitlinks().shorten(longUrl, toJson = true).startsWith("{\"created_at\":")) - } - - @Test - fun `get user`() { - assertThat(bitly.call("user", method = Methods.GET), "call(user)") - .prop(CallResponse::isSuccessful).isTrue() - assertThat(Utils.call(bitly.accessToken, "user".toEndPoint(), method = Methods.GET), "call(/user)").all { - prop(CallResponse::isSuccessful).isTrue() - prop(CallResponse::body).contains("login") - } - } - - @Test - fun `created by`() { - assertEquals( - "ethauvin", - JSONObject( - bitly.call( - "/bitlinks/${shortUrl.removeHttp()}", - method = Methods.GET - ).body - ).getString("created_by") - ) - } - - @Test - fun `bitlinks shorten`() { - assertEquals(shortUrl, Bitlinks(bitly.accessToken).shorten(longUrl, domain = "bit.ly")) - } - - @Test - fun `bitlinks expand`() { - assertEquals(longUrl, Bitlinks(bitly.accessToken).expand(shortUrl)) - } - - @Test - fun `bitlinks lastCallResponse`() { - val bl = Bitlinks(bitly.accessToken) - bl.shorten(longUrl, domain = "bit.ly") - assertThat(bl.lastCallResponse, "shorten(longUrl)").all { - prop(CallResponse::isSuccessful).isTrue() - prop(CallResponse::statusCode).isEqualTo(200) - prop(CallResponse::body).contains("\"link\":\"$shortUrl\"") - prop(CallResponse::message).isEmpty() - } - - bl.shorten(shortUrl) - assertThat(bl.lastCallResponse, "shorten(shortUrl)").all { - prop(CallResponse::isSuccessful).isFalse() - prop(CallResponse::statusCode).isEqualTo(400) - prop(CallResponse::isBadRequest).isTrue() - prop(CallResponse::message).isEqualTo("ALREADY_A_BITLY_LINK") - prop(CallResponse::description).isEqualTo("The value provided is invalid.") - } - } - - @Test - fun `clicks summary`() { - val bl = bitly.bitlinks() - assertThat(bl.clicks(shortUrl)).isNotEqualTo(Constants.EMPTY) - val clicks = bl.clicks(shortUrl, unit = Units.MONTH, units = 1) - assertThat(bl.lastCallResponse).all { - prop(CallResponse::isSuccessful).isTrue() - prop(CallResponse::statusCode).isEqualTo(200) - prop(CallResponse::description).isEmpty() - } - assertThat(clicks.toInt()).isGreaterThanOrEqualTo(0) - } - - @Test - fun `create bitlink`() { - assertThat(bitly.bitlinks().create(long_url = longUrl), "create(longUrl)") - .matches("https://\\w+.\\w{2}/\\w{7}".toRegex()) - assertEquals( - shortUrl, - bitly.bitlinks().create( - domain = "bit.ly", - title = "Erik's Blog", - tags = arrayOf("erik", "thauvin", "blog", "weblog"), - long_url = longUrl - ) - ) - } - - @Test - fun `create bitlink with config`() { - var config = CreateConfig.Builder(longUrl).build() - assertThat(bitly.bitlinks().create(config), "create(config)") - .matches("https://\\w+.\\w{2}/\\w{7}".toRegex()) - - config = CreateConfig.Builder(longUrl) - .domain("bit.ly") - .title("Erik's Blog") - .tags(arrayOf("erik", "thauvin", "blog", "weblog")) - .build() - assertEquals( - shortUrl, - bitly.bitlinks().create(config) - ) - } - - @Test - fun `create bitlink with deeplinks`() { - val bl = bitly.bitlinks() - val dl = CreateDeeplinks().apply { - install_type(InstallType.NO_INSTALL) - app_uri_path("/store?id=123456") - install_url("https://play.google.com/store/apps/details?id=com.bitly.app&hl=en_US") - } - - val config = CreateConfig.Builder(longUrl) - .domain("bit.ly") - .deeplinks(dl) - .build() - - assertThat(bl.create(config)).isEqualTo(Constants.EMPTY) - assertThat(bl.lastCallResponse.isUpgradeRequired).isTrue() - } - - @Test - fun `shorten with invalid domain`() { - val bl = bitly.bitlinks() - bl.shorten("https://www.examples.com", domain = "foo.com") - assertThat(bl.lastCallResponse).all { - prop(CallResponse::isSuccessful).isFalse() - prop(CallResponse::isBadRequest).isTrue() - prop(CallResponse::message).isEqualTo("INVALID_ARG_DOMAIN") - prop(CallResponse::description).contains("invalid") - } - } - - @Test - @DisableOnCi - fun `update custom bitlink`() { - val bl = bitly.bitlinks() - assertEquals( - Constants.TRUE, - bl.updateCustom("https://thauv.in/2NwtljT", "thauv.in/2NwtljT") - ) - } - - @Test - fun `update bitlink`() { - val bl = bitly.bitlinks() - assertEquals( - Constants.TRUE, - bl.update(shortUrl, title = "Erik's Weblog", tags = arrayOf("blog", "weblog"), archived = true) - ) - - assertThat(bl.update(shortUrl, tags = emptyArray(), toJson = true), "update(tags)") - .contains("\"tags\":[]") - } - - @Test - fun `update bitlink with config`() { - val bl = bitly.bitlinks() - var config = UpdateConfig.Builder(shortUrl) - .title("Erik's Weblog") - .tags(arrayOf("blog", "weblog")) - .archived(true) - .build() - - assertEquals(Constants.TRUE, bl.update(config)) - - config = UpdateConfig.Builder(shortUrl) - .toJson(true) - .build() - - assertThat(bl.update(config), "update(tags)").contains("\"tags\":[]") - } - - @Test - fun `update bitlink with deeplinks`() { - val bl = bitly.bitlinks() - val dl = UpdateDeeplinks().apply { - os(Os.ANDROID) - brand_guid("Ba1bc23dE4F") - } - val config = UpdateConfig.Builder(shortUrl) - .deeplinks(dl) - .build() - - assertThat(bl.update(config)).isEqualTo(Constants.FALSE) - assertThat(bl.lastCallResponse.isUpgradeRequired).isTrue() - } - - @Test - fun `validate URL`() { - assertTrue("https://www.example.com".isValidUrl(), "valid url") - assertFalse("this is a test".isValidUrl(), "invalid url") - } - companion object { @JvmStatic @BeforeAll @@ -321,4 +67,46 @@ class BitlyTest { } } } + + + @Nested + @DisplayName("API Call Tests") + inner class ApiCallTests { + @Test + fun `Created by`() { + assertEquals( + "ethauvin", + JSONObject( + bitly.call( + "/bitlinks/${shortUrl.removeHttp()}", + method = Methods.GET + ).body + ).getString("created_by") + ) + } + + @Test + fun `EndPoint should be specified`() { + assertFailsWith(IllegalArgumentException::class, "bitly.call()") { + bitly.call("") + } + assertFailsWith(IllegalArgumentException::class, "Utils.call()") { + Utils.call("1234568", "") + } + } + + @Test + fun `Get user`() { + assertThat(bitly.call("user", method = Methods.GET), "call(user)") + .prop(CallResponse::isSuccessful).isTrue() + assertThat( + Utils.call( + bitly.accessToken, "user".toEndPoint(), method = Methods.GET + ), "call(/user)" + ).all { + prop(CallResponse::isSuccessful).isTrue() + prop(CallResponse::body).contains("login") + } + } + } } diff --git a/src/test/kotlin/net/thauvin/erik/bitly/UtilsTests.kt b/src/test/kotlin/net/thauvin/erik/bitly/UtilsTests.kt new file mode 100644 index 0000000..a9a878b --- /dev/null +++ b/src/test/kotlin/net/thauvin/erik/bitly/UtilsTests.kt @@ -0,0 +1,114 @@ +/* + * UtilsTests.kt + * + * Copyright 2020-2025 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.bitly + +import assertk.assertThat +import assertk.assertions.isEqualTo +import net.thauvin.erik.bitly.Utils.isValidUrl +import net.thauvin.erik.bitly.Utils.removeHttp +import net.thauvin.erik.bitly.Utils.toEndPoint +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class UtilsTests { + @Nested + @DisplayName("Endpoint Conversion Tests") + inner class EndpointConversionTests { + @Test + fun `Convert endpoint with empty string`() { + assertThat("".toEndPoint()).isEqualTo("") + } + + @Test + fun `Convert endpoint with full URL`() { + assertThat("https://example.com/path".toEndPoint()).isEqualTo("https://example.com/path") + } + + @Test + fun `Convert endpoint with leading slash`() { + assertThat("/path".toEndPoint()).isEqualTo("${Constants.API_BASE_URL}/path") + } + + @Test + fun `Convert endpoint with multiple path segments`() { + assertThat("/existing/path".toEndPoint()).isEqualTo("${Constants.API_BASE_URL}/existing/path") + } + + @Test + fun `Convert endpoint with no leading slash`() { + assertThat("path".toEndPoint()).isEqualTo("${Constants.API_BASE_URL}/path") + } + + @Test + fun `Convert endpoint with trailing slash`() { + assertThat("path/".toEndPoint()).isEqualTo("${Constants.API_BASE_URL}/path/") + } + } + + @Nested + @DisplayName("Remote HTTP Tests") + inner class RemoteHTTPTests { + @Test + @Suppress("HttpUrlsUsage") + fun `Remove HTTP`() { + assertThat("http://example.com".removeHttp()).isEqualTo("example.com") + } + + @Test + fun `Remove HTTPS`() { + assertThat("https://example.com".removeHttp()).isEqualTo("example.com") + } + + @Test + fun `Remove mixed case`() { + assertThat("HtTPs://EXAMPLE.Com".removeHttp()).isEqualTo("EXAMPLE.Com") + } + + @Test + fun `Remove no scheme`() { + assertThat("example.com".removeHttp()).isEqualTo("example.com") + } + } + + @Test + fun `Validate invalid URL`() { + assertFalse("this is a test".isValidUrl(), "invalid url") + } + + @Test + fun `Validate URL`() { + assertTrue("https://www.example.com".isValidUrl(), "valid url") + } +} diff --git a/src/test/kotlin/net/thauvin/erik/bitly/config/ConfigTest.kt b/src/test/kotlin/net/thauvin/erik/bitly/config/ConfigTest.kt index 1472d1e..53debb4 100644 --- a/src/test/kotlin/net/thauvin/erik/bitly/config/ConfigTest.kt +++ b/src/test/kotlin/net/thauvin/erik/bitly/config/ConfigTest.kt @@ -31,49 +31,69 @@ package net.thauvin.erik.bitly.config +import assertk.all import assertk.assertThat import assertk.assertions.isEqualTo +import assertk.assertions.isTrue +import assertk.assertions.prop +import net.thauvin.erik.bitly.Constants import net.thauvin.erik.bitly.config.deeplinks.CreateDeeplinks import net.thauvin.erik.bitly.config.deeplinks.UpdateDeeplinks import net.thauvin.erik.bitly.config.deeplinks.enums.InstallType import net.thauvin.erik.bitly.config.deeplinks.enums.Os import org.json.JSONObject +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested import kotlin.test.Test class ConfigTest { - @Test - fun `create config test`() { - val deeplinks = CreateDeeplinks().apply { - app_id("app_id") - install_type(InstallType.AUTO_INSTALL) - } + @Nested + @DisplayName("Build Configuration Tests") + inner class BuildConfigurationTests { + @Test + fun `Build create configuration`() { + val deeplinks = CreateDeeplinks().apply { + app_id("app_id") + install_type(InstallType.AUTO_INSTALL) + } - val config = CreateConfig.Builder("long_url") - .domain("domain") - .groupGuid("group_guid") - .title("title") - .tags(arrayOf("tag", "tag2")) - .deeplinks(deeplinks) - .build() + val config = CreateConfig.Builder("long_url") + .deeplinks(deeplinks) + .domain("domain") + .groupGuid("group_guid") + .tags(arrayOf("tag", "tag2")) + .title("title") + .build() - val map = mapOf( - "long_url" to config.long_url, - "domain" to config.domain, - "group_guid" to config.group_guid, - "title" to config.title, - "tags" to config.tags, - "deeplinks" to arrayOf(deeplinks.links()) - ) + assertThat(config).all { + prop(CreateConfig::deeplinks).isEqualTo(deeplinks) + prop(CreateConfig::domain).isEqualTo("domain") + prop(CreateConfig::group_guid).isEqualTo("group_guid") + prop(CreateConfig::long_url).isEqualTo("long_url") + prop(CreateConfig::tags).isEqualTo(arrayOf("tag", "tag2")) + prop(CreateConfig::title).isEqualTo("title") + prop(CreateConfig::toJson).isEqualTo(false) + } - assertThat(JSONObject(map).toString()).isEqualTo( - """ - {"group_guid":"group_guid","long_url":"long_url","title":"title","deeplinks":[{"app_id":"app_id","install_type":"auto_install"}],"domain":"domain","tags":["tag","tag2"]} + val map = mapOf( + "deeplinks" to arrayOf(deeplinks.links()), + "domain" to config.domain, + "group_guid" to config.group_guid, + "long_url" to config.long_url, + "tags" to config.tags, + "title" to config.title + ) + + assertThat(JSONObject(map).toString()).isEqualTo( + """ + {"group_guid":"group_guid","deeplinks":[{"app_id":"app_id","install_type":"auto_install"}],"long_url":"long_url","title":"title","domain":"domain","tags":["tag","tag2"]} """.trimIndent() - ) + ) + } } @Test - fun `update config test`() { + fun `Build update configuration`() { val deeplinks = UpdateDeeplinks().apply { os(Os.IOS) install_type(InstallType.PROMOTE_INSTALL) @@ -81,25 +101,123 @@ class ConfigTest { } val config = UpdateConfig.Builder("blink") - .title("title") .archived(true) - .tags(arrayOf("tag", "tag2")) .deeplinks(deeplinks) + .tags(arrayOf("tag", "tag2")) + .title("title") .build() + assertThat(config).all { + prop(UpdateConfig::archived).isTrue() + prop(UpdateConfig::bitlink).isEqualTo("blink") + prop(UpdateConfig::deeplinks).isEqualTo(deeplinks) + prop(UpdateConfig::tags).isEqualTo(arrayOf("tag", "tag2")) + prop(UpdateConfig::title).isEqualTo("title") + prop(UpdateConfig::toJson).isEqualTo(false) + } + val map = mapOf( - "bitlink" to config.bitlink, - "title" to config.title, "archived" to config.archived, + "bitlink" to config.bitlink, + "deeplinks" to arrayOf(deeplinks.links()), "tags" to config.tags, - "deeplinks" to arrayOf(deeplinks.links()) + "title" to config.title ) assertThat(JSONObject(map).toString()).isEqualTo( """ - {"archived":true,"bitlink":"blink","title":"title","deeplinks":[{"os":"ios","app_guid":"app_guid","install_type":"promote_install"}],"tags":["tag","tag2"]} + {"archived":true,"bitlink":"blink","deeplinks":[{"os":"ios","app_guid":"app_guid","install_type":"promote_install"}],"title":"title","tags":["tag","tag2"]} """.trimIndent() ) + } + @Nested + @DisplayName("Validate Configuration Tests") + inner class ValidateConfigurationTests { + @Test + fun `Validate create configuration`() { + val deeplinks = CreateDeeplinks().apply { + app_id("app_id") + install_type(InstallType.AUTO_INSTALL) + } + + val config = CreateConfig.Builder("long_url") + .deeplinks(deeplinks) + .domain("domain") + .groupGuid("group_guid") + .tags(arrayOf("tag", "tag2")) + .title("title") + .toJson(true) + + assertThat(config).all { + prop(CreateConfig.Builder::deeplinks).prop(CreateDeeplinks::links).isEqualTo(deeplinks.links()) + prop(CreateConfig.Builder::domain).isEqualTo("domain") + prop(CreateConfig.Builder::group_guid).isEqualTo("group_guid") + prop(CreateConfig.Builder::long_url).isEqualTo("long_url") + prop(CreateConfig.Builder::tags).isEqualTo(arrayOf("tag", "tag2")) + prop(CreateConfig.Builder::title).isEqualTo("title") + prop(CreateConfig.Builder::toJson).isTrue() + } + + config.longUrl("longer_url") + assertThat(config).prop(CreateConfig.Builder::long_url).isEqualTo("longer_url") + } + + @Test + fun `Validate create default configuration`() { + val config = CreateConfig.Builder("long_url") + + assertThat(config).all { + prop(CreateConfig.Builder::long_url).isEqualTo("long_url") + prop(CreateConfig.Builder::domain).isEqualTo(Constants.EMPTY) + prop(CreateConfig.Builder::group_guid).isEqualTo(Constants.EMPTY) + prop(CreateConfig.Builder::title).isEqualTo(Constants.EMPTY) + prop(CreateConfig.Builder::tags).isEqualTo(emptyArray()) + prop(CreateConfig.Builder::deeplinks).prop(CreateDeeplinks::links).isEqualTo(CreateDeeplinks().links()) + prop(CreateConfig.Builder::toJson).isEqualTo(false) + } + } + + @Test + fun `Validate update configuration`() { + val deeplinks = UpdateDeeplinks().apply { + os(Os.IOS) + install_type(InstallType.PROMOTE_INSTALL) + app_guid("app_guid") + } + + val config = UpdateConfig.Builder("bitlink") + .title("title") + .archived(true) + .tags(arrayOf("tag", "tag2")) + .deeplinks(deeplinks) + .toJson(true) + + assertThat(config).all { + prop(UpdateConfig.Builder::bitlink).isEqualTo("bitlink") + prop(UpdateConfig.Builder::title).isEqualTo("title") + prop(UpdateConfig.Builder::archived).isTrue() + prop(UpdateConfig.Builder::tags).isEqualTo(arrayOf("tag", "tag2")) + prop(UpdateConfig.Builder::deeplinks).isEqualTo(deeplinks) + prop(UpdateConfig.Builder::toJson).isTrue() + } + + config.bitlink("blink") + assertThat(config).prop(UpdateConfig.Builder::bitlink).isEqualTo("blink") + } + + @Test + fun `Validate update default configuration`() { + val config = UpdateConfig.Builder("bitlink") + + assertThat(config).all { + prop(UpdateConfig.Builder::bitlink).isEqualTo("bitlink") + prop(UpdateConfig.Builder::title).isEqualTo(Constants.EMPTY) + prop(UpdateConfig.Builder::archived).isEqualTo(false) + prop(UpdateConfig.Builder::tags).isEqualTo(emptyArray()) + prop(UpdateConfig.Builder::deeplinks).prop(UpdateDeeplinks::links).isEqualTo(UpdateDeeplinks().links()) + prop(UpdateConfig.Builder::toJson).isEqualTo(false) + } + } } } diff --git a/src/test/kotlin/net/thauvin/erik/bitly/config/deeplinks/DeeplinksTest.kt b/src/test/kotlin/net/thauvin/erik/bitly/config/deeplinks/DeeplinksTest.kt index c5dff39..9a0fcb4 100644 --- a/src/test/kotlin/net/thauvin/erik/bitly/config/deeplinks/DeeplinksTest.kt +++ b/src/test/kotlin/net/thauvin/erik/bitly/config/deeplinks/DeeplinksTest.kt @@ -31,11 +31,11 @@ package net.thauvin.erik.bitly.config.deeplinks +import assertk.all import assertk.assertThat -import assertk.assertions.contains -import assertk.assertions.doesNotContain import assertk.assertions.isEqualTo import assertk.assertions.isNull +import assertk.assertions.prop import net.thauvin.erik.bitly.config.deeplinks.enums.InstallType import net.thauvin.erik.bitly.config.deeplinks.enums.Os import org.json.JSONObject @@ -45,88 +45,92 @@ import java.time.ZonedDateTime class DeeplinksTest { @Test - fun `create test`() { + fun `Create deeplink`() { val deeplinks = CreateDeeplinks().apply { app_uri_path("app_uri_path") install_type(InstallType.NO_INSTALL) } - assertThat(deeplinks.install_url()).isNull() - deeplinks.install_url("install_url") - - assertThat(deeplinks.app_uri_path()).isEqualTo("app_uri_path") - assertThat(deeplinks.install_type()).isEqualTo(InstallType.NO_INSTALL) + assertThat(deeplinks).all { + prop(CreateDeeplinks::app_id).isNull() + prop(CreateDeeplinks::app_uri_path).isEqualTo("app_uri_path") + prop(CreateDeeplinks::install_type).isEqualTo(InstallType.NO_INSTALL) + prop(CreateDeeplinks::install_url).isNull() + prop(CreateDeeplinks::links).isEqualTo(deeplinks.links()) + } assertThat(JSONObject(deeplinks.links()).toString()).isEqualTo( """ - {"app_uri_path":"app_uri_path","install_type":"no_install","install_url":"install_url"} + {"app_uri_path":"app_uri_path","install_type":"no_install"} """.trimIndent() ) - deeplinks.install_type(InstallType.PROMOTE_INSTALL) deeplinks.app_id("app_id") + deeplinks.install_type(InstallType.PROMOTE_INSTALL) + deeplinks.install_url("install_url") - assertThat(deeplinks.app_id()).isEqualTo("app_id") - - assertThat(JSONObject(deeplinks.links()).toString()).apply { - doesNotContain(InstallType.NO_INSTALL.type) - contains(InstallType.PROMOTE_INSTALL.type) - contains("\"app_id\":\"app_id\"") + assertThat(deeplinks).all { + prop(CreateDeeplinks::app_id).isEqualTo("app_id") + prop(CreateDeeplinks::install_type).isEqualTo(InstallType.PROMOTE_INSTALL) + prop(CreateDeeplinks::install_url).isEqualTo("install_url") } + + assertThat(JSONObject(deeplinks.links()).toString()).isEqualTo( + """ + {"install_url":"install_url","app_id":"app_id","app_uri_path":"app_uri_path","install_type":"promote_install"} + """.trimIndent() + ) } @Test - fun `update test`() { + fun `Update deeplink`() { val deeplinks = UpdateDeeplinks().apply { app_guid("app_guid") - os(Os.IOS) - install_type(InstallType.NO_INSTALL) - guid("guid") - install_url("install_url") app_uri_path("app_uri_path") created("created") + guid("guid") + install_type(InstallType.NO_INSTALL) + install_url("install_url") modified("modified") + os(Os.IOS) } - assertThat(deeplinks.brand_guid()).isNull() + assertThat(deeplinks).all { + prop(UpdateDeeplinks::app_guid).isEqualTo("app_guid") + prop(UpdateDeeplinks::app_uri_path).isEqualTo("app_uri_path") + prop(UpdateDeeplinks::bitlink).isNull() + prop(UpdateDeeplinks::brand_guid).isNull() + prop(UpdateDeeplinks::created).isEqualTo("created") + prop(UpdateDeeplinks::guid).isEqualTo("guid") + prop(UpdateDeeplinks::install_type).isEqualTo(InstallType.NO_INSTALL) + prop(UpdateDeeplinks::install_url).isEqualTo("install_url") + prop(UpdateDeeplinks::links).isEqualTo(deeplinks.links()) + prop(UpdateDeeplinks::modified).isEqualTo("modified") + prop(UpdateDeeplinks::os).isEqualTo(Os.IOS) + } + + val zdt = ZonedDateTime.of(1997, 8, 29, 2, 14, 0, 0, ZoneId.of("US/Eastern")) + + deeplinks.bitlink("bitlink") deeplinks.brand_guid("brand_guid") + deeplinks.created(zdt) + deeplinks.install_type(InstallType.PROMOTE_INSTALL) + deeplinks.modified(zdt) + deeplinks.os(Os.ANDROID) - assertThat(deeplinks.app_uri_path()).isEqualTo("app_uri_path") - assertThat(deeplinks.install_url()).isEqualTo("install_url") - - assertThat(deeplinks.os()).isEqualTo(Os.IOS) - assertThat(deeplinks.install_type()).isEqualTo(InstallType.NO_INSTALL) - assertThat(deeplinks.app_guid()).isEqualTo("app_guid") - assertThat(deeplinks.modified()).isEqualTo("modified") - assertThat(deeplinks.brand_guid()).isEqualTo("brand_guid") - + assertThat(deeplinks).all { + prop(UpdateDeeplinks::bitlink).isEqualTo("bitlink") + prop(UpdateDeeplinks::brand_guid).isEqualTo("brand_guid") + prop(UpdateDeeplinks::created).isEqualTo("1997-08-29T02:14:00-0400") + prop(UpdateDeeplinks::install_type).isEqualTo(InstallType.PROMOTE_INSTALL) + prop(UpdateDeeplinks::modified).isEqualTo("1997-08-29T02:14:00-0400") + prop(UpdateDeeplinks::os).isEqualTo(Os.ANDROID) + } assertThat(JSONObject(deeplinks.links()).toString()).isEqualTo( """ - {"app_guid":"app_guid","install_url":"install_url","os":"ios","app_uri_path":"app_uri_path","created":"created","brand_guid":"brand_guid","guid":"guid","modified":"modified","install_type":"no_install"} + {"app_guid":"app_guid","install_url":"install_url","bitlink":"bitlink","os":"android","app_uri_path":"app_uri_path","created":"1997-08-29T02:14:00-0400","brand_guid":"brand_guid","guid":"guid","modified":"1997-08-29T02:14:00-0400","install_type":"promote_install"} """.trimIndent() ) - - deeplinks.install_type(InstallType.PROMOTE_INSTALL) - deeplinks.os(Os.ANDROID) - deeplinks.bitlink("bitlink") - - val zdt = ZonedDateTime.of(1997, 8, 29, 2, 14, 0, 0, ZoneId.of("US/Eastern")) - deeplinks.modified(zdt) - deeplinks.created(zdt) - - assertThat(deeplinks.bitlink()).isEqualTo("bitlink") - assertThat(deeplinks.created()).isEqualTo("1997-08-29T02:14:00-0400") - assertThat(deeplinks.modified()).isEqualTo("1997-08-29T02:14:00-0400") - - assertThat(JSONObject(deeplinks.links()).toString()).apply { - doesNotContain(InstallType.NO_INSTALL.type) - contains(InstallType.PROMOTE_INSTALL.type) - - doesNotContain(Os.IOS.type) - contains("\"os\":\"android\"") - - contains("\"bitlink\":\"bitlink\"") - } } } From fc3e641793255e6d4b11b86ba3f0294776d02fc9 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 14 May 2025 22:01:27 -0700 Subject: [PATCH 16/28] Bumped Kotlin to version 2.1.21 --- .github/workflows/bld.yml | 2 +- .idea/kotlinc.xml | 16 ++++++++++++++++ README.md | 2 +- examples/gradle/.idea/kotlinc.xml | 4 ++-- examples/gradle/build.gradle.kts | 2 +- 5 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 .idea/kotlinc.xml diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index 2d75217..b5a8fee 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: java-version: [ 17, 21, 24 ] - kotlin-version: [ 1.9.25, 2.0.21, 2.1.20 ] + kotlin-version: [ 1.9.25, 2.0.21, 2.1.21 ] os: [ ubuntu-latest, windows-latest, macos-latest ] runs-on: ${{ matrix.os }} diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..43546f2 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 02d7aae..75e9103 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![License (3-Clause BSD)](https://img.shields.io/badge/license-BSD%203--Clause-blue.svg?style=flat-square)](https://opensource.org/licenses/BSD-3-Clause) -[![Kotlin](https://img.shields.io/badge/kotlin-2.1.20-7f52ff)](https://kotlinlang.org/) +[![Kotlin](https://img.shields.io/badge/kotlin-2.1.21-7f52ff)](https://kotlinlang.org/) [![bld](https://img.shields.io/badge/2.2.1-FA9052?label=bld&labelColor=2392FF)](https://rife2.com/bld) [![Release](https://img.shields.io/github/release/ethauvin/bitly-shorten.svg)](https://github.com/ethauvin/bitly-shorten/releases/latest) [![Maven Central](https://img.shields.io/maven-central/v/net.thauvin.erik/bitly-shorten.svg?color=blue)](https://central.sonatype.com/artifact/net.thauvin.erik/bitly-shorten) diff --git a/examples/gradle/.idea/kotlinc.xml b/examples/gradle/.idea/kotlinc.xml index 6d0ee1c..750533e 100644 --- a/examples/gradle/.idea/kotlinc.xml +++ b/examples/gradle/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - - \ No newline at end of file + diff --git a/examples/gradle/build.gradle.kts b/examples/gradle/build.gradle.kts index e265ddb..cf9405b 100644 --- a/examples/gradle/build.gradle.kts +++ b/examples/gradle/build.gradle.kts @@ -1,7 +1,7 @@ plugins { id("application") id("com.github.ben-manes.versions") version "0.51.0" - kotlin("jvm") version "2.1.20" + kotlin("jvm") version "2.1.21" } repositories { From 820ec736bb5fce08cf5a9245f5fc457301307f79 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 14 May 2025 22:01:57 -0700 Subject: [PATCH 17/28] Generates and convert JUnit test reports for xunit-view --- lib/bld/bld-wrapper.properties | 1 + .../thauvin/erik/bitly/BitlyShortenBuild.java | 40 ++++++++++---- .../net/thauvin/erik/bitly/BeforeAll.kt | 52 +++++++++++++++++++ .../{BitlinksTest.kt => BitlinksTests.kt} | 20 ++----- .../bitly/{BitlyTest.kt => BitlyTests.kt} | 19 ++----- .../config/{ConfigTest.kt => ConfigTests.kt} | 4 +- .../{DeeplinksTest.kt => DeeplinksTests.kt} | 4 +- 7 files changed, 96 insertions(+), 44 deletions(-) create mode 100644 src/test/kotlin/net/thauvin/erik/bitly/BeforeAll.kt rename src/test/kotlin/net/thauvin/erik/bitly/{BitlinksTest.kt => BitlinksTests.kt} (96%) rename src/test/kotlin/net/thauvin/erik/bitly/{BitlyTest.kt => BitlyTests.kt} (92%) rename src/test/kotlin/net/thauvin/erik/bitly/config/{ConfigTest.kt => ConfigTests.kt} (99%) rename src/test/kotlin/net/thauvin/erik/bitly/config/deeplinks/{DeeplinksTest.kt => DeeplinksTests.kt} (99%) diff --git a/lib/bld/bld-wrapper.properties b/lib/bld/bld-wrapper.properties index 751133d..d1179fb 100644 --- a/lib/bld/bld-wrapper.properties +++ b/lib/bld/bld-wrapper.properties @@ -3,6 +3,7 @@ bld.downloadExtensionSources=true bld.downloadLocation= bld.extension-detekt=com.uwyn.rife2:bld-detekt:0.9.10-SNAPSHOT bld.extension-dokka=com.uwyn.rife2:bld-dokka:1.0.4-SNAPSHOT +bld.extension-exec=com.uwyn.rife2:bld-exec:1.0.5 bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.10 bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.1.0-SNAPSHOT bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES diff --git a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java index 4465ac4..ea44e28 100644 --- a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java +++ b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java @@ -33,14 +33,10 @@ package net.thauvin.erik.bitly; import rife.bld.BuildCommand; import rife.bld.Project; -import rife.bld.extension.CompileKotlinOperation; -import rife.bld.extension.DetektOperation; -import rife.bld.extension.DokkaOperation; -import rife.bld.extension.JacocoReportOperation; +import rife.bld.extension.*; import rife.bld.extension.dokka.LoggingLevel; import rife.bld.extension.dokka.OutputFormat; import rife.bld.extension.dokka.SourceSet; -import rife.bld.extension.kotlin.CompileOptions; import rife.bld.operations.exceptions.ExitStatusException; import rife.bld.publish.PomBuilder; import rife.bld.publish.PublishDeveloper; @@ -50,6 +46,8 @@ import rife.tools.exceptions.FileUtilsErrorException; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; import java.util.logging.ConsoleHandler; import java.util.logging.Level; @@ -68,12 +66,14 @@ public class BitlyShortenBuild extends Project { version = version(2, 0, 1, "SNAPSHOT"); javaRelease = 11; + downloadSources = true; autoDownloadPurge = true; + repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL); var okHttp = version(4, 12, 0); - final var kotlin = version(2, 1, 20); + final var kotlin = version(2, 1, 21); scope(compile) // Kotlin .include(dependency("org.jetbrains.kotlin", "kotlin-stdlib", kotlin)) @@ -140,10 +140,9 @@ public class BitlyShortenBuild extends Project { @BuildCommand(summary = "Compiles the Kotlin project") @Override public void compile() throws Exception { - new CompileKotlinOperation() - .fromProject(this) - .compileOptions(new CompileOptions().verbose(true)) - .execute(); + var op = new CompileKotlinOperation().fromProject(this); + op.compileOptions().languageVersion("1.9").verbose(true); + op.execute(); } @BuildCommand(summary = "Checks source with Detekt") @@ -220,4 +219,25 @@ public class BitlyShortenBuild extends Project { PomBuilder.generateInto(publishOperation().fromProject(this).info(), dependencies(), new File(workDirectory, "pom.xml")); } + + @Override + public void test() throws Exception { + var testResultsDir = "build/test-results/test/"; + + var op = testOperation().fromProject(this); + op.testToolOptions().reportsDir(new File(testResultsDir)); + op.execute(); + + var xunitViewer = new File("/usr/bin/xunit-viewer"); + if (xunitViewer.exists() && xunitViewer.canExecute()) { + var reportsDir = "build/reports/tests/test/"; + + Files.createDirectories(Path.of(reportsDir)); + + new ExecOperation() + .fromProject(this) + .command(xunitViewer.getPath(), "-r", testResultsDir, "-o", reportsDir + "index.html") + .execute(); + } + } } diff --git a/src/test/kotlin/net/thauvin/erik/bitly/BeforeAll.kt b/src/test/kotlin/net/thauvin/erik/bitly/BeforeAll.kt new file mode 100644 index 0000000..56f12d8 --- /dev/null +++ b/src/test/kotlin/net/thauvin/erik/bitly/BeforeAll.kt @@ -0,0 +1,52 @@ +/* + * BeforeAll.kt + * + * Copyright 2020-2025 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.bitly + +import org.junit.jupiter.api.extension.BeforeAllCallback +import org.junit.jupiter.api.extension.ExtensionContext +import java.util.concurrent.atomic.AtomicBoolean +import java.util.logging.ConsoleHandler +import java.util.logging.Level + +class BeforeAll : BeforeAllCallback { + private val isFirstTime: AtomicBoolean = AtomicBoolean(true) + + override fun beforeAll(context: ExtensionContext?) { + if (isFirstTime.getAndSet(false)) { + with(Utils.logger) { + addHandler(ConsoleHandler().apply { level = Level.FINE }) + level = Level.FINE + } + } + } +} + diff --git a/src/test/kotlin/net/thauvin/erik/bitly/BitlinksTest.kt b/src/test/kotlin/net/thauvin/erik/bitly/BitlinksTests.kt similarity index 96% rename from src/test/kotlin/net/thauvin/erik/bitly/BitlinksTest.kt rename to src/test/kotlin/net/thauvin/erik/bitly/BitlinksTests.kt index 66de791..19d7467 100644 --- a/src/test/kotlin/net/thauvin/erik/bitly/BitlinksTest.kt +++ b/src/test/kotlin/net/thauvin/erik/bitly/BitlinksTests.kt @@ -1,5 +1,5 @@ /* - * BitlinksTest.kt + * BitlinksTests.kt * * Copyright 2020-2025 Erik C. Thauvin (erik@thauvin.net) * @@ -41,18 +41,18 @@ import net.thauvin.erik.bitly.config.deeplinks.CreateDeeplinks import net.thauvin.erik.bitly.config.deeplinks.UpdateDeeplinks import net.thauvin.erik.bitly.config.deeplinks.enums.InstallType import net.thauvin.erik.bitly.config.deeplinks.enums.Os -import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable +import org.junit.jupiter.api.extension.ExtendWith import java.io.File -import java.util.logging.Level import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertTrue -class BitlinksTest { +@ExtendWith(BeforeAll::class) +class BitlinksTests { private val bitly = with(File("local.properties")) { if (exists()) { Bitly(toPath()) @@ -63,16 +63,6 @@ class BitlinksTest { private val longUrl = "https://erik.thauvin.net/blog" private val shortUrl = "https://bit.ly/380ojFd" - companion object { - @JvmStatic - @BeforeAll - fun before() { - with(Utils.logger) { - level = Level.FINE - } - } - } - @Nested @DisplayName("Bitlinks Tests") inner class BitlinksTests { @@ -319,7 +309,7 @@ class BitlinksTest { @Test @EnabledIfEnvironmentVariable(named = "CI", matches = "true") fun `Token not specified on CI`() { - val test = Bitly(Constants.EMPTY) // to void picking up the environment variable + val test = Bitly(Constants.EMPTY) // to avoid picking up the environment variable assertFailsWith(IllegalArgumentException::class) { test.bitlinks().shorten(longUrl) diff --git a/src/test/kotlin/net/thauvin/erik/bitly/BitlyTest.kt b/src/test/kotlin/net/thauvin/erik/bitly/BitlyTests.kt similarity index 92% rename from src/test/kotlin/net/thauvin/erik/bitly/BitlyTest.kt rename to src/test/kotlin/net/thauvin/erik/bitly/BitlyTests.kt index 3ad00cf..aa33b48 100644 --- a/src/test/kotlin/net/thauvin/erik/bitly/BitlyTest.kt +++ b/src/test/kotlin/net/thauvin/erik/bitly/BitlyTests.kt @@ -1,5 +1,5 @@ /* - * BitlyTest.kt + * BitlyTests.kt * * Copyright 2020-2025 Erik C. Thauvin (erik@thauvin.net) * @@ -39,16 +39,16 @@ import assertk.assertions.prop import net.thauvin.erik.bitly.Utils.removeHttp import net.thauvin.erik.bitly.Utils.toEndPoint import org.json.JSONObject -import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.extension.ExtendWith import java.io.File -import java.util.logging.Level import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith -class BitlyTest { +@ExtendWith(BeforeAll::class) +class BitlyTests { private val bitly = with(File("local.properties")) { if (exists()) { Bitly(toPath()) @@ -58,17 +58,6 @@ class BitlyTest { } private val shortUrl = "https://bit.ly/380ojFd" - companion object { - @JvmStatic - @BeforeAll - fun before() { - with(Utils.logger) { - level = Level.FINE - } - } - } - - @Nested @DisplayName("API Call Tests") inner class ApiCallTests { diff --git a/src/test/kotlin/net/thauvin/erik/bitly/config/ConfigTest.kt b/src/test/kotlin/net/thauvin/erik/bitly/config/ConfigTests.kt similarity index 99% rename from src/test/kotlin/net/thauvin/erik/bitly/config/ConfigTest.kt rename to src/test/kotlin/net/thauvin/erik/bitly/config/ConfigTests.kt index 53debb4..09c45ed 100644 --- a/src/test/kotlin/net/thauvin/erik/bitly/config/ConfigTest.kt +++ b/src/test/kotlin/net/thauvin/erik/bitly/config/ConfigTests.kt @@ -1,5 +1,5 @@ /* - * ConfigTest.kt + * ConfigTests.kt * * Copyright 2020-2025 Erik C. Thauvin (erik@thauvin.net) * @@ -46,7 +46,7 @@ import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Nested import kotlin.test.Test -class ConfigTest { +class ConfigTests { @Nested @DisplayName("Build Configuration Tests") inner class BuildConfigurationTests { diff --git a/src/test/kotlin/net/thauvin/erik/bitly/config/deeplinks/DeeplinksTest.kt b/src/test/kotlin/net/thauvin/erik/bitly/config/deeplinks/DeeplinksTests.kt similarity index 99% rename from src/test/kotlin/net/thauvin/erik/bitly/config/deeplinks/DeeplinksTest.kt rename to src/test/kotlin/net/thauvin/erik/bitly/config/deeplinks/DeeplinksTests.kt index 9a0fcb4..cf3ecbb 100644 --- a/src/test/kotlin/net/thauvin/erik/bitly/config/deeplinks/DeeplinksTest.kt +++ b/src/test/kotlin/net/thauvin/erik/bitly/config/deeplinks/DeeplinksTests.kt @@ -1,5 +1,5 @@ /* - * DeeplinksTest.kt + * DeeplinksTests.kt * * Copyright 2020-2025 Erik C. Thauvin (erik@thauvin.net) * @@ -43,7 +43,7 @@ import org.junit.Test import java.time.ZoneId import java.time.ZonedDateTime -class DeeplinksTest { +class DeeplinksTests { @Test fun `Create deeplink`() { val deeplinks = CreateDeeplinks().apply { From 4b4b27346122b1d8da8f02f96544155a7440b69c Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 28 May 2025 18:19:02 -0700 Subject: [PATCH 18/28] Bump org.json to version 20250517 --- examples/bld/src/bld/java/com/example/ExampleBuild.java | 2 +- pom.xml | 2 +- src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/bld/src/bld/java/com/example/ExampleBuild.java b/examples/bld/src/bld/java/com/example/ExampleBuild.java index 0a3eb7a..ec0be3e 100644 --- a/examples/bld/src/bld/java/com/example/ExampleBuild.java +++ b/examples/bld/src/bld/java/com/example/ExampleBuild.java @@ -25,7 +25,7 @@ public class ExampleBuild extends BaseProject { scope(compile) .include(dependency("net.thauvin.erik:bitly-shorten:2.0.1-SNAPSHOT")) - .include(dependency("org.json:json:20250107")); + .include(dependency("org.json:json:20250517")); } public static void main(String[] args) { diff --git a/pom.xml b/pom.xml index 75bbccc..75c951b 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ org.json json - 20250107 + 20250517 compile diff --git a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java index ea44e28..dda144b 100644 --- a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java +++ b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java @@ -83,7 +83,7 @@ public class BitlyShortenBuild extends Project { .include(dependency("com.squareup.okhttp3", "okhttp", okHttp)) .include(dependency("com.squareup.okhttp3", "logging-interceptor", okHttp)) // JSON - .include(dependency("org.json", "json", "20250107")); + .include(dependency("org.json", "json", "20250517")); scope(test) .include(dependency("org.jetbrains.kotlin", "kotlin-test-junit5", kotlin)) .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 2))) From 3eeae9c19b2ae35a5348111def4ab82e1c01d20d Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 28 May 2025 18:20:22 -0700 Subject: [PATCH 19/28] Bump Gradle to version 8.14.1 --- examples/gradle/gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gradle/gradle/wrapper/gradle-wrapper.properties b/examples/gradle/gradle/wrapper/gradle-wrapper.properties index ca025c8..002b867 100644 --- a/examples/gradle/gradle/wrapper/gradle-wrapper.properties +++ b/examples/gradle/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 3fe4c9cfc530ffc9d2b7d24afa6b95f297d1b1ff Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 28 May 2025 18:21:29 -0700 Subject: [PATCH 20/28] Generate and convert JUnit reports for xunit-viewer --- lib/bld/bld-wrapper.properties | 2 +- .../thauvin/erik/bitly/BitlyShortenBuild.java | 86 ++++++++++++------- 2 files changed, 56 insertions(+), 32 deletions(-) diff --git a/lib/bld/bld-wrapper.properties b/lib/bld/bld-wrapper.properties index d1179fb..1645ccd 100644 --- a/lib/bld/bld-wrapper.properties +++ b/lib/bld/bld-wrapper.properties @@ -4,7 +4,7 @@ bld.downloadLocation= bld.extension-detekt=com.uwyn.rife2:bld-detekt:0.9.10-SNAPSHOT bld.extension-dokka=com.uwyn.rife2:bld-dokka:1.0.4-SNAPSHOT bld.extension-exec=com.uwyn.rife2:bld-exec:1.0.5 -bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.10 +bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.11-SNAPSHOT bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.1.0-SNAPSHOT bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES bld.sourceDirectories= diff --git a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java index dda144b..44ed5e7 100644 --- a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java +++ b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java @@ -58,6 +58,7 @@ import static rife.bld.dependencies.Scope.compile; import static rife.bld.dependencies.Scope.test; public class BitlyShortenBuild extends Project { + static final String TEST_RESULTS_DIR = "build/test-results/test/"; final File srcMainKotlin = new File(srcMainDirectory(), "kotlin"); public BitlyShortenBuild() { @@ -184,10 +185,60 @@ public class BitlyShortenBuild extends Project { @BuildCommand(summary = "Generates JaCoCo Reports") public void jacoco() throws Exception { - new JacocoReportOperation() - .fromProject(this) - .sourceFiles(srcMainKotlin) - .execute(); + var op = new JacocoReportOperation().fromProject(this); + op.testToolOptions("--reports-dir=" + TEST_RESULTS_DIR); + + Exception ex = null; + try { + op.execute(); + } catch (Exception e) { + ex = e; + } + + renderWithXunitViewer(); + + if (ex != null) { + throw ex; + } + } + + @BuildCommand(value = "pom-root", summary = "Generates the POM file in the root directory") + public void pomRoot() throws FileUtilsErrorException { + PomBuilder.generateInto(publishOperation().fromProject(this).info(), dependencies(), + new File(workDirectory, "pom.xml")); + } + + private void renderWithXunitViewer() throws Exception { + var xunitViewer = new File("/usr/bin/xunit-viewer"); + if (xunitViewer.exists() && xunitViewer.canExecute()) { + var reportsDir = "build/reports/tests/test/"; + + Files.createDirectories(Path.of(reportsDir)); + + new ExecOperation() + .fromProject(this) + .command(xunitViewer.getPath(), "-r", TEST_RESULTS_DIR, "-o", reportsDir + "index.html") + .execute(); + } + } + + @Override + public void test() throws Exception { + var op = testOperation().fromProject(this); + op.testToolOptions().reportsDir(new File(TEST_RESULTS_DIR)); + + Exception ex = null; + try { + op.execute(); + } catch (Exception e) { + ex = e; + } + + renderWithXunitViewer(); + + if (ex != null) { + throw ex; + } } @Override @@ -213,31 +264,4 @@ public class BitlyShortenBuild extends Project { super.publishLocal(); pomRoot(); } - - @BuildCommand(value = "pom-root", summary = "Generates the POM file in the root directory") - public void pomRoot() throws FileUtilsErrorException { - PomBuilder.generateInto(publishOperation().fromProject(this).info(), dependencies(), - new File(workDirectory, "pom.xml")); - } - - @Override - public void test() throws Exception { - var testResultsDir = "build/test-results/test/"; - - var op = testOperation().fromProject(this); - op.testToolOptions().reportsDir(new File(testResultsDir)); - op.execute(); - - var xunitViewer = new File("/usr/bin/xunit-viewer"); - if (xunitViewer.exists() && xunitViewer.canExecute()) { - var reportsDir = "build/reports/tests/test/"; - - Files.createDirectories(Path.of(reportsDir)); - - new ExecOperation() - .fromProject(this) - .command(xunitViewer.getPath(), "-r", testResultsDir, "-o", reportsDir + "index.html") - .execute(); - } - } } From 8c036692402d63468a9363aee02d721e050b19e9 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Tue, 24 Jun 2025 09:01:40 -0700 Subject: [PATCH 21/28] Rename tests class --- .../net/thauvin/erik/bitly/{BeforeAll.kt => BeforeAllTests.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/kotlin/net/thauvin/erik/bitly/{BeforeAll.kt => BeforeAllTests.kt} (100%) diff --git a/src/test/kotlin/net/thauvin/erik/bitly/BeforeAll.kt b/src/test/kotlin/net/thauvin/erik/bitly/BeforeAllTests.kt similarity index 100% rename from src/test/kotlin/net/thauvin/erik/bitly/BeforeAll.kt rename to src/test/kotlin/net/thauvin/erik/bitly/BeforeAllTests.kt From 58fbc4ec2cd7ca6dc0b5c3086fc4d2448cb10615 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Tue, 24 Jun 2025 09:01:59 -0700 Subject: [PATCH 22/28] Bump JUnit to version 5.13.2 --- src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java index 44ed5e7..66bc5fd 100644 --- a/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java +++ b/src/bld/java/net/thauvin/erik/bitly/BitlyShortenBuild.java @@ -87,9 +87,9 @@ public class BitlyShortenBuild extends Project { .include(dependency("org.json", "json", "20250517")); scope(test) .include(dependency("org.jetbrains.kotlin", "kotlin-test-junit5", kotlin)) - .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 2))) - .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 2))) - .include(dependency("org.junit.platform", "junit-platform-launcher", version(1, 12, 2))) + .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 13, 2))) + .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 13, 2))) + .include(dependency("org.junit.platform", "junit-platform-launcher", version(1, 13, 2))) .include(dependency("com.willowtreeapps.assertk", "assertk-jvm", version(0, 28, 1))); publishOperation() From 6283fc8aeff480bcdaac49d83791f60471b284fb Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Mon, 30 Jun 2025 16:07:17 -0700 Subject: [PATCH 23/28] Bump Kotlin to version 2.2.0 --- .github/workflows/bld.yml | 18 ++++++++++-------- .idea/kotlinc.xml | 2 +- README.md | 2 +- examples/bld/lib/bld/bld-wrapper.properties | 2 +- examples/gradle/.idea/kotlinc.xml | 2 +- examples/gradle/build.gradle.kts | 2 +- lib/bld/bld-wrapper.properties | 2 +- .../thauvin/erik/bitly/BitlyShortenBuild.java | 2 +- 8 files changed, 17 insertions(+), 15 deletions(-) diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index b5a8fee..dd17a9c 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -5,14 +5,13 @@ on: [ push, pull_request, workflow_dispatch ] env: BITLY_ACCESS_TOKEN: ${{ secrets.BITLY_ACCESS_TOKEN }} COVERAGE_JDK: "21" - COVERAGE_KOTLIN: "2.0.21" + KOTLIN_VERSION: "2.2.0" jobs: build-bld-project: strategy: matrix: java-version: [ 17, 21, 24 ] - kotlin-version: [ 1.9.25, 2.0.21, 2.1.21 ] os: [ ubuntu-latest, windows-latest, macos-latest ] runs-on: ${{ matrix.os }} @@ -23,12 +22,17 @@ jobs: with: fetch-depth: 0 - - name: Set up JDK ${{ matrix.java-version }} with Kotlin ${{ matrix.kotlin-version }} + - name: Set up JDK ${{ matrix.java-version }} uses: actions/setup-java@v4 with: distribution: "zulu" java-version: ${{ matrix.java-version }} + - name: Setup Kotlin ${{ env.KOTLIN_VERSION }} + uses: fwilhe2/setup-kotlin@main + with: + version: ${{ env.KOTLIN_VERSION }} + - name: Download dependencies [bld example] working-directory: examples/bld run: ./bld download @@ -58,14 +62,12 @@ jobs: run: ./bld jacoco - name: Remove pom.xml - if: success() && matrix.java-version == env.COVERAGE_JDK && matrix.kotlin-version == env.COVERAGE_KOTLIN - && matrix.os == 'ubuntu-latest' + if: success() && matrix.java-version == env.COVERAGE_JDK && matrix.os == 'ubuntu-latest' run: rm -rf pom.xml - name: SonarCloud Scan - uses: sonarsource/sonarcloud-github-action@master - if: success() && matrix.java-version == env.COVERAGE_JDK && matrix.kotlin-version == env.COVERAGE_KOTLIN - && matrix.os == 'ubuntu-latest' + uses: SonarSource/sonarqube-scan-action@v5.2.0 + if: success() && matrix.java-version == env.COVERAGE_JDK && matrix.os == 'ubuntu-latest' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 43546f2..9fc28bd 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -11,6 +11,6 @@