@@ -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