package handlers import ( "net/http" "net/http/httptest" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/fx" "go.uber.org/fx/fxtest" "sneak.berlin/go/webhooker/internal/config" "sneak.berlin/go/webhooker/internal/database" "sneak.berlin/go/webhooker/internal/delivery" "sneak.berlin/go/webhooker/internal/globals" "sneak.berlin/go/webhooker/internal/healthcheck" "sneak.berlin/go/webhooker/internal/logger" "sneak.berlin/go/webhooker/internal/session" ) // noopNotifier is a no-op delivery.Notifier for tests. type noopNotifier struct{} func (n *noopNotifier) Notify([]delivery.DeliveryTask) {} func TestHandleIndex(t *testing.T) { var h *Handlers app := fxtest.New( t, fx.Provide( globals.New, logger.New, func() *config.Config { return &config.Config{ DataDir: t.TempDir(), } }, database.New, database.NewWebhookDBManager, healthcheck.New, session.New, func() delivery.Notifier { return &noopNotifier{} }, New, ), fx.Populate(&h), ) app.RequireStart() defer app.RequireStop() // Since we can't test actual template rendering without templates, // let's test that the handler is created and doesn't panic handler := h.HandleIndex() assert.NotNil(t, handler) } func TestRenderTemplate(t *testing.T) { var h *Handlers app := fxtest.New( t, fx.Provide( globals.New, logger.New, func() *config.Config { return &config.Config{ DataDir: t.TempDir(), } }, database.New, database.NewWebhookDBManager, healthcheck.New, session.New, func() delivery.Notifier { return &noopNotifier{} }, New, ), fx.Populate(&h), ) app.RequireStart() defer app.RequireStop() t.Run("handles missing templates gracefully", func(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/", nil) w := httptest.NewRecorder() data := map[string]interface{}{ "Version": "1.0.0", } // When a non-existent template name is requested, renderTemplate // should return an internal server error h.renderTemplate(w, req, "nonexistent.html", data) // Should return internal server error when template is not found assert.Equal(t, http.StatusInternalServerError, w.Code) }) } func TestFormatUptime(t *testing.T) { tests := []struct { name string duration string expected string }{ { name: "minutes only", duration: "45m", expected: "45m", }, { name: "hours and minutes", duration: "2h30m", expected: "2h 30m", }, { name: "days, hours and minutes", duration: "25h45m", expected: "1d 1h 45m", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { d, err := time.ParseDuration(tt.duration) require.NoError(t, err) result := formatUptime(d) assert.Equal(t, tt.expected, result) }) } }