mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 11:07:10 +00:00
refactor: rename project uatu -> sanderling (#24)
* refactor: rename Go module path uatu -> sanderling
Module path github.com/priyanshujain/uatu -> github.com/priyanshujain/sanderling,
including all imports and the proto go_package option. Generated .pb.go files
rewritten in-place; safe to regenerate with protoc later.
* chore(proto): regenerate driverpb after module path rename
The previous sed-based module rename corrupted the embedded descriptor
byte lengths. buf generate rewrites them cleanly.
* refactor: rename CLI binary uatu -> sanderling
Updates Makefile target + UATU_BIN var, .goreleaser project/build IDs,
.gitignore comment, and all user-facing strings in the CLI help text,
error messages, and tests. Binary is now bin/sanderling.
* refactor(sdk): rename Kotlin package dev.uatu.sdk -> dev.sanderling.sdk
Moves sdk/android/src/{main,test}/kotlin/dev/uatu -> dev/sanderling and
rewrites package declarations, imports, and the Gradle namespace. Class
names (Uatu, UatuRuntime) are renamed in a follow-up commit.
* refactor(sidecar): rename Kotlin package dev.uatu.sidecar -> dev.sanderling.sidecar
Moves sidecar/src/{main,test}/kotlin/dev/uatu -> dev/sanderling and
rewrites package declarations, imports, and the application mainClass.
* refactor: rename Uatu API surface -> Sanderling
- Kotlin: Uatu -> Sanderling, UatuRuntime -> SanderlingRuntime (+ files).
- JS host binding: globalThis.__uatu__ -> __sanderling__ (Go verifier,
spec-api, tests).
- TS interface: UatuRuntime -> SanderlingRuntime; internal tags
__uatuFormula / __uatuActionGenerator -> __sanderling* variants.
- Go trace: UatuVersion field + uatu_version JSON tag renamed.
- Socket naming: uatu-agent / uatu-agent-reader -> sanderling-agent*.
- Sample app, docs, inline-JS test strings updated to match.
* refactor(examples): rename examples/folio/uatu -> examples/folio/sanderling
Renames the example spec directory; updates justfile paths + gitignore
entries accordingly. Package.json name/description and @uatu/spec
dependency are renamed in the npm + docs commits.
* chore(build): rename gradle property + rootProject.name uatu -> sanderling
- Renames the uatu.version gradle property and all its -P references in
Makefile, build.gradle.kts files, and .github/workflows/release.yml.
- settings.gradle.kts rootProject.name = "sanderling".
- Renames .env.local.example header + release-cli workflow job name.
* refactor(proto): rename proto package uatu.driver.v1 -> sanderling.driver.v1
Updates the proto package and java_package, regenerates driver.pb.go +
driver_grpc.pb.go, rewrites Kotlin imports and the gRPC ServiceName
assertion in driver_test.go.
* refactor: rename npm package @uatu/spec -> @sanderling/spec
Renames package name in pkg/spec-api/package.json + lockfile, all
consumer imports (examples/folio spec, testdata, verifier tests), the
esbuild alias in cmd/sanderling/test_run.go, and related doc references.
* docs: rename uatu -> sanderling in README, docs, and URLs
- README + docs/{manual,development}/*: narrative + GitHub + Pages URLs.
- POM + npm package.json repo/homepage/bugs URLs.
- .gitignore + embed_stub + Makefile-comment references updated to
'make sanderling'.
- Minor narrative comments in cmd/sanderling/test_run.go and
internal/inspect/server.go.
* refactor: rename remaining internal uatu strings -> sanderling
- SANDERLING_TEST_PHONE/OTP env vars (cmd + bundler tests).
- sanderling-sidecar runtime tmp dir + extracted JAR filename.
- Inspect web UI: @sanderling/inspect-web package, title, theme
localStorage key, RunList empty-state copy, uatu_version TS field.
- Sample app storage key sanderling.ledger.v1.
- Test data: sanderling_test AVD name + com.example.sanderling_test.
- Release docs tarball name template.
This commit is contained in:
111 files changed
+514
-514
No files matched your search
@@ -6,7 +6,7 @@ iosApp/build/
|
||||
iosApp/iosApp.xcodeproj/
|
||||
iosApp/iosApp.xcodeproj/**
|
||||
.DS_Store
|
||||
uatu/node_modules/
|
||||
uatu/runs/
|
||||
sanderling/node_modules/
|
||||
sanderling/runs/
|
||||
.playwright-mcp/
|
||||
web-*.png
|
||||
@@ -3,14 +3,14 @@
|
||||
A minimal Kotlin Multiplatform personal-ledger app: login with demo
|
||||
credentials, create accounts, add credits and debits. Shared UI across
|
||||
Android, iOS, and Web via Compose Multiplatform. Doubles as the example
|
||||
uatu runs its property-based specs against.
|
||||
sanderling runs its property-based specs against.
|
||||
|
||||
## Stack
|
||||
|
||||
- Kotlin Multiplatform + Compose Multiplatform (shared UI)
|
||||
- kotlinx.serialization for file-backed persistence
|
||||
- kotlinx.coroutines for state flows
|
||||
- uatu `sdk-android` for harness integration on Android
|
||||
- sanderling `sdk-android` for harness integration on Android
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -46,13 +46,13 @@ email: [email protected]
|
||||
password: ledger123
|
||||
```
|
||||
|
||||
## Run a uatu test (Android)
|
||||
## Run a sanderling test (Android)
|
||||
|
||||
```sh
|
||||
just test
|
||||
```
|
||||
|
||||
If no device is connected, uatu boots the single AVD it finds. With multiple
|
||||
If no device is connected, sanderling boots the single AVD it finds. With multiple
|
||||
AVDs, pick one:
|
||||
|
||||
```sh
|
||||
@@ -66,13 +66,13 @@ AVD=Pixel_7
|
||||
DURATION=5m
|
||||
```
|
||||
|
||||
Traces land in `./uatu/runs/<timestamp>/`.
|
||||
Traces land in `./sanderling/runs/<timestamp>/`.
|
||||
|
||||
## How it connects to uatu
|
||||
## How it connects to sanderling
|
||||
|
||||
- `composeApp/src/androidMain/.../FolioApplication.kt` calls `Uatu.start(this)`
|
||||
- `composeApp/src/androidMain/.../FolioApplication.kt` calls `Sanderling.start(this)`
|
||||
and registers snapshot extractors (`logged_in`, `account_count`,
|
||||
`total_balance`, `route`)
|
||||
- `uatu/spec.ts` imports `@uatu/spec`, reads those snapshots, asserts
|
||||
- `sanderling/spec.ts` imports `@sanderling/spec`, reads those snapshots, asserts
|
||||
properties, and weights the actions the fuzzer picks from
|
||||
- `just test` invokes `uatu test` against the installed APK
|
||||
- `just test` invokes `sanderling test` against the installed APK
|
||||
@@ -10,7 +10,7 @@ plugins {
|
||||
id("app.cash.sqldelight")
|
||||
}
|
||||
|
||||
val uatuVersion = findProperty("uatu.version") as String? ?: "0.0.0-dev"
|
||||
val sanderlingVersion = findProperty("sanderling.version") as String? ?: "0.0.0-dev"
|
||||
val sqldelightVersion = "2.3.2"
|
||||
|
||||
kotlin {
|
||||
@@ -83,7 +83,7 @@ kotlin {
|
||||
androidMain.dependencies {
|
||||
implementation("androidx.activity:activity-compose:1.13.0")
|
||||
implementation("app.cash.sqldelight:android-driver:$sqldelightVersion")
|
||||
implementation("io.github.priyanshujain:sdk-android:$uatuVersion")
|
||||
implementation("io.github.priyanshujain:sdk-android:$sanderlingVersion")
|
||||
}
|
||||
|
||||
iosMain.dependencies {
|
||||
@@ -101,7 +101,7 @@ android {
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = 1
|
||||
versionName = uatuVersion
|
||||
versionName = sanderlingVersion
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
|
||||
@@ -11,18 +11,18 @@ import app.folio.navigation.Navigator
|
||||
import app.folio.navigation.Route
|
||||
import app.folio.platform.balanceOf
|
||||
import app.folio.platform.signedAmount
|
||||
import dev.uatu.sdk.Uatu
|
||||
import dev.sanderling.sdk.Sanderling
|
||||
|
||||
class FolioApplication : Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
AndroidLedgerContext.context = applicationContext
|
||||
Repository.init()
|
||||
Uatu.start(this)
|
||||
Uatu.extract("logged_in") { Repository.session.value != null }
|
||||
Uatu.extract("account_count") { Repository.accounts.value.size }
|
||||
Uatu.extract("total_balance") { balanceOf(Repository.transactions.value) }
|
||||
Uatu.extract("route") {
|
||||
Sanderling.start(this)
|
||||
Sanderling.extract("logged_in") { Repository.session.value != null }
|
||||
Sanderling.extract("account_count") { Repository.accounts.value.size }
|
||||
Sanderling.extract("total_balance") { balanceOf(Repository.transactions.value) }
|
||||
Sanderling.extract("route") {
|
||||
when (Navigator.current.value) {
|
||||
Route.Login -> "login"
|
||||
Route.Home -> "home"
|
||||
@@ -31,10 +31,10 @@ class FolioApplication : Application() {
|
||||
is Route.AddTransaction -> "add-transaction"
|
||||
}
|
||||
}
|
||||
Uatu.extract("auth_status") {
|
||||
Sanderling.extract("auth_status") {
|
||||
if (Repository.session.value != null) "logged-in" else "logged-out"
|
||||
}
|
||||
Uatu.extract("accounts") {
|
||||
Sanderling.extract("accounts") {
|
||||
val txns = Repository.transactions.value
|
||||
Repository.accounts.value.map { a ->
|
||||
val rows = txns.filter { it.accountId == a.id }
|
||||
@@ -46,14 +46,14 @@ class FolioApplication : Application() {
|
||||
)
|
||||
}
|
||||
}
|
||||
Uatu.extract("active_account_id") {
|
||||
Sanderling.extract("active_account_id") {
|
||||
when (val r = Navigator.current.value) {
|
||||
is Route.Ledger -> r.accountId
|
||||
is Route.AddTransaction -> r.accountId
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
Uatu.extract("ledger_rows") {
|
||||
Sanderling.extract("ledger_rows") {
|
||||
val active = when (val r = Navigator.current.value) {
|
||||
is Route.Ledger -> r.accountId
|
||||
is Route.AddTransaction -> r.accountId
|
||||
@@ -72,7 +72,7 @@ class FolioApplication : Application() {
|
||||
)
|
||||
}
|
||||
}
|
||||
Uatu.extract("ledger_balance") {
|
||||
Sanderling.extract("ledger_balance") {
|
||||
val active = when (val r = Navigator.current.value) {
|
||||
is Route.Ledger -> r.accountId
|
||||
is Route.AddTransaction -> r.accountId
|
||||
@@ -81,13 +81,13 @@ class FolioApplication : Application() {
|
||||
if (active == null) 0L
|
||||
else balanceOf(Repository.transactions.value.filter { it.accountId == active })
|
||||
}
|
||||
Uatu.extract("focused_input") { FocusTracker.current.value }
|
||||
Uatu.extract("txn_form_type") { AddTransactionUiState.txnFormType.value }
|
||||
Uatu.extract("txn_form_account_id") {
|
||||
Sanderling.extract("focused_input") { FocusTracker.current.value }
|
||||
Sanderling.extract("txn_form_type") { AddTransactionUiState.txnFormType.value }
|
||||
Sanderling.extract("txn_form_account_id") {
|
||||
(Navigator.current.value as? Route.AddTransaction)?.accountId
|
||||
}
|
||||
Uatu.extract("login_error") { LoginUiState.loginError.value }
|
||||
Uatu.extract("add_account_error") { AddAccountUiState.addAccountError.value }
|
||||
Uatu.extract("txn_error") { AddTransactionUiState.txnError.value }
|
||||
Sanderling.extract("login_error") { LoginUiState.loginError.value }
|
||||
Sanderling.extract("add_account_error") { AddAccountUiState.addAccountError.value }
|
||||
Sanderling.extract("txn_error") { AddTransactionUiState.txnError.value }
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.browser.localStorage
|
||||
|
||||
private const val STORAGE_KEY = "uatu.ledger.v1"
|
||||
private const val STORAGE_KEY = "sanderling.ledger.v1"
|
||||
|
||||
class WebLedgerStore : LedgerStore {
|
||||
private val _accounts = MutableStateFlow<List<Account>>(emptyList())
|
||||
|
||||
@@ -5,6 +5,6 @@ kotlin.code.style=official
|
||||
android.useAndroidX=true
|
||||
android.nonTransitiveRClass=true
|
||||
|
||||
# Pin the uatu SDK version consumed by this app. Override with
|
||||
# `-Puatu.version=<version>`.
|
||||
uatu.version=0.0.0-dev
|
||||
# Pin the sanderling SDK version consumed by this app. Override with
|
||||
# `-Psanderling.version=<version>`.
|
||||
sanderling.version=0.0.0-dev
|
||||
@@ -1,11 +1,11 @@
|
||||
set shell := ["bash", "-cu"]
|
||||
set dotenv-load := true
|
||||
|
||||
uatu := env_var_or_default("UATU", "uatu")
|
||||
avd := env_var_or_default("AVD", "")
|
||||
duration := env_var_or_default("DURATION", "1m")
|
||||
seed := env_var_or_default("SEED", "0")
|
||||
output := env_var_or_default("OUTPUT", justfile_directory() / "uatu" / "runs")
|
||||
sanderling := env_var_or_default("SANDERLING", "sanderling")
|
||||
avd := env_var_or_default("AVD", "")
|
||||
duration := env_var_or_default("DURATION", "1m")
|
||||
seed := env_var_or_default("SEED", "0")
|
||||
output := env_var_or_default("OUTPUT", justfile_directory() / "sanderling" / "runs")
|
||||
ios_device := env_var_or_default("IOS_DEVICE", "iPhone 17 Pro")
|
||||
|
||||
default:
|
||||
@@ -81,7 +81,7 @@ ios:
|
||||
xcrun simctl install booted iosApp/build/Build/Products/Debug-iphonesimulator/iosApp.app
|
||||
xcrun simctl launch booted app.folio
|
||||
|
||||
# Run 'uatu test' against the folio app. Uses a connected device if one is
|
||||
# Run 'sanderling test' against the folio app. Uses a connected device if one is
|
||||
# online, otherwise boots AVD=<name> if provided.
|
||||
test:
|
||||
#!/usr/bin/env bash
|
||||
@@ -90,8 +90,8 @@ test:
|
||||
if [[ -n "{{avd}}" ]]; then
|
||||
avd_flag=(--avd "{{avd}}")
|
||||
fi
|
||||
"{{uatu}}" test \
|
||||
--spec "{{justfile_directory()}}/uatu/spec.ts" \
|
||||
"{{sanderling}}" test \
|
||||
--spec "{{justfile_directory()}}/sanderling/spec.ts" \
|
||||
--bundle-id app.folio \
|
||||
"${avd_flag[@]}" \
|
||||
--duration "{{duration}}" \
|
||||
|
||||
+3
-3
@@ -6,12 +6,12 @@
|
||||
"": {
|
||||
"name": "folio",
|
||||
"devDependencies": {
|
||||
"@uatu/spec": "next"
|
||||
"@sanderling/spec": "next"
|
||||
}
|
||||
},
|
||||
"node_modules/@uatu/spec": {
|
||||
"node_modules/@sanderling/spec": {
|
||||
"version": "0.0.1-rc3",
|
||||
"resolved": "https://registry.npmjs.org/@uatu/spec/-/spec-0.0.1-rc3.tgz",
|
||||
"resolved": "https://registry.npmjs.org/@sanderling/spec/-/spec-0.0.1-rc3.tgz",
|
||||
"integrity": "sha512-mCayssOqM2wfzrQDnFGE8FAlUlDzBl1fx2L/MLDIuPrQHBMlUC350xBB8Z7I/DYI98eCWJMqjtw3iU6yVWKtIQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0"
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "folio",
|
||||
"private": true,
|
||||
"description": "Minimal sanderling integration example.",
|
||||
"devDependencies": {
|
||||
"@sanderling/spec": "next"
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,8 @@ import {
|
||||
taps,
|
||||
waitOnce,
|
||||
weighted,
|
||||
} from "@uatu/spec";
|
||||
import { noUncaughtExceptions } from "@uatu/spec/defaults/properties";
|
||||
} from "@sanderling/spec";
|
||||
import { noUncaughtExceptions } from "@sanderling/spec/defaults/properties";
|
||||
|
||||
interface AccountSnapshot {
|
||||
id: string;
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"name": "folio",
|
||||
"private": true,
|
||||
"description": "Minimal uatu integration example.",
|
||||
"devDependencies": {
|
||||
"@uatu/spec": "next"
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user