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.
This commit is contained in:
pj committed 2026-04-18 10:33:35 +07:00
1 parent c12a3e242f
commit 0c775c199d
3 files changed
+47 -6

No files matched your search

+1 -5
View File
@@ -17,11 +17,7 @@ func main() {
specApiPath := filepath.Join(repoRoot, "pkg/spec-api/src/index.ts") specApiPath := filepath.Join(repoRoot, "pkg/spec-api/src/index.ts")
result, err := bundler.Bundle(bundler.Options{ result, err := bundler.Bundle(bundler.Options{
EntryFile: "examples/specs/merchant-ledger.ts", EntryFile: "examples/sample-app/spec.ts",
Defines: map[string]string{
"UATU_TEST_PHONE": "+910000000000",
"UATU_TEST_OTP": "000000",
},
Aliases: map[string]string{ Aliases: map[string]string{
"@uatu/spec": specApiPath, "@uatu/spec": specApiPath,
}, },
+45
View File
@@ -0,0 +1,45 @@
import {
extract,
always,
actions,
weighted,
Tap,
taps,
swipes,
} from "@uatu/spec";
// ── Snapshot extractors (fed by SampleApplication.kt) ──────────
// See ./android/src/main/kotlin/dev/uatu/sample/SampleApplication.kt
const appState = extract<string>(
(state) => (state.snapshots.app_state as string) ?? "",
);
const clickCount = extract<number>(
(state) => (state.snapshots.click_count as number) ?? 0,
);
// ── UI elements ────────────────────────────────────────────────
const clickButton = extract((state) => state.ax.find("text:Click me"));
// ── Properties ─────────────────────────────────────────────────
export const properties = {
appIsRunning: always(() => appState.current === "running"),
clickCountNonNegative: always(() => clickCount.current >= 0),
clickCountNeverDecreases: always(() => {
const previous = clickCount.previous;
return previous === undefined || clickCount.current >= previous;
}),
};
// ── Actions ────────────────────────────────────────────────────
const tapClickMe = actions(() => {
return clickButton.current ? [Tap({ on: clickButton.current })] : [];
});
export const actionsRoot = weighted(
[100, tapClickMe],
[10, taps],
[2, swipes],
);
(globalThis as { actions?: unknown; properties?: unknown }).actions = actionsRoot;
(globalThis as { properties?: unknown }).properties = properties;
+1 -1
View File
@@ -20,7 +20,7 @@ func TestWriteMeta_RoundTrip(t *testing.T) {
meta := Meta{ meta := Meta{
Seed: 42, Seed: 42,
SpecPath: "examples/specs/merchant-ledger.ts", SpecPath: "examples/sample-app/spec.ts",
BundleSHA256: "deadbeef", BundleSHA256: "deadbeef",
Platform: "android", Platform: "android",
BundleID: "in.okcredit.merchant", BundleID: "in.okcredit.merchant",