Testing

irgo provides testing utilities to help you test your handlers and templates.

Test Client

The testing package provides an HTTP client for testing handlers:

import (    "testing"    irgotest "github.com/stukennedy/irgo/pkg/testing")func TestListTodos(t *testing.T) {    r := app.NewRouter()    client := irgotest.NewClient(r.Handler())    resp := client.Get("/todos")    resp.AssertOK(t)    resp.AssertContains(t, "My Todos")}

HTTP Methods

client := irgotest.NewClient(handler)// GET requestresp := client.Get("/users")// GET with query parametersresp := client.Get("/search?q=hello")// POST with form dataresp := client.PostForm("/users", map[string]string{    "name":  "John",    "email": "john@example.com",})// POST with JSONresp := client.PostJSON("/api/users", map[string]any{    "name":  "John",    "email": "john@example.com",})// PUT requestresp := client.Put("/users/123", map[string]string{    "name": "Jane",})// PATCH requestresp := client.Patch("/users/123", map[string]string{    "name": "Jane",})// DELETE requestresp := client.Delete("/users/123")

Assertions

resp := client.Get("/users")// Status assertionsresp.AssertOK(t)                    // 200resp.AssertStatus(t, 201)           // Specific statusresp.AssertRedirect(t, "/login")    // 3xx redirect// Content assertionsresp.AssertContains(t, "Welcome")resp.AssertNotContains(t, "Error")// Header assertionsresp.AssertHeader(t, "Content-Type", "text/html")// Get response databody := resp.Body()           // stringstatus := resp.StatusCode     // int

Testing HTMX Requests

func TestHTMXRequest(t *testing.T) {    client := irgotest.NewClient(handler)    // Simulate HTMX request    resp := client.GetWithHeaders("/users", map[string]string{        "HX-Request": "true",        "HX-Target":  "#user-list",    })    resp.AssertOK(t)    // Should return fragment, not full page    resp.AssertNotContains(t, "<!DOCTYPE html>")    resp.AssertContains(t, "<div class="user-card">")}

Testing Handlers Directly

func TestCreateUser(t *testing.T) {    // Create mock context    ctx := irgotest.NewContext()    ctx.SetFormValue("name", "John")    ctx.SetFormValue("email", "john@example.com")    // Call handler    html, err := handlers.CreateUser(ctx)    if err != nil {        t.Fatalf("unexpected error: %v", err)    }    if !strings.Contains(html, "John") {        t.Error("expected response to contain user name")    }}

Testing Templates

func TestUserCard(t *testing.T) {    user := User{        ID:    "123",        Name:  "John",        Email: "john@example.com",    }    renderer := render.NewTemplRenderer()    html, err := renderer.Render(templates.UserCard(user))    if err != nil {        t.Fatalf("render error: %v", err)    }    if !strings.Contains(html, "John") {        t.Error("expected card to contain user name")    }    if !strings.Contains(html, "john@example.com") {        t.Error("expected card to contain email")    }}

Running Tests

# Run all testsgo test ./...# Run with verbose outputgo test -v ./...# Run specific packagego test ./handlers/...# Run with coveragego test -cover ./...

Example Test File

handlers/todos_test.go
package handlersimport (    "testing"    "myapp/app"    irgotest "github.com/stukennedy/irgo/pkg/testing")func TestTodoWorkflow(t *testing.T) {    r := app.NewRouter()    client := irgotest.NewClient(r.Handler())    // List todos (empty)    resp := client.Get("/todos")    resp.AssertOK(t)    resp.AssertContains(t, "No todos yet")    // Create todo    resp = client.PostForm("/todos", map[string]string{        "title": "Buy groceries",    })    resp.AssertOK(t)    resp.AssertContains(t, "Buy groceries")    // Toggle todo    resp = client.PostForm("/todos/1/toggle", nil)    resp.AssertOK(t)    resp.AssertContains(t, "completed")    // Delete todo    resp = client.Delete("/todos/1")    resp.AssertOK(t)}

Next Steps