✨ feat(server): add /api/healthz endpoint with rich health info (#20)
Adds Kubernetes-style /api/healthz endpoint with status/version/uptime_seconds/timestamp. Non-breaking — /api/health preserved. Includes unit test (passes locally) and BDD scenario (validated by CI). Généré ~95% en autonomie par Mistral Vibe via workspace ICM ~/Work/Vibe/workspaces/healthz-feature/. Co-authored-by: Gabriel Radureau <arcodange@gmail.com> Co-committed-by: Gabriel Radureau <arcodange@gmail.com>
This commit was merged in pull request #20.
This commit is contained in:
@@ -63,3 +63,39 @@ func (s *CommonSteps) theStatusCodeShouldBe(expectedStatus int) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// JSON field validation
|
||||
func (s *CommonSteps) theResponseShouldBeJSONWithFields(fields string) error {
|
||||
// Parse the fields comma-separated list
|
||||
fieldList := strings.Split(fields, ", ")
|
||||
for _, field := range fieldList {
|
||||
field = strings.TrimSpace(field)
|
||||
if !s.responseContainsJSONField(field) {
|
||||
return fmt.Errorf("response does not contain field %q", field)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *CommonSteps) responseContainsJSONField(field string) bool {
|
||||
body := string(s.client.GetLastBody())
|
||||
// Simple check - look for "field":" in the JSON
|
||||
// This works for simple fields, may need enhancement for nested objects
|
||||
searchString := `"` + field + `":`
|
||||
return strings.Contains(body, searchString)
|
||||
}
|
||||
|
||||
func (s *CommonSteps) theFieldShouldEqual(field, expectedValue string) error {
|
||||
body := string(s.client.GetLastBody())
|
||||
// Look for the field and extract its value
|
||||
// Simple implementation: look for "field":"value" pattern
|
||||
searchPattern := `"` + field + `":"` + expectedValue + `"`
|
||||
if !strings.Contains(body, searchPattern) {
|
||||
// Also try without quotes (for numbers)
|
||||
searchPatternNum := `"` + field + `":` + expectedValue
|
||||
if !strings.Contains(body, searchPatternNum) {
|
||||
return fmt.Errorf("field %q does not equal %q in response: %s", field, expectedValue, body)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@ func (s *HealthSteps) iRequestTheHealthEndpoint() error {
|
||||
return s.client.Request("GET", "/api/health", nil)
|
||||
}
|
||||
|
||||
func (s *HealthSteps) iRequestTheHealthzEndpoint() error {
|
||||
return s.client.Request("GET", "/api/healthz", nil)
|
||||
}
|
||||
|
||||
func (s *HealthSteps) theServerIsRunning() error {
|
||||
// Actually verify the server is running by checking the readiness endpoint
|
||||
return s.client.Request("GET", "/api/ready", nil)
|
||||
|
||||
@@ -83,6 +83,7 @@ func InitializeAllSteps(ctx *godog.ScenarioContext, client *testserver.Client, s
|
||||
|
||||
// Health steps
|
||||
ctx.Step(`^I request the health endpoint$`, sc.healthSteps.iRequestTheHealthEndpoint)
|
||||
ctx.Step(`^I request the healthz endpoint$`, sc.healthSteps.iRequestTheHealthzEndpoint)
|
||||
ctx.Step(`^the server is running$`, sc.healthSteps.theServerIsRunning)
|
||||
|
||||
// Auth steps
|
||||
@@ -297,4 +298,6 @@ func InitializeAllSteps(ctx *godog.ScenarioContext, client *testserver.Client, s
|
||||
ctx.Step(`^the response should be "{\\"([^"]*)":\\"([^"]*)"}"$`, sc.commonSteps.theResponseShouldBe)
|
||||
ctx.Step(`^the response should contain error "([^"]*)"$`, sc.commonSteps.theResponseShouldContainError)
|
||||
ctx.Step(`^the status code should be (\d+)$`, sc.commonSteps.theStatusCodeShouldBe)
|
||||
ctx.Step(`^the response should be JSON with fields "([^"]*)"$`, sc.commonSteps.theResponseShouldBeJSONWithFields)
|
||||
ctx.Step(`^the "([^"]*)" field should equal "([^"]*)"$`, sc.commonSteps.theFieldShouldEqual)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user