Commit 38574bc49e8165b73af012d58fbe81b7f7fab02b

Authored by zichun
1 parent bbceb21d

test(mod): module list integration coverage REQ-MOD-004

backend/src/main/java/com/xly/erp/module/mod/controller/ModuleController.java
... ... @@ -4,15 +4,19 @@ import com.xly.erp.common.response.Result;
4 4 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 +import com.xly.erp.module.mod.vo.ModuleTreeVO;
7 8 import jakarta.validation.Valid;
8 9 import org.springframework.web.bind.annotation.DeleteMapping;
  10 +import org.springframework.web.bind.annotation.GetMapping;
9 11 import org.springframework.web.bind.annotation.PathVariable;
10 12 import org.springframework.web.bind.annotation.PostMapping;
11 13 import org.springframework.web.bind.annotation.PutMapping;
12 14 import org.springframework.web.bind.annotation.RequestBody;
13 15 import org.springframework.web.bind.annotation.RequestMapping;
  16 +import org.springframework.web.bind.annotation.RequestParam;
14 17 import org.springframework.web.bind.annotation.RestController;
15 18  
  19 +import java.util.List;
16 20 import java.util.Map;
17 21  
18 22 @RestController
... ... @@ -43,4 +47,9 @@ public class ModuleController {
43 47 moduleService.delete(id);
44 48 return Result.ok();
45 49 }
  50 +
  51 + @GetMapping("/modules")
  52 + public Result<List<ModuleTreeVO>> list(@RequestParam(required = false) String keyword) {
  53 + return Result.ok(moduleService.listTree(keyword));
  54 + }
46 55 }
... ...
backend/src/test/java/com/xly/erp/module/mod/controller/ModuleControllerIT.java
... ... @@ -388,6 +388,110 @@ class ModuleControllerIT {
388 388 assertThat(stillAlive).isFalse();
389 389 }
390 390  
  391 + @Test
  392 + void getEmptyKeyword_returnsCompleteTreeAsForest() throws Exception {
  393 + Integer rootId = insertOriginal("sp_test_get_root", "查询用根", "ORIG");
  394 + jdbcTemplate.update(
  395 + "INSERT INTO tModule (sBrandsId, sSubsidiaryId, tCreateDate, sDisplayType, sProcedureName, "
  396 + + "sModuleType, sManageDeptEn, bShowPermission, sModuleNameZh, iParentId, iSortOrder, sCreatedBy, bDeleted) "
  397 + + "VALUES ('XLY','XLY', NOW(), '手机端', 'sp_test_get_child', '业务模块', 'IT', 0, '查询用子', ?, 0, 'ORIG', 0)",
  398 + rootId);
  399 + Integer childId = jdbcTemplate.queryForObject(
  400 + "SELECT iIncrement FROM tModule WHERE sProcedureName = 'sp_test_get_child'", Integer.class);
  401 +
  402 + String token = testJwtHelper.signFor("ADMIN001");
  403 + HttpHeaders headers = jsonHeaders();
  404 + headers.set("Authorization", "Bearer " + token);
  405 + ResponseEntity<String> resp = rest.exchange(
  406 + listUrl(null), HttpMethod.GET, new HttpEntity<>(headers), String.class);
  407 +
  408 + JsonNode jb = objectMapper.readTree(resp.getBody());
  409 + assertThat(jb.get("code").asInt()).isZero();
  410 + JsonNode data = jb.get("data");
  411 + assertThat(data.isArray()).isTrue();
  412 + JsonNode rootNode = findById(data, rootId);
  413 + assertThat(rootNode).isNotNull();
  414 + JsonNode childNode = findById(rootNode.get("children"), childId);
  415 + assertThat(childNode).isNotNull();
  416 + assertThat(childNode.get("sModuleNameZh").asText()).isEqualTo("查询用子");
  417 + }
  418 +
  419 + @Test
  420 + void getKeywordMatch_returnsForest() throws Exception {
  421 + insertOriginal("sp_test_get_kw_a", "系统模块A", "ORIG");
  422 + insertOriginal("sp_test_get_kw_b", "用户模块B", "ORIG");
  423 + String token = testJwtHelper.signFor("ADMIN001");
  424 + HttpHeaders headers = jsonHeaders();
  425 + headers.set("Authorization", "Bearer " + token);
  426 +
  427 + ResponseEntity<String> resp = rest.exchange(
  428 + listUrl("系统"), HttpMethod.GET, new HttpEntity<>(headers), String.class);
  429 +
  430 + JsonNode jb = objectMapper.readTree(resp.getBody());
  431 + assertThat(jb.get("code").asInt()).isZero();
  432 + JsonNode data = jb.get("data");
  433 + assertThat(data.isArray()).isTrue();
  434 + for (JsonNode node : data) {
  435 + assertThat(node.get("sModuleNameZh").asText()).contains("系统");
  436 + }
  437 + }
  438 +
  439 + @Test
  440 + void getKeywordTooLong_returns40001() throws Exception {
  441 + String token = testJwtHelper.signFor("ADMIN001");
  442 + HttpHeaders headers = jsonHeaders();
  443 + headers.set("Authorization", "Bearer " + token);
  444 +
  445 + ResponseEntity<String> resp = rest.exchange(
  446 + listUrl("x".repeat(101)), HttpMethod.GET, new HttpEntity<>(headers), String.class);
  447 +
  448 + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(40001);
  449 + }
  450 +
  451 + @Test
  452 + void getNoMatch_returnsEmptyArray() throws Exception {
  453 + String token = testJwtHelper.signFor("ADMIN001");
  454 + HttpHeaders headers = jsonHeaders();
  455 + headers.set("Authorization", "Bearer " + token);
  456 +
  457 + ResponseEntity<String> resp = rest.exchange(
  458 + listUrl("不存在的关键字XYZ-zzz"), HttpMethod.GET, new HttpEntity<>(headers), String.class);
  459 +
  460 + JsonNode data = objectMapper.readTree(resp.getBody()).get("data");
  461 + assertThat(data.isArray()).isTrue();
  462 + assertThat(data.size()).isZero();
  463 + }
  464 +
  465 + @Test
  466 + void getWithoutJwt_permitAllStub_returns200() throws Exception {
  467 + HttpHeaders headers = jsonHeaders();
  468 + ResponseEntity<String> resp = rest.exchange(
  469 + listUrl(null), HttpMethod.GET, new HttpEntity<>(headers), String.class);
  470 + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isZero();
  471 + }
  472 +
  473 + @Test
  474 + void getTamperedJwt_returns20001() throws Exception {
  475 + HttpHeaders headers = jsonHeaders();
  476 + headers.set("Authorization", "Bearer not.a.real.jwt");
  477 + ResponseEntity<String> resp = rest.exchange(
  478 + listUrl(null), HttpMethod.GET, new HttpEntity<>(headers), String.class);
  479 + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(20001);
  480 + }
  481 +
  482 + private String listUrl(String keyword) {
  483 + String base = "http://localhost:" + port + "/api/mod/modules";
  484 + return keyword == null ? base : base + "?keyword=" + java.net.URLEncoder.encode(keyword, java.nio.charset.StandardCharsets.UTF_8);
  485 + }
  486 +
  487 + private static JsonNode findById(JsonNode array, Integer id) {
  488 + if (array == null || !array.isArray()) return null;
  489 + for (JsonNode n : array) {
  490 + if (n.get("iIncrement").asInt() == id) return n;
  491 + }
  492 + return null;
  493 + }
  494 +
391 495 private Integer insertOriginal(String procedureName, String nameZh, String createdBy) {
392 496 jdbcTemplate.update(
393 497 "INSERT INTO tModule (sBrandsId, sSubsidiaryId, tCreateDate, sDisplayType, sProcedureName, "
... ...