package p.packer.services; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import p.packer.messages.assets.AssetFamilyCatalog; import p.packer.messages.assets.OutputCodecCatalog; import p.packer.messages.diagnostics.PackerDiagnosticCategory; import p.packer.testing.PackerFixtureLocator; import java.nio.file.Files; import java.nio.file.Path; import static org.junit.jupiter.api.Assertions.*; final class PackerAssetDeclarationParserTest { private final PackerAssetDeclarationParser parser = new PackerAssetDeclarationParser(); @TempDir Path tempDir; @Test void parsesValidDeclarationFixture() { final var result = parser.parse(PackerFixtureLocator.fixtureRoot("workspaces/managed-basic/assets/ui/atlas/asset.json")); assertTrue(result.valid()); assertNotNull(result.declaration()); assertEquals(1, result.declaration().schemaVersion()); assertEquals("fixture-uuid-1", result.declaration().assetUuid()); assertEquals("ui_atlas", result.declaration().name()); assertEquals(AssetFamilyCatalog.IMAGE_BANK, result.declaration().assetFamily()); assertEquals("TILES/indexed_v1", result.declaration().outputFormat().displayName()); assertEquals(OutputCodecCatalog.NONE, result.declaration().outputCodec()); assertTrue(result.declaration().preloadEnabled()); } @Test void rejectsMalformedJsonWithStructuralDiagnostic() { final var result = parser.parse(PackerFixtureLocator.fixtureRoot("workspaces/invalid-malformed/assets/bad/asset.json")); assertFalse(result.valid()); assertNull(result.declaration()); assertTrue(result.diagnostics().stream().anyMatch(diagnostic -> diagnostic.category() == PackerDiagnosticCategory.STRUCTURAL)); } @Test void rejectsMissingRequiredFields() { final var result = parser.parse(PackerFixtureLocator.fixtureRoot("workspaces/invalid-missing-fields/assets/bad/asset.json")); assertFalse(result.valid()); assertTrue(result.diagnostics().stream().anyMatch(diagnostic -> diagnostic.message().contains("name"))); assertTrue(result.diagnostics().stream().anyMatch(diagnostic -> diagnostic.message().contains("asset_uuid"))); assertTrue(result.diagnostics().stream().anyMatch(diagnostic -> diagnostic.message().contains("format"))); } @Test void rejectsUnsupportedSchemaVersion() { final var result = parser.parse(PackerFixtureLocator.fixtureRoot("workspaces/invalid-version/assets/bad/asset.json")); assertFalse(result.valid()); assertTrue(result.diagnostics().stream().anyMatch(diagnostic -> diagnostic.category() == PackerDiagnosticCategory.VERSIONING)); } @Test void rejectsUntrustedInputPaths() throws Exception { final Path manifest = tempDir.resolve("asset.json"); Files.writeString(manifest, """ { "schema_version": 1, "asset_uuid": "uuid-outside", "name": "bad_asset", "type": "image_bank", "inputs": { "sprites": ["../outside.png"] }, "output": { "format": "TILES/indexed_v1", "codec": "NONE" }, "preload": { "enabled": true } } """); final var result = parser.parse(manifest); assertFalse(result.valid()); assertTrue(result.diagnostics().stream().anyMatch(diagnostic -> diagnostic.message().contains("untrusted path"))); } @Test void rejectsUnknownAssetFamily() throws Exception { final Path manifest = tempDir.resolve("asset.json"); Files.writeString(manifest, """ { "schema_version": 1, "asset_uuid": "uuid-video", "name": "bad_asset", "type": "video_bank", "inputs": { "sprites": ["atlas.png"] }, "output": { "format": "TILES/indexed_v1", "codec": "NONE" }, "preload": { "enabled": true } } """); final var result = parser.parse(manifest); assertFalse(result.valid()); assertTrue(result.diagnostics().stream().anyMatch(diagnostic -> diagnostic.message().contains("Field 'type' must be one of"))); } }