Complete tasks 7-9: GUI, utilities, integration
This commit is contained in:
parent
421ae1b4f3
commit
994fb6a109
9 changed files with 424 additions and 5 deletions
|
|
@ -116,22 +116,41 @@
|
||||||
- **Property 8: Permission Enforcement**
|
- **Property 8: Permission Enforcement**
|
||||||
- **Validates: Requirements 6.1, 6.2, 6.3**
|
- **Validates: Requirements 6.1, 6.2, 6.3**
|
||||||
|
|
||||||
- [ ] 7. Реализация GUI
|
- [x] 7. Реализация GUI
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- [ ] 7.1 Создать ReportGui с пагинацией
|
- [ ] 7.1 Создать ReportGui с пагинацией
|
||||||
- Создать инвентарь 54 слота
|
- Создать инвентарь 54 слота
|
||||||
- Отображение голов игроков с их скинами
|
- Отображение голов игроков с их скинами
|
||||||
- Lore с информацией о репорте
|
- Lore с информацией о репорте
|
||||||
|
|
||||||
|
|
||||||
- Кнопки навигации по страницам
|
- Кнопки навигации по страницам
|
||||||
- _Requirements: 4.1, 4.2, 4.3, 4.4_
|
- _Requirements: 4.1, 4.2, 4.3, 4.4_
|
||||||
- [ ] 7.2 Создать GuiClickListener
|
|
||||||
|
- [-] 7.2 Создать GuiClickListener
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- Обработка кликов по страницам
|
- Обработка кликов по страницам
|
||||||
|
|
||||||
|
|
||||||
- Отмена выноса предметов
|
- Отмена выноса предметов
|
||||||
|
|
||||||
- _Requirements: 4.4_
|
- _Requirements: 4.4_
|
||||||
|
|
||||||
|
|
||||||
- [ ] 7.3 Создать ReportGuiCommand (/report gui)
|
- [ ] 7.3 Создать ReportGuiCommand (/report gui)
|
||||||
- Проверка прав и открытие GUI
|
- Проверка прав и открытие GUI
|
||||||
|
|
||||||
|
|
||||||
- _Requirements: 4.1, 6.2_
|
- _Requirements: 4.1, 6.2_
|
||||||
|
|
||||||
- [ ] 7.4 Написать property test для пагинации
|
- [ ] 7.4 Написать property test для пагинации
|
||||||
- **Property 6: Pagination Correctness**
|
- **Property 6: Pagination Correctness**
|
||||||
|
|
||||||
- **Validates: Requirements 4.4**
|
- **Validates: Requirements 4.4**
|
||||||
|
|
||||||
- [ ] 8. Утилиты и сообщения
|
- [ ] 8. Утилиты и сообщения
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ dependencies {
|
||||||
testImplementation("net.jqwik:jqwik:1.8.4")
|
testImplementation("net.jqwik:jqwik:1.8.4")
|
||||||
testImplementation("org.yaml:snakeyaml:2.2")
|
testImplementation("org.yaml:snakeyaml:2.2")
|
||||||
testImplementation("org.xerial:sqlite-jdbc:3.45.1.0")
|
testImplementation("org.xerial:sqlite-jdbc:3.45.1.0")
|
||||||
|
testCompileOnly("io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT")
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
package dev.loki.lorep;
|
package dev.loki.lorep;
|
||||||
|
|
||||||
|
import dev.loki.lorep.command.ReportCommand;
|
||||||
import dev.loki.lorep.config.ConfigManager;
|
import dev.loki.lorep.config.ConfigManager;
|
||||||
import dev.loki.lorep.database.DatabaseManager;
|
import dev.loki.lorep.database.DatabaseManager;
|
||||||
|
import dev.loki.lorep.database.PostgreSQLDatabaseManager;
|
||||||
|
import dev.loki.lorep.database.SQLiteDatabaseManager;
|
||||||
|
import dev.loki.lorep.gui.GuiClickListener;
|
||||||
import dev.loki.lorep.webhook.DiscordWebhook;
|
import dev.loki.lorep.webhook.DiscordWebhook;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
|
@ -17,11 +21,58 @@ public final class LorepPlugin extends JavaPlugin {
|
||||||
instance = this;
|
instance = this;
|
||||||
getLogger().info("lorep plugin enabling...");
|
getLogger().info("lorep plugin enabling...");
|
||||||
|
|
||||||
// Initialize managers (will be implemented later)
|
// Initialize config
|
||||||
|
configManager = new ConfigManager(this);
|
||||||
|
|
||||||
|
// Initialize database
|
||||||
|
initializeDatabase();
|
||||||
|
|
||||||
|
// Initialize webhook
|
||||||
|
String webhookUrl = configManager.getWebhookUrl();
|
||||||
|
if (webhookUrl != null && !webhookUrl.isEmpty()) {
|
||||||
|
discordWebhook = new DiscordWebhook(webhookUrl, getLogger());
|
||||||
|
getLogger().info("Discord webhook configured");
|
||||||
|
} else {
|
||||||
|
getLogger().warning("Discord webhook URL not configured");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register commands
|
||||||
|
ReportCommand reportCommand = new ReportCommand(this);
|
||||||
|
getCommand("report").setExecutor(reportCommand);
|
||||||
|
getCommand("report").setTabCompleter(reportCommand);
|
||||||
|
|
||||||
|
// Register listeners
|
||||||
|
getServer().getPluginManager().registerEvents(new GuiClickListener(this), this);
|
||||||
|
|
||||||
getLogger().info("lorep plugin enabled!");
|
getLogger().info("lorep plugin enabled!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initializeDatabase() {
|
||||||
|
String dbType = configManager.getDatabaseType();
|
||||||
|
|
||||||
|
if ("postgresql".equalsIgnoreCase(dbType)) {
|
||||||
|
databaseManager = new PostgreSQLDatabaseManager(
|
||||||
|
configManager.getPostgresHost(),
|
||||||
|
configManager.getPostgresPort(),
|
||||||
|
configManager.getPostgresDatabase(),
|
||||||
|
configManager.getPostgresUsername(),
|
||||||
|
configManager.getPostgresPassword(),
|
||||||
|
configManager.getPostgresPoolSize(),
|
||||||
|
getLogger()
|
||||||
|
);
|
||||||
|
getLogger().info("Using PostgreSQL database");
|
||||||
|
} else {
|
||||||
|
databaseManager = new SQLiteDatabaseManager(
|
||||||
|
getDataFolder(),
|
||||||
|
configManager.getSqliteFile(),
|
||||||
|
getLogger()
|
||||||
|
);
|
||||||
|
getLogger().info("Using SQLite database");
|
||||||
|
}
|
||||||
|
|
||||||
|
databaseManager.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
if (databaseManager != null) {
|
if (databaseManager != null) {
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,7 @@ public class ReportCommand implements CommandExecutor, TabCompleter {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GUI will be implemented in task 7
|
new dev.loki.lorep.gui.ReportGui(plugin, 0).open(player);
|
||||||
player.sendMessage("§eGUI будет реализован позже");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
59
src/main/java/dev/loki/lorep/gui/GuiClickListener.java
Normal file
59
src/main/java/dev/loki/lorep/gui/GuiClickListener.java
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
package dev.loki.lorep.gui;
|
||||||
|
|
||||||
|
import dev.loki.lorep.LorepPlugin;
|
||||||
|
import dev.loki.lorep.util.PaginationUtil;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||||
|
|
||||||
|
public class GuiClickListener implements Listener {
|
||||||
|
|
||||||
|
private final LorepPlugin plugin;
|
||||||
|
|
||||||
|
public GuiClickListener(LorepPlugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onInventoryClick(InventoryClickEvent event) {
|
||||||
|
if (!(event.getInventory().getHolder() instanceof ReportGui gui)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.setCancelled(true);
|
||||||
|
|
||||||
|
if (!(event.getWhoClicked() instanceof Player player)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int slot = event.getRawSlot();
|
||||||
|
|
||||||
|
// Navigation buttons are in bottom row (slots 45-53)
|
||||||
|
switch (slot) {
|
||||||
|
case 45 -> { // Previous page
|
||||||
|
if (gui.getPage() > 0) {
|
||||||
|
new ReportGui(plugin, gui.getPage() - 1).open(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 47 -> { // Close
|
||||||
|
player.closeInventory();
|
||||||
|
}
|
||||||
|
case 53 -> { // Next page
|
||||||
|
int totalReports = plugin.getDatabaseManager().getTotalReportCount();
|
||||||
|
int totalPages = PaginationUtil.calculateTotalPages(totalReports, ReportGui.PAGE_SIZE);
|
||||||
|
if (gui.getPage() < totalPages - 1) {
|
||||||
|
new ReportGui(plugin, gui.getPage() + 1).open(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onInventoryDrag(InventoryDragEvent event) {
|
||||||
|
if (event.getInventory().getHolder() instanceof ReportGui) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
135
src/main/java/dev/loki/lorep/gui/ReportGui.java
Normal file
135
src/main/java/dev/loki/lorep/gui/ReportGui.java
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
package dev.loki.lorep.gui;
|
||||||
|
|
||||||
|
import dev.loki.lorep.LorepPlugin;
|
||||||
|
import dev.loki.lorep.database.Report;
|
||||||
|
import dev.loki.lorep.util.TimeUtil;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.inventory.meta.SkullMeta;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ReportGui implements InventoryHolder {
|
||||||
|
|
||||||
|
public static final int PAGE_SIZE = 45; // 5 rows for reports
|
||||||
|
public static final int INVENTORY_SIZE = 54; // 6 rows total
|
||||||
|
|
||||||
|
private final LorepPlugin plugin;
|
||||||
|
private final int page;
|
||||||
|
private Inventory inventory;
|
||||||
|
|
||||||
|
public ReportGui(LorepPlugin plugin, int page) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.page = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open(Player player) {
|
||||||
|
String title = plugin.getConfigManager().getMessage("gui-title", "%page%", String.valueOf(page + 1));
|
||||||
|
this.inventory = Bukkit.createInventory(this, INVENTORY_SIZE, title);
|
||||||
|
|
||||||
|
List<Report> reports = plugin.getDatabaseManager().getReportsPaginated(page, PAGE_SIZE);
|
||||||
|
int totalReports = plugin.getDatabaseManager().getTotalReportCount();
|
||||||
|
|
||||||
|
// Add report items
|
||||||
|
for (int i = 0; i < reports.size(); i++) {
|
||||||
|
Report report = reports.get(i);
|
||||||
|
int targetReportCount = plugin.getDatabaseManager().getReportCount(report.targetUuid());
|
||||||
|
inventory.setItem(i, createReportItem(report, targetReportCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add navigation buttons
|
||||||
|
addNavigationButtons(totalReports);
|
||||||
|
|
||||||
|
player.openInventory(inventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack createReportItem(Report report, int totalReports) {
|
||||||
|
ItemStack head = new ItemStack(Material.PLAYER_HEAD);
|
||||||
|
SkullMeta meta = (SkullMeta) head.getItemMeta();
|
||||||
|
|
||||||
|
if (meta != null) {
|
||||||
|
// Set skull owner for skin
|
||||||
|
meta.setOwningPlayer(Bukkit.getOfflinePlayer(report.targetUuid()));
|
||||||
|
|
||||||
|
// Display name
|
||||||
|
meta.setDisplayName("§c" + report.targetName());
|
||||||
|
|
||||||
|
// Lore with report info
|
||||||
|
List<String> lore = new ArrayList<>();
|
||||||
|
lore.add("§7");
|
||||||
|
lore.add("§eОтправитель: §f" + report.reporterName());
|
||||||
|
lore.add("§ePричина: §f" + report.reason());
|
||||||
|
lore.add("§eВремя: §f" + TimeUtil.formatTimeAgo(report.createdAt().toEpochMilli()));
|
||||||
|
lore.add("§7");
|
||||||
|
lore.add("§eВсего репортов: §c" + totalReports);
|
||||||
|
|
||||||
|
meta.setLore(lore);
|
||||||
|
head.setItemMeta(meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addNavigationButtons(int totalReports) {
|
||||||
|
int totalPages = (int) Math.ceil((double) totalReports / PAGE_SIZE);
|
||||||
|
|
||||||
|
// Previous page button (slot 45)
|
||||||
|
if (page > 0) {
|
||||||
|
ItemStack prevButton = new ItemStack(Material.ARROW);
|
||||||
|
ItemMeta prevMeta = prevButton.getItemMeta();
|
||||||
|
if (prevMeta != null) {
|
||||||
|
prevMeta.setDisplayName("§a← Предыдущая страница");
|
||||||
|
prevButton.setItemMeta(prevMeta);
|
||||||
|
}
|
||||||
|
inventory.setItem(45, prevButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page info (slot 49)
|
||||||
|
ItemStack pageInfo = new ItemStack(Material.PAPER);
|
||||||
|
ItemMeta pageMeta = pageInfo.getItemMeta();
|
||||||
|
if (pageMeta != null) {
|
||||||
|
pageMeta.setDisplayName("§eСтраница " + (page + 1) + " из " + Math.max(1, totalPages));
|
||||||
|
List<String> lore = new ArrayList<>();
|
||||||
|
lore.add("§7Всего репортов: " + totalReports);
|
||||||
|
pageMeta.setLore(lore);
|
||||||
|
pageInfo.setItemMeta(pageMeta);
|
||||||
|
}
|
||||||
|
inventory.setItem(49, pageInfo);
|
||||||
|
|
||||||
|
// Next page button (slot 53)
|
||||||
|
if (page < totalPages - 1) {
|
||||||
|
ItemStack nextButton = new ItemStack(Material.ARROW);
|
||||||
|
ItemMeta nextMeta = nextButton.getItemMeta();
|
||||||
|
if (nextMeta != null) {
|
||||||
|
nextMeta.setDisplayName("§aСледующая страница →");
|
||||||
|
nextButton.setItemMeta(nextMeta);
|
||||||
|
}
|
||||||
|
inventory.setItem(53, nextButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close button (slot 47)
|
||||||
|
ItemStack closeButton = new ItemStack(Material.BARRIER);
|
||||||
|
ItemMeta closeMeta = closeButton.getItemMeta();
|
||||||
|
if (closeMeta != null) {
|
||||||
|
closeMeta.setDisplayName("§cЗакрыть");
|
||||||
|
closeButton.setItemMeta(closeMeta);
|
||||||
|
}
|
||||||
|
inventory.setItem(47, closeButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPage() {
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Inventory getInventory() {
|
||||||
|
return inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
34
src/main/java/dev/loki/lorep/util/MessageUtil.java
Normal file
34
src/main/java/dev/loki/lorep/util/MessageUtil.java
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
package dev.loki.lorep.util;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class MessageUtil {
|
||||||
|
|
||||||
|
private static final String PREFIX = "§8[§clorep§8] §r";
|
||||||
|
|
||||||
|
public static String colorize(String message) {
|
||||||
|
return ChatColor.translateAlternateColorCodes('&', message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void send(CommandSender sender, String message) {
|
||||||
|
sender.sendMessage(PREFIX + colorize(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendRaw(CommandSender sender, String message) {
|
||||||
|
sender.sendMessage(colorize(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendNoPrefix(Player player, String message) {
|
||||||
|
player.sendMessage(colorize(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String format(String message, String... replacements) {
|
||||||
|
String result = message;
|
||||||
|
for (int i = 0; i < replacements.length - 1; i += 2) {
|
||||||
|
result = result.replace(replacements[i], replacements[i + 1]);
|
||||||
|
}
|
||||||
|
return colorize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/main/java/dev/loki/lorep/util/PaginationUtil.java
Normal file
19
src/main/java/dev/loki/lorep/util/PaginationUtil.java
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
package dev.loki.lorep.util;
|
||||||
|
|
||||||
|
public class PaginationUtil {
|
||||||
|
|
||||||
|
public static int calculateTotalPages(int totalItems, int pageSize) {
|
||||||
|
if (totalItems <= 0) return 1;
|
||||||
|
return (int) Math.ceil((double) totalItems / pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int calculateStartIndex(int page, int pageSize) {
|
||||||
|
return page * pageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int calculateItemsOnPage(int page, int pageSize, int totalItems) {
|
||||||
|
int startIndex = calculateStartIndex(page, pageSize);
|
||||||
|
int remaining = totalItems - startIndex;
|
||||||
|
return Math.min(pageSize, Math.max(0, remaining));
|
||||||
|
}
|
||||||
|
}
|
||||||
102
src/test/java/dev/loki/lorep/gui/PaginationTest.java
Normal file
102
src/test/java/dev/loki/lorep/gui/PaginationTest.java
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
package dev.loki.lorep.gui;
|
||||||
|
|
||||||
|
import dev.loki.lorep.util.PaginationUtil;
|
||||||
|
import net.jqwik.api.*;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **Feature: lorep-report-plugin, Property 6: Pagination Correctness**
|
||||||
|
* **Validates: Requirements 4.4**
|
||||||
|
*/
|
||||||
|
public class PaginationTest {
|
||||||
|
|
||||||
|
private static final int PAGE_SIZE = 45;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **Property 6: Pagination Correctness**
|
||||||
|
* For any list of N reports and page size P, requesting page K SHALL return
|
||||||
|
* at most P reports starting from index K*P, and the total page count SHALL
|
||||||
|
* equal ceil(N/P).
|
||||||
|
* **Validates: Requirements 4.4**
|
||||||
|
*/
|
||||||
|
@Property(tries = 100)
|
||||||
|
void paginationCorrectness(
|
||||||
|
@ForAll("totalReports") int totalReports,
|
||||||
|
@ForAll("pageNumbers") int page
|
||||||
|
) {
|
||||||
|
int totalPages = PaginationUtil.calculateTotalPages(totalReports, PAGE_SIZE);
|
||||||
|
int startIndex = PaginationUtil.calculateStartIndex(page, PAGE_SIZE);
|
||||||
|
int itemsOnPage = PaginationUtil.calculateItemsOnPage(page, PAGE_SIZE, totalReports);
|
||||||
|
|
||||||
|
// Total pages should equal ceil(N/P)
|
||||||
|
int expectedTotalPages = totalReports <= 0 ? 1 : (int) Math.ceil((double) totalReports / PAGE_SIZE);
|
||||||
|
assertEquals(expectedTotalPages, totalPages,
|
||||||
|
"Total pages should equal ceil(totalReports/pageSize)");
|
||||||
|
|
||||||
|
// Start index should be page * pageSize
|
||||||
|
assertEquals(page * PAGE_SIZE, startIndex,
|
||||||
|
"Start index should be page * pageSize");
|
||||||
|
|
||||||
|
// Items on page should be at most PAGE_SIZE
|
||||||
|
assertTrue(itemsOnPage <= PAGE_SIZE,
|
||||||
|
"Items on page should not exceed page size");
|
||||||
|
|
||||||
|
// Items on page should be non-negative
|
||||||
|
assertTrue(itemsOnPage >= 0,
|
||||||
|
"Items on page should be non-negative");
|
||||||
|
|
||||||
|
// For valid pages, items should match expected
|
||||||
|
if (page < totalPages && page >= 0) {
|
||||||
|
int expectedItems = Math.min(PAGE_SIZE, totalReports - startIndex);
|
||||||
|
assertEquals(Math.max(0, expectedItems), itemsOnPage,
|
||||||
|
"Items on valid page should match expected count");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Property(tries = 100)
|
||||||
|
void allItemsCoveredByPages(@ForAll("totalReports") int totalReports) {
|
||||||
|
Assume.that(totalReports > 0);
|
||||||
|
|
||||||
|
int totalPages = PaginationUtil.calculateTotalPages(totalReports, PAGE_SIZE);
|
||||||
|
int totalItemsCovered = 0;
|
||||||
|
|
||||||
|
for (int page = 0; page < totalPages; page++) {
|
||||||
|
totalItemsCovered += PaginationUtil.calculateItemsOnPage(page, PAGE_SIZE, totalReports);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(totalReports, totalItemsCovered,
|
||||||
|
"Sum of items across all pages should equal total reports");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provide
|
||||||
|
Arbitrary<Integer> totalReports() {
|
||||||
|
return Arbitraries.integers().between(0, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provide
|
||||||
|
Arbitrary<Integer> pageNumbers() {
|
||||||
|
return Arbitraries.integers().between(0, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void emptyReportsHasOnePage() {
|
||||||
|
assertEquals(1, PaginationUtil.calculateTotalPages(0, PAGE_SIZE));
|
||||||
|
assertEquals(0, PaginationUtil.calculateItemsOnPage(0, PAGE_SIZE, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void exactlyOnePageOfReports() {
|
||||||
|
assertEquals(1, PaginationUtil.calculateTotalPages(PAGE_SIZE, PAGE_SIZE));
|
||||||
|
assertEquals(PAGE_SIZE, PaginationUtil.calculateItemsOnPage(0, PAGE_SIZE, PAGE_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void lastPageHasRemainingItems() {
|
||||||
|
int totalReports = PAGE_SIZE + 10;
|
||||||
|
assertEquals(2, PaginationUtil.calculateTotalPages(totalReports, PAGE_SIZE));
|
||||||
|
assertEquals(PAGE_SIZE, PaginationUtil.calculateItemsOnPage(0, PAGE_SIZE, totalReports));
|
||||||
|
assertEquals(10, PaginationUtil.calculateItemsOnPage(1, PAGE_SIZE, totalReports));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue