package games.dmg.spigotstealth; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.nio.file.Files; import java.nio.file.Path; import java.time.Instant; import java.util.Map; import java.util.UUID; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; class YamlStealthStateRepositoryTest { @TempDir Path temporaryDirectory; @Test void missingOrInvalidSleepCountPolicyDefaultsToExclude() throws Exception { Path missingFile = temporaryDirectory.resolve("missing.yml"); YamlStealthStateRepository missing = new YamlStealthStateRepository(missingFile); assertEquals(SleepCountPolicy.EXCLUDE, missing.load().sleepCountPolicy()); Path invalidFile = temporaryDirectory.resolve("invalid.yml"); Files.writeString(invalidFile, "sleep-count-policy: surprise\n"); YamlStealthStateRepository invalid = new YamlStealthStateRepository(invalidFile); assertEquals(SleepCountPolicy.EXCLUDE, invalid.load().sleepCountPolicy()); } @Test void roundTripsUuidStateAndPreservesUnknownFields() throws Exception { UUID playerId = UUID.randomUUID(); Path stateFile = temporaryDirectory.resolve("state.yml"); Files.writeString(stateFile, "schema-version: 1\nsleep-count-policy: include\nfuture-root: keep\nplayers:\n " + playerId + ":\n accumulated-millis: 25\n unlocked: false\n prepared-login: true\n concealed: false\n qualifying-since: '2026-08-14T10:00:00Z'\n last-known-name: Alex\n future-player: keep-too\n"); YamlStealthStateRepository repository = new YamlStealthStateRepository(stateFile); PersistentStealthState loaded = repository.load(); PlayerStealthState player = loaded.player(playerId); assertEquals(SleepCountPolicy.INCLUDE, loaded.sleepCountPolicy()); assertEquals(25L, player.accumulatedMillis()); assertTrue(player.preparedLogin()); assertEquals(Instant.parse("2026-08-14T10:00:00Z"), player.qualifyingSince()); repository.save(loaded.withPlayer(player.withAccumulatedMillis(50L))); String saved = Files.readString(stateFile); assertTrue(saved.contains("future-root: keep")); assertTrue(saved.contains("sleep-count-policy: include")); assertTrue(saved.contains("future-player: keep-too")); assertEquals(50L, repository.load().player(playerId).accumulatedMillis()); } @Test void invalidRecordsCannotGrantProgressOrAbilities() throws Exception { UUID playerId = UUID.randomUUID(); Path stateFile = temporaryDirectory.resolve("state.yml"); Files.writeString(stateFile, "players:\n " + playerId + ":\n accumulated-millis: -1\n unlocked: true\n prepared-login: true\n concealed: true\n"); PlayerStealthState player = new YamlStealthStateRepository(stateFile).load().player(playerId); assertEquals(0L, player.accumulatedMillis()); assertFalse(player.unlocked()); assertFalse(player.preparedLogin()); assertFalse(player.concealed()); } @Test void missingPlayerHasSafeDefaults() { PersistentStealthState state = new PersistentStealthState(Map.of(), Map.of()); PlayerStealthState player = state.player(UUID.randomUUID()); assertEquals(0L, player.accumulatedMillis()); assertFalse(player.unlocked()); } }