diff --git a/play-admin/src/test/java/com/starry/admin/api/PlayClerkUserInfoApiTest.java b/play-admin/src/test/java/com/starry/admin/api/PlayClerkUserInfoApiTest.java index d9e17d6..2672c59 100644 --- a/play-admin/src/test/java/com/starry/admin/api/PlayClerkUserInfoApiTest.java +++ b/play-admin/src/test/java/com/starry/admin/api/PlayClerkUserInfoApiTest.java @@ -17,8 +17,10 @@ import com.starry.admin.utils.SecurityUtils; import com.starry.common.utils.IdUtils; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -37,6 +39,7 @@ class PlayClerkUserInfoApiTest extends AbstractApiTest { private final List levelIdsToCleanup = new ArrayList<>(); private final List clerkIdsToCleanup = new ArrayList<>(); + private int scenarioSequence = 0; @AfterEach void tearDown() { @@ -362,6 +365,69 @@ class PlayClerkUserInfoApiTest extends AbstractApiTest { .isLessThan(orderedIds.indexOf(offline)); } + @Test + void listOrderingHandlesBulkDataset() throws Exception { + ensureTenantContext(); + String token = "bulk-" + IdUtils.getUuid().substring(0, 6); + PlayClerkLevelInfoEntity platinum = createClerkLevel(token + "-plat", 1L, 90); + PlayClerkLevelInfoEntity gold = createClerkLevel(token + "-gold", 2L, 80); + PlayClerkLevelInfoEntity silver = createClerkLevel(token + "-silver", 3L, 70); + PlayClerkLevelInfoEntity bronze = createClerkLevel(token + "-bronze", 4L, 60); + + List scenarios = new ArrayList<>(); + PlayClerkLevelInfoEntity[] levels = {platinum, gold, silver, bronze}; + String[] levelKeys = {"plat", "gold", "silver", "bronze"}; + for (int i = 0; i < levels.length; i++) { + PlayClerkLevelInfoEntity level = levels[i]; + String key = levelKeys[i]; + scenarios.add(buildScenario(token, key + "-on-pin", level, true, true)); + scenarios.add(buildScenario(token, key + "-on", level, true, false)); + scenarios.add(buildScenario(token, key + "-on-two", level, true, false)); + scenarios.add(buildScenario(token, key + "-off-pin", level, false, true)); + scenarios.add(buildScenario(token, key + "-off", level, false, false)); + } + // push total above 20 entries with a few extras + scenarios.add(buildScenario(token, "extra-on-pin", platinum, true, true)); + scenarios.add(buildScenario(token, "extra-off", bronze, false, false)); + + MvcResult result = mockMvc.perform(get("/clerk/user/list") + .param("pageNum", "1") + .param("pageSize", "80") + .param("nickname", token) + .header(TENANT_HEADER, DEFAULT_TENANT) + .header(USER_HEADER, DEFAULT_USER)) + .andExpect(status().isOk()) + .andReturn(); + + JsonNode root = objectMapper.readTree(result.getResponse().getContentAsString()); + JsonNode records = root.path("data"); + List orderedIds = new ArrayList<>(); + for (JsonNode record : records) { + orderedIds.add(record.path("id").asText()); + } + + List expectedOrder = scenarios.stream() + .sorted(Comparator.comparing(ClerkScenario::isOnline).reversed() + .thenComparing(ClerkScenario::isPinned).reversed() + .thenComparingLong(ClerkScenario::getLevelOrder) + .thenComparingInt(ClerkScenario::getSequence)) + .map(ClerkScenario::getId) + .collect(Collectors.toList()); + + assertThat(orderedIds).containsExactlyElementsOf(expectedOrder); + } + + + private ClerkScenario buildScenario(String token, String suffix, PlayClerkLevelInfoEntity level, boolean online, boolean pinned) { + String id = createClerk(token + "-" + suffix, level.getId(), online ? "1" : "0"); + if (pinned) { + togglePin(id, "1"); + } + long levelOrder = level.getOrderNumber() == null ? Long.MAX_VALUE : level.getOrderNumber(); + ClerkScenario scenario = new ClerkScenario(id, levelOrder, online, pinned, scenarioSequence++); + pause(15); + return scenario; + } private void togglePin(String clerkId, String pinState) { ensureTenantContext(); @@ -378,4 +444,40 @@ class PlayClerkUserInfoApiTest extends AbstractApiTest { Thread.currentThread().interrupt(); } } + + private static class ClerkScenario { + private final String id; + private final long levelOrder; + private final boolean online; + private final boolean pinned; + private final int sequence; + + ClerkScenario(String id, long levelOrder, boolean online, boolean pinned, int sequence) { + this.id = id; + this.levelOrder = levelOrder; + this.online = online; + this.pinned = pinned; + this.sequence = sequence; + } + + String getId() { + return id; + } + + long getLevelOrder() { + return levelOrder; + } + + boolean isOnline() { + return online; + } + + boolean isPinned() { + return pinned; + } + + int getSequence() { + return sequence; + } + } }