Commit 087eb8f5feea91739008e6adc1cddc70bbbbee7a
1 parent
bf2370ba
test(mod): module delete integration coverage REQ-MOD-003
Showing
2 changed files
with
108 additions
and
0 deletions
backend/src/main/java/com/xly/erp/module/mod/controller/ModuleController.java
| ... | ... | @@ -5,6 +5,7 @@ import com.xly.erp.module.mod.dto.CreateModuleDTO; |
| 5 | 5 | import com.xly.erp.module.mod.dto.UpdateModuleDTO; |
| 6 | 6 | import com.xly.erp.module.mod.service.ModuleService; |
| 7 | 7 | import jakarta.validation.Valid; |
| 8 | +import org.springframework.web.bind.annotation.DeleteMapping; | |
| 8 | 9 | import org.springframework.web.bind.annotation.PathVariable; |
| 9 | 10 | import org.springframework.web.bind.annotation.PostMapping; |
| 10 | 11 | import org.springframework.web.bind.annotation.PutMapping; |
| ... | ... | @@ -36,4 +37,10 @@ public class ModuleController { |
| 36 | 37 | Integer updated = moduleService.update(id, dto); |
| 37 | 38 | return Result.ok(Map.of("iIncrement", updated)); |
| 38 | 39 | } |
| 40 | + | |
| 41 | + @DeleteMapping("/modules/{id}") | |
| 42 | + public Result<Void> delete(@PathVariable Integer id) { | |
| 43 | + moduleService.delete(id); | |
| 44 | + return Result.ok(); | |
| 45 | + } | |
| 39 | 46 | } | ... | ... |
backend/src/test/java/com/xly/erp/module/mod/controller/ModuleControllerIT.java
| ... | ... | @@ -287,6 +287,107 @@ class ModuleControllerIT { |
| 287 | 287 | assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(20001); |
| 288 | 288 | } |
| 289 | 289 | |
| 290 | + @Test | |
| 291 | + void deleteValidId_with_jwt_returns200_andSoftDeletes() throws Exception { | |
| 292 | + Integer id = insertOriginal("sp_test_del_ok", "原", "ORIG_USER"); | |
| 293 | + String token = testJwtHelper.signFor("ADMIN001"); | |
| 294 | + HttpHeaders headers = jsonHeaders(); | |
| 295 | + headers.set("Authorization", "Bearer " + token); | |
| 296 | + | |
| 297 | + ResponseEntity<String> resp = rest.exchange( | |
| 298 | + idUrl(id), HttpMethod.DELETE, new HttpEntity<>(headers), String.class); | |
| 299 | + | |
| 300 | + assertThat(resp.getStatusCode().value()).isEqualTo(200); | |
| 301 | + JsonNode jb = objectMapper.readTree(resp.getBody()); | |
| 302 | + assertThat(jb.get("code").asInt()).isZero(); | |
| 303 | + assertThat(jb.get("data").isNull()).isTrue(); | |
| 304 | + | |
| 305 | + Map<String, Object> row = jdbcTemplate.queryForMap( | |
| 306 | + "SELECT bDeleted, sDeletedBy, tDeletedDate, sProcedureName, sCreatedBy FROM tModule WHERE iIncrement = ?", id); | |
| 307 | + assertThat(row.get("bDeleted")).isEqualTo(true); | |
| 308 | + assertThat(row.get("sDeletedBy")).isEqualTo("ADMIN001"); | |
| 309 | + assertThat(row.get("tDeletedDate")).isNotNull(); | |
| 310 | + assertThat(row.get("sProcedureName")).isEqualTo("sp_test_del_ok"); | |
| 311 | + assertThat(row.get("sCreatedBy")).isEqualTo("ORIG_USER"); | |
| 312 | + } | |
| 313 | + | |
| 314 | + @Test | |
| 315 | + void deleteNonExistentId_returns40400() throws Exception { | |
| 316 | + String token = testJwtHelper.signFor("ADMIN001"); | |
| 317 | + HttpHeaders headers = jsonHeaders(); | |
| 318 | + headers.set("Authorization", "Bearer " + token); | |
| 319 | + | |
| 320 | + ResponseEntity<String> resp = rest.exchange( | |
| 321 | + idUrl(99999996), HttpMethod.DELETE, new HttpEntity<>(headers), String.class); | |
| 322 | + | |
| 323 | + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(40400); | |
| 324 | + } | |
| 325 | + | |
| 326 | + @Test | |
| 327 | + void deleteAlreadyDeletedId_returns40400() throws Exception { | |
| 328 | + Integer id = insertOriginal("sp_test_del_already", "已删", "ORIG"); | |
| 329 | + jdbcTemplate.update("UPDATE tModule SET bDeleted = 1 WHERE iIncrement = ?", id); | |
| 330 | + String token = testJwtHelper.signFor("ADMIN001"); | |
| 331 | + HttpHeaders headers = jsonHeaders(); | |
| 332 | + headers.set("Authorization", "Bearer " + token); | |
| 333 | + | |
| 334 | + ResponseEntity<String> resp = rest.exchange( | |
| 335 | + idUrl(id), HttpMethod.DELETE, new HttpEntity<>(headers), String.class); | |
| 336 | + | |
| 337 | + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(40400); | |
| 338 | + } | |
| 339 | + | |
| 340 | + @Test | |
| 341 | + void deleteWithActiveChildren_returns40901() throws Exception { | |
| 342 | + Integer rootId = insertOriginal("sp_test_del_root", "根", "ORIG"); | |
| 343 | + jdbcTemplate.update( | |
| 344 | + "INSERT INTO tModule (sBrandsId, sSubsidiaryId, tCreateDate, sDisplayType, sProcedureName, " | |
| 345 | + + "sModuleType, sManageDeptEn, bShowPermission, sModuleNameZh, iParentId, iSortOrder, sCreatedBy, bDeleted) " | |
| 346 | + + "VALUES ('XLY','XLY', NOW(), '手机端', 'sp_test_del_child', '业务模块', 'IT', 0, '子', ?, 0, 'ORIG', 0)", | |
| 347 | + rootId); | |
| 348 | + String token = testJwtHelper.signFor("ADMIN001"); | |
| 349 | + HttpHeaders headers = jsonHeaders(); | |
| 350 | + headers.set("Authorization", "Bearer " + token); | |
| 351 | + | |
| 352 | + ResponseEntity<String> resp = rest.exchange( | |
| 353 | + idUrl(rootId), HttpMethod.DELETE, new HttpEntity<>(headers), String.class); | |
| 354 | + | |
| 355 | + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(40901); | |
| 356 | + Boolean stillAlive = jdbcTemplate.queryForObject( | |
| 357 | + "SELECT bDeleted FROM tModule WHERE iIncrement = ?", Boolean.class, rootId); | |
| 358 | + assertThat(stillAlive).isFalse(); | |
| 359 | + } | |
| 360 | + | |
| 361 | + @Test | |
| 362 | + void deleteWithoutJwt_permitAllStub_returns200_andDeletedByIsSTUB() throws Exception { | |
| 363 | + Integer id = insertOriginal("sp_test_del_nojwt", "原", "ORIG"); | |
| 364 | + HttpHeaders headers = jsonHeaders(); | |
| 365 | + | |
| 366 | + ResponseEntity<String> resp = rest.exchange( | |
| 367 | + idUrl(id), HttpMethod.DELETE, new HttpEntity<>(headers), String.class); | |
| 368 | + | |
| 369 | + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isZero(); | |
| 370 | + Map<String, Object> row = jdbcTemplate.queryForMap( | |
| 371 | + "SELECT bDeleted, sDeletedBy FROM tModule WHERE iIncrement = ?", id); | |
| 372 | + assertThat(row.get("bDeleted")).isEqualTo(true); | |
| 373 | + assertThat(row.get("sDeletedBy")).isEqualTo("STUB_ADMIN"); | |
| 374 | + } | |
| 375 | + | |
| 376 | + @Test | |
| 377 | + void deleteTamperedJwt_returns20001() throws Exception { | |
| 378 | + Integer id = insertOriginal("sp_test_del_tamper", "原", "ORIG"); | |
| 379 | + HttpHeaders headers = jsonHeaders(); | |
| 380 | + headers.set("Authorization", "Bearer not.a.real.jwt"); | |
| 381 | + | |
| 382 | + ResponseEntity<String> resp = rest.exchange( | |
| 383 | + idUrl(id), HttpMethod.DELETE, new HttpEntity<>(headers), String.class); | |
| 384 | + | |
| 385 | + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(20001); | |
| 386 | + Boolean stillAlive = jdbcTemplate.queryForObject( | |
| 387 | + "SELECT bDeleted FROM tModule WHERE iIncrement = ?", Boolean.class, id); | |
| 388 | + assertThat(stillAlive).isFalse(); | |
| 389 | + } | |
| 390 | + | |
| 290 | 391 | private Integer insertOriginal(String procedureName, String nameZh, String createdBy) { |
| 291 | 392 | jdbcTemplate.update( |
| 292 | 393 | "INSERT INTO tModule (sBrandsId, sSubsidiaryId, tCreateDate, sDisplayType, sProcedureName, " | ... | ... |