mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 11:07:10 +00:00
323878c34ac1d7257a341172c66242645b88a77c
18
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a2e96af1af |
WIP: rename sample app to Folio (#20)
* refactor: rename examples/sample-app to examples/folio Directory-level rename and path references in Go tests, bundle-check, top-level README, and getting-started docs. Package declarations, Gradle config, iOS bundle IDs, and class names follow in later commits. * refactor(folio): rename Kotlin package dev.uatu.sample to app.folio Moves source dirs and sqldelight schema from dev/uatu/sample to app/folio, updates package declarations and imports, and switches Android namespace/applicationId, iOS binaryOption bundleId, and sqldelight database packageName to the new identifier. * refactor(folio): rename SampleApplication to FolioApplication Android manifest now points at .FolioApplication with label 'Folio' instead of 'Uatu Sample'. * refactor(folio): set iOS bundle id and display name to Folio bundleIdPrefix + PRODUCT_BUNDLE_IDENTIFIER -> app.folio. CFBundleName + CFBundleDisplayName -> 'Folio'. * refactor(folio): update demo email to [email protected] * refactor(folio): point justfile at app.folio bundle id Updates xcrun simctl launch target, uatu test --bundle-id, and the build/uninstall comments to reference folio instead of sample. * test: update fixture package ids to app.folio Sidecar activity-resolver test and verifier spec-integration XML fixtures referenced the old dev.uatu.sample Android package. Updates them to match the folio app's real package id so the tests stay representative of what the CLI sees on-device. * test(verifier): rename SampleApp identifiers to Folio Renames TestSampleAppSpec* functions, bundleSampleAppSpec helper, and sampleAppHierarchyXML const (now loginHierarchyXML for consistency with the other per-screen fixtures). Updates trailing sample-app mentions in comments and assertion messages. * refactor(folio): rename Gradle/npm/wasm project identifiers to folio settings.gradle.kts rootProject.name, package.json + package-lock.json name, and the WasmJS index.html <title> all still read 'uatu-sample' / 'Uatu Sample'. Realigns them with the Folio brand. * docs(folio): rewrite README title + getting-started bundle id examples/folio/README.md is now titled 'Folio' with the Kotlin source paths corrected to app/folio. Getting-started example uses --bundle-id app.folio. Harness launch message is now generic ('app under test') since uatu-sample-harness is not specific to folio. * chore(folio): drop trailing 'sample' reference in gradle.properties * refactor(folio): rename LoginPage composable to LoginScreen Align with KMP/Android industry convention (NowInAndroid, Cash App, JetBrains samples use Screen, not Page). * refactor(folio): rename HomePage composable to HomeScreen * refactor(folio): rename AddAccountPage composable to AddAccountScreen * refactor(folio): rename LedgerPage composable to LedgerScreen * refactor(folio): rename AddTransactionPage composable to AddTransactionScreen * refactor(folio): split Models.kt into app.folio.data package Account, Transaction (with TxnType), and Session move into their own files under app.folio.data, matching NowInAndroid-style per-type organization. * refactor(folio): move data layer into app.folio.data package Repository, LedgerStore (expect + interface), SqlLedgerStore, WebLedgerStore, DriverFactory (expect + actuals), AndroidLedgerContext, and Snapshot move into app.folio.data. Update all consumer imports. * refactor(folio): move Navigation into app.folio.navigation package Split the former Navigation.kt into Route.kt (sealed interface) and Navigator.kt (singleton). Update consumer imports across screens, App.kt, and FolioApplication. * refactor(folio): move Platform and Format into app.folio.platform Both files carry expect declarations (Platform object, formatDate); grouping them into a dedicated platform package makes the KMP seam obvious and mirrors the structure used by JetBrains samples. * refactor(folio): move login into feature/auth package Create app.folio.feature.auth with LoginScreen + LoginUiState. Inline the former Auth.kt (DEMO_EMAIL, DEMO_PASSWORD, checkCredentials) into LoginScreen since it is the sole caller. * refactor(folio): move HomeScreen into feature/home package * refactor(folio): move account creation into feature/account package AddAccountScreen gets its own AddAccountUiState colocated with the screen, replacing the shared UiState.addAccountError. * refactor(folio): move ledger screens into feature/ledger package LedgerScreen and AddTransactionScreen move into app.folio.feature.ledger with AddTransactionUiState (txnError, txnFormType) colocated. The former catch-all UiState.kt is removed now that each screen owns its state alongside its UI. * refactor(folio): split Theme.kt; move theme and icons to subpackages Theme split into Theme.kt (tokens, layout dims, LedgerTheme) and Type.kt (typography) under app.folio.ui.theme. Icons moves to app.folio.ui.icon. Update every consumer's imports to match. * refactor(folio): split ui components into per-file under ui/component Former Widgets.kt and Components.kt become 10 focused files: AppButton, Card, EmptyState, ErrorText, FieldLabel, Header, IconButton (w/ BackButton), Screen, Segmented, TextInput. Matches NowInAndroid style of one composable per file in a designsystem/component package. * chore(folio): consolidate uatu testing files under uatu/ folder Move spec.ts, package.json, package-lock.json into examples/folio/uatu so all uatu-specific testing artifacts live in one place. runs/ and node_modules/ follow the same convention (both remain gitignored). Update justfile, README, and the two Go consumers (bundle-check tool + verifier/trace tests) that referenced the old path. * refactor(trace): drop folio path in writer test Round-trip only needs a non-empty string; neutralize to keep the library free of folio references. * refactor(sidecar): neutralize ResolveActivity test fixtures Swap app.folio for com.example.app in the fixture strings so the sidecar tests don't reference the example app by name. * refactor(bundle-check): take spec path as argument Previously the tool hardcoded examples/folio/uatu/spec.ts. Accept a positional spec path instead so the tool works for any example and leaves no folio reference in the library surface. * test(verifier): add neutral integration spec and hierarchy fixtures Adds testdata/integration_spec.ts with two routes ("list", "form"), an InputText on text_field, a Tap on primary/secondary_action, a safety property (itemCountNonNegative), and a liveness property (submitEventually). Adds hierarchies_test.go with matching XML fixtures. Constants intentionally go in a _test.go at package root rather than testdata/hierarchies.go because go skips .go files under testdata/. * refactor(verifier): replace folio integration tests with neutral ones Renames bundleFolioSpec -> bundleIntegrationSpec and the three Test* entry points to TestIntegrationSpec*. Uses the synthetic spec and hierarchies added in the previous commit so the library's test suite no longer references examples/folio at all. Folio-specific coverage remains covered by examples/folio/justfile's 'just test' which exercises the real spec on device/emulator. * chore: remove cmd/uatu-sample-harness Not referenced by Makefile, docs, CI, or any script. Duplicates the adb reverse helpers already in cmd/uatu/test_run.go, and its name implies ownership by the sample app which violates the library/ example decoupling. If a bare-protocol debugging tool is later needed it belongs inside cmd/uatu/. * docs(folio): drop Layout section and KMP layout paragraph; fix AVD override syntax The directory-tree Layout section rots faster than the code and duplicates what ls shows for free. The expect/actual paragraph in Stack was the same kind of filler. The README also claimed 'just AVD=Pixel_7 test' but the justfile reads AVD as an env var via env_var_or_default, so the correct invocation is 'AVD=Pixel_7 just test'. |
||
|
|
c1de4bf57a |
fix(sample-app): address PR #18 review findings (#19)
- WebLedgerStore.accountExistsByName case-insensitive (matches SQL COLLATE NOCASE) - drop SampleApplication.maybeInjectDebugError; sample spec now passes clean - drop noLogcatErrors from sample spec (default matches system-wide E logs) - openRandomAccount picks uniformly from findAll instead of first match - clear txnError on any add-transaction interaction, not only valid amount input - escapeForAdbInputText quotes shell metacharacters (quotes, backslash, etc.) - extract buildClearKeyevents helper with empty/normal/cap tests - broaden spec_integration_test.go to cover home, add-account, ledger, add-transaction action generators - document FocusTracker single-focus invariant |
||
|
|
8381a98aaf |
feat(sample-app): ledger spec parity (#18)
* feat(sample-app): add FocusTracker * feat(sample-app): support description on TextInput * feat(sample-app): support description on AppButton and Segmented * feat(sample-app): stable ids on login screen * feat(sample-app): stable ids on add-account screen * feat(sample-app): stable ids on add-transaction screen * feat(sample-app): stable ids on home and ledger screens * feat(sample-app): hoist error + form state into UiState * feat(sample-app): register auth_status + accounts snapshots * feat(sample-app): register ledger_rows + ledger_balance snapshots * feat(sample-app): register error + focused_input snapshots * refactor(sample-app): scaffold spec.ts extractors + safety * feat(sample-app): spec accounting invariants * feat(sample-app): spec state-machine monotonicity * feat(sample-app): spec liveness properties * feat(sample-app): spec auth + account action generators * feat(sample-app): spec transaction action generators * feat(sample-app): spec weighted workflow * feat(sample-app): publish login form input snapshots * feat(sample-app): publish account + txn input snapshots * feat(sample-app): register form input snapshots * fix(sample-app): sequence login + idempotent text inputs in spec * fix(sample-app): clear UiState on page dispose * fix(sample-app): tighten adversarial login, allow retype on error * test(verifier): update sample-app spec integration for new selectors * feat(sidecar): clear focused field before InputText types * refactor(sample-app): simplify loginHelper to focus-driven sequencing * refactor(sample-app): drop input-value UiState mirrors * refactor(sample-app): drop input-value snapshot registrations * test(verifier): adjust sample-app integration for replace-on-type |
||
|
|
7493945251 |
feat: LTL operators, sampling, and default generators (#17)
* feat(ltl): add Now/Next/Eventually/Implies/Or/And/Not formulas Replace the fold-with-latch evaluator with a residual-formula reducer. Each Observe() instantiates a fresh obligation from the root (stripping an outer Always), reduces each pending obligation against current state, latches Violated on first failure, and surfaces Pending verdicts for deferred obligations. Existing Always/Pure/Thunk tests continue to pass. * feat(ltl): support relative duration for eventually().within() * feat(proto): add Swipe, PressKey, RecentLogs RPCs * feat(verifier,runner): formula handles, new action kinds, rich state - verifier: add formula-spec registry; bindNow/bindNext/bindEventually with chainable .implies/.or/.and/.not and .within(n,unit) on eventually; bindFrom for uniform sampling. bindAlways keeps accepting plain predicates. - verifier: store lastTree, lastAction, step time, logs, exceptions on the Verifier; SnapshotInput replaces the (snapshots, tree) pair. stateObject now produces state.lastAction/time/logs/exceptions matching the TS State type. - verifier: make taps/swipes/waitOnce/pressKey built-in generators actually fire; taps picks a clickable, enabled element from the last hierarchy. - agent: add exceptions field to Message wire format. - driver: add Swipe/PressKey/RecentLogs to Driver interface; wire maestro client and mock driver. LogEntry exposed for runner consumption. - runner: apply Swipe/PressKey/Wait actions; collect logcat and exceptions; pass lastAction and step time into PushSnapshot. * feat(spec-api): LTL operators, new actions, richer State - ltl.ts exports now/next/eventually; always overload accepts a Formula - types.ts: Formula gains implies/or/and/not; EventuallyFormula adds .within; State gains lastAction/time/logs/exceptions; Swipe/PressKey/Wait action types - actions.ts: Swipe/PressKey/Wait/from constructors; waitOnce + pressKey default generators - tests exercise the chaining, sampling, and new actions through a recorded fake runtime * feat(sidecar): add swipe, pressKey, recentLogs RPC handlers * feat(sdk-android): capture uncaught exceptions Install a default uncaught handler on Uatu.start, chained with any existing handler so Android's crash reporter still runs. Expose Uatu.reportError for callers to forward caught throwables. A bounded circular buffer (default 50) drains into each STATE message's new exceptions field. Protocol.kt serializes/deserializes the field, matching the Go wire format added to internal/agent/protocol.go. * feat(spec-api): add @uatu/spec/defaults/properties bundle * feat(sample-app): exercise new LTL operators + defaults spec.ts now imports eventually/next/now/from from @uatu/spec and noUncaughtExceptions from @uatu/spec/defaults/properties. It declares three properties that exercise the new surface: - accountCountNonNegative: plain always() safety - addAccountAdvances: always(now(x).implies(next(y))) - eventuallyLoggedIn: eventually(p).within(30, "seconds") - noUncaughtExceptions: imported default The weighted actions root uses from() for random phone/name sampling and entries for taps/swipes/waitOnce/pressKey built-ins. SampleApplication gains a debug hook gated on the system property uatu.inject_error so the e2e run can synthesize an Uatu.reportError and verify noUncaughtExceptions violates. cmd/uatu/test_run.go adds a subpath alias so specs importing "@uatu/spec/defaults/properties" resolve against the in-tree source when running from the uatu checkout. The spec-integration tests swap the old click-counter fixtures for the new login hierarchy. * feat(trace): record swipe/key/wait details + exceptions trace.Step gains an Exceptions array so the trace captures the class/message/stackTrace for each SDK-reported throwable in a step. trace.Action gains FromX/FromY/ToX/ToY/Key/DurationMillis so the full payload of Swipe/PressKey/Wait actions is visible in trace.jsonl. sample-app's debug error hook now gates on ApplicationInfo.DEBUGGABLE instead of a system property (adb setprop fails on non-rooted emulators). |
||
|
|
5b5594ee05 |
Port sample-app to KMP with Android, iOS, Web, and SQLite (#16)
* chore(sample-app): hoist gradle wrapper to sample-app root * chore(sample-app): add KMP root gradle config * chore(sample-app): add composeApp KMP module build config * chore(sample-app): add Android manifest for composeApp * feat(sample-app): add shared domain models and auth constants * feat(sample-app): add shared number and date formatting * feat(sample-app): add cross-platform storage, clock, and id * feat(sample-app): add shared repository with file-backed state * feat(sample-app): add shared in-memory navigator * feat(sample-app): add Compose theme and design tokens * feat(sample-app): add shared UI components (icons, screen, widgets) * feat(sample-app): add Login and Home pages * feat(sample-app): add AddAccount, Ledger, AddTransaction pages * feat(sample-app): add App root composable with routing * feat(sample-app): add Android Application and Activity hosting Compose UI * chore(sample-app): remove legacy android module (replaced by composeApp) * chore(sample-app): bump to latest stable Kotlin/AGP/Compose deps * fix(sample-app): make iOS compile (drop @Volatile, set bundleId) * feat(sample-app): add xcodegen spec, SwiftUI host, and iOS Info.plist * chore(sample-app): ignore build artifacts and generated xcodeproj * chore(sample-app): update justfile for composeApp layout, add ios target * docs(sample-app): rewrite README for KMP + iOS flow * refactor(sample-app): drop in-app status bar and formatClock * feat(sample-app): add SQLDelight schema and per-platform drivers * refactor(sample-app): back Repository with SQLite, drop file serializer * feat(sample-app): wire native back on Android and iOS edge swipe * feat(sample-app): semantic roles, labels, and a11y descriptions * fix(sample-app): link libsqlite3 for iOS target SQLDelight's native driver needs libsqlite3.tbd on iOS; without it the linker fails with undefined _sqlite3_bind_blob and friends. * refactor(sample-app): abstract storage behind LedgerStore interface Platform-specific createLedgerStore() returns a SqlLedgerStore backed by SQLDelight on Android + iOS. Opens the door for a pure in-memory web implementation that does not require a SQLite driver. * feat(sample-app): add wasmJs target with in-memory LedgerStore Wires a Compose Multiplatform browser canvas entry point. The web implementation of LedgerStore is an in-memory model with localStorage persistence, so it does not need a SQLite driver. Back navigation maps the browser back button to the same BackHandler contract Android and iOS use. * chore(sample-app): settings + gitignore for wasmJs dev run Registers the Node.js distributions repository and switches repositoriesMode to PREFER_PROJECT so the Kotlin wasmJs plugin can download its toolchain. Adds kotlin-js-store (lockfile) and ignores runs/, web screenshots, playwright-mcp scratch output. * fix(sample-app): singularize transaction count on Home Shows "1 transaction" not "1 transactions" for accounts with a single transaction; falls back to "$count transactions" otherwise. |
||
|
|
69002b07b1 |
fix(runner,sample-app): surface silent errors and demo a failing property (#15)
* fix(runner): surface non-deadline WaitForIdle errors Previously the WaitForIdle return value was discarded entirely, hiding real driver failures (gRPC transport errors, sidecar crashes) behind the expected deadline-exceeded case. Log non-deadline errors so they are visible without changing control flow. * chore(sample-app): drop unused uptime_millis extractor Registered in SampleApplication but never consumed by spec.ts. * fix(sample-app): drop trivial appIsRunning property app_state was hardcoded to 'running' so the property was a tautology that could never fail. Removing both the extractor and the property is the simplest fix; demo-grade properties that can fail land next. * feat(sample-app): add Reset button that zeroes clickCount Pairs with the next commit's tap-reset action so the fuzzer can violate clickCountNeverDecreases and demonstrate uatu actually finding a property violation. * feat(sample-app): add tap-reset action to exercise Reset button Weighted at 10/122, fuzzer reaches it within a short run. Pairs with the Reset button to demonstrate uatu detecting the clickCountNeverDecreases violation. * fix(runner): filter WaitForIdle errors via context state, not errors.Is errors.Is(err, context.DeadlineExceeded) misses gRPC's wrapped status.DeadlineExceeded, so every step under the maestro driver logged a spurious warning. Check idleCtx.Err() instead — captures both deadline-fired and parent-canceled cases regardless of how the driver wraps them. * chore(sample-app): tune action weights so demo violates in ~30s Prior weights left tap-reset rare enough that short demo runs missed the violation by chance. Bumped to 30/107, with typeUsername reduced since username noise doesn't help exercise clickCount. * refactor(runner): route warnings through slog Adds Options.Logger (defaults to slog.Default()) and converts the three warning sites that were using fmt.Printf. Progress line stays on Printf since it's user-facing UI, not a log. Makes the warnings testable via a capturing handler. * test(runner): assert WaitForIdle driver errors are logged Captures slog output via TextHandler into a buffer and asserts the warning message + injected error text appear when the mock driver returns a non-context error from WaitForIdle. Guards against a regression of the silent-error swallow. |
||
|
|
00f66ba48d |
fix: pre-v0.1 review feedback (#14)
* fix(sdk-android): add @JvmOverloads to Uatu.start Java callers can now invoke start(application) without supplying a Configuration, matching the Kotlin default-arg ergonomics. * feat(agent): add protocol_version to HELLO handshake ProtocolVersion=1 lives on Message and is set by Hello(). Server.Accept rejects mismatches with a clear error. SDK upgrades that don't change the wire format keep the same protocol_version; bump on breaking changes. * test(agent): assert protocol_version in Hello round-trip * feat(sdk-android): send protocol_version=1 in HELLO Mirrors agent.ProtocolVersion on the Go side. Bump in lockstep with the Go constant when the wire format breaks. * chore(sample-app): pull @uatu/spec from npm next tag Replaces the file: dep. Copy-paste users can now npm install against the registry. The release workflow publishes pre-release tags to npm dist-tag 'next', so the sample tracks the latest rc without manual version bumps. Lockfile currently resolves to 0.0.1-rc3. |
||
|
|
d0578dbaaa |
fix(runner): warn on malformed screen snapshot (#13)
* fix(runner): warn on malformed screen snapshot screenFromSnapshot swallowed json.Unmarshal errors, so a non-string screen value silently became "" in the step log and trace while the verifier still saw the raw JSON. Return the error and warn at the call site, matching the hierarchy warning pattern. * docs: clarify --avd is optional for uatu test The CLI accepts --avd as an empty-string default (cmd/uatu/main.go:49) and only requires it when no device is connected and multiple AVDs exist (cmd/uatu/android_env.go:63). Docs and examples that showed it as required or always-passed were misleading. |
||
|
|
16e55086d8 |
fix(runner): surface focus-tap errors in InputText (#12)
* fix(runner): surface focus-tap errors in InputText action A failed Tap/TapSelector before InputText was swallowed, so text typed into the wrong field (or no field) still reported success. Return the error so the step fails explicitly. * feat(sample-app): add username EditText and snapshot Gives the spec a real EditText target (content-desc: username_field) so the InputText action path can be exercised end-to-end. The typed value is mirrored into MainActivity.username and surfaced as the "username" snapshot for spec assertions. * feat(sample-app): exercise InputText action against username field Adds typeUsername action and usernameNeverShrinks property to the sample spec, and extends the integration test to assert the bundled spec emits an InputText(desc:username_field, "alice") action and that the property correctly violates when a snapshot reports a shorter string. |
||
|
|
6b1c17328c |
fix(sample-app): make it standalone, no repo_root assumptions (#8)
* fix(cli): fall back to node_modules for @uatu/spec resolution
Drop the hard failure when the uatu source tree is not reachable from
the spec file. Users integrating uatu in their own app have @uatu/spec
installed via npm; esbuild now resolves it from node_modules.
* build(gradle): drop :sample-app include from root settings
The sample now has its own Gradle project in examples/sample-app/android.
* build(sample-app): vendor gradle wrapper
Users running the sample build the APK via ./gradlew from inside the
sample-app's own android/ directory, no repo-root wrapper required.
* build(sample-app): make gradle project standalone
Drop the project(':sdk-android') dependency in favor of the Maven
Central coordinate io.github.priyanshujain:sdk-android. The sample now
owns its settings.gradle.kts and gradle.properties, so it builds
without any pieces of the uatu source tree.
* chore(sample-app): declare @uatu/spec npm dependency
Mirrors what a downstream user would put in their own package.json.
Uses file: for pre-release development; becomes a normal semver pin
once @uatu/spec ships to npm.
* docs(sample-app): rewrite justfile and add README
Justfile drops repo_root; all recipes run against the local gradle
wrapper and uatu from PATH. README is scoped to what a user needs to
run the sample against their own device.
* docs(manual): update sample install steps to standalone layout
./gradlew :sample-app:installDebug no longer exists; the sample owns
its own wrapper under android/.
* feat(sdk): log when Uatu.start succeeds
Silent SDK start makes the "SDK didn't connect" failure mode
impossible to debug. One INFO line at start time is enough.
* fix(sidecar): launch via am start -W instead of monkey
monkey -p <pkg> -c LAUNCHER 1 is unreliable on API 36+: it reports no
error but silently fails to start the activity, so the SDK never runs
and the CLI times out on the SDK-accept handshake.
Resolve the launcher activity via `cmd package resolve-activity
--brief` and launch it with `am start -W -n`. -W makes the call block
until the activity is up, which also makes the subsequent SDK
accept timing deterministic.
* feat(cli): auto-resolve Android device; boot AVD if none connected
--avd becomes optional. Resolution order:
- use any already-connected adb device;
- else if --avd names an existing AVD, boot it and wait for boot;
- else if --avd is missing or names no AVD, error with a clear message.
Falls back to $ANDROID_HOME/emulator/emulator when the binary is not on
PATH, so a standard Android SDK install works without extra shell setup.
* docs(sample-app): AVD is optional; document both paths
just test runs against any connected device. If none, pass AVD=<name>
to have uatu boot the emulator for you.
* feat(cli): auto-discover Android SDK; auto-pick the lone AVD
adb and emulator are looked up via PATH, then $ANDROID_HOME,
$ANDROID_SDK_ROOT, ~/Library/Android/sdk, ~/Android/Sdk, and the
Homebrew cask path. The discovered platform-tools directory is
prepended to the sidecar's PATH so its adb subprocess calls work too.
When --avd isn't passed and no device is connected, the CLI picks the
sole local AVD and boots it. Multiple AVDs → error listing them.
* build(make): add `make install` that go-installs uatu onto PATH
Puts `uatu` into $GOBIN (or $GOPATH/bin) so the sample and any local
dev flow can call it without PATH= prefixes.
* docs(sample-app): zero-config just test; dotenv-load for persistence
Drop the expectation that users prefix commands with PATH=, ANDROID_HOME=,
or AVD=. `just test` now works as-is; optional knobs can be pinned in a
.env file alongside the justfile.
* fix(sample-app): auto-detect ANDROID_HOME for Gradle tasks
The Go CLI finds the SDK itself, but AGP still needs ANDROID_HOME to
resolve `sdk.dir`. The justfile now resolves it from env or canonical
install paths before invoking ./gradlew, so `just install` works out
of the box on a standard Android SDK setup.
* gitignore runs directory for sample app
|
||
|
|
a74d9fbeae |
build(examples): add justfile for sample-app
Targets: install/uninstall the APK, build the uatu CLI, run 'uatu test' against a named AVD, run the Go verify tests, and clean. Keeps the example self-contained so users can 'just test AVD=pixel_7' after cloning. |
||
|
|
ec3764ad85 |
chore(examples): remove merchant-ledger spec
No longer referenced anywhere — sample-app replaces it as the in-tree example. |
||
|
|
0c775c199d |
feat(examples): add sample-app spec
Introduce examples/sample-app/spec.ts — a minimal property-based spec that taps the sample app's "Click me" button and asserts click_count is monotonic. Bundle-check and the trace writer test now reference the new path. |
||
|
|
c12a3e242f |
refactor(android): move sample app under examples/sample-app/
Rename the gradle sample project from :sdk-android-sample to :sample-app so the isolated example for users lives beside its spec in examples/. |
||
|
|
6a07284e24 | fix(spec): screen-aware sign convention + leaveLedger generator to cycle counterparties | ||
|
|
b19d83fd54 | fix(spec): state-aware enterMobile + globalise properties for evaluator pickup | ||
|
|
6ce4eabe86 | feat(spec): drive merchant onboarding (English, phone, OTP, multi-device, home) | ||
|
|
4dbad9073e |
feat(spec): merchant-ledger property + login/navigation generators
Property ledgerBalanceMatchesTxns asserts displayed balance equals sum(Given) - sum(Received) on either ledger screen. Catches the class of bug where the server-fed CustomerModel.balance diverges from the local-DB-fed CoreDatabaseDao sums (stale cache, partial sync, deleted-txn handling glitch, etc.). Generators are gated by screen state and weighted to push the run through login -> home -> ledger quickly: enterPhone (100), enterOtp (100), openCustomerOrSupplier (80), taps (10), swipes (2). Phone/OTP read from process.env via esbuild defines so credentials never land in source. cmd/internal-tools/bundle-check is a quick sanity tool to confirm the spec bundles before running uatu test. |