Files
JIMRI/java/test/jmri/util/ValidatingInputPaneTest.java
T
2026-06-17 14:00:51 +02:00

239 lines
7.7 KiB
Java

package jmri.util;
import java.awt.BorderLayout;
import java.awt.GraphicsEnvironment;
import java.util.concurrent.Callable;
import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import jmri.util.junit.annotations.DisabledIfHeadless;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
*
* @author Svata Dedic Copyright (c) 2019
*/
public class ValidatingInputPaneTest {
/**
* Checks that inconvertible input produces an error message.
*/
@Test
public void testInconvertibleInputFails() {
ValidatingInputPane<Integer> intValidator = new ValidatingInputPane<>((s) -> Integer.parseInt(s));
intValidator.validateText("nonInteger");
assertTrue( intValidator.hasError(), "Non-number must produce error");
NumberFormatException ex = assertInstanceOf(NumberFormatException.class, intValidator.getException());
assertNotNull( ex, "Converter exception expected");
}
/**
* Empty input should be accepted as no-op
*/
@Test
public void testEmptyInputOK() {
ValidatingInputPane<Integer> intValidator = new ValidatingInputPane<>((s) -> Integer.parseInt(s));
intValidator.validateText("");
assertFalse( intValidator.hasError(), "Empty string must be accepted");
}
@Test
public void testValidationRejects() {
ValidatingInputPane<Integer> intValidator = new ValidatingInputPane<>((s) -> Integer.parseInt(s));
intValidator.validator((i) -> i >= 5);
intValidator.validateText("3");
assertTrue( intValidator.hasError(), "Bad number should produce error");
assertNull( intValidator.getException(), "Validator rejection does not record an exception");
assertEquals( Bundle.getMessage("InputDialogError"), intValidator.getErrorMessage(), "General message expected");
}
@Test
public void testValidationPasses() {
ValidatingInputPane<Integer> intValidator = new ValidatingInputPane<>((s) -> Integer.parseInt(s));
intValidator.validator((i) -> i >= 5);
intValidator.validateText("6");
assertFalse( intValidator.hasError(), "Validation must pass");
assertNull( intValidator.getException(), "Exception must be null on OK result");
assertNull( intValidator.getErrorMessage(), "No message for OK result");
}
@Test
public void testValidationThrowsCustomMessage() {
setupLargeValidator();
// now should fail:
intValidator.validateText("6");
assertNotNull( intValidator.getException(), "Exception must non-null");
assertEquals( "Large", intValidator.getException().getMessage(), "Exception must non-null");
assertEquals( "Large", intValidator.getErrorMessage(), "Invalid message");
// should pass
intValidator.validateText("3");
assertNull( intValidator.getErrorMessage(), "Message must be null on successful validation");
assertFalse( intValidator.hasError(), "No error must be indicated");
}
private ValidatingInputPane<Integer> intValidator;
private JButton control;
private void setupLargeValidator() {
setupLargeValidator(false);
}
private void setupLargeValidator(boolean useControl) {
intValidator = new ValidatingInputPane<>((s) -> Integer.parseInt(s));
if (useControl) {
control = new JButton("OK");
intValidator = intValidator.attachConfirmUI(control);
}
intValidator.validator((i) -> {
if (i >= 5) {
throw new IllegalArgumentException("Large");
}
return true;
});
}
@Test
public void testErrorStatusClearedAfterCorrection() {
setupLargeValidator();
// now should fail:
intValidator.validateText("6");
assertNotNull( intValidator.getException(), "Exception must non-null");
// should pass
intValidator.validateText("3");
assertNull( intValidator.getErrorMessage(), "Message must be null on successful validation");
assertFalse( intValidator.hasError(), "No error must be indicated");
}
/**
* Wraps the tested panel into a Window and makes it visible. Runs the
* Callable in EDT to properly process UI. Terminate
* the test without failure in headless env.
*/
private <T> void testInGUI(Callable<T> check) throws Exception {
// terminate tests which require GUI
assertFalse(GraphicsEnvironment.isHeadless());
// display the panel
JWindow dlg = new JWindow();
dlg.setLayout(new BorderLayout());
dlg.add(intValidator, BorderLayout.CENTER);
if (control != null) {
dlg.add(control, BorderLayout.SOUTH);
}
dlg.setVisible(true);
Exception[] out = new Exception[1];
SwingUtilities.invokeAndWait(() -> {
try {
check.call();
} catch (Exception ex) {
out[0] = ex;
}
});
dlg.dispose();
if (out[0] != null) {
throw out[0];
}
}
@Test
@DisabledIfHeadless
public void testValidationHappensWhenAfterDisplayed() throws Exception {
setupLargeValidator();
intValidator.setText("6");
// no validation yet.
assertNull(intValidator.getErrorMessage());
testInGUI(() -> {
assertTrue(intValidator.hasError());
return null;
});
}
@Test
@DisabledIfHeadless
public void testTextChangeValidatesFalse() throws Exception {
setupLargeValidator();
intValidator.setText("3");
// no validation yet.
assertNull(intValidator.getErrorMessage());
testInGUI(() -> {
assertFalse(intValidator.hasError());
JTextField input = intValidator.getTextField();
input.getDocument().insertString(1, "3", null);
// now the text should be validated and error message present
assertTrue(intValidator.hasError());
assertNotNull(intValidator.getException());
return null;
});
}
@Test
@DisabledIfHeadless
public void testClearAllNoError() throws Exception {
setupLargeValidator();
intValidator.setText("6");
// no validation yet.
assertNull(intValidator.getErrorMessage());
testInGUI(() -> {
assertTrue(intValidator.hasError());
JTextField input = intValidator.getTextField();
input.setSelectionStart(0);
input.setSelectionEnd(1);
// should clear the text
input.replaceSelection("");
// now the text should be validated and error message present
assertFalse(intValidator.hasError());
assertNull(intValidator.getException());
return null;
});
}
@Test
@DisabledIfHeadless
public void testControlBecomesDisabled() throws Exception {
setupLargeValidator(true);
intValidator.setText("4");
testInGUI(() -> {
assertTrue(control.isEnabled());
intValidator.getTextField().replaceSelection("44");
assertFalse(control.isEnabled());
return null;
});
}
@BeforeEach
public void setUp() {
JUnitUtil.setUp();
}
@AfterEach
public void tearDown() {
JUnitUtil.resetWindows(false, false);
JUnitUtil.tearDown();
}
}