diff --git a/doc/reference/item_details.md b/doc/reference/item_details.md index 3472e4d45..a140e1056 100644 --- a/doc/reference/item_details.md +++ b/doc/reference/item_details.md @@ -93,7 +93,7 @@ item has a certain tag: ```lua --- Check if the item in the turtle's inventory is a log. local function is_log(slot) - local ok, block = turtle.getItemDetails(slot, true) + local ok, block = turtle.getItemDetail(slot, true) return ok and block.tags["minecraft:logs"] end ``` diff --git a/projects/common/src/test/java/dan200/computercraft/shared/details/ItemDetailsTest.java b/projects/common/src/test/java/dan200/computercraft/shared/details/ItemDetailsTest.java new file mode 100644 index 000000000..257d86b30 --- /dev/null +++ b/projects/common/src/test/java/dan200/computercraft/shared/details/ItemDetailsTest.java @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: 2025 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.shared.details; + +import dan200.computercraft.api.detail.VanillaDetailRegistries; +import dan200.computercraft.test.core.CustomMatchers; +import dan200.computercraft.test.shared.WithMinecraft; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.Potions; +import org.hamcrest.Matcher; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.contains; + +@WithMinecraft +class ItemDetailsTest { + @BeforeAll + public static void setup() { + VanillaDetailRegistries.ITEM_STACK.addProvider(ItemDetails::fill); + } + + /** + * Test that all potion-imbued items (potions, throwables and arrows) have the correct duration. + */ + @Test + public void testPotionDurations() { + assertThat( + VanillaDetailRegistries.ITEM_STACK.getDetails(PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.LONG_NIGHT_VISION)), + containsEntryWith("potionEffects", contains(allOf(containsEntry("name", "minecraft:night_vision"), containsEntry("duration", 480.0)))) + ); + + assertThat( + VanillaDetailRegistries.ITEM_STACK.getDetails(PotionUtils.setPotion(new ItemStack(Items.LINGERING_POTION), Potions.LONG_NIGHT_VISION)), + containsEntryWith("potionEffects", contains(allOf(containsEntry("name", "minecraft:night_vision"), containsEntry("duration", 120.0)))) + ); + + assertThat( + VanillaDetailRegistries.ITEM_STACK.getDetails(PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), Potions.LONG_NIGHT_VISION)), + containsEntryWith("potionEffects", contains(allOf(containsEntry("name", "minecraft:night_vision"), containsEntry("duration", 480.0)))) + ); + + assertThat( + VanillaDetailRegistries.ITEM_STACK.getDetails(PotionUtils.setPotion(new ItemStack(Items.TIPPED_ARROW), Potions.LONG_NIGHT_VISION)), + containsEntryWith("potionEffects", contains(allOf(containsEntry("name", "minecraft:night_vision"), containsEntry("duration", 60.0)))) + ); + } + + private static Matcher> containsEntry(String key, Object value) { + return CustomMatchers.containsEntry(key, value); + } + + @SuppressWarnings("unchecked") + private static Matcher> containsEntryWith(String key, Matcher value) { + return CustomMatchers.containsEntryWith(key, (Matcher) value); + } +} diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt index c24126db2..a9620bbc0 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt @@ -430,7 +430,7 @@ class Turtle_Test { } /** - * Checks turtles can use IDetailProviders by getting details for a printed page. + * Checks turtles can use [VanillaDetailRegistries.ITEM_STACK] by getting details for a printed page. */ @GameTest fun Item_detail_provider(helper: GameTestHelper) = helper.sequence { diff --git a/projects/core/src/testFixtures/java/dan200/computercraft/test/core/CustomMatchers.java b/projects/core/src/testFixtures/java/dan200/computercraft/test/core/CustomMatchers.java index 679f79258..8841bbf39 100644 --- a/projects/core/src/testFixtures/java/dan200/computercraft/test/core/CustomMatchers.java +++ b/projects/core/src/testFixtures/java/dan200/computercraft/test/core/CustomMatchers.java @@ -5,11 +5,14 @@ package dan200.computercraft.test.core; import org.hamcrest.Matcher; +import org.hamcrest.StringDescription; import java.util.List; +import java.util.Map; import java.util.function.Function; import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.is; public class CustomMatchers { /** @@ -25,4 +28,32 @@ public class CustomMatchers { public static Matcher> containsWith(List items, Function> matcher) { return contains(items.stream().map(matcher).toList()); } + + /** + * An alternative to {@link org.hamcrest.Matchers#hasEntry(Object, Object)}, that acts as a projection, rather than + * searching the map. + * + * @param key The key to extract. + * @param value The expected value. + * @param The type of keys in the map. + * @param The type of values in the map. + * @return A matcher that projects out of a map. + */ + public static Matcher> containsEntry(K key, V value) { + return containsEntryWith(key, is(value)); + } + + /** + * An alternative to {@link org.hamcrest.Matchers#hasEntry(Matcher, Matcher)}, that acts as a projection, rather + * than searching the map. + * + * @param key The key to extract. + * @param value The expected value. + * @param The type of keys in the map. + * @param The type of values in the map. + * @return A matcher that projects out of a map. + */ + public static Matcher> containsEntryWith(K key, Matcher value) { + return ContramapMatcher.contramap(value, new StringDescription().appendValue(key).toString(), x -> x.get(key)); + } }