Skip to content

Commit

Permalink
36: Allow multiple check methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Lichtenberger committed Feb 29, 2024
1 parent 3f42354 commit 61d4982
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 17 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ build
bin
.settings
*~

# Ignore IntelliJ stuff
/.idea
13 changes: 9 additions & 4 deletions src/main/java/net/synedra/validatorfx/Check.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
public class Check {

private Map<String, ObservableValue<? extends Object>> dependencies = new HashMap<>(1);
private Consumer<Context> checkMethod;
private List<Consumer<Context>> checkMethods = new ArrayList<>();
private ReadOnlyObjectWrapper<ValidationResult> validationResultProperty = new ReadOnlyObjectWrapper<>();
private ValidationResult nextValidationResult = new ValidationResult();
private List<Node> targets = new ArrayList<>(1);
Expand Down Expand Up @@ -66,9 +66,13 @@ public Check() {
validationResultProperty.set(new ValidationResult());
decorationFactory = DefaultDecoration.getFactory();
}


/** Add a method to be called in order to perform this check.
* If called multiple times, multiple check methods can be registered.
* @param checkMethod The code to be called in order to check the validity of this Check.
*/
public Check withMethod(Consumer<Context> checkMethod) {
this.checkMethod = checkMethod;
checkMethods.add(checkMethod);
return this;
}

Expand Down Expand Up @@ -138,7 +142,8 @@ private void removeListener(ChangeListener<? super Object> listener) {
/** Evaluate all dependencies and apply decorations of this check. You should not normally need to call this method directly. */
public void recheck() {
nextValidationResult = new ValidationResult();
checkMethod.accept(new Context());
Context context = new Context();
checkMethods.forEach(checkMethod -> checkMethod.accept(context));
removeDecorations();
for (Node target : targets) {
for (ValidationMessage validationMessage : nextValidationResult.getMessages()) {
Expand Down
56 changes: 46 additions & 10 deletions src/test/java/net/synedra/validatorfx/CheckTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@
@ExtendWith(ApplicationExtension.class)
class CheckTest {

private static String WARNING = "This is a warning.";
private static final String WARNING = "This is a warning.";

private TextField textfield;

@Start
private void setupScene(Stage stage) {
textfield = new TextField();
stage.setScene(new Scene(new StackPane(textfield), 100, 100));
stage.show();
stage.show();
}

@Test
Expand Down Expand Up @@ -84,12 +84,45 @@ void testImmediateClear() {
c.recheck();
checkMessage(c, Severity.ERROR, "Must not be bar");
}



private void check2(Check.Context c) {
c.error("Must not be " + c.get("content"));
}


@Test
void testMultipleMethods() {
StringProperty text = new SimpleStringProperty("foo");
Check c = new Check()
.withMethod(this::mustNotBeEmpty)
.withMethod(this::checkLength)
.dependsOn("text", text);

checkNoMessage(c);
text.set(" ");
c.recheck();
checkMessage(c, Severity.ERROR, "Cannot be empty");
text.set("12345678901");
c.recheck();
checkMessage(c, Severity.ERROR, "Too long");
text.set(" ");
c.recheck();
checkMessage(c, Severity.ERROR, "Cannot be empty", "Too long");
}

private void mustNotBeEmpty(Check.Context c) {
String text = c.get("text");
if (text.trim().isEmpty()) {
c.error("Cannot be empty");
}
}

private void checkLength(Check.Context c) {
String text = c.get("text");
if (text.length() > 10) {
c.error("Too long");
}
}

@Test
void testTextFieldMaxLength(FxRobot robot) {
Check c = new Check()
Expand Down Expand Up @@ -118,11 +151,14 @@ private void check3(Check.Context c) {
}
}

private void checkMessage(Check c, Severity severity, String text) {
private void checkMessage(Check c, Severity severity, String ... texts) {
List<ValidationMessage> messages = c.getValidationResult().getMessages();
assertEquals(1, messages.size());
assertEquals(text, messages.get(0).getText());
assertEquals(severity, messages.get(0).getSeverity());
assertEquals(texts.length, messages.size());
for (int i = 0; i < texts.length; i++) {
assertEquals(texts[i], messages.get(i).getText());
assertEquals(severity, messages.get(i).getSeverity());

}
}

private void checkNoMessage(Check c) {
Expand Down
16 changes: 13 additions & 3 deletions src/test/java/net/synedra/validatorfx/demo/LateImmediateDemo.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.synedra.validatorfx.demo;

import java.util.Arrays;
import java.util.function.Consumer;

import javafx.application.Application;
import javafx.event.ActionEvent;
Expand All @@ -19,6 +20,7 @@
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import net.synedra.validatorfx.Check;
import net.synedra.validatorfx.DefaultDecoration;
import net.synedra.validatorfx.Validator;

Expand Down Expand Up @@ -62,6 +64,7 @@ public void start(Stage primaryStage) throws Exception {
c.error("Username is required.");
}
})
.withMethod(required("username"))
.dependsOn("username", userTextField.textProperty())
.decorates(userTextField)
;
Expand All @@ -71,10 +74,8 @@ public void start(Stage primaryStage) throws Exception {
if (!c.get("password").equals(c.get("passwordConfirmation"))) {
c.error("Passwords do not match");
}
if (((String) c.get("password")).isBlank()) {
c.error("Password is required.");
}
})
.withMethod(required("password"))
.dependsOn("password", password.textProperty())
.dependsOn("passwordConfirmation", passwordConfirmation.textProperty())
.decorates(password)
Expand All @@ -97,6 +98,15 @@ public void start(Stage primaryStage) throws Exception {
primaryStage.show();
}

private Consumer<Check.Context> required(String key) {
return c -> {
String text = c.get(key);
if (text.trim().isEmpty()) {
c.error(key + " cannot be empty");
}
};
}

private GridPane createGrid() {
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
Expand Down

0 comments on commit 61d4982

Please sign in to comment.