Skip to content

Sync main with short-io-sdk, add SDK test suite and CI - #4

Open
rajpootathar wants to merge 18 commits into
mainfrom
release/v1.1.0
Open

Sync main with short-io-sdk, add SDK test suite and CI#4
rajpootathar wants to merge 18 commits into
mainfrom
release/v1.1.0

Conversation

@rajpootathar

@rajpootathar rajpootathar commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Supersedes #3. Brings main up to date with short-io-sdk, adds a test suite and CI.

Work to merge

Already released as v1.0.6v1.0.9, never merged to main:

  • Integrated encrypted links functionality
  • Implemented automatic tracking conversions
  • destination url returned from handleIntent function

New here, seven defect fixes, no API changes:

  • utm_medium lost on URLs with a fragment — appended by string concat keyed on contains("?"), so …/abc#frag became …#frag?utm_medium=android and never reached the server. Now uses Uri.buildUpon().
  • handleClick ran network on the caller's threadwithContext(Dispatchers.IO) wrapped only openConnection().
  • trackConversion threw instead of returning — with no domain it built https:///… and let OkHttp's IllegalArgumentException escape. Returns false now.
  • Deprecated createShortLink overload ignored the configured key — its apiKey parameter is declared optional (String? = null), but a null was stringified to the literal "null" and sent as the auth header instead of falling back to the key from initialize(). Java callers hit this directly, having no default-argument resolution.
  • handleClick returned the sentinel "Not Found" for a missing Location, which handleIntent exposed as destinationUrl — non-null, passes a null check, not a URL. Returns null; the type was already String?.
  • createShortLink called the API with no key — without initialize() the auth header went out empty and the caller got a 401 that gave no hint initialize() was missing. Returns a NOT_INITIALIZED error before any request. Checks the resolved key, not isInitialized, so passing an explicit key without initializing still works.
  • println/printStackTraceLog; KDoc notes createShortLink blocks.

The combined diff mixes released and new code (ShortIO.kt +266, README.md +102), so review by commit: nine previously released, then four new.

Tests

24 tests across four classes, replacing assertEquals(4, 2 + 2).

OkHttp interceptor for createShortLink/trackConversion; MockWebServer for handleClick/handleIntent (it uses HttpURLConnection, which an interceptor can't see). Robolectric for Uri, Base64, Log, Intent. No network.

Verified by mutation: 22 mutations applied one at a time, all caught.

CI

  • unit-test — suite + lint
  • instrumentation-compile — type-checks androidTest, no emulator
  • jitpack-publish — rehearses JitPack's publish command

JitPack publishes with -xtest -xlint, so no test has ever run against a published artifact. jitpack.yml pins JDK 17 (JitPack starts on 11, then downloads 17 mid-build).

All four commits pass testDebugUnitTest independently, so bisect works.

Follow-ups, not here

  • createShortLink blocks the caller; fixing it means suspend, which breaks callers. Documented instead.
  • performCreateShortLink mutates the caller's ShortIOParameters.
  • initialize is one-shot; a second call is silently ignored.
  • Tags v1.0.6v1.0.9 live on short-io-sdk, so where v1.1.0 goes is worth a decision.
  • Example app pins v1.0.9; no change needed until v1.1.0 is tagged.

rajpootathar and others added 12 commits June 18, 2025 11:20
included section for conversion tracking with better copy
- utm_medium was appended by string concatenation keyed on contains("?"),
  so a URL with a fragment and no query had the parameter placed inside the
  fragment and it never reached the server. Build it with Uri instead.
- handleClick wrapped only openConnection() in Dispatchers.IO; connect()
  and the header reads ran on the caller's thread. Wrap the whole body.
- trackConversion built "https:///..." with no domain and let OkHttp's
  IllegalArgumentException escape. Guard and return false.
- The deprecated createShortLink overload stringified a null apiKey and
  sent the literal "null" as the authorization header.
- handleClick returned the sentinel "Not Found" for a missing Location
  header, which handleIntent then exposed as destinationUrl. Return null.
- Route println and printStackTrace through Log.
- Add an internal seam so the HTTP client can be replaced in tests.
Replaces the Android Studio placeholder with 23 tests across four classes.
createShortLink and trackConversion are faked through an OkHttp interceptor;
handleClick and handleIntent use MockWebServer, since handleClick goes
through HttpURLConnection and an interceptor cannot observe it. Robolectric
supplies Uri, Base64, Log and Intent.

Every test was checked by mutating the source and confirming the suite
fails, so the coverage is verified rather than assumed.
Runs the unit tests and lint, compiles the instrumented tests without an
emulator, and rehearses the JitPack publish so a broken release surfaces in
the PR rather than at tag time. JitPack publishes with -xtest -xlint, so
nothing else gates a release on the suite.

jitpack.yml pins JDK 17; JitPack otherwise starts on 11, finds AGP needs 17
and downloads a toolchain mid-build.

Also ignores .idea and .kotlin, and untracks the .idea files already
committed.
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1e668e47-0f1b-4027-afcd-5118f8481f23


Comment @coderabbitai help to get the list of available commands.

Without initialize(), the authorization header went out empty and the caller
got a 401 that gave no hint the real problem was a missing initialize().
Return a NOT_INITIALIZED error before any request.

Checks the resolved key rather than isInitialized, so passing an explicit key
without calling initialize() still works. Returns an error rather than
throwing, matching how the function already reports failures.
@rajpootathar
rajpootathar marked this pull request as ready for review August 31, 2026 10:19
Copilot AI lite review requested due to automatic review settings August 31, 2026 10:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR syncs main with the short-io-sdk branch and adds a real unit test suite plus CI workflows to validate the SDK (including deep-link handling, secure-link creation, and conversion tracking) without touching the network.

Changes:

  • Updated SDK implementation (ShortioSdk) to use a shared OkHttp client, improved click/intent handling, added secure-link support, and conversion tracking behavior.
  • Added Robolectric + MockWebServer based unit tests and supporting test utilities.
  • Added GitHub Actions CI (unit test + lint, androidTest compilation check, and a JitPack publish rehearsal) and updated documentation.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
ShortIOSDK/src/main/java/com/github/shortiosdk/ShortIO.kt Major SDK logic updates: initialization, short-link creation, intent/click handling, secure URLs, conversion tracking.
ShortIOSDK/src/main/java/com/github/shortiosdk/Model/UrlComponents.kt Adds destinationUrl to returned deep-link components.
ShortIOSDK/src/main/java/com/github/shortiosdk/Model/ShortIOResult.kt Adjusts visibility modifiers and adds SecureResult model.
ShortIOSDK/src/main/java/com/github/shortiosdk/Model/ShortIOParameters.kt Makes domain optional (String?) to support initialize-based defaults.
ShortIOSDK/src/main/java/com/github/shortiosdk/Helpers/HelperMethods.kt Replaces old click helper with clid extraction + UTM stripping utilities.
ShortIOSDK/src/main/java/com/github/shortiosdk/Constants.kt Renames API endpoint constant (shortenUrlbaseURL).
ShortIOSDK/src/test/resources/robolectric.properties Pins Robolectric SDK level for unit tests.
ShortIOSDK/src/test/java/com/github/shortiosdk/StubInterceptor.kt Adds OkHttp interceptor to stub API calls in-memory.
ShortIOSDK/src/test/java/com/github/shortiosdk/ShortIOSdkTests.kt Adds unit tests for initialization, createShortLink, and trackConversion behavior.
ShortIOSDK/src/test/java/com/github/shortiosdk/HandleIntentTests.kt Adds tests validating intent handling and destination URL extraction.
ShortIOSDK/src/test/java/com/github/shortiosdk/HandleClickTests.kt Adds tests validating click tracking and utm_medium behavior (incl. fragments).
ShortIOSDK/src/test/java/com/github/shortiosdk/CreateSecureTests.kt Adds tests validating secure-link encryption/decryption and IV reuse prevention.
ShortIOSDK/src/test/java/com/github/shortiosdk/ExampleUnitTest.kt Removes placeholder test.
ShortIOSDK/build.gradle.kts Enables Android resources for unit tests and adds test dependencies.
README.md Updates usage/docs, adds CI badge, and documents new/updated features.
.github/workflows/ci.yml Adds CI workflow: unit tests + lint, androidTest compilation, JitPack publish rehearsal.
.github/jitpack-publish.init.gradle Adds init script to emulate JitPack publishing in CI.
jitpack.yml Pins JDK 17 for JitPack builds.
gradle/libs.versions.toml Adds versions/libs for Robolectric, MockWebServer, coroutines-test.
.gitignore Simplifies IDE/Kotlin ignores.
Suppressed comments (1)

README.md:150

  • The API parameters table describes domain as required/deprecated and "inferred from API key", but the implementation uses the domain from initialize() when parameters.domain is null/blank. This row should reflect the current behavior and type (String?).
| `domain`            | `String`    | ✅ (Deprecated)        | Your Short.io domain (e.g., `example.short.gy`). ⚠️ Deprecated. No longer required — inferred from API key. May be removed in future versions.              |
| `originalURL`       | `String`    | ✅       | The original URL to be shortened                             |

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread ShortIOSDK/src/main/java/com/github/shortiosdk/ShortIO.kt
Comment thread ShortIOSDK/src/main/java/com/github/shortiosdk/ShortIO.kt Outdated
Comment thread ShortIOSDK/src/main/java/com/github/shortiosdk/ShortIO.kt
Comment thread ShortIOSDK/src/main/java/com/github/shortiosdk/ShortIO.kt
Comment thread ShortIOSDK/src/main/java/com/github/shortiosdk/ShortIO.kt
Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread ShortIOSDK/src/main/java/com/github/shortiosdk/Model/UrlComponents.kt Outdated
Comment thread ShortIOSDK/src/main/java/com/github/shortiosdk/Constants.kt Outdated
- trackConversion logged "createSecure failed" in its catch block.
- trackConversion rethrew on transport errors, which defeats its Boolean
  return. Return false, matching the empty-domain guard.
- handleIntent wrapped handleClick in Dispatchers.IO, which handleClick now
  does itself.
- Correct the "SDk" typo in the not-initialized message, the Swift-style
  KDoc on trackConversion, and three README errors: the deprecated overload
  argument order, the domain parameter row, and a conversion tracking
  example that did not compile.
Both were broken against main by earlier releases. Cheap to restore, so
restore them:

- shortenUrl comes back as a deprecated alias for baseURL.
- UrlComponents.destinationUrl gets a null default, so callers that
  constructed it before the field existed still compile.

handleIntent stays suspend. It performs a network call, so the signature is
correct, and a blocking overload would invite main-thread work.
Checkout leaves a repo-scoped token in .git/config for the rest of the job; nothing here pushes, so it does not need one.
@rajpootathar
rajpootathar requested a review from gugu August 31, 2026 10:56
The main ruleset requires a status check called test; the jobs above report under their own names, so nothing satisfied it and PRs stayed blocked.
The Uri rewrite skipped tagging whenever any utm_medium was present, so a campaign link (utm_medium=cpc) stopped being marked android. The original skipped only when already tagged android; restore that.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants