4.6 KB
app_test.go
package application
import (
"net/http"
"net/http/httptest"
"testing"
)
func TestAppServeCreatesView(t *testing.T) {
app := &App{
funcs: make(map[string]any),
viewsFS: testViews,
controllers: make(map[string]Controller),
}
app.base = app.parseBaseTemplates(testViews)
view := app.Serve("pages/home.html", nil)
if view == nil {
t.Fatal("expected view to be created")
}
if view.App != app {
t.Error("expected view to reference app")
}
if view.template != "pages/home.html" {
t.Errorf("expected template 'pages/home.html', got %q", view.template)
}
}
func TestAppMethod(t *testing.T) {
app := &App{}
ctrl := &methodTestController{}
handler := app.Method(ctrl, "DoSomething", nil)
req := httptest.NewRequest(http.MethodPost, "/", nil)
rec := httptest.NewRecorder()
handler.ServeHTTP(rec, req)
if !ctrl.called {
t.Error("expected method to be called")
}
if rec.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", rec.Code)
}
}
func TestAppMethodWithBouncer(t *testing.T) {
app := &App{}
ctrl := &methodTestController{}
bouncer := func(app *App, w http.ResponseWriter, r *http.Request) bool {
http.Error(w, "Forbidden", http.StatusForbidden)
return false
}
handler := app.Method(ctrl, "DoSomething", bouncer)
req := httptest.NewRequest(http.MethodPost, "/", nil)
rec := httptest.NewRecorder()
handler.ServeHTTP(rec, req)
if ctrl.called {
t.Error("expected method NOT to be called when bouncer blocks")
}
if rec.Code != http.StatusForbidden {
t.Errorf("expected status 403, got %d", rec.Code)
}
}
func TestAppMethodNotFound(t *testing.T) {
app := &App{}
ctrl := &methodTestController{}
handler := app.Method(ctrl, "NonexistentMethod", nil)
req := httptest.NewRequest(http.MethodPost, "/", nil)
rec := httptest.NewRecorder()
handler.ServeHTTP(rec, req)
if rec.Code != http.StatusInternalServerError {
t.Errorf("expected status 500, got %d", rec.Code)
}
}
// TestBuildTemplateData removed - controllers are now injected as template functions
func TestTemplateFuncs(t *testing.T) {
app := &App{
funcs: map[string]any{
"custom": func() string { return "custom" },
},
}
funcs := app.templateFuncs()
// Should have built-in dict function
if _, ok := funcs["dict"]; !ok {
t.Error("expected 'dict' function")
}
// Should have custom function
if _, ok := funcs["custom"]; !ok {
t.Error("expected 'custom' function")
}
}
func TestTemplateFuncsDict(t *testing.T) {
app := &App{funcs: make(map[string]any)}
funcs := app.templateFuncs()
dictFn := funcs["dict"].(func(...any) map[string]any)
// Valid dict
result := dictFn("a", 1, "b", 2)
if result["a"] != 1 || result["b"] != 2 {
t.Errorf("expected dict with a=1, b=2, got %v", result)
}
// Odd number of args returns nil
result = dictFn("a", 1, "b")
if result != nil {
t.Error("expected nil for odd number of args")
}
// Non-string key is skipped
result = dictFn(123, "value", "valid", "ok")
if _, ok := result[""]; ok {
t.Error("expected non-string key to be skipped")
}
if result["valid"] != "ok" {
t.Error("expected valid key to work")
}
}
// Test helpers
type methodTestController struct {
called bool
}
func (c *methodTestController) DoSomething(w http.ResponseWriter, r *http.Request) {
c.called = true
w.WriteHeader(http.StatusOK)
}
type templateDataTestController struct {
BaseController
name string
}
func (c *templateDataTestController) Handle(r *http.Request) Controller {
return c
}
// Emailer tests
type testEmailer struct {
lastTo string
lastSubject string
lastTemplate string
lastData map[string]any
}
func (e *testEmailer) Send(to, subject, templateName string, data map[string]any) error {
e.lastTo = to
e.lastSubject = subject
e.lastTemplate = templateName
e.lastData = data
return nil
}
func TestEmailerInterface(t *testing.T) {
emailer := &testEmailer{}
err := emailer.Send("user@example.com", "Hello", "welcome.html", map[string]any{"name": "Alice"})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if emailer.lastTo != "user@example.com" {
t.Errorf("expected to 'user@example.com', got %q", emailer.lastTo)
}
if emailer.lastSubject != "Hello" {
t.Errorf("expected subject 'Hello', got %q", emailer.lastSubject)
}
if emailer.lastTemplate != "welcome.html" {
t.Errorf("expected template 'welcome.html', got %q", emailer.lastTemplate)
}
if emailer.lastData["name"] != "Alice" {
t.Errorf("expected data name 'Alice', got %v", emailer.lastData["name"])
}
}
func TestAppWithEmailer(t *testing.T) {
emailer := &testEmailer{}
app := &App{}
opt := WithEmailer(emailer)
opt(app)
if app.Emailer != emailer {
t.Error("expected emailer to be set on app")
}
}