Skip to content

Commit 0424db8

Browse files
authored
Merge pull request #3 from metaobjectsdev/feat/fr019-cross-port
test(codegen-spring): pin TPH enum-@Discriminator as enum-typed
2 parents d33beb7 + 47e2629 commit 0424db8

1 file changed

Lines changed: 65 additions & 0 deletions

File tree

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.metaobjects.generator.spring;
2+
3+
import com.metaobjects.loader.MetaDataLoader;
4+
import com.metaobjects.registry.SharedRegistryTestBase;
5+
import org.junit.Rule;
6+
import org.junit.Test;
7+
import org.junit.rules.TemporaryFolder;
8+
9+
import java.io.IOException;
10+
import java.nio.file.Files;
11+
import java.nio.file.Path;
12+
import java.util.HashMap;
13+
import java.util.Map;
14+
15+
import static org.junit.Assert.assertFalse;
16+
import static org.junit.Assert.assertTrue;
17+
18+
/**
19+
* FR-017 / typed-enum coherence guard: a TPH {@code @discriminator} that is declared
20+
* {@code field.enum} MUST be typed in the generated DTO as the value-constrained enum (the
21+
* cross-port typed-enum contract — TS string-literal union, Python {@code Literal}, C#/Kotlin/Java
22+
* enum), NEVER as a raw {@code String}.
23+
*
24+
* <p>This is otherwise only exercised end-to-end by the docker-gated api-contract TPH corpus, where
25+
* a regression to a {@code String}-typed discriminator would slip past the HTTP/JSON-seeding ports
26+
* (it deserializes fine) and only break the direct-constructing Java lane. This fast unit-level
27+
* assertion pins the static type so the discriminator can't silently regress to {@code String}.
28+
* Loads the SAME shared fixture the integration lane uses
29+
* ({@code fixtures/api-contract-conformance/tph/meta.json}: TPH base {@code Auth} with a
30+
* {@code field.enum type} discriminator over {@code Bridge|Copay|PriorAuth}).</p>
31+
*/
32+
public class TphDiscriminatorEnumConformanceTest extends SharedRegistryTestBase {
33+
34+
@Rule
35+
public TemporaryFolder tmp = new TemporaryFolder();
36+
37+
@Test
38+
public void tphEnumDiscriminatorIsTypedAsTheEnumNotString() throws Exception {
39+
Path repoRoot = Path.of(System.getProperty("user.dir")).resolve("../../..").normalize();
40+
Path fixture = repoRoot.resolve("fixtures/api-contract-conformance/tph/meta.json");
41+
assertTrue("shared TPH fixture must exist at " + fixture, Files.exists(fixture));
42+
MetaDataLoader loader = SpringTestFixtures.loadFixture(
43+
tmp.newFolder().toPath(), "tphDiscriminatorEnum", Files.readString(fixture));
44+
45+
Path out = tmp.newFolder().toPath();
46+
Map<String, String> args = new HashMap<>();
47+
args.put("outputDir", out.toString());
48+
SpringDtoGenerator gen = new SpringDtoGenerator();
49+
gen.setArgs(args);
50+
gen.execute(loader);
51+
52+
// The TPH base's union DTO carries the discriminator.
53+
Path dto = out.resolve("acme/auth/AuthDto.java");
54+
assertTrue("AuthDto.java must be emitted", Files.exists(dto));
55+
String src = Files.readString(dto);
56+
57+
// The discriminator component is the value-constrained enum, not a bare String.
58+
assertTrue("the @discriminator field.enum must be typed as the generated enum; saw:\n" + src,
59+
src.contains("AuthType type"));
60+
assertTrue("the discriminator enum must be materialized with its @values; saw:\n" + src,
61+
src.contains("public enum AuthType { Bridge, Copay, PriorAuth }"));
62+
assertFalse("the @discriminator must NOT regress to a raw String component; saw:\n" + src,
63+
src.contains("String type"));
64+
}
65+
}

0 commit comments

Comments
 (0)