From deab7a9aa2b0bc2956a5e98634a6fcdf108ab7ed Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Sat, 16 May 2026 10:37:29 +0200 Subject: [PATCH] test(phase-12): add discussion schema validation --- .../internal/web/handlers_discussion_test.go | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/backend/internal/web/handlers_discussion_test.go b/backend/internal/web/handlers_discussion_test.go index d264142..304b20e 100644 --- a/backend/internal/web/handlers_discussion_test.go +++ b/backend/internal/web/handlers_discussion_test.go @@ -65,6 +65,51 @@ func insertDiscussionTestMessage(t *testing.T, ctx context.Context, pool *pgxpoo return msg } +func TestDiscussionSchemaIncludesLifecycleMetadataAndBodyConstraints(t *testing.T) { + pool, cleanup := setupTestDB(t) + defer cleanup() + + ctx := context.Background() + q := sqlc.New(pool) + user := preInsertUser(t, ctx, q, "discussion-schema@example.com", "correct-horse-12") + tablo := insertDiscussionTestTablo(t, ctx, q, user, "Discussion Schema Tablo") + + rows, err := pool.Query(ctx, ` + SELECT column_name + FROM information_schema.columns + WHERE table_schema = current_schema() + AND table_name = 'discussion_messages' + `) + if err != nil { + t.Fatalf("query discussion_messages columns: %v", err) + } + defer rows.Close() + + columns := make(map[string]bool) + for rows.Next() { + var name string + if err := rows.Scan(&name); err != nil { + t.Fatalf("scan discussion_messages column: %v", err) + } + columns[name] = true + } + if err := rows.Err(); err != nil { + t.Fatalf("iterate discussion_messages columns: %v", err) + } + for _, want := range []string{"edited_at", "edited_by_user_id", "deleted_at", "deleted_by_user_id"} { + if !columns[want] { + t.Fatalf("discussion_messages missing lifecycle metadata column %q", want) + } + } + + if _, err := pool.Exec(ctx, `INSERT INTO discussion_messages (tablo_id, author_user_id, body) VALUES ($1, $2, $3)`, tablo.ID, user.ID, " "); err == nil { + t.Fatal("blank discussion message body inserted; want check constraint rejection") + } + if _, err := pool.Exec(ctx, `INSERT INTO discussion_messages (tablo_id, author_user_id, body) VALUES ($1, $2, $3)`, tablo.ID, user.ID, strings.Repeat("x", 10001)); err == nil { + t.Fatal("too-long discussion message body inserted; want check constraint rejection") + } +} + func TestDiscussionTabRendersHistoryAndComposer(t *testing.T) { pool, cleanup := setupTestDB(t) defer cleanup()