test: add M1 broadcast acceptance reproducers
This commit is contained in:
+161
@@ -0,0 +1,161 @@
|
||||
package org.dromara.aihr.broadcast;
|
||||
|
||||
import org.dromara.aihr.broadcast.AihrBroadcastDto.BroadcastListResponse;
|
||||
import org.dromara.aihr.broadcast.AihrBroadcastDto.BroadcastTargetRequest;
|
||||
import org.dromara.aihr.broadcast.AihrBroadcastDto.PublishRequest;
|
||||
import org.dromara.aihr.broadcast.AihrBroadcastDto.PublishResponse;
|
||||
import org.dromara.aihr.knowledge.domain.AihrKnowledgePrincipal;
|
||||
import org.dromara.aihr.knowledge.service.AihrKnowledgePrincipalResolver;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.PreparedStatementCreator;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.KeyHolder;
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@Tag("dev")
|
||||
class AihrBroadcastM1ServiceTest {
|
||||
|
||||
@Test
|
||||
void targetedPublicationFreezesActiveOrganizationRecipientsAndKeepsUnmatchedSubjectsAuditable() {
|
||||
TargetingJdbcTemplate jdbcTemplate = new TargetingJdbcTemplate();
|
||||
jdbcTemplate.targetCandidates = List.of(
|
||||
Map.of("subject_ref", "EMP-1003", "user_id", 31L),
|
||||
Map.of("subject_ref", "EMP-1004")
|
||||
);
|
||||
AihrBroadcastService service = new AihrBroadcastService(jdbcTemplate, RESOLVER);
|
||||
|
||||
PublishResponse response = service.publish(new PublishRequest(
|
||||
"m1-targeted-1", "夏季服务标准", "请项目客服人员在今日完成学习。", "tenant-a", true,
|
||||
new BroadcastTargetRequest(List.of("PRJ-FCW"), List.of("物业管家"), List.of())
|
||||
));
|
||||
|
||||
assertEquals(42L, response.id());
|
||||
assertEquals(1L, response.matchedRecipientCount());
|
||||
assertEquals(1L, response.unmatchedTargetCount());
|
||||
assertTrue(jdbcTemplate.targetCandidateSql.contains("from aihr_org_snapshot o"));
|
||||
assertTrue(jdbcTemplate.targetCandidateSql.contains("binary o.tenant_id = binary u.tenant_id"));
|
||||
assertTrue(jdbcTemplate.targetCandidateSql.contains("o.employment_status = 'active'"));
|
||||
assertTrue(jdbcTemplate.targetCandidateSql.contains("o.project_code in (?)"));
|
||||
assertTrue(jdbcTemplate.targetCandidateSql.contains("o.position_name in (?)"));
|
||||
assertArrayEquals(new Object[]{"tenant-a", "PRJ-FCW", "物业管家"}, jdbcTemplate.targetCandidateArgs);
|
||||
assertTrue(jdbcTemplate.updateSqls.stream().anyMatch(sql -> sql.contains("aihr_broadcast_target_rule")));
|
||||
assertTrue(jdbcTemplate.updateSqls.stream().anyMatch(sql -> sql.contains("aihr_broadcast_target_recipient")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void requiredUnreadScopeUsesRecipientSnapshotsWhileAllScopeKeepsPublicMessagesVisible() {
|
||||
TargetingJdbcTemplate jdbcTemplate = new TargetingJdbcTemplate();
|
||||
AihrBroadcastService service = new AihrBroadcastService(jdbcTemplate, RESOLVER);
|
||||
|
||||
BroadcastListResponse requiredUnread = service.messages(1, 20, "REQUIRED_UNREAD");
|
||||
|
||||
assertEquals(1, requiredUnread.rows().size());
|
||||
assertTrue(requiredUnread.rows().get(0).requiredRead());
|
||||
assertTrue(requiredUnread.rows().get(0).targeted());
|
||||
assertFalse(requiredUnread.rows().get(0).read());
|
||||
assertTrue(jdbcTemplate.messageListSql.contains("m.required_read = 1"));
|
||||
assertTrue(jdbcTemplate.messageListSql.contains("aihr_broadcast_target_recipient"));
|
||||
assertTrue(jdbcTemplate.messageListSql.contains("tr.user_id is not null"));
|
||||
|
||||
service.messages(1, 20, "ALL");
|
||||
|
||||
assertFalse(jdbcTemplate.messageListSql.contains("tr.user_id is not null"));
|
||||
assertTrue(jdbcTemplate.messageListSql.contains("m.status = 'PUBLISHED'"));
|
||||
}
|
||||
|
||||
private static final AihrKnowledgePrincipalResolver RESOLVER = new AihrKnowledgePrincipalResolver(null) {
|
||||
@Override
|
||||
public AihrKnowledgePrincipal current() {
|
||||
return new AihrKnowledgePrincipal(
|
||||
"tenant-a", 7L, "app_user", "staff-7", Set.of("employee"), Set.of(), "mobile");
|
||||
}
|
||||
};
|
||||
|
||||
private static final class TargetingJdbcTemplate extends JdbcTemplate {
|
||||
private List<Map<String, Object>> targetCandidates = List.of();
|
||||
private String targetCandidateSql;
|
||||
private Object[] targetCandidateArgs;
|
||||
private String messageListSql;
|
||||
private final List<String> updateSqls = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public <T> T queryForObject(String sql, Class<T> requiredType, Object... args) {
|
||||
if (sql.contains("from sys_user u")) return requiredType.cast(1L);
|
||||
return requiredType.cast(1L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args) {
|
||||
if (sql.contains("publish_request_key")) return List.of();
|
||||
if (sql.contains("from aihr_org_snapshot o")) {
|
||||
targetCandidateSql = sql;
|
||||
targetCandidateArgs = args;
|
||||
return targetCandidates.stream().map(values -> map(rowMapper, values)).toList();
|
||||
}
|
||||
if (sql.contains("from aihr_broadcast_message m")) {
|
||||
messageListSql = sql;
|
||||
return List.of(map(rowMapper, Map.of(
|
||||
"id", 42L,
|
||||
"title", "夏季服务标准",
|
||||
"published_time", Timestamp.valueOf("2026-07-23 09:00:00"),
|
||||
"read_flag", false,
|
||||
"required_read", true,
|
||||
"targeted_flag", true,
|
||||
"target_reason", "项目、岗位"
|
||||
)));
|
||||
}
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(String sql, Object... args) {
|
||||
updateSqls.add(sql);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder) {
|
||||
generatedKeyHolder.getKeyList().add(Map.of("id", 42L));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static <T> T map(RowMapper<T> rowMapper, Map<String, Object> values) {
|
||||
try {
|
||||
return rowMapper.mapRow(resultSet(values), 0);
|
||||
} catch (SQLException ex) {
|
||||
throw new AssertionError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static ResultSet resultSet(Map<String, Object> values) {
|
||||
return (ResultSet) Proxy.newProxyInstance(
|
||||
TargetingJdbcTemplate.class.getClassLoader(), new Class<?>[]{ResultSet.class}, (proxy, method, args) -> {
|
||||
String name = method.getName();
|
||||
Object value = args == null || args.length == 0 ? null : values.get(args[0]);
|
||||
if ("getString".equals(name)) return value == null ? null : value.toString();
|
||||
if ("getLong".equals(name)) return value == null ? 0L : ((Number) value).longValue();
|
||||
if ("getBoolean".equals(name)) return value instanceof Boolean bool && bool;
|
||||
if ("getTimestamp".equals(name)) return value;
|
||||
if ("getObject".equals(name)) return value;
|
||||
if ("wasNull".equals(name)) return value == null;
|
||||
if ("toString".equals(name)) return values.toString();
|
||||
throw new UnsupportedOperationException(name);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user