package de.neitzel.fxdesigner.target; import static org.junit.jupiter.api.Assertions.*; import de.neitzel.fx.view.ViewModelClass; import java.util.*; import javafx.beans.property.*; import javafx.scene.layout.HBox; import org.junit.jupiter.api.Test; class TableDiscoveryTest { public static class Item { static { System.setProperty("table.item.initialized", "yes"); } public String getStreet() { throw new AssertionError(); } public void setStreet(String v) {} public int getNumber() { throw new AssertionError(); } public void setNumber(int v) {} public Item getNested() { throw new AssertionError(); } public void setNested(Item v) {} public char getLetter() { throw new AssertionError(); } public void setLetter(char v) {} public String getReadOnly() { throw new AssertionError(); } } public static class Model { static { System.setProperty("table.model.initialized", "yes"); } public List getItems() { throw new AssertionError(); } public void setItems(List v) {} public List getRaw() { throw new AssertionError(); } public void setRaw(List v) {} public String getName() { throw new AssertionError(); } public void setName(String v) {} } public static class TableRow extends HBox { static { System.setProperty("table.row.initialized", "yes"); } public ObjectProperty modelProperty() { throw new AssertionError(); } } public static class UnknownRow extends HBox { public ObjectProperty modelProperty() { throw new AssertionError(); } } public static class DuplicateRow extends TableRow {} public static class BeanModel extends Model {} public static class BeanModelBeanInfo extends java.beans.SimpleBeanInfo { static { System.setProperty("table.beaninfo.initialized", "yes"); } public BeanModelBeanInfo() { throw new AssertionError("BeanInfo executed"); } } public static class Replacement { public Replacement(Model m) { throw new AssertionError(); } public ListProperty itemsProperty() { throw new AssertionError(); } } @ViewModelClass(Replacement.class) public static class Controller {} private String xml(String path, String row, String cols, String controller) { return "" + "" + cols + "
"; } private String col(String attr) { return ""; } private de.neitzel.fxdesigner.protocol.BindingMetadata inspect( String path, Class row, String cols, String controller) throws Exception { return BindingDiscovery.inspect( xml(path, row.getName(), cols, controller), path, "view", getClass().getClassLoader()); } @Test void discoversTableTypesAndDeclaredAlignmentWithoutInitialization() throws Exception { var m = inspect("items", TableRow.class, col("street") + col("number"), ""); assertTrue( m.problems().stream().noneMatch(p -> p.severity().equals("ERROR")), m.problems().toString()); assertTrue( m.problems().stream() .anyMatch(p -> p.property().equals("alignment") && p.severity().equals("INFO"))); assertTrue( m.tableColumns().stream() .anyMatch(c -> c.name().equals("street") && c.status().equals("COMPATIBLE"))); for (String name : List.of("nested", "letter", "readOnly")) assertTrue( m.tableColumns().stream() .anyMatch(c -> c.name().equals(name) && c.status().equals("INCOMPATIBLE"))); for (String key : List.of("table.model.initialized", "table.item.initialized", "table.row.initialized")) assertNull(System.getProperty(key)); } @Test void warnsOnReorderedAndUnknownFieldsWithoutChangingXml() throws Exception { var mismatch = inspect("items", TableRow.class, col("number") + col("street"), ""); assertTrue( mismatch.problems().stream() .anyMatch(p -> p.severity().equals("WARNING") && p.message().contains("mismatch"))); var unknown = inspect("items", UnknownRow.class, col("street"), ""); assertTrue( unknown.problems().stream() .anyMatch(p -> p.property().equals("alignment") && p.message().contains("unverified"))); } @Test void keepsCustomBeanInfoAndDuplicateFieldIdsUnverified() throws Exception { String text = xml("items", TableRow.class.getName(), col("street"), "") .replace(Model.class.getName(), BeanModel.class.getName()); var bean = BindingDiscovery.inspect(text, "items", "view", getClass().getClassLoader()); assertTrue( bean.problems().stream() .anyMatch(p -> p.property().equals("collection") && p.severity().equals("WARNING"))); assertNull(System.getProperty("table.beaninfo.initialized")); var duplicate = inspect("items", DuplicateRow.class, col("street"), ""); assertTrue( duplicate.problems().stream() .anyMatch( p -> p.property().equals("alignment") && p.message().contains("unique fx:id"))); } @Test void rejectsMissingComplexReadOnlyAndUnsupportedScalarAttributes() throws Exception { for (String name : List.of("absent", "nested", "letter", "readOnly", "nested.street")) { var m = inspect("items", TableRow.class, col(name), ""); assertTrue( m.problems().stream() .anyMatch(p -> p.property().equals("columns") && p.severity().equals("ERROR")), name); } } @Test void tableNeedsBeanMetadataEvenWhenReplacementHasListProperty() throws Exception { var m = inspect("items", TableRow.class, col("street"), Controller.class.getName()); assertTrue( m.problems().stream() .anyMatch(p -> p.property().equals("collection") && p.severity().equals("ERROR"))); for (String path : List.of("raw", "name", "missing", "items.street")) assertTrue( inspect(path, TableRow.class, col("street"), "").problems().stream() .anyMatch(p -> p.property().equals("collection") && p.severity().equals("ERROR")), path); } @Test void rejectsWrongRowModelAndKeepsUnknownSourceSyntaxUnverified() throws Exception { var wrong = inspect("items", RepeatDiscoveryTest.Wrong.class, col("street"), ""); assertTrue( wrong.problems().stream() .anyMatch(p -> p.property().equals("row") && p.severity().equals("ERROR"))); var nested = inspect("items", TableRow.class, "street", ""); assertTrue(nested.problems().stream().anyMatch(p -> p.message().contains("Nested Column"))); } }