package ar.com.companeros.suggestions; import ar.com.companeros.Companeros; import com.google.gson.*; import java.nio.file.*; import java.util.UUID; import net.minecraft.gametest.framework.*; import net.minecraftforge.gametest.*; import net.minecraftforge.fml.loading.FMLPaths; /** Borradores persistentes con autor real, límites y ninguna ruta elegida por el modelo. */ @GameTestHolder(Companeros.ID) @PrefixGameTestTemplate(false) public final class SuggestionTests { @GameTest(template="empty", batch="suggestions_metadata", timeoutTicks=30) public void developerDraftPreservesAuthorshipAndRemainsText(GameTestHelper helper) throws Exception { Path root = FMLPaths.CONFIGDIR.get().resolve("raps-tests-suggestions-" + UUID.randomUUID()).toAbsolutePath().normalize(); UUID author = UUID.randomUUID(); var store = new SuggestionStore(root); String request = "{\"title\":\"Un evento nocturno\",\"kind\":\"event\",\"description\":\"Falta una capacidad para luces del mod\",\"language\":\"python\",\"source\":\"raise RuntimeError('este borrador no se ejecuta')\"}"; Path folder = store.submit(author, "Fermi", "minecraft:overworld 1, 64, 2", request, System.currentTimeMillis()); JsonObject record = JsonParser.parseString(Files.readString(folder.resolve("proposal.json"))).getAsJsonObject(); helper.assertTrue(record.get("authorUuid").getAsString().equals(author.toString()) && record.get("status").getAsString().equals("pending_review"), "Autor y estado proceden del servidor"); helper.assertTrue(Files.readString(folder.resolve("proposal.md")).contains("Fermi") && Files.exists(folder.resolve("draft.python.txt")) && !Files.exists(folder.resolve("draft.py")), "El código se conserva como texto para revisión"); helper.succeed(); } @GameTest(template="empty", batch="suggestions_limits", timeoutTicks=30) public void rejectsPathsForgedAuthorsAndPersistentSpam(GameTestHelper helper) throws Exception { Path root = FMLPaths.CONFIGDIR.get().resolve("raps-tests-suggestions-" + UUID.randomUUID()).toAbsolutePath().normalize(); UUID author = UUID.randomUUID(); long now = System.currentTimeMillis(); String request = "{\"title\":\"Más piezas\",\"kind\":\"capability\",\"description\":\"Quiero una nueva articulación\"}"; new SuggestionStore(root).submit(author, "Curio", "base", request, now); boolean limited=false, protectedPath=false; try { new SuggestionStore(root).submit(author, "Curio", "base", request, now+1000); } catch (IllegalArgumentException expected) { limited=true; } JsonObject forged=JsonParser.parseString(request).getAsJsonObject(); forged.addProperty("path", "../../fuera.py"); forged.addProperty("author", "Admin"); try { new SuggestionStore(root).submit(UUID.randomUUID(), "Curio", "base", forged.toString(), now); } catch (IllegalArgumentException expected) { protectedPath=true; } helper.assertTrue(limited && protectedPath, "Reabrir el almacén no elimina límites ni permite seleccionar rutas o autores"); helper.assertTrue(new SuggestionStore(root).submit(author, "Curio", "base", request, now+301000).startsWith(root), "Tras cinco minutos se acepta otro pedido dentro de la carpeta autorizada"); helper.succeed(); } }