refactor(folio-web): weight valid generators against edgeCaseText for names/amounts

This commit is contained in:
pj committed 2026-06-01 21:13:33 +05:30
1 parent 3aba528c87
commit 2c410780fa
1 file changed
+26 -23
+26 -23
View File
@@ -3,9 +3,11 @@ import {
Tap, Tap,
actions, actions,
always, always,
edgeCaseText,
eventually, eventually,
extract, extract,
from, from,
integers,
next, next,
now, now,
taps, taps,
@@ -175,7 +177,9 @@ const openAddAccount = actions(() => {
return btn ? [Tap({ on: btn })] : []; return btn ? [Tap({ on: btn })] : [];
}); });
const accountNameSampler = from([ // Readable enumeration keeps the demo legible; repeats over a run still
// exercise duplicate-name handling.
const accountNames = from([
"Checking", "Checking",
"Savings", "Savings",
"Travel", "Travel",
@@ -183,17 +187,19 @@ const accountNameSampler = from([
"Emergency Fund", "Emergency Fund",
"Investments", "Investments",
"Groceries", "Groceries",
" ",
"Checking",
"A".repeat(41),
"Petty Cash", "Petty Cash",
]); ]);
const typeAccountName = actions(() => { function typeAccountNameWith(sampler: { generate(): string }) {
return actions(() => {
if (!onAddAccountPage.current) return []; if (!onAddAccountPage.current) return [];
const field = accountNameField.current; const field = accountNameField.current;
return field ? [InputText({ into: field, text: accountNameSampler.generate() })] : []; return field ? [InputText({ into: field, text: sampler.generate() })] : [];
}); });
}
const typeAccountName = typeAccountNameWith(accountNames);
const typeAccountNameEdge = typeAccountNameWith(edgeCaseText());
const submitAddAccount = actions(() => { const submitAddAccount = actions(() => {
if (!onAddAccountPage.current) return []; if (!onAddAccountPage.current) return [];
@@ -214,25 +220,20 @@ const openAddTxn = actions(() => {
return btn ? [Tap({ on: btn })] : []; return btn ? [Tap({ on: btn })] : [];
}); });
const amountSampler = from([ // Valid happy-path amounts keep the balance properties exercised; the edge
"12.34", // branch (weighted in actionsRoot) stresses parsing with the adversarial corpus.
"100", const validAmounts = integers().between(1, 99999);
"0.01",
"999.99",
"5.5",
"42",
"0",
"",
"1e4",
"0.001",
"-5",
]);
const typeAmount = actions(() => { function typeAmountWith(sampler: { generate(): string }) {
return actions(() => {
if (!onAddTxnPage.current) return []; if (!onAddTxnPage.current) return [];
const field = txnAmountField.current; const field = txnAmountField.current;
return field ? [InputText({ into: field, text: amountSampler.generate() })] : []; return field ? [InputText({ into: field, text: sampler.generate() })] : [];
}); });
}
const typeAmount = typeAmountWith({ generate: () => String(validAmounts.generate()) });
const typeAmountEdge = typeAmountWith(edgeCaseText());
const noteSampler = from([ const noteSampler = from([
"Coffee", "Coffee",
@@ -277,11 +278,13 @@ export const actionsRoot = weighted(
[30, loginHelper], [30, loginHelper],
[2, adversarialLogin], [2, adversarialLogin],
[14, openAddAccount], [14, openAddAccount],
[18, typeAccountName], [14, typeAccountName],
[4, typeAccountNameEdge],
[14, submitAddAccount], [14, submitAddAccount],
[14, openAccount], [14, openAccount],
[12, openAddTxn], [12, openAddTxn],
[18, typeAmount], [14, typeAmount],
[4, typeAmountEdge],
[8, typeNote], [8, typeNote],
[6, toggleTxnType], [6, toggleTxnType],
[16, submitTxn], [16, submitTxn],