mirror of
https://github.com/tiennm99/miti99bot.git
synced 2026-06-09 14:12:10 +00:00
daeaf0c605
The CF→AWS data migration (closed 2026-05-16) is long done and the tooling isn't wired into any production path. Remove the one-shot binary, its support package, and the migration runbook. In live code, replace 'JS-parity' / 'same shape as JS' / 'cross-runtime KV migration' comments with the real, stable reason for each behavior (wire-format invariant, null-vs-zero distinction, CloudWatch alarm field name, etc.). 24 files touched across lolschedule, loldle, wordle, twentyq, trading, misc, util, server, metrics, ai, keylock. - delete cmd/migrate_cf_data/ - delete internal/migration/ - delete docs/cf-to-aws-migration-runbook.md
88 lines
3.5 KiB
Go
88 lines
3.5 KiB
Go
package loldle
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// TestRenderGuess_AlignsLabelColumn locks the monospace column-alignment
|
|
// invariant: the label column must be padded to the longest label so stacked
|
|
// guesses on the board line up.
|
|
func TestRenderGuess_AlignsLabelColumn(t *testing.T) {
|
|
rows := []AttributeRow{
|
|
{Key: "gender", Label: "Gender", Type: attrExact, GuessValue: "Male", Result: ResultCorrect},
|
|
{Key: "release_date", Label: "Release year", Type: attrYear, GuessValue: "2010", Result: ResultWrong, Direction: "up"},
|
|
}
|
|
out := renderGuess("Aatrox", rows)
|
|
|
|
// HTML envelope must be a <pre>…</pre> so Telegram renders the columns.
|
|
if !strings.HasPrefix(out, "<pre>") || !strings.HasSuffix(out, "</pre>") {
|
|
t.Fatalf("expected <pre>…</pre>, got %q", out)
|
|
}
|
|
|
|
// Longest label is "Release year" (12 chars). All inner rows must pad
|
|
// their label to that width so the value column starts at the same
|
|
// offset on every line.
|
|
body := strings.TrimSuffix(strings.TrimPrefix(out, "<pre>"), "</pre>")
|
|
for _, line := range strings.Split(body, "\n") {
|
|
if line == "" {
|
|
continue
|
|
}
|
|
// Format: "<emoji> <label-padded-to-width> <value...>"
|
|
// We assert the label is followed by whitespace (or a space-only run
|
|
// totalling label width) before the value. Easiest check: the value
|
|
// column always starts after the same number of bytes from the
|
|
// start-of-line.
|
|
if !strings.Contains(line, "Release year") && !strings.Contains(line, "Champion ") && !strings.Contains(line, "Gender ") {
|
|
t.Errorf("row not padded to longest-label width: %q", line)
|
|
}
|
|
}
|
|
|
|
// Year direction arrow appears for wrong rows.
|
|
if !strings.Contains(out, "⬆️") {
|
|
t.Errorf("expected up-arrow for wrong year row; got %q", out)
|
|
}
|
|
}
|
|
|
|
func TestRenderGuess_EscapesHTMLInValues(t *testing.T) {
|
|
rows := []AttributeRow{
|
|
{Key: "gender", Label: "Gender", Type: attrExact, GuessValue: "Tom & <Jerry>", Result: ResultWrong},
|
|
}
|
|
out := renderGuess("Aatrox", rows)
|
|
if !strings.Contains(out, "Tom & <Jerry>") {
|
|
t.Errorf("html metachars not escaped: %s", out)
|
|
}
|
|
}
|
|
|
|
func TestRenderBoard_EmptyShowsHint(t *testing.T) {
|
|
if got := renderBoard(nil); !strings.Contains(got, "No guesses yet") {
|
|
t.Errorf("empty board placeholder missing: %q", got)
|
|
}
|
|
}
|
|
|
|
func TestRenderBoard_StackedGuessesUseUnifiedWidth(t *testing.T) {
|
|
// First guess has the longest label "Release year"; second guess uses
|
|
// the same set so unified width should still be 12. Both blocks must
|
|
// align — verify by checking that a 'Gender' row in the second block
|
|
// has the same padding as in the first.
|
|
rowsA := []AttributeRow{
|
|
{Key: "gender", Label: "Gender", Type: attrExact, GuessValue: "Male", Result: ResultCorrect},
|
|
{Key: "release_date", Label: "Release year", Type: attrYear, GuessValue: "2013", Result: ResultCorrect},
|
|
}
|
|
rowsB := []AttributeRow{
|
|
{Key: "gender", Label: "Gender", Type: attrExact, GuessValue: "Female", Result: ResultWrong},
|
|
{Key: "release_date", Label: "Release year", Type: attrYear, GuessValue: "2011", Result: ResultWrong, Direction: "up"},
|
|
}
|
|
board := renderBoard([]boardEntry{
|
|
{Champion: "Aatrox", Results: rowsA},
|
|
{Champion: "Ahri", Results: rowsB},
|
|
})
|
|
// Two row-groups, blank-line separated, share a single <pre> envelope.
|
|
if strings.Count(board, "<pre>") != 1 || strings.Count(board, "</pre>") != 1 {
|
|
t.Errorf("expected single <pre>…</pre> envelope wrapping both groups; got %q", board)
|
|
}
|
|
if !strings.Contains(board, "\n\n") {
|
|
t.Errorf("expected blank-line separator between groups; got %q", board)
|
|
}
|
|
}
|