|
|
@@ -14,7 +14,6 @@ import org.mockito.junit.jupiter.MockitoSettings;
|
|
|
import org.mockito.quality.Strictness;
|
|
|
import org.springframework.jdbc.core.JdbcTemplate;
|
|
|
|
|
|
-import java.util.ArrayList;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
@@ -42,38 +41,73 @@ class WorkspaceServiceTest {
|
|
|
lenient().when(periodMapper.selectById(1L)).thenReturn(period);
|
|
|
lenient().when(periodMapper.selectList(any()))
|
|
|
.thenReturn(List.of(period));
|
|
|
+ // Prevent NPE from buildTodos / buildTeamSummary queryForObject calls
|
|
|
+ lenient().when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class), any(), any()))
|
|
|
+ .thenReturn(0);
|
|
|
+ lenient().when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class), any()))
|
|
|
+ .thenReturn(0);
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- void buildRisksFiltersByUserId() {
|
|
|
- // One blocked KR for the user's team
|
|
|
- Map<String, Object> blockedKr = new HashMap<>();
|
|
|
- blockedKr.put("title", "Blocked KR");
|
|
|
- blockedKr.put("real_name", "Subordinate A");
|
|
|
- List<Map<String, Object>> blockedList = new ArrayList<>();
|
|
|
- blockedList.add(blockedKr);
|
|
|
-
|
|
|
- // Mock: blocked KRs returned for the query parameters
|
|
|
- lenient().when(jdbcTemplate.queryForList(
|
|
|
- contains("SELECT k.title, u.real_name FROM kr_key_result"),
|
|
|
- eq(1L), eq(2L), eq(2L)))
|
|
|
- .thenReturn((List) blockedList);
|
|
|
- // Default: empty for other queries
|
|
|
- lenient().when(jdbcTemplate.queryForList(anyString(), any(), any(), any()))
|
|
|
+ void buildRisksIsolatesAcrossManagers() {
|
|
|
+ // ---- Data setup: two managers, each with one blocked KR on their team ----
|
|
|
+ Map<String, Object> krA = new HashMap<>();
|
|
|
+ krA.put("title", "子系统A交付受阻");
|
|
|
+ krA.put("real_name", "员工A");
|
|
|
+
|
|
|
+ Map<String, Object> krB = new HashMap<>();
|
|
|
+ krB.put("title", "子系统B接口延迟");
|
|
|
+ krB.put("real_name", "员工B");
|
|
|
+
|
|
|
+ // Default: blocked-KR query returns empty for any unmatched userId
|
|
|
+ lenient().when(jdbcTemplate.queryForList(contains("SELECT k.title"), any(), any(), any()))
|
|
|
.thenReturn((List) List.of());
|
|
|
- lenient().when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class), any()))
|
|
|
- .thenReturn(0);
|
|
|
|
|
|
- WorkspaceOverviewDto dto = workspaceService.getOverview(2L, 1L);
|
|
|
- assertNotNull(dto.getRisks());
|
|
|
+ // Manager A (userId=2) query returns krA
|
|
|
+ lenient().when(jdbcTemplate.queryForList(
|
|
|
+ contains("SELECT k.title"), eq(1L), eq(2L), eq(2L)))
|
|
|
+ .thenReturn((List) List.of(krA));
|
|
|
+
|
|
|
+ // Manager B (userId=3) query returns krB
|
|
|
+ lenient().when(jdbcTemplate.queryForList(
|
|
|
+ contains("SELECT k.title"), eq(1L), eq(3L), eq(3L)))
|
|
|
+ .thenReturn((List) List.of(krB));
|
|
|
+
|
|
|
+ // ---- Act: each manager fetches overview ----
|
|
|
+ WorkspaceOverviewDto dtoA = workspaceService.getOverview(2L, 1L);
|
|
|
+ WorkspaceOverviewDto dtoB = workspaceService.getOverview(3L, 1L);
|
|
|
+
|
|
|
+ // ---- Assert: Manager A sees only A's risk ----
|
|
|
+ List<WorkspaceOverviewDto.RiskItem> risksA = dtoA.getRisks();
|
|
|
+ assertEquals(1, risksA.size(), "Manager A should see exactly 1 blocked KR");
|
|
|
+ assertEquals("BLOCKED_KR", risksA.get(0).getType());
|
|
|
+ assertEquals("子系统A交付受阻", risksA.get(0).getLabel());
|
|
|
+ assertEquals("员工A", risksA.get(0).getUserName());
|
|
|
+
|
|
|
+ // ---- Assert: Manager B sees only B's risk ----
|
|
|
+ List<WorkspaceOverviewDto.RiskItem> risksB = dtoB.getRisks();
|
|
|
+ assertEquals(1, risksB.size(), "Manager B should see exactly 1 blocked KR");
|
|
|
+ assertEquals("BLOCKED_KR", risksB.get(0).getType());
|
|
|
+ assertEquals("子系统B接口延迟", risksB.get(0).getLabel());
|
|
|
+ assertEquals("员工B", risksB.get(0).getUserName());
|
|
|
+
|
|
|
+ // ---- Assert: Cross-isolation — A's data differs from B's ----
|
|
|
+ assertNotEquals(risksA.get(0).getLabel(), risksB.get(0).getLabel(),
|
|
|
+ "Manager A must not see Manager B's blocked KR title");
|
|
|
+ assertNotEquals(risksA.get(0).getUserName(), risksB.get(0).getUserName(),
|
|
|
+ "Manager A must not see Manager B's subordinate name");
|
|
|
+
|
|
|
+ // ---- Verify: queryForList called with correct per-user parameters ----
|
|
|
+ verify(jdbcTemplate, atLeastOnce()).queryForList(
|
|
|
+ contains("SELECT k.title"), eq(1L), eq(2L), eq(2L));
|
|
|
+ verify(jdbcTemplate, atLeastOnce()).queryForList(
|
|
|
+ contains("SELECT k.title"), eq(1L), eq(3L), eq(3L));
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
void getOverviewReturnsActions() {
|
|
|
- lenient().when(jdbcTemplate.queryForList(anyString(), any(), any(), any()))
|
|
|
+ lenient().when(jdbcTemplate.queryForList(contains("SELECT k.title"), any(), any(), any()))
|
|
|
.thenReturn((List) List.of());
|
|
|
- lenient().when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class), any()))
|
|
|
- .thenReturn(0);
|
|
|
|
|
|
WorkspaceOverviewDto dto = workspaceService.getOverview(2L, 1L);
|
|
|
assertNotNull(dto.getAllowedActions());
|