Add new endpoint that returns server start time and uptime duration in seconds.
The endpoint follows the same pattern as handleHealth and handleInfo handlers,
using the existing startedAt field from the Server struct.
Response format:
{
"start_time": "2026-05-05T19:30:00Z",
"uptime_seconds": 1234
}
Includes unit tests with httptest.NewRecorder() to verify JSON response
structure and content type headers.
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
82 lines
2.3 KiB
Go
82 lines
2.3 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"dance-lessons-coach/pkg/config"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestHandleUptime(t *testing.T) {
|
|
// Setup with a known start time
|
|
cfg := &config.Config{}
|
|
// We need to create a server and then set its startedAt to a known time
|
|
// Since NewServer sets startedAt to time.Now(), we'll create the server
|
|
// and then use reflection or we can use NewServerWithUserRepo which also sets startedAt
|
|
s := NewServer(cfg, context.Background())
|
|
|
|
// Set a fixed start time for deterministic testing
|
|
// We can't directly set s.startedAt since it's unexported, but we can test
|
|
// that the handler uses the server's startedAt
|
|
// The test will verify the structure and that uptime_seconds is >= 0
|
|
|
|
// Create request
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/uptime", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
// Call handler
|
|
s.handleUptime(w, req)
|
|
|
|
// Check status code
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
// Check content type
|
|
assert.Equal(t, "application/json", w.Header().Get("Content-Type"))
|
|
|
|
// Decode response
|
|
var resp UptimeResponse
|
|
err := json.NewDecoder(w.Body).Decode(&resp)
|
|
assert.NoError(t, err)
|
|
|
|
// Assert fields
|
|
assert.NotEmpty(t, resp.StartTime)
|
|
// Verify start_time is in RFC3339 format
|
|
_, err = time.Parse(time.RFC3339, resp.StartTime)
|
|
assert.NoError(t, err)
|
|
assert.GreaterOrEqual(t, resp.UptimeSeconds, 0)
|
|
}
|
|
|
|
func TestHandleUptime_Deterministic(t *testing.T) {
|
|
// For a more deterministic test, we would need to be able to set startedAt
|
|
// Since startedAt is unexported, we test the behavior with a known server
|
|
// that was just created (uptime should be very small)
|
|
cfg := &config.Config{}
|
|
s := NewServer(cfg, context.Background())
|
|
|
|
// Small delay to ensure uptime is at least 0 seconds
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/uptime", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
s.handleUptime(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp UptimeResponse
|
|
err := json.NewDecoder(w.Body).Decode(&resp)
|
|
assert.NoError(t, err)
|
|
|
|
// Uptime should be at least 0 (it's int() of seconds, so minimum is 0)
|
|
assert.GreaterOrEqual(t, resp.UptimeSeconds, 0)
|
|
// Start time should be parseable
|
|
_, err = time.Parse(time.RFC3339, resp.StartTime)
|
|
assert.NoError(t, err)
|
|
}
|