feat(go): M6.6 — /qr, /sync-bank, /flush-cache, /version pages
All checks were successful
Deploy to K8s / deploy (push) Successful in 8s
All checks were successful
Deploy to K8s / deploy (push) Successful in 8s
- GET /qr: Czech QR Platba PNG; ports Python qr_code() exactly
(account validation, amount clamping, * stripping, SPD format)
- GET /sync-bank: Fio sync → infer → cache flush with captured log
- GET+POST /flush-cache: form + action, shows deleted count
- GET /version: JSON alias of /api/version (Python parity)
- FlushCache() added to membership.Sources; wired through api.Handler
- web.ActionHandlers{BankSync} closure-based dep injection for sync
- New dep: github.com/skip2/go-qrcode
- TestQRBuildSPD (9 cases), TestServeQR, TestServeFlushCache{GET,POST},
TestServeSync, TestServeVersion added
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
91
go/internal/web/qr_test.go
Normal file
91
go/internal/web/qr_test.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestQRBuildSPD(t *testing.T) {
|
||||
const def = "2702008874/2010"
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
account string
|
||||
amount string
|
||||
message string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "czech account",
|
||||
account: "2702008874/2010",
|
||||
amount: "700",
|
||||
message: "Test Member: 01/2026",
|
||||
want: "SPD*1.0*ACC:2702008874*BC:2010*AM:700.00*CC:CZK*MSG:Test Member: 01/2026",
|
||||
},
|
||||
{
|
||||
name: "IBAN account",
|
||||
account: "CZ6508000000192000145399",
|
||||
amount: "500",
|
||||
message: "hi",
|
||||
want: "SPD*1.0*ACC:CZ6508000000192000145399*AM:500.00*CC:CZK*MSG:hi",
|
||||
},
|
||||
{
|
||||
name: "invalid account falls back to default",
|
||||
account: "NOTANACCOUNT",
|
||||
amount: "100",
|
||||
message: "x",
|
||||
want: "SPD*1.0*ACC:2702008874*BC:2010*AM:100.00*CC:CZK*MSG:x",
|
||||
},
|
||||
{
|
||||
name: "empty account falls back to default",
|
||||
account: "",
|
||||
amount: "0",
|
||||
message: "",
|
||||
want: "SPD*1.0*ACC:2702008874*BC:2010*AM:0.00*CC:CZK*MSG:",
|
||||
},
|
||||
{
|
||||
name: "negative amount clamped to 0.00",
|
||||
account: def,
|
||||
amount: "-1",
|
||||
message: "",
|
||||
want: "SPD*1.0*ACC:2702008874*BC:2010*AM:0.00*CC:CZK*MSG:",
|
||||
},
|
||||
{
|
||||
name: "amount over 10M clamped to 0.00",
|
||||
account: def,
|
||||
amount: "99999999",
|
||||
message: "",
|
||||
want: "SPD*1.0*ACC:2702008874*BC:2010*AM:0.00*CC:CZK*MSG:",
|
||||
},
|
||||
{
|
||||
name: "non-numeric amount becomes 0.00",
|
||||
account: def,
|
||||
amount: "abc",
|
||||
message: "",
|
||||
want: "SPD*1.0*ACC:2702008874*BC:2010*AM:0.00*CC:CZK*MSG:",
|
||||
},
|
||||
{
|
||||
name: "asterisks stripped from message",
|
||||
account: def,
|
||||
amount: "100",
|
||||
message: "pay*now",
|
||||
want: "SPD*1.0*ACC:2702008874*BC:2010*AM:100.00*CC:CZK*MSG:paynow",
|
||||
},
|
||||
{
|
||||
name: "message truncated to 60 runes",
|
||||
account: def,
|
||||
amount: "0",
|
||||
message: strings.Repeat("á", 65),
|
||||
want: "SPD*1.0*ACC:2702008874*BC:2010*AM:0.00*CC:CZK*MSG:" + strings.Repeat("á", 60),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
got := BuildSPD(tc.account, tc.amount, tc.message, def)
|
||||
if got != tc.want {
|
||||
t.Errorf("\ngot: %s\nwant: %s", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user