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) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-21 21:15:16 +02:00
parent 9046070529
commit 7436a37b99

View File

@@ -40,6 +40,7 @@ class AgentRegistrationControllerIT extends AbstractPostgresIT {
{ {
"instanceId": "%s", "instanceId": "%s",
"applicationId": "test-group", "applicationId": "test-group",
"environmentId": "default",
"version": "1.0.0", "version": "1.0.0",
"routeIds": ["route-1", "route-2"], "routeIds": ["route-1", "route-2"],
"capabilities": {"tracing": true} "capabilities": {"tracing": true}
@@ -60,7 +61,9 @@ class AgentRegistrationControllerIT extends AbstractPostgresIT {
JsonNode body = objectMapper.readTree(response.getBody()); JsonNode body = objectMapper.readTree(response.getBody());
assertThat(body.get("instanceId").asText()).isEqualTo("agent-it-1"); 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.get("heartbeatIntervalMs").asLong()).isGreaterThan(0);
assertThat(body.has("serverPublicKey")).isTrue(); assertThat(body.has("serverPublicKey")).isTrue();
assertThat(body.get("serverPublicKey").asText()).isNotEmpty(); assertThat(body.get("serverPublicKey").asText()).isNotEmpty();
@@ -96,14 +99,20 @@ class AgentRegistrationControllerIT extends AbstractPostgresIT {
} }
@Test @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<Void> response = restTemplate.exchange( ResponseEntity<Void> response = restTemplate.exchange(
"/api/v1/agents/unknown-agent-xyz/heartbeat", "/api/v1/agents/unknown-agent-xyz/heartbeat",
HttpMethod.POST, HttpMethod.POST,
new HttpEntity<>(securityHelper.authHeadersNoBody(jwt)), new HttpEntity<>(securityHelper.authHeadersNoBody(jwt)),
Void.class); Void.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
} }
@Test @Test
@@ -112,7 +121,7 @@ class AgentRegistrationControllerIT extends AbstractPostgresIT {
registerAgent("agent-it-list-2", "List Agent 2"); registerAgent("agent-it-list-2", "List Agent 2");
ResponseEntity<String> response = restTemplate.exchange( ResponseEntity<String> response = restTemplate.exchange(
"/api/v1/agents", "/api/v1/environments/default/agents",
HttpMethod.GET, HttpMethod.GET,
new HttpEntity<>(securityHelper.authHeadersNoBody(viewerJwt)), new HttpEntity<>(securityHelper.authHeadersNoBody(viewerJwt)),
String.class); String.class);
@@ -129,7 +138,7 @@ class AgentRegistrationControllerIT extends AbstractPostgresIT {
registerAgent("agent-it-filter", "Filter Agent"); registerAgent("agent-it-filter", "Filter Agent");
ResponseEntity<String> response = restTemplate.exchange( ResponseEntity<String> response = restTemplate.exchange(
"/api/v1/agents?status=LIVE", "/api/v1/environments/default/agents?status=LIVE",
HttpMethod.GET, HttpMethod.GET,
new HttpEntity<>(securityHelper.authHeadersNoBody(viewerJwt)), new HttpEntity<>(securityHelper.authHeadersNoBody(viewerJwt)),
String.class); String.class);
@@ -146,7 +155,7 @@ class AgentRegistrationControllerIT extends AbstractPostgresIT {
@Test @Test
void listAgentsWithInvalidStatus_returns400() { void listAgentsWithInvalidStatus_returns400() {
ResponseEntity<String> response = restTemplate.exchange( ResponseEntity<String> response = restTemplate.exchange(
"/api/v1/agents?status=INVALID", "/api/v1/environments/default/agents?status=INVALID",
HttpMethod.GET, HttpMethod.GET,
new HttpEntity<>(securityHelper.authHeadersNoBody(viewerJwt)), new HttpEntity<>(securityHelper.authHeadersNoBody(viewerJwt)),
String.class); String.class);