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,6 +5,7 @@ import com.xly.erp.module.mod.dto.CreateModuleDTO; | ||
| 5 | import com.xly.erp.module.mod.dto.UpdateModuleDTO; | 5 | import com.xly.erp.module.mod.dto.UpdateModuleDTO; |
| 6 | import com.xly.erp.module.mod.service.ModuleService; | 6 | import com.xly.erp.module.mod.service.ModuleService; |
| 7 | import jakarta.validation.Valid; | 7 | import jakarta.validation.Valid; |
| 8 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 8 | import org.springframework.web.bind.annotation.PathVariable; | 9 | import org.springframework.web.bind.annotation.PathVariable; |
| 9 | import org.springframework.web.bind.annotation.PostMapping; | 10 | import org.springframework.web.bind.annotation.PostMapping; |
| 10 | import org.springframework.web.bind.annotation.PutMapping; | 11 | import org.springframework.web.bind.annotation.PutMapping; |
| @@ -36,4 +37,10 @@ public class ModuleController { | @@ -36,4 +37,10 @@ public class ModuleController { | ||
| 36 | Integer updated = moduleService.update(id, dto); | 37 | Integer updated = moduleService.update(id, dto); |
| 37 | return Result.ok(Map.of("iIncrement", updated)); | 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,6 +287,107 @@ class ModuleControllerIT { | ||
| 287 | assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(20001); | 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 | private Integer insertOriginal(String procedureName, String nameZh, String createdBy) { | 391 | private Integer insertOriginal(String procedureName, String nameZh, String createdBy) { |
| 291 | jdbcTemplate.update( | 392 | jdbcTemplate.update( |
| 292 | "INSERT INTO tModule (sBrandsId, sSubsidiaryId, tCreateDate, sDisplayType, sProcedureName, " | 393 | "INSERT INTO tModule (sBrandsId, sSubsidiaryId, tCreateDate, sDisplayType, sProcedureName, " |