aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorcirakg <cirakg@cirakg.xyz>2026-10-19 22:28:09 +0200
committercirakg <cirakg@cirakg.xyz>2026-10-19 22:28:09 +0200
commit2373b6f02ef027a423762d5d6349cd9e0f36090e (patch)
tree7509b0b1905d7c593074bba8ed4c94e30e437604 /test
parent35042ff04ffc50e55ff59a385849442be4429d6b (diff)
test(ui): drive the simulator with a scripted flow and check every screen
tools/ui_flow.py clicks buttons and taps from the device files, waits for DIAG shown lines and compares 10 screens per watch with goldens on four test and three spot-check devices. Adds the fixture-wrap generator, UI logic tests and driver tests; the launcher opens apps from their glance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'test')
-rw-r--r--test/golden/fenix7/about.pngbin0 -> 3828 bytes
-rw-r--r--test/golden/fenix7/list.pngbin0 -> 4654 bytes
-rw-r--r--test/golden/fenix7/menu.pngbin0 -> 2732 bytes
-rw-r--r--test/golden/fenix7/otp.pngbin0 -> 4714 bytes
-rw-r--r--test/golden/fenix7/otp_hotp.pngbin0 -> 3261 bytes
-rw-r--r--test/golden/fenix7/otp_hotp_next.pngbin0 -> 3143 bytes
-rw-r--r--test/golden/fenix7/otp_locked.pngbin0 -> 4509 bytes
-rw-r--r--test/golden/fenix7/pin.pngbin0 -> 2918 bytes
-rw-r--r--test/golden/fenix7/pin_error.pngbin0 -> 3292 bytes
-rw-r--r--test/golden/fenix7/pin_wait.pngbin0 -> 3279 bytes
-rw-r--r--test/golden/fr255s/about.pngbin0 -> 2532 bytes
-rw-r--r--test/golden/fr255s/list.pngbin0 -> 3160 bytes
-rw-r--r--test/golden/fr255s/menu.pngbin0 -> 1716 bytes
-rw-r--r--test/golden/fr255s/otp.pngbin0 -> 3531 bytes
-rw-r--r--test/golden/fr255s/otp_hotp.pngbin0 -> 2394 bytes
-rw-r--r--test/golden/fr255s/otp_hotp_next.pngbin0 -> 2338 bytes
-rw-r--r--test/golden/fr255s/otp_locked.pngbin0 -> 3374 bytes
-rw-r--r--test/golden/fr255s/pin.pngbin0 -> 1352 bytes
-rw-r--r--test/golden/fr255s/pin_error.pngbin0 -> 1720 bytes
-rw-r--r--test/golden/fr255s/pin_wait.pngbin0 -> 2058 bytes
-rw-r--r--test/golden/fr70/about.pngbin0 -> 15633 bytes
-rw-r--r--test/golden/fr70/list.pngbin0 -> 21003 bytes
-rw-r--r--test/golden/fr70/menu.pngbin0 -> 37900 bytes
-rw-r--r--test/golden/fr70/otp.pngbin0 -> 18705 bytes
-rw-r--r--test/golden/fr70/otp_hotp.pngbin0 -> 13568 bytes
-rw-r--r--test/golden/fr70/otp_hotp_next.pngbin0 -> 13361 bytes
-rw-r--r--test/golden/fr70/otp_locked.pngbin0 -> 17406 bytes
-rw-r--r--test/golden/fr70/pin.pngbin0 -> 8869 bytes
-rw-r--r--test/golden/fr70/pin_error.pngbin0 -> 10833 bytes
-rw-r--r--test/golden/fr70/pin_wait.pngbin0 -> 12737 bytes
-rw-r--r--test/golden/fr965/about.pngbin0 -> 17081 bytes
-rw-r--r--test/golden/fr965/list.pngbin0 -> 21792 bytes
-rw-r--r--test/golden/fr965/menu.pngbin0 -> 42767 bytes
-rw-r--r--test/golden/fr965/otp.pngbin0 -> 23628 bytes
-rw-r--r--test/golden/fr965/otp_hotp.pngbin0 -> 15712 bytes
-rw-r--r--test/golden/fr965/otp_hotp_next.pngbin0 -> 15343 bytes
-rw-r--r--test/golden/fr965/otp_locked.pngbin0 -> 22483 bytes
-rw-r--r--test/golden/fr965/pin.pngbin0 -> 11461 bytes
-rw-r--r--test/golden/fr965/pin_error.pngbin0 -> 13315 bytes
-rw-r--r--test/golden/fr965/pin_wait.pngbin0 -> 15898 bytes
-rw-r--r--test/golden/instinct3amoled45mm/about.pngbin0 -> 13211 bytes
-rw-r--r--test/golden/instinct3amoled45mm/list.pngbin0 -> 15614 bytes
-rw-r--r--test/golden/instinct3amoled45mm/menu.pngbin0 -> 41632 bytes
-rw-r--r--test/golden/instinct3amoled45mm/otp.pngbin0 -> 14674 bytes
-rw-r--r--test/golden/instinct3amoled45mm/otp_hotp.pngbin0 -> 12460 bytes
-rw-r--r--test/golden/instinct3amoled45mm/otp_hotp_next.pngbin0 -> 12478 bytes
-rw-r--r--test/golden/instinct3amoled45mm/otp_locked.pngbin0 -> 14194 bytes
-rw-r--r--test/golden/instinct3amoled45mm/pin.pngbin0 -> 9569 bytes
-rw-r--r--test/golden/instinct3amoled45mm/pin_error.pngbin0 -> 10508 bytes
-rw-r--r--test/golden/instinct3amoled45mm/pin_wait.pngbin0 -> 11459 bytes
-rw-r--r--test/golden/venusq2/list.pngbin0 -> 5160 bytes
-rw-r--r--test/golden/venusq2/menu.pngbin0 -> 3126 bytes
-rw-r--r--test/golden/venusq2/otp.pngbin0 -> 4456 bytes
-rw-r--r--test/golden/venusq2/otp_hotp.pngbin0 -> 4291 bytes
-rw-r--r--test/golden/venusq2/otp_hotp_next.pngbin0 -> 4130 bytes
-rw-r--r--test/golden/venusq2/otp_locked.pngbin0 -> 4337 bytes
-rw-r--r--test/golden/venusq2/pin.pngbin0 -> 2734 bytes
-rw-r--r--test/golden/venusq2/pin_error.pngbin0 -> 3152 bytes
-rw-r--r--test/golden/venusq2/pin_wait.pngbin0 -> 3632 bytes
-rw-r--r--test/golden/venux1/list.pngbin0 -> 26735 bytes
-rw-r--r--test/golden/venux1/menu.pngbin0 -> 49066 bytes
-rw-r--r--test/golden/venux1/otp.pngbin0 -> 16178 bytes
-rw-r--r--test/golden/venux1/otp_hotp.pngbin0 -> 15547 bytes
-rw-r--r--test/golden/venux1/otp_hotp_next.pngbin0 -> 15221 bytes
-rw-r--r--test/golden/venux1/otp_locked.pngbin0 -> 15040 bytes
-rw-r--r--test/golden/venux1/pin.pngbin0 -> 11861 bytes
-rw-r--r--test/golden/venux1/pin_error.pngbin0 -> 13551 bytes
-rw-r--r--test/golden/venux1/pin_wait.pngbin0 -> 15922 bytes
-rw-r--r--test/storage/PinTest.mc13
-rw-r--r--test/ui/UiLogicTest.mc92
70 files changed, 105 insertions, 0 deletions
diff --git a/test/golden/fenix7/about.png b/test/golden/fenix7/about.png
new file mode 100644
index 0000000..d6a87a2
--- /dev/null
+++ b/test/golden/fenix7/about.png
Binary files differ
diff --git a/test/golden/fenix7/list.png b/test/golden/fenix7/list.png
new file mode 100644
index 0000000..ffcc3ff
--- /dev/null
+++ b/test/golden/fenix7/list.png
Binary files differ
diff --git a/test/golden/fenix7/menu.png b/test/golden/fenix7/menu.png
new file mode 100644
index 0000000..3ceb597
--- /dev/null
+++ b/test/golden/fenix7/menu.png
Binary files differ
diff --git a/test/golden/fenix7/otp.png b/test/golden/fenix7/otp.png
new file mode 100644
index 0000000..8ef0cad
--- /dev/null
+++ b/test/golden/fenix7/otp.png
Binary files differ
diff --git a/test/golden/fenix7/otp_hotp.png b/test/golden/fenix7/otp_hotp.png
new file mode 100644
index 0000000..a325345
--- /dev/null
+++ b/test/golden/fenix7/otp_hotp.png
Binary files differ
diff --git a/test/golden/fenix7/otp_hotp_next.png b/test/golden/fenix7/otp_hotp_next.png
new file mode 100644
index 0000000..a9ff510
--- /dev/null
+++ b/test/golden/fenix7/otp_hotp_next.png
Binary files differ
diff --git a/test/golden/fenix7/otp_locked.png b/test/golden/fenix7/otp_locked.png
new file mode 100644
index 0000000..ef29840
--- /dev/null
+++ b/test/golden/fenix7/otp_locked.png
Binary files differ
diff --git a/test/golden/fenix7/pin.png b/test/golden/fenix7/pin.png
new file mode 100644
index 0000000..d1fe80b
--- /dev/null
+++ b/test/golden/fenix7/pin.png
Binary files differ
diff --git a/test/golden/fenix7/pin_error.png b/test/golden/fenix7/pin_error.png
new file mode 100644
index 0000000..48541c8
--- /dev/null
+++ b/test/golden/fenix7/pin_error.png
Binary files differ
diff --git a/test/golden/fenix7/pin_wait.png b/test/golden/fenix7/pin_wait.png
new file mode 100644
index 0000000..77cce98
--- /dev/null
+++ b/test/golden/fenix7/pin_wait.png
Binary files differ
diff --git a/test/golden/fr255s/about.png b/test/golden/fr255s/about.png
new file mode 100644
index 0000000..f8f23d2
--- /dev/null
+++ b/test/golden/fr255s/about.png
Binary files differ
diff --git a/test/golden/fr255s/list.png b/test/golden/fr255s/list.png
new file mode 100644
index 0000000..df30245
--- /dev/null
+++ b/test/golden/fr255s/list.png
Binary files differ
diff --git a/test/golden/fr255s/menu.png b/test/golden/fr255s/menu.png
new file mode 100644
index 0000000..047504c
--- /dev/null
+++ b/test/golden/fr255s/menu.png
Binary files differ
diff --git a/test/golden/fr255s/otp.png b/test/golden/fr255s/otp.png
new file mode 100644
index 0000000..f1637d7
--- /dev/null
+++ b/test/golden/fr255s/otp.png
Binary files differ
diff --git a/test/golden/fr255s/otp_hotp.png b/test/golden/fr255s/otp_hotp.png
new file mode 100644
index 0000000..fb4fb2e
--- /dev/null
+++ b/test/golden/fr255s/otp_hotp.png
Binary files differ
diff --git a/test/golden/fr255s/otp_hotp_next.png b/test/golden/fr255s/otp_hotp_next.png
new file mode 100644
index 0000000..2c36aaf
--- /dev/null
+++ b/test/golden/fr255s/otp_hotp_next.png
Binary files differ
diff --git a/test/golden/fr255s/otp_locked.png b/test/golden/fr255s/otp_locked.png
new file mode 100644
index 0000000..6b185ad
--- /dev/null
+++ b/test/golden/fr255s/otp_locked.png
Binary files differ
diff --git a/test/golden/fr255s/pin.png b/test/golden/fr255s/pin.png
new file mode 100644
index 0000000..bb3e989
--- /dev/null
+++ b/test/golden/fr255s/pin.png
Binary files differ
diff --git a/test/golden/fr255s/pin_error.png b/test/golden/fr255s/pin_error.png
new file mode 100644
index 0000000..b580338
--- /dev/null
+++ b/test/golden/fr255s/pin_error.png
Binary files differ
diff --git a/test/golden/fr255s/pin_wait.png b/test/golden/fr255s/pin_wait.png
new file mode 100644
index 0000000..cc1e27b
--- /dev/null
+++ b/test/golden/fr255s/pin_wait.png
Binary files differ
diff --git a/test/golden/fr70/about.png b/test/golden/fr70/about.png
new file mode 100644
index 0000000..c46fa11
--- /dev/null
+++ b/test/golden/fr70/about.png
Binary files differ
diff --git a/test/golden/fr70/list.png b/test/golden/fr70/list.png
new file mode 100644
index 0000000..eaa657e
--- /dev/null
+++ b/test/golden/fr70/list.png
Binary files differ
diff --git a/test/golden/fr70/menu.png b/test/golden/fr70/menu.png
new file mode 100644
index 0000000..b35e078
--- /dev/null
+++ b/test/golden/fr70/menu.png
Binary files differ
diff --git a/test/golden/fr70/otp.png b/test/golden/fr70/otp.png
new file mode 100644
index 0000000..af4f2d4
--- /dev/null
+++ b/test/golden/fr70/otp.png
Binary files differ
diff --git a/test/golden/fr70/otp_hotp.png b/test/golden/fr70/otp_hotp.png
new file mode 100644
index 0000000..7e341f2
--- /dev/null
+++ b/test/golden/fr70/otp_hotp.png
Binary files differ
diff --git a/test/golden/fr70/otp_hotp_next.png b/test/golden/fr70/otp_hotp_next.png
new file mode 100644
index 0000000..75e8f2a
--- /dev/null
+++ b/test/golden/fr70/otp_hotp_next.png
Binary files differ
diff --git a/test/golden/fr70/otp_locked.png b/test/golden/fr70/otp_locked.png
new file mode 100644
index 0000000..8730813
--- /dev/null
+++ b/test/golden/fr70/otp_locked.png
Binary files differ
diff --git a/test/golden/fr70/pin.png b/test/golden/fr70/pin.png
new file mode 100644
index 0000000..71f6579
--- /dev/null
+++ b/test/golden/fr70/pin.png
Binary files differ
diff --git a/test/golden/fr70/pin_error.png b/test/golden/fr70/pin_error.png
new file mode 100644
index 0000000..9a3de60
--- /dev/null
+++ b/test/golden/fr70/pin_error.png
Binary files differ
diff --git a/test/golden/fr70/pin_wait.png b/test/golden/fr70/pin_wait.png
new file mode 100644
index 0000000..ed8132e
--- /dev/null
+++ b/test/golden/fr70/pin_wait.png
Binary files differ
diff --git a/test/golden/fr965/about.png b/test/golden/fr965/about.png
new file mode 100644
index 0000000..61b9745
--- /dev/null
+++ b/test/golden/fr965/about.png
Binary files differ
diff --git a/test/golden/fr965/list.png b/test/golden/fr965/list.png
new file mode 100644
index 0000000..d0904b2
--- /dev/null
+++ b/test/golden/fr965/list.png
Binary files differ
diff --git a/test/golden/fr965/menu.png b/test/golden/fr965/menu.png
new file mode 100644
index 0000000..ba1149d
--- /dev/null
+++ b/test/golden/fr965/menu.png
Binary files differ
diff --git a/test/golden/fr965/otp.png b/test/golden/fr965/otp.png
new file mode 100644
index 0000000..111001b
--- /dev/null
+++ b/test/golden/fr965/otp.png
Binary files differ
diff --git a/test/golden/fr965/otp_hotp.png b/test/golden/fr965/otp_hotp.png
new file mode 100644
index 0000000..fbcc1a4
--- /dev/null
+++ b/test/golden/fr965/otp_hotp.png
Binary files differ
diff --git a/test/golden/fr965/otp_hotp_next.png b/test/golden/fr965/otp_hotp_next.png
new file mode 100644
index 0000000..181bc37
--- /dev/null
+++ b/test/golden/fr965/otp_hotp_next.png
Binary files differ
diff --git a/test/golden/fr965/otp_locked.png b/test/golden/fr965/otp_locked.png
new file mode 100644
index 0000000..537dc0c
--- /dev/null
+++ b/test/golden/fr965/otp_locked.png
Binary files differ
diff --git a/test/golden/fr965/pin.png b/test/golden/fr965/pin.png
new file mode 100644
index 0000000..06cab65
--- /dev/null
+++ b/test/golden/fr965/pin.png
Binary files differ
diff --git a/test/golden/fr965/pin_error.png b/test/golden/fr965/pin_error.png
new file mode 100644
index 0000000..c187ada
--- /dev/null
+++ b/test/golden/fr965/pin_error.png
Binary files differ
diff --git a/test/golden/fr965/pin_wait.png b/test/golden/fr965/pin_wait.png
new file mode 100644
index 0000000..e381d23
--- /dev/null
+++ b/test/golden/fr965/pin_wait.png
Binary files differ
diff --git a/test/golden/instinct3amoled45mm/about.png b/test/golden/instinct3amoled45mm/about.png
new file mode 100644
index 0000000..1400601
--- /dev/null
+++ b/test/golden/instinct3amoled45mm/about.png
Binary files differ
diff --git a/test/golden/instinct3amoled45mm/list.png b/test/golden/instinct3amoled45mm/list.png
new file mode 100644
index 0000000..d4b9323
--- /dev/null
+++ b/test/golden/instinct3amoled45mm/list.png
Binary files differ
diff --git a/test/golden/instinct3amoled45mm/menu.png b/test/golden/instinct3amoled45mm/menu.png
new file mode 100644
index 0000000..6c6f81e
--- /dev/null
+++ b/test/golden/instinct3amoled45mm/menu.png
Binary files differ
diff --git a/test/golden/instinct3amoled45mm/otp.png b/test/golden/instinct3amoled45mm/otp.png
new file mode 100644
index 0000000..0b780ae
--- /dev/null
+++ b/test/golden/instinct3amoled45mm/otp.png
Binary files differ
diff --git a/test/golden/instinct3amoled45mm/otp_hotp.png b/test/golden/instinct3amoled45mm/otp_hotp.png
new file mode 100644
index 0000000..def95cf
--- /dev/null
+++ b/test/golden/instinct3amoled45mm/otp_hotp.png
Binary files differ
diff --git a/test/golden/instinct3amoled45mm/otp_hotp_next.png b/test/golden/instinct3amoled45mm/otp_hotp_next.png
new file mode 100644
index 0000000..9608c2c
--- /dev/null
+++ b/test/golden/instinct3amoled45mm/otp_hotp_next.png
Binary files differ
diff --git a/test/golden/instinct3amoled45mm/otp_locked.png b/test/golden/instinct3amoled45mm/otp_locked.png
new file mode 100644
index 0000000..0ef7e4b
--- /dev/null
+++ b/test/golden/instinct3amoled45mm/otp_locked.png
Binary files differ
diff --git a/test/golden/instinct3amoled45mm/pin.png b/test/golden/instinct3amoled45mm/pin.png
new file mode 100644
index 0000000..92b60d5
--- /dev/null
+++ b/test/golden/instinct3amoled45mm/pin.png
Binary files differ
diff --git a/test/golden/instinct3amoled45mm/pin_error.png b/test/golden/instinct3amoled45mm/pin_error.png
new file mode 100644
index 0000000..9d330b8
--- /dev/null
+++ b/test/golden/instinct3amoled45mm/pin_error.png
Binary files differ
diff --git a/test/golden/instinct3amoled45mm/pin_wait.png b/test/golden/instinct3amoled45mm/pin_wait.png
new file mode 100644
index 0000000..39eae8d
--- /dev/null
+++ b/test/golden/instinct3amoled45mm/pin_wait.png
Binary files differ
diff --git a/test/golden/venusq2/list.png b/test/golden/venusq2/list.png
new file mode 100644
index 0000000..f778d10
--- /dev/null
+++ b/test/golden/venusq2/list.png
Binary files differ
diff --git a/test/golden/venusq2/menu.png b/test/golden/venusq2/menu.png
new file mode 100644
index 0000000..6393819
--- /dev/null
+++ b/test/golden/venusq2/menu.png
Binary files differ
diff --git a/test/golden/venusq2/otp.png b/test/golden/venusq2/otp.png
new file mode 100644
index 0000000..3948080
--- /dev/null
+++ b/test/golden/venusq2/otp.png
Binary files differ
diff --git a/test/golden/venusq2/otp_hotp.png b/test/golden/venusq2/otp_hotp.png
new file mode 100644
index 0000000..2331618
--- /dev/null
+++ b/test/golden/venusq2/otp_hotp.png
Binary files differ
diff --git a/test/golden/venusq2/otp_hotp_next.png b/test/golden/venusq2/otp_hotp_next.png
new file mode 100644
index 0000000..564df92
--- /dev/null
+++ b/test/golden/venusq2/otp_hotp_next.png
Binary files differ
diff --git a/test/golden/venusq2/otp_locked.png b/test/golden/venusq2/otp_locked.png
new file mode 100644
index 0000000..9181d66
--- /dev/null
+++ b/test/golden/venusq2/otp_locked.png
Binary files differ
diff --git a/test/golden/venusq2/pin.png b/test/golden/venusq2/pin.png
new file mode 100644
index 0000000..9b51943
--- /dev/null
+++ b/test/golden/venusq2/pin.png
Binary files differ
diff --git a/test/golden/venusq2/pin_error.png b/test/golden/venusq2/pin_error.png
new file mode 100644
index 0000000..80a803e
--- /dev/null
+++ b/test/golden/venusq2/pin_error.png
Binary files differ
diff --git a/test/golden/venusq2/pin_wait.png b/test/golden/venusq2/pin_wait.png
new file mode 100644
index 0000000..618e517
--- /dev/null
+++ b/test/golden/venusq2/pin_wait.png
Binary files differ
diff --git a/test/golden/venux1/list.png b/test/golden/venux1/list.png
new file mode 100644
index 0000000..8ba6f1f
--- /dev/null
+++ b/test/golden/venux1/list.png
Binary files differ
diff --git a/test/golden/venux1/menu.png b/test/golden/venux1/menu.png
new file mode 100644
index 0000000..6930419
--- /dev/null
+++ b/test/golden/venux1/menu.png
Binary files differ
diff --git a/test/golden/venux1/otp.png b/test/golden/venux1/otp.png
new file mode 100644
index 0000000..52d83df
--- /dev/null
+++ b/test/golden/venux1/otp.png
Binary files differ
diff --git a/test/golden/venux1/otp_hotp.png b/test/golden/venux1/otp_hotp.png
new file mode 100644
index 0000000..e6b8c6c
--- /dev/null
+++ b/test/golden/venux1/otp_hotp.png
Binary files differ
diff --git a/test/golden/venux1/otp_hotp_next.png b/test/golden/venux1/otp_hotp_next.png
new file mode 100644
index 0000000..7ffbdf5
--- /dev/null
+++ b/test/golden/venux1/otp_hotp_next.png
Binary files differ
diff --git a/test/golden/venux1/otp_locked.png b/test/golden/venux1/otp_locked.png
new file mode 100644
index 0000000..5564888
--- /dev/null
+++ b/test/golden/venux1/otp_locked.png
Binary files differ
diff --git a/test/golden/venux1/pin.png b/test/golden/venux1/pin.png
new file mode 100644
index 0000000..6263938
--- /dev/null
+++ b/test/golden/venux1/pin.png
Binary files differ
diff --git a/test/golden/venux1/pin_error.png b/test/golden/venux1/pin_error.png
new file mode 100644
index 0000000..ff2e723
--- /dev/null
+++ b/test/golden/venux1/pin_error.png
Binary files differ
diff --git a/test/golden/venux1/pin_wait.png b/test/golden/venux1/pin_wait.png
new file mode 100644
index 0000000..c91126f
--- /dev/null
+++ b/test/golden/venux1/pin_wait.png
Binary files differ
diff --git a/test/storage/PinTest.mc b/test/storage/PinTest.mc
index 7dc677d..0212936 100644
--- a/test/storage/PinTest.mc
+++ b/test/storage/PinTest.mc
@@ -248,3 +248,16 @@ function pinKeyBuffersAreWiped(logger as Test.Logger) as Boolean {
keys.wipe();
return derived && wiped && StorageFixtures.allZero(keys.encKey) && StorageFixtures.allZero(keys.macKey);
}
+
+// The UI-test fixture's wrap was computed in Python (tools/gen_fixture_wrap.py);
+// the app's unlock code must accept it with the fixture PIN and recover the
+// fixture master key, which cross-checks the wrap format.
+(:test)
+function pinOpensThePythonComputedFixtureWrap(logger as Test.Logger) as Boolean {
+ var store = new MemoryBackend();
+ store.setValue(KeyManager.WRAP_KEY, Bytes.fromHex(Fixtures.FIXTURE_WRAP));
+ var vault = new Vault(store, new FakeTime());
+ var wrongRejected = !StorageFixtures.unlock(vault, StorageFixtures.OTHER_PIN);
+ var opened = StorageFixtures.unlock(vault, Fixtures.FIXTURE_PIN);
+ return wrongRejected && opened && Bytes.equal(vault.session.masterKey(), Bytes.fromHex(Fixtures.FIXTURE_MASTER_KEY));
+}
diff --git a/test/ui/UiLogicTest.mc b/test/ui/UiLogicTest.mc
new file mode 100644
index 0000000..01b7dae
--- /dev/null
+++ b/test/ui/UiLogicTest.mc
@@ -0,0 +1,92 @@
+// Author: cirakg & claude ai
+// Summary: Tests for the UI's logic without a screen: the code cache, code grouping, text helpers and option defaults.
+
+import Toybox.Lang;
+import Toybox.Test;
+
+(:test)
+function codeCacheSplitsCodesForReading(logger as Test.Logger) as Boolean {
+ var cases = [["123456", "123|456"], ["1234567", "123|4567"], ["12345678", "1234|5678"], ["R7VXK", "R7VXK"]];
+ for (var i = 0; i < cases.size(); i++) {
+ var c = cases[i] as Array<String>;
+ var parts = CodeCache.split(c[0]);
+ var joined = parts.size() == 2 ? parts[0] + "|" + parts[1] : parts[0];
+ if (!TestSupport.sameString(logger, "split " + c[0], joined, c[1])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+// The cache gives the same codes as the OTP module, keeps them until the
+// period ends, and learns the period and cost from the encrypted part.
+(:test)
+function codeCacheComputesAndExpiresCodes(logger as Test.Logger) as Boolean {
+ var vault = new Vault(new MemoryBackend(), new FakeTime());
+ var e = StorageFixtures.totp("Cache");
+ var secret = Bytes.copy(e.secret as ByteArray);
+ var id = vault.add(e);
+ var cache = new CodeCache(vault);
+ var now = 1800000026l; // 34 s left in the fixture's 60 s period
+ var expected = Otp.totp(Hashes.SHA256, secret, now, 60, 8);
+ var next = Otp.totp(Hashes.SHA256, secret, now + 60, 60, 8);
+ var unknownCost = cache.costOf(e);
+ var code = cache.code(id, now, 0);
+ var stillCached = cache.cached(id, now + 33) != null;
+ var expired = cache.cached(id, now + 34) == null;
+ return TestSupport.sameString(logger, "current", code, expected)
+ && TestSupport.sameString(logger, "next", cache.code(id, now, 1), next)
+ && stillCached && expired && cache.periodOf(id) == 60
+ && unknownCost == CodeCache.COST_SHA512 && cache.costOf(e) == CodeCache.COST_NATIVE;
+}
+
+(:test)
+function codeCacheHotpAndInvalidate(logger as Test.Logger) as Boolean {
+ var vault = new Vault(new MemoryBackend(), new FakeTime());
+ var id = vault.add(StorageFixtures.hotp("Counter", 5l));
+ var cache = new CodeCache(vault);
+ var first = cache.code(id, 0l, 0);
+ vault.setCounter(id, 6l);
+ var stale = cache.code(id, 0l, 0);
+ cache.invalidate(id);
+ var fresh = cache.code(id, 0l, 0);
+ // RFC 4226 Appendix D: counters 5 and 6.
+ return first.equals("254676") && stale.equals("254676") && fresh.equals("287922");
+}
+
+(:test)
+function codeCacheRefusesLockedEntriesWhileLocked(logger as Test.Logger) as Boolean {
+ var vault = new Vault(new MemoryBackend(), new FakeTime());
+ StorageFixtures.setPin(vault, StorageFixtures.PIN);
+ var e = StorageFixtures.totp("Locked");
+ e.locked = true;
+ var id = vault.add(e);
+ var cache = new CodeCache(vault);
+ var unlockedCode = cache.code(id, 1800000026l, 0);
+ vault.lock();
+ cache.clear();
+ var code = 0;
+ try {
+ cache.code(id, 1800000026l, 0);
+ } catch (err instanceof VaultError) {
+ code = err.code;
+ }
+ return unlockedCode.length() == 8 && code == VaultError.LOCKED && cache.cached(id, 1800000026l) == null;
+}
+
+(:test)
+function uiTextHelpers(logger as Test.Logger) as Boolean {
+ var parts = Ui.split("a b c", " ");
+ return Ui.isDigits("123 456") && !Ui.isDigits("12a") && !Ui.isDigits("") && !Ui.isDigits("------")
+ && parts.size() == 4 && parts[0].equals("a") && parts[2].equals("") && parts[3].equals("c")
+ && Ui.minutesSeconds(90).equals("1:30") && Ui.minutesSeconds(3600).equals("60:00") && Ui.minutesSeconds(5).equals("0:05");
+}
+
+// resources/settings/properties.xml defaults give README 10.2's defaults.
+(:test)
+function optionsDefaults(logger as Test.Logger) as Boolean {
+ var o = new Options();
+ o.load();
+ return o.autoLockMs == 60000 && !o.eraseAfterFailures && o.timeOffset == 0 && o.codeSize == Options.CODE_LARGE
+ && o.theme == Options.THEME_DARK && o.showGroups && !o.encryptNames && !o.glanceCode && o.fullBrightness;
+}