diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-02-03 15:15:07 -1000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-02-03 15:15:07 -1000 |
| commit | 9f35f7149d8fb790bbe8e4f0ee74f895aea1fc58 (patch) | |
| tree | 5faa41878609a5c9c332b794a85300090d65bec5 /internal/handlers/renderer.go | |
| parent | f10044eac1997537bcdf7699f5b4284aac16f8e2 (diff) | |
Refactor template rendering with Renderer interface for testability
Introduce a Renderer interface to abstract template rendering, enabling
tests to use MockRenderer instead of requiring real template files.
Changes:
- Add renderer.go with Renderer interface, TemplateRenderer, and MockRenderer
- Update Handler struct to use Renderer instead of *template.Template
- Update HTMLResponse() to accept Renderer interface
- Replace all h.templates.ExecuteTemplate() calls with h.renderer.Render()
- Update all tests to use MockRenderer, removing template file dependencies
This eliminates 15+ tests that previously skipped with "Templates not
available" and improves test isolation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal/handlers/renderer.go')
| -rw-r--r-- | internal/handlers/renderer.go | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/internal/handlers/renderer.go b/internal/handlers/renderer.go new file mode 100644 index 0000000..246a82a --- /dev/null +++ b/internal/handlers/renderer.go @@ -0,0 +1,63 @@ +package handlers + +import ( + "fmt" + "html/template" + "io" +) + +// Renderer abstracts template rendering for testability. +type Renderer interface { + Render(w io.Writer, name string, data interface{}) error +} + +// TemplateRenderer wraps *template.Template to implement Renderer. +type TemplateRenderer struct { + templates *template.Template +} + +// NewTemplateRenderer creates a new TemplateRenderer. +func NewTemplateRenderer(tmpl *template.Template) *TemplateRenderer { + return &TemplateRenderer{templates: tmpl} +} + +// Render executes the named template with the given data. +func (r *TemplateRenderer) Render(w io.Writer, name string, data interface{}) error { + if r.templates == nil { + return fmt.Errorf("templates not loaded") + } + return r.templates.ExecuteTemplate(w, name, data) +} + +// Compile-time interface check +var _ Renderer = (*TemplateRenderer)(nil) + +// MockRenderer is a test double for Renderer. +type MockRenderer struct { + RenderFunc func(w io.Writer, name string, data interface{}) error + Calls []RenderCall +} + +// RenderCall records a call to Render. +type RenderCall struct { + Name string + Data interface{} +} + +// Render implements Renderer for testing. +func (m *MockRenderer) Render(w io.Writer, name string, data interface{}) error { + m.Calls = append(m.Calls, RenderCall{Name: name, Data: data}) + if m.RenderFunc != nil { + return m.RenderFunc(w, name, data) + } + fmt.Fprintf(w, "rendered:%s", name) + return nil +} + +// NewMockRenderer creates a new MockRenderer. +func NewMockRenderer() *MockRenderer { + return &MockRenderer{} +} + +// Compile-time interface check +var _ Renderer = (*MockRenderer)(nil) |
