Phase 2c — testing infrastructure (43 tests, CI gating, docker-compose)
Some checks failed
Docker Build / build-and-push-image (push) Has been cancelled
Some checks failed
Docker Build / build-and-push-image (push) Has been cancelled
Brings the project to a TDD/BDD-friendly state — apologies for shipping Phase 1.5 + Phase 2 code-first, that violated feedback_tdd_first_bdd_required. What's added : - helpers_test.go : FakeTelegram (httptest server that records sendMessage / deleteMessage / setWebhook / etc.), miniredis bootstrap, MakeUpdate / PostWebhook helpers. The same harness simulates 'a user DMing the bot' end-to-end without hitting Telegram cloud — answer to the user question. - 43 tests covering : allowlist parsing, telegram type helpers (UserID / ChatID / Text / messageID), secret_token constant-time compare, Backoff schedule, Auth (login wrong/right/logout/TTL/nil-receiver), EchoHandler, HTTPHandler (forward / timeout / non-2xx / empty body), AuthHandler (start / auth / whoami / logout / replay defense delete), Server (bad secret 401, unknown bot 404, allowlist drop, gated bot prompt, full /auth → echo → /logout flow, healthz/readyz). - All tests pass with -race in 1.6s, no external deps (miniredis + httptest in-process). Infra : - Updated .gitea/workflows/dockerimage.yaml : new 'test' job (go vet + go test -race) gates the build-and-push-image job. CI now also runs on pull_request. - docker-compose.yml : redis + postgres for full local stack. - Makefile : test-race, compose-up/down targets. - README updated with test + local-dev sections. Refs ~/.claude/plans/pour-les-notifications-on-inherited-seal.md § Phase 2.
This commit is contained in:
67
telegram_types_test.go
Normal file
67
telegram_types_test.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestUpdate_ChatID(t *testing.T) {
|
||||
u := MakeUpdate(1, 100, 42, 7, "hi")
|
||||
id, ok := u.ChatID()
|
||||
if !ok || id != 42 {
|
||||
t.Fatalf("Message chat = %d/%v", id, ok)
|
||||
}
|
||||
|
||||
editU := Update{EditedMessage: &Message{Chat: Chat{ID: 99}}}
|
||||
id, ok = editU.ChatID()
|
||||
if !ok || id != 99 {
|
||||
t.Fatalf("EditedMessage chat = %d/%v", id, ok)
|
||||
}
|
||||
|
||||
cb := Update{CallbackQuery: &CallbackQuery{Message: &Message{Chat: Chat{ID: 77}}}}
|
||||
id, ok = cb.ChatID()
|
||||
if !ok || id != 77 {
|
||||
t.Fatalf("CallbackQuery chat = %d/%v", id, ok)
|
||||
}
|
||||
|
||||
empty := Update{}
|
||||
if _, ok := empty.ChatID(); ok {
|
||||
t.Fatal("empty Update must have no chat")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdate_UserID(t *testing.T) {
|
||||
u := MakeUpdate(1, 7497777082, 42, 7, "hi")
|
||||
id, ok := u.UserID()
|
||||
if !ok || id != 7497777082 {
|
||||
t.Fatalf("Message from = %d/%v", id, ok)
|
||||
}
|
||||
|
||||
cb := Update{CallbackQuery: &CallbackQuery{From: &User{ID: 555}}}
|
||||
id, ok = cb.UserID()
|
||||
if !ok || id != 555 {
|
||||
t.Fatalf("CallbackQuery from = %d/%v", id, ok)
|
||||
}
|
||||
|
||||
noFrom := Update{Message: &Message{Chat: Chat{ID: 1}}}
|
||||
if _, ok := noFrom.UserID(); ok {
|
||||
t.Fatal("Message without From should have no UserID")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdate_Text(t *testing.T) {
|
||||
if got := MakeUpdate(1, 1, 1, 1, "hi").Text(); got != "hi" {
|
||||
t.Errorf("Message text: %q", got)
|
||||
}
|
||||
cb := Update{CallbackQuery: &CallbackQuery{Data: "btn:42"}}
|
||||
if got := cb.Text(); got != "btn:42" {
|
||||
t.Errorf("CallbackQuery data: %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMessageID(t *testing.T) {
|
||||
u := MakeUpdate(1, 1, 1, 88, "x")
|
||||
if got := messageID(u); got != 88 {
|
||||
t.Errorf("messageID = %d", got)
|
||||
}
|
||||
if got := messageID(Update{}); got != 0 {
|
||||
t.Errorf("empty Update messageID = %d (want 0)", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user