Skip to content

Commit b26b963

Browse files
aksOpsPaperclip-Paperclipclaude
committed
test: add validation and boundary tests for GraphController coverage
Cover the new input validation (invalid NodeKind → 400), negative offset clamping, and limit capping on /kinds, /nodes, and /edges endpoints to satisfy SonarCloud 80% new code coverage gate. Co-Authored-By: Paperclip <noreply@paperclip.ing> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3333498 commit b26b963

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

src/test/java/io/github/randomcodespace/iq/api/GraphControllerTest.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,34 @@ void nodesByKindShouldAcceptPaginationParams() throws Exception {
114114
.andExpect(jsonPath("$.limit").value(25));
115115
}
116116

117+
@Test
118+
void nodesByKindShouldReturn400ForInvalidKind() throws Exception {
119+
mockMvc.perform(get("/api/kinds/not_a_real_kind"))
120+
.andExpect(status().isBadRequest());
121+
}
122+
123+
@Test
124+
void nodesByKindShouldClampNegativeOffset() throws Exception {
125+
Map<String, Object> result = new LinkedHashMap<>();
126+
result.put("kind", "endpoint");
127+
result.put("nodes", List.of());
128+
when(queryService.nodesByKind("endpoint", 50, 0)).thenReturn(result);
129+
130+
mockMvc.perform(get("/api/kinds/endpoint?offset=-5"))
131+
.andExpect(status().isOk());
132+
}
133+
134+
@Test
135+
void nodesByKindShouldCapLimitTo1000() throws Exception {
136+
Map<String, Object> result = new LinkedHashMap<>();
137+
result.put("kind", "endpoint");
138+
result.put("nodes", List.of());
139+
when(queryService.nodesByKind("endpoint", 1000, 0)).thenReturn(result);
140+
141+
mockMvc.perform(get("/api/kinds/endpoint?limit=5000"))
142+
.andExpect(status().isOk());
143+
}
144+
117145
// --- /api/nodes ---
118146

119147
@Test
@@ -140,6 +168,34 @@ void listNodesShouldFilterByKind() throws Exception {
140168
.andExpect(jsonPath("$.count").value(0));
141169
}
142170

171+
@Test
172+
void listNodesShouldReturn400ForInvalidKind() throws Exception {
173+
mockMvc.perform(get("/api/nodes?kind=bogus_kind"))
174+
.andExpect(status().isBadRequest());
175+
}
176+
177+
@Test
178+
void listNodesShouldClampNegativeOffset() throws Exception {
179+
Map<String, Object> result = new LinkedHashMap<>();
180+
result.put("nodes", List.of());
181+
result.put("count", 0);
182+
when(queryService.listNodes(null, 100, 0)).thenReturn(result);
183+
184+
mockMvc.perform(get("/api/nodes?offset=-10"))
185+
.andExpect(status().isOk());
186+
}
187+
188+
@Test
189+
void listNodesShouldCapLimitTo1000() throws Exception {
190+
Map<String, Object> result = new LinkedHashMap<>();
191+
result.put("nodes", List.of());
192+
result.put("count", 0);
193+
when(queryService.listNodes(null, 1000, 0)).thenReturn(result);
194+
195+
mockMvc.perform(get("/api/nodes?limit=9999"))
196+
.andExpect(status().isOk());
197+
}
198+
143199
// --- /api/nodes/{nodeId}/detail ---
144200

145201
@Test
@@ -208,6 +264,30 @@ void listEdgesShouldReturnEdges() throws Exception {
208264
.andExpect(jsonPath("$.total").value(0));
209265
}
210266

267+
@Test
268+
void listEdgesShouldClampNegativeOffset() throws Exception {
269+
Map<String, Object> result = new LinkedHashMap<>();
270+
result.put("edges", List.of());
271+
result.put("count", 0);
272+
result.put("total", 0);
273+
when(queryService.listEdges(null, 100, 0)).thenReturn(result);
274+
275+
mockMvc.perform(get("/api/edges?offset=-3"))
276+
.andExpect(status().isOk());
277+
}
278+
279+
@Test
280+
void listEdgesShouldCapLimitTo1000() throws Exception {
281+
Map<String, Object> result = new LinkedHashMap<>();
282+
result.put("edges", List.of());
283+
result.put("count", 0);
284+
result.put("total", 0);
285+
when(queryService.listEdges(null, 1000, 0)).thenReturn(result);
286+
287+
mockMvc.perform(get("/api/edges?limit=5000"))
288+
.andExpect(status().isOk());
289+
}
290+
211291
// --- /api/ego/{center} ---
212292

213293
@Test

0 commit comments

Comments
 (0)