Files
miti99bot/internal/modules/wordle/lookup_test.go
T
tiennm99 ee5e127b51 feat(modules): port wordle module + per-subject locking
Phase 5b of go-port-cloud-run plan. Port 14855-word dictionary
(89 KB, byte-identical to JS source) and four wordle commands
(/wordle, /wordle_new, /wordle_giveup, /wordle_stats).

KV wire-format parity: GameState/Stats JSON match JS shape;
*int64 LastResultAt for null-value compatibility. Two real bugs
caught and fixed: (1) defaultRNG data race in handlers — switched
to math/rand.Intn (mutex-protected package-level); (2) Get→mutate→Put
logical race in groups — added per-subject sync.Mutex map to serialize
access. TTL deferred (Firestore has no expirationTtl equiv — Phase 11 GC).
2026-05-09 09:35:23 +07:00

50 lines
1.4 KiB
Go

package wordle
import "testing"
func TestNormalizeWord(t *testing.T) {
cases := map[string]string{
"": "",
"crane": "crane",
"CRANE": "crane",
" crane ": "crane",
"c-r-a-n-e": "crane",
"héllo": "hllo", // strips non a-z (including the é and accented o-equivalent)
"!@#$%": "",
"42 crane": "crane",
}
for in, want := range cases {
if got := normalizeWord(in); got != want {
t.Errorf("normalizeWord(%q) = %q, want %q", in, got, want)
}
}
}
func TestValidateGuess(t *testing.T) {
dict := map[string]struct{}{"crane": {}, "shale": {}}
type want struct {
ok bool
reason rejectReason
word string
}
cases := []struct {
input string
want want
}{
{"", want{ok: false, reason: reasonEmpty, word: ""}},
{"!!!", want{ok: false, reason: reasonEmpty, word: ""}},
{"cat", want{ok: false, reason: reasonLength, word: "cat"}},
{"craning", want{ok: false, reason: reasonLength, word: "craning"}},
{"there", want{ok: false, reason: reasonUnknown, word: "there"}},
{"crane", want{ok: true, word: "crane"}},
{" CRANE!", want{ok: true, word: "crane"}}, // normalization survives
}
for _, c := range cases {
got := validateGuess(dict, c.input)
if got.OK != c.want.ok || got.Reason != c.want.reason || got.Word != c.want.word {
t.Errorf("validateGuess(%q) = %+v, want %+v", c.input, got, c.want)
}
}
}