From 38b8f1bb8537f8b288bf4ae54461946308386613 Mon Sep 17 00:00:00 2001 From: Cruck Store Date: Wed, 11 Mar 2026 17:32:18 +0100 Subject: [PATCH 01/10] =?UTF-8?q?fix:=20d=C3=A9placement=20du=20SpawnerExt?= =?UTF-8?q?ractorListener=20dans=20le=20guard=20isUnitTestVersion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/fr/openmc/core/ListenersManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/fr/openmc/core/ListenersManager.java b/src/main/java/fr/openmc/core/ListenersManager.java index c4a5a44d1..511e0a076 100644 --- a/src/main/java/fr/openmc/core/ListenersManager.java +++ b/src/main/java/fr/openmc/core/ListenersManager.java @@ -40,12 +40,12 @@ public static void init() { new EquipableItemListener(), new NoMoreRabbit(), new ArmorListener(), - new SpawnerExtractorListener(), new BlockBreakListener() ); if (!OMCPlugin.isUnitTestVersion()) { registerEvents( + new SpawnerExtractorListener(), new ItemsAddersListener(), new TicketListener() ); From 74b91e4bdf6dc14e081b11a05fb2f346de047b20 Mon Sep 17 00:00:00 2001 From: Cruck Store Date: Wed, 11 Mar 2026 17:39:46 +0100 Subject: [PATCH 02/10] chore: logs verbeux pour diagnostiquer les tests unitaires --- build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle b/build.gradle index 5a2c1be0d..e1c184138 100644 --- a/build.gradle +++ b/build.gradle @@ -134,4 +134,10 @@ tasks.shadowJar { tasks.test { useJUnitPlatform() + testLogging { + exceptionFormat "full" + showExceptions true + showCauses true + showStackTraces true + } } From a5e6a04c3cf84fb93f29dfbb2403b0ecd4e4038b Mon Sep 17 00:00:00 2001 From: Cruck Store Date: Wed, 11 Mar 2026 17:45:10 +0100 Subject: [PATCH 03/10] fix: ignorer TabList dans les tests unitaires MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TabList utilise PacketAdapter de ProtocolLib (dépendance compileOnly), ce qui cause un ClassNotFoundException au lancement des tests MockBukkit. --- src/main/java/fr/openmc/core/OMCPlugin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/fr/openmc/core/OMCPlugin.java b/src/main/java/fr/openmc/core/OMCPlugin.java index 3518e9882..30d956fca 100644 --- a/src/main/java/fr/openmc/core/OMCPlugin.java +++ b/src/main/java/fr/openmc/core/OMCPlugin.java @@ -132,7 +132,8 @@ public void onEnable() { TPAQueue.initCommand(); FreezeManager.init(); QuestProgressSaveManager.init(); - TabList.init(); + if (!isUnitTestVersion()) + TabList.init(); AdminShopManager.init(); BossbarManager.init(); AnimationsManager.init(); From 81ed6e9301304996d0fec99439b3e5b08bd7bcd5 Mon Sep 17 00:00:00 2001 From: Cruck Store Date: Wed, 11 Mar 2026 18:33:24 +0100 Subject: [PATCH 04/10] fix: null check dans MultiBlockManager.save() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MultiBlockManager.init() est appelé via loadWithItemsAdder() qui ne s'exécute pas en environnement de test. config reste null et provoque un NPE lors du onDisable. --- .../openmc/core/features/cube/multiblocks/MultiBlockManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/fr/openmc/core/features/cube/multiblocks/MultiBlockManager.java b/src/main/java/fr/openmc/core/features/cube/multiblocks/MultiBlockManager.java index b1adcf75c..e8c6596a7 100644 --- a/src/main/java/fr/openmc/core/features/cube/multiblocks/MultiBlockManager.java +++ b/src/main/java/fr/openmc/core/features/cube/multiblocks/MultiBlockManager.java @@ -103,6 +103,7 @@ public static void save() { list.add(map); } + if (config == null) return; config.set("multiblocks", list); try { config.save(file); From 47a96695ab86df74159ff1b5c63991a33d1f5e42 Mon Sep 17 00:00:00 2001 From: Cruck Store Date: Wed, 11 Mar 2026 18:34:31 +0100 Subject: [PATCH 05/10] =?UTF-8?q?fix:=20test=20MotdUtils=20flaky=20avec=20?= =?UTF-8?q?seulement=202=20entr=C3=A9es=20MOTD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le BukkitRunnable (delay 0) s'exécute pendant le load du plugin, donc le MOTD capturé est déjà le custom. Avec 2 entrées dans motd.yml, Random peut piocher la même → assertNotEquals échoue 50% du temps. Fix: forcer un MOTD connu avant de tick. --- src/test/java/fr/openmc/core/utils/MotdUtilsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/fr/openmc/core/utils/MotdUtilsTest.java b/src/test/java/fr/openmc/core/utils/MotdUtilsTest.java index b6902cf2d..8449ae767 100644 --- a/src/test/java/fr/openmc/core/utils/MotdUtilsTest.java +++ b/src/test/java/fr/openmc/core/utils/MotdUtilsTest.java @@ -31,9 +31,9 @@ private String getComponentContent(Component component) { @Test @DisplayName("MOTD switch") void testMOTD() { + server.motd(Component.text("default")); String motd = getComponentContent(server.motd()); - new MotdUtils(); server.getScheduler().performTicks(12001L); Assertions.assertNotEquals(getComponentContent(server.motd()), motd); From fbae4093f77b8bee0160e21f8fd7d23c991dc01f Mon Sep 17 00:00:00 2001 From: Cruck Store Date: Wed, 11 Mar 2026 18:55:15 +0100 Subject: [PATCH 06/10] =?UTF-8?q?fix:=20attendre=20les=20t=C3=A2ches=20asy?= =?UTF-8?q?nc=20dans=20le=20test=20transferBalance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le test testTransferBalanceWithReasonRegistersTransaction échoue car la transaction est enregistrée via runTaskAsynchronously et performTicks ne garantit pas la fin des tâches async. Ajout de waitAsyncTasksFinished() pour attendre la complétion avant de vérifier. --- .../java/fr/openmc/core/features/economy/EconomyManagerTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/fr/openmc/core/features/economy/EconomyManagerTest.java b/src/test/java/fr/openmc/core/features/economy/EconomyManagerTest.java index 5675f2650..85a28bd4a 100644 --- a/src/test/java/fr/openmc/core/features/economy/EconomyManagerTest.java +++ b/src/test/java/fr/openmc/core/features/economy/EconomyManagerTest.java @@ -146,6 +146,7 @@ public void testTransferBalanceWithReasonRegistersTransaction() { EconomyManager.setBalance(player1.getUniqueId(), 400.0); EconomyManager.transferBalance(player1.getUniqueId(), player2.getUniqueId(), 150.0, "Gift"); server.getScheduler().performTicks(120L); + server.getScheduler().waitAsyncTasksFinished(); List transactions = TransactionsManager.getTransactionsByPlayers(player1.getUniqueId()); From 813b7cf09eaee55f9066d8eccac3279d0200158b Mon Sep 17 00:00:00 2001 From: Cruck Store Date: Wed, 11 Mar 2026 21:28:29 +0100 Subject: [PATCH 07/10] =?UTF-8?q?test:=20ajout=20de=20tests=20unitaires=20?= =?UTF-8?q?pour=20les=20utilitaires=20et=20l'=C3=A9conomie?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nouveaux tests: - DateUtils: conversion secondes/millis/ticks, isBefore - InputUtils: pluralize, edge cases null/empty/décimaux - PaddingUtils: centrage, débordement, padding impair - EnumUtils: match valide/invalide/null, valeur par défaut - MathUtils: interpolation de couleurs (lerpColor) - YmlUtils: deep copy de maps/listes imbriquées - Queue: ajout, suppression, éviction LRU, taille max - ColorUtils: conversions couleur/code/nom/matériau/RGB - RandomUtils: bornes int/double/float, cas limites - EconomyManager: formatage simplifié (k/M/B suffixes) --- .../economy/EconomyFormattingTest.java | 58 ++++++++++++ .../fr/openmc/core/utils/ColorUtilsTest.java | 78 ++++++++++++++++ .../fr/openmc/core/utils/DateUtilsTest.java | 84 +++++++++++++++-- .../fr/openmc/core/utils/EnumUtilsTest.java | 47 ++++++++++ .../fr/openmc/core/utils/InputUtilsTest.java | 78 ++++++++++------ .../fr/openmc/core/utils/MathUtilsTest.java | 52 +++++++++++ .../openmc/core/utils/PaddingUtilsTest.java | 46 ++++++++++ .../java/fr/openmc/core/utils/QueueTest.java | 78 ++++++++++++++++ .../fr/openmc/core/utils/RandomUtilsTest.java | 47 ++++++++++ .../fr/openmc/core/utils/YmlUtilsTest.java | 89 +++++++++++++++++++ 10 files changed, 627 insertions(+), 30 deletions(-) create mode 100644 src/test/java/fr/openmc/core/features/economy/EconomyFormattingTest.java create mode 100644 src/test/java/fr/openmc/core/utils/ColorUtilsTest.java create mode 100644 src/test/java/fr/openmc/core/utils/EnumUtilsTest.java create mode 100644 src/test/java/fr/openmc/core/utils/MathUtilsTest.java create mode 100644 src/test/java/fr/openmc/core/utils/PaddingUtilsTest.java create mode 100644 src/test/java/fr/openmc/core/utils/QueueTest.java create mode 100644 src/test/java/fr/openmc/core/utils/RandomUtilsTest.java create mode 100644 src/test/java/fr/openmc/core/utils/YmlUtilsTest.java diff --git a/src/test/java/fr/openmc/core/features/economy/EconomyFormattingTest.java b/src/test/java/fr/openmc/core/features/economy/EconomyFormattingTest.java new file mode 100644 index 000000000..c5db5f5d8 --- /dev/null +++ b/src/test/java/fr/openmc/core/features/economy/EconomyFormattingTest.java @@ -0,0 +1,58 @@ +package fr.openmc.core.features.economy; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class EconomyFormattingTest { + + @Test + @DisplayName("Format zero balance") + void testFormat_Zero() { + Assertions.assertEquals("0", EconomyManager.getFormattedSimplifiedNumber(0)); + } + + @Test + @DisplayName("Format small number without suffix") + void testFormat_SmallNumber() { + Assertions.assertEquals("500", EconomyManager.getFormattedSimplifiedNumber(500)); + } + + @Test + @DisplayName("Format thousands with k suffix") + void testFormat_Thousands() { + String result = EconomyManager.getFormattedSimplifiedNumber(1500); + Assertions.assertEquals("1.5k", result); + } + + @Test + @DisplayName("Format exact thousand") + void testFormat_ExactThousand() { + Assertions.assertEquals("1k", EconomyManager.getFormattedSimplifiedNumber(1000)); + } + + @Test + @DisplayName("Format millions with M suffix") + void testFormat_Millions() { + Assertions.assertEquals("3M", EconomyManager.getFormattedSimplifiedNumber(3_000_000)); + } + + @Test + @DisplayName("Format billions with B suffix") + void testFormat_Billions() { + Assertions.assertEquals("1B", EconomyManager.getFormattedSimplifiedNumber(1_000_000_000)); + } + + @Test + @DisplayName("Format with decimal truncation") + void testFormat_Decimal() { + String result = EconomyManager.getFormattedSimplifiedNumber(2_500_000); + Assertions.assertEquals("2.5M", result); + } + + @Test + @DisplayName("Format number under 1000") + void testFormat_Under1000() { + Assertions.assertEquals("999", EconomyManager.getFormattedSimplifiedNumber(999)); + } +} diff --git a/src/test/java/fr/openmc/core/utils/ColorUtilsTest.java b/src/test/java/fr/openmc/core/utils/ColorUtilsTest.java new file mode 100644 index 000000000..da0958d96 --- /dev/null +++ b/src/test/java/fr/openmc/core/utils/ColorUtilsTest.java @@ -0,0 +1,78 @@ +package fr.openmc.core.utils; + +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class ColorUtilsTest { + + @Test + @DisplayName("getNamedTextColor valid color") + void testGetNamedTextColor_Valid() { + Assertions.assertEquals(NamedTextColor.RED, ColorUtils.getNamedTextColor("red")); + Assertions.assertEquals(NamedTextColor.BLUE, ColorUtils.getNamedTextColor("blue")); + Assertions.assertEquals(NamedTextColor.GREEN, ColorUtils.getNamedTextColor("green")); + } + + @Test + @DisplayName("getNamedTextColor null returns WHITE") + void testGetNamedTextColor_Null() { + Assertions.assertEquals(NamedTextColor.WHITE, ColorUtils.getNamedTextColor(null)); + } + + @Test + @DisplayName("getNamedTextColor invalid returns WHITE") + void testGetNamedTextColor_Invalid() { + Assertions.assertEquals(NamedTextColor.WHITE, ColorUtils.getNamedTextColor("not_a_color")); + } + + @Test + @DisplayName("getColorCode returns correct codes") + void testGetColorCode() { + Assertions.assertEquals("§c", ColorUtils.getColorCode(NamedTextColor.RED)); + Assertions.assertEquals("§a", ColorUtils.getColorCode(NamedTextColor.GREEN)); + Assertions.assertEquals("§9", ColorUtils.getColorCode(NamedTextColor.BLUE)); + Assertions.assertEquals("§f", ColorUtils.getColorCode(NamedTextColor.WHITE)); + Assertions.assertEquals("§0", ColorUtils.getColorCode(NamedTextColor.BLACK)); + } + + @Test + @DisplayName("getNameFromColor returns French names") + void testGetNameFromColor() { + Assertions.assertEquals("§cRouge", ColorUtils.getNameFromColor(NamedTextColor.RED)); + Assertions.assertEquals("§fBlanc", ColorUtils.getNameFromColor(NamedTextColor.WHITE)); + Assertions.assertEquals("§6Orange", ColorUtils.getNameFromColor(NamedTextColor.GOLD)); + } + + @Test + @DisplayName("getMaterialFromColor returns correct wool") + void testGetMaterialFromColor() { + Assertions.assertEquals(Material.RED_WOOL, ColorUtils.getMaterialFromColor(NamedTextColor.RED)); + Assertions.assertEquals(Material.WHITE_WOOL, ColorUtils.getMaterialFromColor(NamedTextColor.WHITE)); + Assertions.assertEquals(Material.BLACK_WOOL, ColorUtils.getMaterialFromColor(NamedTextColor.BLACK)); + } + + @Test + @DisplayName("getReadableColor maps correctly") + void testGetReadableColor() { + Assertions.assertEquals(NamedTextColor.DARK_GRAY, ColorUtils.getReadableColor(NamedTextColor.BLACK)); + Assertions.assertEquals(NamedTextColor.GRAY, ColorUtils.getReadableColor(NamedTextColor.WHITE)); + Assertions.assertEquals(NamedTextColor.GOLD, ColorUtils.getReadableColor(NamedTextColor.YELLOW)); + Assertions.assertEquals(NamedTextColor.RED, ColorUtils.getReadableColor(NamedTextColor.RED)); + } + + @Test + @DisplayName("getRGBFromNamedTextColor returns correct RGB") + void testGetRGBFromNamedTextColor() { + int[] red = ColorUtils.getRGBFromNamedTextColor(NamedTextColor.RED); + Assertions.assertArrayEquals(new int[]{255, 85, 85}, red); + + int[] black = ColorUtils.getRGBFromNamedTextColor(NamedTextColor.BLACK); + Assertions.assertArrayEquals(new int[]{0, 0, 0}, black); + + int[] white = ColorUtils.getRGBFromNamedTextColor(NamedTextColor.WHITE); + Assertions.assertArrayEquals(new int[]{255, 255, 255}, white); + } +} diff --git a/src/test/java/fr/openmc/core/utils/DateUtilsTest.java b/src/test/java/fr/openmc/core/utils/DateUtilsTest.java index 3d3ef954a..865ea00a4 100644 --- a/src/test/java/fr/openmc/core/utils/DateUtilsTest.java +++ b/src/test/java/fr/openmc/core/utils/DateUtilsTest.java @@ -9,10 +9,84 @@ class DateUtilsTest { @Test @DisplayName("Time to Ticks") void testConvertTime() { - Assertions.assertEquals( - "20m", - DateUtils.convertTime(24000) - ); + Assertions.assertEquals("20m", DateUtils.convertTime(24000)); } -} \ No newline at end of file + @Test + @DisplayName("Convert 0 seconds") + void testConvertSecondToTime_Zero() { + Assertions.assertEquals("0s", DateUtils.convertSecondToTime(0)); + } + + @Test + @DisplayName("Convert seconds only") + void testConvertSecondToTime_SecondsOnly() { + Assertions.assertEquals("45s", DateUtils.convertSecondToTime(45)); + } + + @Test + @DisplayName("Convert minutes and seconds") + void testConvertSecondToTime_MinutesAndSeconds() { + Assertions.assertEquals("2m 30s", DateUtils.convertSecondToTime(150)); + } + + @Test + @DisplayName("Convert hours, minutes and seconds") + void testConvertSecondToTime_HoursMinutesSeconds() { + Assertions.assertEquals("1h 5m 10s", DateUtils.convertSecondToTime(3910)); + } + + @Test + @DisplayName("Convert days, hours, minutes and seconds") + void testConvertSecondToTime_Full() { + Assertions.assertEquals("3j 4h 2m 38s", DateUtils.convertSecondToTime(273758)); + } + + @Test + @DisplayName("Convert exact hours") + void testConvertSecondToTime_ExactHours() { + Assertions.assertEquals("2h", DateUtils.convertSecondToTime(7200)); + } + + @Test + @DisplayName("Convert millis to time") + void testConvertMillisToTime() { + Assertions.assertEquals("1m 30s", DateUtils.convertMillisToTime(90000)); + } + + @Test + @DisplayName("Convert 0 millis") + void testConvertMillisToTime_Zero() { + Assertions.assertEquals("0s", DateUtils.convertMillisToTime(0)); + } + + @Test + @DisplayName("isBefore - same year, earlier week") + void testIsBefore_SameYearEarlierWeek() { + Assertions.assertTrue(DateUtils.isBefore("2025-10", "2025-20")); + } + + @Test + @DisplayName("isBefore - same year, same week") + void testIsBefore_SameWeek() { + Assertions.assertTrue(DateUtils.isBefore("2025-10", "2025-10")); + } + + @Test + @DisplayName("isBefore - same year, later week") + void testIsBefore_SameYearLaterWeek() { + Assertions.assertFalse(DateUtils.isBefore("2025-20", "2025-10")); + } + + @Test + @DisplayName("isBefore - earlier year") + void testIsBefore_EarlierYear() { + Assertions.assertTrue(DateUtils.isBefore("2024-50", "2025-1")); + } + + @Test + @DisplayName("isBefore - later year") + void testIsBefore_LaterYear() { + Assertions.assertFalse(DateUtils.isBefore("2026-1", "2025-50")); + } +} diff --git a/src/test/java/fr/openmc/core/utils/EnumUtilsTest.java b/src/test/java/fr/openmc/core/utils/EnumUtilsTest.java new file mode 100644 index 000000000..499489e03 --- /dev/null +++ b/src/test/java/fr/openmc/core/utils/EnumUtilsTest.java @@ -0,0 +1,47 @@ +package fr.openmc.core.utils; + +import org.bukkit.Material; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class EnumUtilsTest { + + @Test + @DisplayName("Match valid enum value") + void testMatch_Valid() { + Assertions.assertEquals(Material.STONE, EnumUtils.match("stone", Material.class)); + } + + @Test + @DisplayName("Match valid enum value case insensitive") + void testMatch_CaseInsensitive() { + Assertions.assertEquals(Material.DIAMOND, EnumUtils.match("diamond", Material.class)); + Assertions.assertEquals(Material.DIAMOND, EnumUtils.match("DIAMOND", Material.class)); + Assertions.assertEquals(Material.DIAMOND, EnumUtils.match("Diamond", Material.class)); + } + + @Test + @DisplayName("Match invalid key returns null") + void testMatch_InvalidReturnsNull() { + Assertions.assertNull(EnumUtils.match("not_a_material", Material.class)); + } + + @Test + @DisplayName("Match invalid key returns default value") + void testMatch_InvalidReturnsDefault() { + Assertions.assertEquals(Material.AIR, EnumUtils.match("not_a_material", Material.class, Material.AIR)); + } + + @Test + @DisplayName("Match null key returns default") + void testMatch_NullKey() { + Assertions.assertEquals(Material.STONE, EnumUtils.match(null, Material.class, Material.STONE)); + } + + @Test + @DisplayName("Match null key returns null without default") + void testMatch_NullKeyNoDefault() { + Assertions.assertNull(EnumUtils.match(null, Material.class)); + } +} diff --git a/src/test/java/fr/openmc/core/utils/InputUtilsTest.java b/src/test/java/fr/openmc/core/utils/InputUtilsTest.java index e72417864..b80b0247b 100644 --- a/src/test/java/fr/openmc/core/utils/InputUtilsTest.java +++ b/src/test/java/fr/openmc/core/utils/InputUtilsTest.java @@ -11,30 +11,20 @@ class InputUtilsTest { @Test @DisplayName("Conversion Sign Input to Money") void testConvertSignInputToMoney_ShouldGiveTheAmountInFloat() { - Assertions.assertEquals( - 3000000.0, - InputUtils.convertToMoneyValue("3m") - ); - Assertions.assertEquals( - 3000.0, - InputUtils.convertToMoneyValue("3k") - ); - Assertions.assertEquals( - 3000000.0, - InputUtils.convertToMoneyValue("3M") - ); - Assertions.assertEquals( - 3000.0, - InputUtils.convertToMoneyValue("3K") - ); - Assertions.assertEquals( - 1.0, - InputUtils.convertToMoneyValue("1") - ); - Assertions.assertEquals( - 3000.0, - InputUtils.convertToMoneyValue("3000") - ); + Assertions.assertEquals(3000000.0, InputUtils.convertToMoneyValue("3m")); + Assertions.assertEquals(3000.0, InputUtils.convertToMoneyValue("3k")); + Assertions.assertEquals(3000000.0, InputUtils.convertToMoneyValue("3M")); + Assertions.assertEquals(3000.0, InputUtils.convertToMoneyValue("3K")); + Assertions.assertEquals(1.0, InputUtils.convertToMoneyValue("1")); + Assertions.assertEquals(3000.0, InputUtils.convertToMoneyValue("3000")); + } + + @Test + @DisplayName("Conversion with decimals") + void testConvertToMoneyValue_Decimals() { + Assertions.assertEquals(2500000.0, InputUtils.convertToMoneyValue("2.5m")); + Assertions.assertEquals(1500.0, InputUtils.convertToMoneyValue("1.5k")); + Assertions.assertEquals(99.99, InputUtils.convertToMoneyValue("99.99")); } @ParameterizedTest @@ -44,9 +34,16 @@ void testConvertSignInputToMoney_ShouldGiveAnError(String input) { Assertions.assertEquals(-1, InputUtils.convertToMoneyValue(input)); } + @Test + @DisplayName("Conversion null and empty returns -1") + void testConvertToMoneyValue_NullAndEmpty() { + Assertions.assertEquals(-1, InputUtils.convertToMoneyValue(null)); + Assertions.assertEquals(-1, InputUtils.convertToMoneyValue("")); + } + @ParameterizedTest @DisplayName("Check is returned value is true") - @ValueSource(strings = {"1", "3m", "3k", "3M", "3K", "3000"}) + @ValueSource(strings = {"1", "3m", "3k", "3M", "3K", "3000", "2.5m", "0.5k"}) void testIsInputMoney_MustReturnTrue(String input) { Assertions.assertTrue(InputUtils.isInputMoney(input)); } @@ -58,4 +55,35 @@ void testIsInputMoney_MustReturnFalse(String input) { Assertions.assertFalse(InputUtils.isInputMoney(input)); } + @Test + @DisplayName("isInputMoney null and empty") + void testIsInputMoney_NullAndEmpty() { + Assertions.assertFalse(InputUtils.isInputMoney(null)); + Assertions.assertFalse(InputUtils.isInputMoney("")); + } + + @Test + @DisplayName("Pluralize with count > 1 adds s") + void testPluralize_Plural() { + Assertions.assertEquals("joueurs", InputUtils.pluralize("joueur", 5)); + } + + @Test + @DisplayName("Pluralize with count 1 no s") + void testPluralize_Singular() { + Assertions.assertEquals("joueur", InputUtils.pluralize("joueur", 1)); + } + + @Test + @DisplayName("Pluralize with count 0 no s") + void testPluralize_Zero() { + Assertions.assertEquals("joueur", InputUtils.pluralize("joueur", 0)); + } + + @Test + @DisplayName("Pluralize long variant") + void testPluralize_Long() { + Assertions.assertEquals("blocs", InputUtils.pluralize("bloc", 100L)); + Assertions.assertEquals("bloc", InputUtils.pluralize("bloc", 1L)); + } } diff --git a/src/test/java/fr/openmc/core/utils/MathUtilsTest.java b/src/test/java/fr/openmc/core/utils/MathUtilsTest.java new file mode 100644 index 000000000..0453bcb0e --- /dev/null +++ b/src/test/java/fr/openmc/core/utils/MathUtilsTest.java @@ -0,0 +1,52 @@ +package fr.openmc.core.utils; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class MathUtilsTest { + + @Test + @DisplayName("lerpColor t=0 returns start color") + void testLerpColor_Start() { + int start = 0xFF0000; + int end = 0x0000FF; + Assertions.assertEquals(start, MathUtils.lerpColor(start, end, 0.0)); + } + + @Test + @DisplayName("lerpColor t=1 returns end color") + void testLerpColor_End() { + int start = 0xFF0000; + int end = 0x0000FF; + Assertions.assertEquals(end, MathUtils.lerpColor(start, end, 1.0)); + } + + @Test + @DisplayName("lerpColor t=0.5 returns midpoint") + void testLerpColor_Midpoint() { + int start = 0x000000; + int end = 0xFEFEFE; + int result = MathUtils.lerpColor(start, end, 0.5); + Assertions.assertEquals(0x7F7F7F, result); + } + + @Test + @DisplayName("lerpColor same colors returns same") + void testLerpColor_SameColors() { + int color = 0xABCDEF; + Assertions.assertEquals(color, MathUtils.lerpColor(color, color, 0.5)); + } + + @Test + @DisplayName("lerpColor black to white at 0.25") + void testLerpColor_QuarterWay() { + int result = MathUtils.lerpColor(0x000000, 0xFFFFFF, 0.25); + int r = (result >> 16) & 0xFF; + int g = (result >> 8) & 0xFF; + int b = result & 0xFF; + Assertions.assertEquals(63, r); + Assertions.assertEquals(63, g); + Assertions.assertEquals(63, b); + } +} diff --git a/src/test/java/fr/openmc/core/utils/PaddingUtilsTest.java b/src/test/java/fr/openmc/core/utils/PaddingUtilsTest.java new file mode 100644 index 000000000..14639345b --- /dev/null +++ b/src/test/java/fr/openmc/core/utils/PaddingUtilsTest.java @@ -0,0 +1,46 @@ +package fr.openmc.core.utils; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class PaddingUtilsTest { + + @Test + @DisplayName("Center text in given width") + void testFormat_Centered() { + String result = PaddingUtils.format("hi", 10); + Assertions.assertEquals(10, result.length()); + Assertions.assertEquals(" hi ", result); + } + + @Test + @DisplayName("Text longer than width returns text without extra padding") + void testFormat_TextLongerThanWidth() { + String result = PaddingUtils.format("hello world", 5); + Assertions.assertEquals("hello world", result); + } + + @Test + @DisplayName("Text exactly equals width") + void testFormat_ExactWidth() { + String result = PaddingUtils.format("abcde", 5); + Assertions.assertEquals("abcde", result); + } + + @Test + @DisplayName("Odd padding distributes correctly") + void testFormat_OddPadding() { + String result = PaddingUtils.format("ab", 5); + Assertions.assertEquals(5, result.length()); + Assertions.assertEquals(" ab ", result); + } + + @Test + @DisplayName("Empty string gets full padding") + void testFormat_EmptyString() { + String result = PaddingUtils.format("", 4); + Assertions.assertEquals(4, result.length()); + Assertions.assertEquals(" ", result); + } +} diff --git a/src/test/java/fr/openmc/core/utils/QueueTest.java b/src/test/java/fr/openmc/core/utils/QueueTest.java new file mode 100644 index 000000000..e00c1764d --- /dev/null +++ b/src/test/java/fr/openmc/core/utils/QueueTest.java @@ -0,0 +1,78 @@ +package fr.openmc.core.utils; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class QueueTest { + + @Test + @DisplayName("Add and get element") + void testAddAndGet() { + Queue queue = new Queue<>(5); + queue.add("a", 1); + Assertions.assertEquals(1, queue.get("a")); + } + + @Test + @DisplayName("Remove element") + void testRemove() { + Queue queue = new Queue<>(5); + queue.add("a", 1); + queue.remove("a"); + Assertions.assertNull(queue.get("a")); + } + + @Test + @DisplayName("Get non-existent key returns null") + void testGet_NonExistent() { + Queue queue = new Queue<>(5); + Assertions.assertNull(queue.get("missing")); + } + + @Test + @DisplayName("Eviction when exceeding size") + void testEviction() { + Queue queue = new Queue<>(3); + queue.add("a", 1); + queue.add("b", 2); + queue.add("c", 3); + queue.add("d", 4); + + Assertions.assertNull(queue.get("a")); + Assertions.assertEquals(2, queue.get("b")); + Assertions.assertEquals(3, queue.get("c")); + Assertions.assertEquals(4, queue.get("d")); + } + + @Test + @DisplayName("Queue respects max size") + void testMaxSize() { + Queue queue = new Queue<>(2); + queue.add(1, "one"); + queue.add(2, "two"); + queue.add(3, "three"); + + Assertions.assertEquals(2, queue.getQueue().size()); + } + + @Test + @DisplayName("Overwrite existing key") + void testOverwrite() { + Queue queue = new Queue<>(5); + queue.add("a", 1); + queue.add("a", 99); + Assertions.assertEquals(99, queue.get("a")); + } + + @Test + @DisplayName("Queue size 1 keeps only last element") + void testSizeOne() { + Queue queue = new Queue<>(1); + queue.add("first", "1"); + queue.add("second", "2"); + + Assertions.assertNull(queue.get("first")); + Assertions.assertEquals("2", queue.get("second")); + } +} diff --git a/src/test/java/fr/openmc/core/utils/RandomUtilsTest.java b/src/test/java/fr/openmc/core/utils/RandomUtilsTest.java new file mode 100644 index 000000000..29c74d7bb --- /dev/null +++ b/src/test/java/fr/openmc/core/utils/RandomUtilsTest.java @@ -0,0 +1,47 @@ +package fr.openmc.core.utils; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; + +class RandomUtilsTest { + + @RepeatedTest(50) + @DisplayName("randomBetween int stays in bounds") + void testRandomBetweenInt_InBounds() { + int result = RandomUtils.randomBetween(5, 10); + Assertions.assertTrue(result >= 5 && result <= 10, + "Expected between 5 and 10, got: " + result); + } + + @RepeatedTest(50) + @DisplayName("randomBetween double stays in bounds") + void testRandomBetweenDouble_InBounds() { + double result = RandomUtils.randomBetween(1.0, 5.0); + Assertions.assertTrue(result >= 1.0 && result < 5.0, + "Expected between 1.0 and 5.0, got: " + result); + } + + @RepeatedTest(50) + @DisplayName("randomBetween float stays in bounds") + void testRandomBetweenFloat_InBounds() { + float result = RandomUtils.randomBetween(0.0f, 1.0f); + Assertions.assertTrue(result >= 0.0f && result < 1.0f, + "Expected between 0.0 and 1.0, got: " + result); + } + + @Test + @DisplayName("randomBetween int same min max returns that value") + void testRandomBetweenInt_SameMinMax() { + Assertions.assertEquals(7, RandomUtils.randomBetween(7, 7)); + } + + @RepeatedTest(50) + @DisplayName("randomBetween int negative range") + void testRandomBetweenInt_NegativeRange() { + int result = RandomUtils.randomBetween(-10, -5); + Assertions.assertTrue(result >= -10 && result <= -5, + "Expected between -10 and -5, got: " + result); + } +} diff --git a/src/test/java/fr/openmc/core/utils/YmlUtilsTest.java b/src/test/java/fr/openmc/core/utils/YmlUtilsTest.java new file mode 100644 index 000000000..426fcb2a3 --- /dev/null +++ b/src/test/java/fr/openmc/core/utils/YmlUtilsTest.java @@ -0,0 +1,89 @@ +package fr.openmc.core.utils; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class YmlUtilsTest { + + @Test + @DisplayName("Deep copy simple map") + void testDeepCopy_SimpleMap() { + Map original = new HashMap<>(); + original.put("key1", "value1"); + original.put("key2", 42); + + Map copy = YmlUtils.deepCopy(original); + + Assertions.assertEquals(original, copy); + Assertions.assertNotSame(original, copy); + } + + @Test + @DisplayName("Deep copy nested map") + void testDeepCopy_NestedMap() { + Map inner = new HashMap<>(); + inner.put("nested", "value"); + + Map original = new HashMap<>(); + original.put("outer", inner); + + Map copy = YmlUtils.deepCopy(original); + + Assertions.assertEquals("value", ((Map) copy.get("outer")).get("nested")); + + inner.put("nested", "modified"); + Assertions.assertEquals("value", ((Map) copy.get("outer")).get("nested")); + } + + @Test + @DisplayName("Deep copy with list") + void testDeepCopy_WithList() { + List list = new ArrayList<>(); + list.add("a"); + list.add("b"); + + Map original = new HashMap<>(); + original.put("items", list); + + Map copy = YmlUtils.deepCopy(original); + + list.add("c"); + List copiedList = (List) copy.get("items"); + Assertions.assertEquals(2, copiedList.size()); + } + + @Test + @DisplayName("Deep copy primitives are preserved") + void testDeepCopyObject_Primitives() { + Assertions.assertEquals("hello", YmlUtils.deepCopyObject("hello")); + Assertions.assertEquals(42, YmlUtils.deepCopyObject(42)); + Assertions.assertEquals(3.14, YmlUtils.deepCopyObject(3.14)); + Assertions.assertTrue((Boolean) YmlUtils.deepCopyObject(true)); + } + + @Test + @DisplayName("Deep copy empty map") + void testDeepCopy_EmptyMap() { + Map copy = YmlUtils.deepCopy(new HashMap<>()); + Assertions.assertTrue(copy.isEmpty()); + } + + @Test + @DisplayName("Deep copy null key is skipped") + void testDeepCopy_NullKey() { + Map original = new HashMap<>(); + original.put(null, "value"); + original.put("key", "val"); + + Map copy = YmlUtils.deepCopy(original); + + Assertions.assertFalse(copy.containsKey(null)); + Assertions.assertEquals("val", copy.get("key")); + } +} From 5f5c6ec42c96abd849eb505e7c20a4bb946ef31a Mon Sep 17 00:00:00 2001 From: Cruck Store Date: Wed, 11 Mar 2026 21:38:59 +0100 Subject: [PATCH 08/10] fix: waitAsyncTasksFinished sur tous les tests de transactions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajout de waitAsyncTasksFinished() après performTicks() dans tous les tests Economy qui vérifient des transactions enregistrées en async. --- .../openmc/core/features/economy/EconomyManagerTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/java/fr/openmc/core/features/economy/EconomyManagerTest.java b/src/test/java/fr/openmc/core/features/economy/EconomyManagerTest.java index 85a28bd4a..e1147d614 100644 --- a/src/test/java/fr/openmc/core/features/economy/EconomyManagerTest.java +++ b/src/test/java/fr/openmc/core/features/economy/EconomyManagerTest.java @@ -76,6 +76,7 @@ public void testSetBalance() { public void testAddBalanceWithReasonRegistersTransaction() { EconomyManager.addBalance(player1.getUniqueId(), 100.0, "Test Reason"); server.getScheduler().performTicks(20L); + server.getScheduler().waitAsyncTasksFinished(); List transactions = TransactionsManager.getTransactionsByPlayers(player1.getUniqueId()); boolean found = transactions.stream().anyMatch(t -> @@ -92,10 +93,11 @@ public void testWithdrawBalanceWithReasonRegistersTransaction() { EconomyManager.setBalance(player1.getUniqueId(), 200.0); EconomyManager.withdrawBalance(player1.getUniqueId(), 50.0, "Withdrawal Reason"); server.getScheduler().performTicks(20L); + server.getScheduler().waitAsyncTasksFinished(); List transactions = TransactionsManager.getTransactionsByPlayers(player1.getUniqueId()); - boolean found = transactions.stream().anyMatch(t -> + boolean found = transactions.stream().anyMatch(t -> t.sender.equals(player1.getUniqueId().toString()) && t.amount == 50.0 && t.reason.equals("Withdrawal Reason") @@ -109,9 +111,10 @@ public void testWithdrawBalanceWithoutReasonDoesNotRegisterTransaction() { EconomyManager.setBalance(player1.getUniqueId(), 200.0); EconomyManager.withdrawBalance(player1.getUniqueId(), 50.0); server.getScheduler().performTicks(20L); + server.getScheduler().waitAsyncTasksFinished(); List transactions = TransactionsManager.getTransactionsByPlayers(player1.getUniqueId()); - boolean found = transactions.stream().anyMatch(t -> + boolean found = transactions.stream().anyMatch(t -> t.sender.equals(player1.getUniqueId().toString()) && t.amount == 50.0 ); From ffeacbde6a1d0516616edf3a2dc44904bcb1e76d Mon Sep 17 00:00:00 2001 From: Cruck Store Date: Thu, 12 Mar 2026 19:41:09 +0100 Subject: [PATCH 09/10] =?UTF-8?q?fix:=20d=C3=A9placer=20le=20null=20check?= =?UTF-8?q?=20au=20d=C3=A9but=20de=20MultiBlockManager.save()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Évite d'itérer inutilement sur les multiblocks si config n'a pas été initialisé (init() appelé uniquement via loadWithItemsAdder). --- .../core/features/cube/multiblocks/MultiBlockManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/fr/openmc/core/features/cube/multiblocks/MultiBlockManager.java b/src/main/java/fr/openmc/core/features/cube/multiblocks/MultiBlockManager.java index e8c6596a7..ca264d4e1 100644 --- a/src/main/java/fr/openmc/core/features/cube/multiblocks/MultiBlockManager.java +++ b/src/main/java/fr/openmc/core/features/cube/multiblocks/MultiBlockManager.java @@ -81,6 +81,8 @@ public static void load() { } public static void save() { + if (config == null) return; + List> list = new ArrayList<>(); for (MultiBlock mb : multiBlocks) { Map map = new HashMap<>(); @@ -103,7 +105,6 @@ public static void save() { list.add(map); } - if (config == null) return; config.set("multiblocks", list); try { config.save(file); From 257b2a6fc1e09a62d39cb3d5b5a90bd34b9677bc Mon Sep 17 00:00:00 2001 From: Cruck Store Date: Thu, 19 Mar 2026 16:21:26 +0100 Subject: [PATCH 10/10] fix: appliquer les retours de review PR #1170 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Suppression des performTicks redondants avant waitAsyncTasksFinished - Ajout de tests NaN, Infinity, -Infinity dans InputUtilsTest - Suppression du bloc testLogging de debug dans build.gradle - Fix locale EconomyFormattingTest pour éviter les échecs liés au séparateur décimal --- build.gradle | 6 ------ .../core/features/economy/EconomyFormattingTest.java | 8 ++++++++ .../openmc/core/features/economy/EconomyManagerTest.java | 4 ---- src/test/java/fr/openmc/core/utils/InputUtilsTest.java | 4 ++-- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index e1c184138..5a2c1be0d 100644 --- a/build.gradle +++ b/build.gradle @@ -134,10 +134,4 @@ tasks.shadowJar { tasks.test { useJUnitPlatform() - testLogging { - exceptionFormat "full" - showExceptions true - showCauses true - showStackTraces true - } } diff --git a/src/test/java/fr/openmc/core/features/economy/EconomyFormattingTest.java b/src/test/java/fr/openmc/core/features/economy/EconomyFormattingTest.java index c5db5f5d8..c0443cd71 100644 --- a/src/test/java/fr/openmc/core/features/economy/EconomyFormattingTest.java +++ b/src/test/java/fr/openmc/core/features/economy/EconomyFormattingTest.java @@ -1,11 +1,19 @@ package fr.openmc.core.features.economy; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.Locale; + class EconomyFormattingTest { + @BeforeAll + static void setUpLocale() { + Locale.setDefault(Locale.US); + } + @Test @DisplayName("Format zero balance") void testFormat_Zero() { diff --git a/src/test/java/fr/openmc/core/features/economy/EconomyManagerTest.java b/src/test/java/fr/openmc/core/features/economy/EconomyManagerTest.java index e1147d614..a9ddcfb13 100644 --- a/src/test/java/fr/openmc/core/features/economy/EconomyManagerTest.java +++ b/src/test/java/fr/openmc/core/features/economy/EconomyManagerTest.java @@ -75,7 +75,6 @@ public void testSetBalance() { @Test public void testAddBalanceWithReasonRegistersTransaction() { EconomyManager.addBalance(player1.getUniqueId(), 100.0, "Test Reason"); - server.getScheduler().performTicks(20L); server.getScheduler().waitAsyncTasksFinished(); List transactions = TransactionsManager.getTransactionsByPlayers(player1.getUniqueId()); @@ -92,7 +91,6 @@ public void testAddBalanceWithReasonRegistersTransaction() { public void testWithdrawBalanceWithReasonRegistersTransaction() { EconomyManager.setBalance(player1.getUniqueId(), 200.0); EconomyManager.withdrawBalance(player1.getUniqueId(), 50.0, "Withdrawal Reason"); - server.getScheduler().performTicks(20L); server.getScheduler().waitAsyncTasksFinished(); List transactions = TransactionsManager.getTransactionsByPlayers(player1.getUniqueId()); @@ -110,7 +108,6 @@ public void testWithdrawBalanceWithReasonRegistersTransaction() { public void testWithdrawBalanceWithoutReasonDoesNotRegisterTransaction() { EconomyManager.setBalance(player1.getUniqueId(), 200.0); EconomyManager.withdrawBalance(player1.getUniqueId(), 50.0); - server.getScheduler().performTicks(20L); server.getScheduler().waitAsyncTasksFinished(); List transactions = TransactionsManager.getTransactionsByPlayers(player1.getUniqueId()); @@ -148,7 +145,6 @@ public void testFailedTransferBalanceDueToInsufficientFunds() { public void testTransferBalanceWithReasonRegistersTransaction() { EconomyManager.setBalance(player1.getUniqueId(), 400.0); EconomyManager.transferBalance(player1.getUniqueId(), player2.getUniqueId(), 150.0, "Gift"); - server.getScheduler().performTicks(120L); server.getScheduler().waitAsyncTasksFinished(); List transactions = TransactionsManager.getTransactionsByPlayers(player1.getUniqueId()); diff --git a/src/test/java/fr/openmc/core/utils/InputUtilsTest.java b/src/test/java/fr/openmc/core/utils/InputUtilsTest.java index b80b0247b..a399df5f3 100644 --- a/src/test/java/fr/openmc/core/utils/InputUtilsTest.java +++ b/src/test/java/fr/openmc/core/utils/InputUtilsTest.java @@ -29,7 +29,7 @@ void testConvertToMoneyValue_Decimals() { @ParameterizedTest @DisplayName("Conversion of input sign to -1") - @ValueSource(strings = {"-3", "-1", "489y", "4,5"}) + @ValueSource(strings = {"-3", "-1", "489y", "4,5", "NaN", "Infinity", "-Infinity"}) void testConvertSignInputToMoney_ShouldGiveAnError(String input) { Assertions.assertEquals(-1, InputUtils.convertToMoneyValue(input)); } @@ -50,7 +50,7 @@ void testIsInputMoney_MustReturnTrue(String input) { @ParameterizedTest @DisplayName("Check is returned value is false") - @ValueSource(strings = {"0", "-3", "-1", "489y", "4,5"}) + @ValueSource(strings = {"0", "-3", "-1", "489y", "4,5", "NaN", "Infinity", "-Infinity"}) void testIsInputMoney_MustReturnFalse(String input) { Assertions.assertFalse(InputUtils.isInputMoney(input)); }