package notification import ( "path/filepath" "testing" "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" ) var expectedNotificationRuntimeDocumentationSnippets = []string{ "`GET /healthz` returns `{\"status\":\"ok\"}`", "`GET /readyz` returns `{\"status\":\"ready\"}`", "`readyz` is process-local after successful startup and does not perform a live Redis ping per request", "there is no `/metrics` route", "`NOTIFICATION_INTERNAL_HTTP_ADDR` with default `:8092`", "`NOTIFICATION_INTERNAL_HTTP_READ_HEADER_TIMEOUT` with default `2s`", "`NOTIFICATION_INTERNAL_HTTP_READ_TIMEOUT` with default `10s`", "`NOTIFICATION_INTERNAL_HTTP_IDLE_TIMEOUT` with default `1m`", "`NOTIFICATION_USER_SERVICE_TIMEOUT` with default `1s`", } func TestNotificationRuntimeDocsStayInSync(t *testing.T) { t.Parallel() readme := loadTextFile(t, "README.md") runtimeDoc := loadTextFile(t, filepath.Join("docs", "runtime.md")) docsIndex := loadTextFile(t, filepath.Join("docs", "README.md")) architecture := loadTextFile(t, filepath.Join("..", "ARCHITECTURE.md")) testingDoc := loadTextFile(t, filepath.Join("..", "TESTING.md")) normalizedReadme := normalizeWhitespace(readme) normalizedRuntimeDoc := normalizeWhitespace(runtimeDoc) require.Contains(t, docsIndex, "- [Runtime and components](runtime.md)") require.Contains(t, architecture, "private probe HTTP listener with") require.Contains(t, testingDoc, "* Runtime-skeleton tests:") require.Contains(t, testingDoc, "* `GET /healthz`") require.Contains(t, testingDoc, "* `GET /readyz`") require.Contains(t, testingDoc, "* no `/metrics`") require.Contains(t, runtimeDoc, "Redis client with startup connectivity check") require.Contains(t, runtimeDoc, "OpenTelemetry traces and metrics exporters") for _, snippet := range expectedNotificationRuntimeDocumentationSnippets { normalizedSnippet := normalizeWhitespace(snippet) require.Contains(t, normalizedReadme, normalizedSnippet) require.Contains(t, normalizedRuntimeDoc, normalizedSnippet) } } func TestNotificationProbeOpenAPIContractDocumentsImplementedSurface(t *testing.T) { t.Parallel() specText := loadTextFile(t, "openapi.yaml") var spec map[string]any err := yaml.Unmarshal([]byte(specText), &spec) require.NoError(t, err) require.Equal(t, "3.1.0", getStringValue(t, spec, "openapi")) require.Equal(t, "Notification Service Probe API", getStringValue(t, getMapValue(t, spec, "info"), "title")) paths := getMapValue(t, spec, "paths") require.ElementsMatch(t, []string{"/healthz", "/readyz"}, mapKeys(paths)) require.NotContains(t, paths, "/metrics") healthz := getMapValue(t, paths, "/healthz") readyz := getMapValue(t, paths, "/readyz") for _, path := range []map[string]any{healthz, readyz} { require.Contains(t, path, "get") require.NotContains(t, path, "post") responses := getMapValue(t, getMapValue(t, path, "get"), "responses") require.Contains(t, responses, "200") require.Equal(t, "#/components/responses/MethodNotAllowed", getStringValue(t, getMapValue(t, responses, "405"), "$ref")) } components := getMapValue(t, spec, "components") responses := getMapValue(t, components, "responses") require.Contains(t, responses, "NotFound") require.Contains(t, responses, "MethodNotAllowed") }