From 7436a37b9981f0b7755c31301cc0d87aed488ab3 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Tue, 21 Apr 2026 21:15:16 +0200 Subject: [PATCH] fix(test): align AgentRegistrationControllerIT with current spec Four drifts against the current server contract, all now corrected: - Registration body missing required environmentId (spec: 400 if absent). - Agent list moved to env-scoped /api/v1/environments/{envSlug}/agents; flat /api/v1/agents no longer exists. - heartbeatUnknownAgent now auto-heals via JWT env claim (fb54f9cb); the 404 branch is only reachable without a JWT, which the security filter rejects before the controller sees the request. - sseEndpoint is an absolute URL (ServletUriComponentsBuilder.fromCurrentContextPath), so assert endsWith the path rather than equals-to-relative. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../AgentRegistrationControllerIT.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/cameleer-server-app/src/test/java/com/cameleer/server/app/controller/AgentRegistrationControllerIT.java b/cameleer-server-app/src/test/java/com/cameleer/server/app/controller/AgentRegistrationControllerIT.java index 7a117c61..fdd904d3 100644 --- a/cameleer-server-app/src/test/java/com/cameleer/server/app/controller/AgentRegistrationControllerIT.java +++ b/cameleer-server-app/src/test/java/com/cameleer/server/app/controller/AgentRegistrationControllerIT.java @@ -40,6 +40,7 @@ class AgentRegistrationControllerIT extends AbstractPostgresIT { { "instanceId": "%s", "applicationId": "test-group", + "environmentId": "default", "version": "1.0.0", "routeIds": ["route-1", "route-2"], "capabilities": {"tracing": true} @@ -60,7 +61,9 @@ class AgentRegistrationControllerIT extends AbstractPostgresIT { JsonNode body = objectMapper.readTree(response.getBody()); assertThat(body.get("instanceId").asText()).isEqualTo("agent-it-1"); - assertThat(body.get("sseEndpoint").asText()).isEqualTo("/api/v1/agents/agent-it-1/events"); + // Controller returns an absolute URL via ServletUriComponentsBuilder.fromCurrentContextPath(), + // so only assert the path suffix — the host:port varies per RANDOM_PORT test run. + assertThat(body.get("sseEndpoint").asText()).endsWith("/api/v1/agents/agent-it-1/events"); assertThat(body.get("heartbeatIntervalMs").asLong()).isGreaterThan(0); assertThat(body.has("serverPublicKey")).isTrue(); assertThat(body.get("serverPublicKey").asText()).isNotEmpty(); @@ -96,14 +99,20 @@ class AgentRegistrationControllerIT extends AbstractPostgresIT { } @Test - void heartbeatUnknownAgent_returns404() { + void heartbeatUnknownAgent_autoHealsFromJwtEnv_returns200() { + // Post-fb54f9cb: heartbeat for an agent not in the registry auto-heals + // from the JWT env claim + heartbeat body (covers agent-side survival of + // server restarts). The no-registry 404 branch is only reachable without + // a JWT, which Spring Security rejects at the filter chain before the + // controller sees the request. See CLAUDE.md "Auto-heals from JWT env + // claim + heartbeat body on heartbeat/SSE after server restart". ResponseEntity response = restTemplate.exchange( "/api/v1/agents/unknown-agent-xyz/heartbeat", HttpMethod.POST, new HttpEntity<>(securityHelper.authHeadersNoBody(jwt)), Void.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); } @Test @@ -112,7 +121,7 @@ class AgentRegistrationControllerIT extends AbstractPostgresIT { registerAgent("agent-it-list-2", "List Agent 2"); ResponseEntity response = restTemplate.exchange( - "/api/v1/agents", + "/api/v1/environments/default/agents", HttpMethod.GET, new HttpEntity<>(securityHelper.authHeadersNoBody(viewerJwt)), String.class); @@ -129,7 +138,7 @@ class AgentRegistrationControllerIT extends AbstractPostgresIT { registerAgent("agent-it-filter", "Filter Agent"); ResponseEntity response = restTemplate.exchange( - "/api/v1/agents?status=LIVE", + "/api/v1/environments/default/agents?status=LIVE", HttpMethod.GET, new HttpEntity<>(securityHelper.authHeadersNoBody(viewerJwt)), String.class); @@ -146,7 +155,7 @@ class AgentRegistrationControllerIT extends AbstractPostgresIT { @Test void listAgentsWithInvalidStatus_returns400() { ResponseEntity response = restTemplate.exchange( - "/api/v1/agents?status=INVALID", + "/api/v1/environments/default/agents?status=INVALID", HttpMethod.GET, new HttpEntity<>(securityHelper.authHeadersNoBody(viewerJwt)), String.class);