From 23bb2a75cc4b34efbc3b7c2fb712b2b6f4b631cd Mon Sep 17 00:00:00 2001 From: PJ Date: Sun, 26 Apr 2026 22:19:20 +0700 Subject: [PATCH] feat(folio): testTag identity for AccountName and ledger row cells Replaces string-heuristic identity in the spec extractors with stable testTags. AccountCard exposes AccountName; LedgerRow exposes TxnNote and TxnDate. Spec extractors read those directly instead of filtering visible text by "starts with $" / "matches digit". --- .../app/folio/feature/home/HomeScreen.kt | 1 + .../app/folio/feature/ledger/LedgerScreen.kt | 3 ++- examples/folio/sanderling/spec.ts | 22 +++++++++---------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/folio/app/shared/src/commonMain/kotlin/app/folio/feature/home/HomeScreen.kt b/examples/folio/app/shared/src/commonMain/kotlin/app/folio/feature/home/HomeScreen.kt index 4fbd28b..29bae99 100644 --- a/examples/folio/app/shared/src/commonMain/kotlin/app/folio/feature/home/HomeScreen.kt +++ b/examples/folio/app/shared/src/commonMain/kotlin/app/folio/feature/home/HomeScreen.kt @@ -151,6 +151,7 @@ private fun AccountCard( color = t.text, maxLines = 1, overflow = TextOverflow.Ellipsis, + modifier = Modifier.testTag("AccountName"), ) Text(txnLabel, style = Type.caption, color = t.textMuted) } diff --git a/examples/folio/app/shared/src/commonMain/kotlin/app/folio/feature/ledger/LedgerScreen.kt b/examples/folio/app/shared/src/commonMain/kotlin/app/folio/feature/ledger/LedgerScreen.kt index d3c20f5..1897d6e 100644 --- a/examples/folio/app/shared/src/commonMain/kotlin/app/folio/feature/ledger/LedgerScreen.kt +++ b/examples/folio/app/shared/src/commonMain/kotlin/app/folio/feature/ledger/LedgerScreen.kt @@ -163,8 +163,9 @@ private fun TxnRow(type: TxnType, amount: Long, note: String, date: String) { color = t.text, maxLines = 1, overflow = TextOverflow.Ellipsis, + modifier = Modifier.testTag("TxnNote"), ) - Text(date, style = Type.caption, color = t.textFaint) + Text(date, style = Type.caption, color = t.textFaint, modifier = Modifier.testTag("TxnDate")) } Text( formatCents(signed, signed = true), diff --git a/examples/folio/sanderling/spec.ts b/examples/folio/sanderling/spec.ts index e5abd9d..2f15654 100644 --- a/examples/folio/sanderling/spec.ts +++ b/examples/folio/sanderling/spec.ts @@ -39,27 +39,25 @@ const route = extract(s => { return null; }); -// Account cards on Home: identified by visible name (the first Text node inside). -// Each card carries an AccountBalance Text with the formatted dollar value. +// Account cards on Home: identity is the AccountName text; balance comes from AccountBalance. const accounts = extract(s => { const home = s.ax.find({ testTag: "HomeScreen" }); if (!home) return []; - return home.findAll({ testTag: "AccountCard" }).map(card => { - const texts = card.findAll({}).map(c => c.text).filter((t): t is string => !!t); - const balance = parseDollarCents(card.find({ testTag: "AccountBalance" })?.text); - const name = texts.find(t => !t.startsWith("$") && !/^\d/.test(t) && t !== "transaction" && t !== "transactions") ?? ""; - return { name, balance }; - }); + return home.findAll({ testTag: "AccountCard" }).map(card => ({ + name: card.find({ testTag: "AccountName" })?.text ?? "", + balance: parseDollarCents(card.find({ testTag: "AccountBalance" })?.text), + })); }); -// Ledger rows: identified by the row's text contents joined together. +// Ledger rows: identity composed from the row's stable testTag'd cells. const ledgerRows = extract(s => { const ledger = s.ax.find({ testTag: "LedgerScreen" }); if (!ledger) return []; return ledger.findAll({ testTag: "LedgerRow" }).map(row => { - const texts = row.findAll({}).map(c => c.text).filter((t): t is string => !!t); - const signed = parseDollarCents(row.find({ testTag: "TxnAmount" })?.text); - return { key: texts.join("|"), signed }; + const note = row.find({ testTag: "TxnNote" })?.text ?? ""; + const date = row.find({ testTag: "TxnDate" })?.text ?? ""; + const amount = row.find({ testTag: "TxnAmount" })?.text ?? ""; + return { key: `${date}|${note}|${amount}`, signed: parseDollarCents(amount) }; }); });