From 5c81ae93630480dd871f641698d43315425ae2f3 Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Tue, 1 Aug 2023 23:16:11 +1200 Subject: [PATCH 1/2] Add example custom regex with CustomMessages.properties --- .../avaje/composable/MyCustomPattern.java | 10 +++ .../java/example/avaje/composable/MyKey.java | 22 +++++++ .../example/avaje/CustomMessages.properties | 1 + .../avaje/CustomMessages_de.properties | 1 + .../avaje/CustomMessages_en.properties | 1 + .../avaje/composable/MyCustomPatternTest.java | 61 +++++++++++++++++++ 6 files changed, 96 insertions(+) create mode 100644 blackbox-test/src/main/java/example/avaje/composable/MyCustomPattern.java create mode 100644 blackbox-test/src/main/java/example/avaje/composable/MyKey.java create mode 100644 blackbox-test/src/main/resources/example/avaje/CustomMessages.properties create mode 100644 blackbox-test/src/main/resources/example/avaje/CustomMessages_de.properties create mode 100644 blackbox-test/src/main/resources/example/avaje/CustomMessages_en.properties create mode 100644 blackbox-test/src/test/java/example/avaje/composable/MyCustomPatternTest.java diff --git a/blackbox-test/src/main/java/example/avaje/composable/MyCustomPattern.java b/blackbox-test/src/main/java/example/avaje/composable/MyCustomPattern.java new file mode 100644 index 00000000..0c48116d --- /dev/null +++ b/blackbox-test/src/main/java/example/avaje/composable/MyCustomPattern.java @@ -0,0 +1,10 @@ +package example.avaje.composable; + +import io.avaje.validation.constraints.NotBlank; +import io.avaje.validation.constraints.Valid; + +@Valid +public record MyCustomPattern( + @MyKey String key, + @NotBlank String value) { +} diff --git a/blackbox-test/src/main/java/example/avaje/composable/MyKey.java b/blackbox-test/src/main/java/example/avaje/composable/MyKey.java new file mode 100644 index 00000000..b6c4db09 --- /dev/null +++ b/blackbox-test/src/main/java/example/avaje/composable/MyKey.java @@ -0,0 +1,22 @@ +package example.avaje.composable; + +import io.avaje.validation.constraints.Constraint; +import io.avaje.validation.constraints.Pattern; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +@Pattern(regexp = "[A-Z0-9_]{2,8}") +@Constraint +@Retention(SOURCE) +@Target({METHOD, FIELD, ANNOTATION_TYPE, PARAMETER, TYPE_USE}) +public @interface MyKey { + + String message() default "{example.avaje.MyKey.message}"; + + Class[] groups() default {}; +} diff --git a/blackbox-test/src/main/resources/example/avaje/CustomMessages.properties b/blackbox-test/src/main/resources/example/avaje/CustomMessages.properties new file mode 100644 index 00000000..8d175a97 --- /dev/null +++ b/blackbox-test/src/main/resources/example/avaje/CustomMessages.properties @@ -0,0 +1 @@ +example.avaje.MyKey.message=Invalid MyKey diff --git a/blackbox-test/src/main/resources/example/avaje/CustomMessages_de.properties b/blackbox-test/src/main/resources/example/avaje/CustomMessages_de.properties new file mode 100644 index 00000000..bbc2cc33 --- /dev/null +++ b/blackbox-test/src/main/resources/example/avaje/CustomMessages_de.properties @@ -0,0 +1 @@ +example.avaje.MyKey.message=darf nicht MyKey diff --git a/blackbox-test/src/main/resources/example/avaje/CustomMessages_en.properties b/blackbox-test/src/main/resources/example/avaje/CustomMessages_en.properties new file mode 100644 index 00000000..1357f566 --- /dev/null +++ b/blackbox-test/src/main/resources/example/avaje/CustomMessages_en.properties @@ -0,0 +1 @@ +# intentionally blank diff --git a/blackbox-test/src/test/java/example/avaje/composable/MyCustomPatternTest.java b/blackbox-test/src/test/java/example/avaje/composable/MyCustomPatternTest.java new file mode 100644 index 00000000..c79f2279 --- /dev/null +++ b/blackbox-test/src/test/java/example/avaje/composable/MyCustomPatternTest.java @@ -0,0 +1,61 @@ +package example.avaje.composable; + +import io.avaje.validation.ConstraintViolation; +import io.avaje.validation.ConstraintViolationException; +import io.avaje.validation.Validator; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; + +class MyCustomPatternTest { + + final Validator validator = Validator.builder() + .addResourceBundles("example.avaje.CustomMessages") + .addLocales(Locale.GERMAN) + .build(); + + @Test + void valid() { + validator.validate(new MyCustomPattern("SDFS", "Hi")); + validator.validate(new MyCustomPattern("12", "Hi")); + validator.validate(new MyCustomPattern("12345678", "Hi")); + validator.validate(new MyCustomPattern("A234567Z", "Hi")); + validator.validate(new MyCustomPattern("A2_456_Z", "Hi")); + } + + @Test + void notValid() { + var violation = one(new MyCustomPattern("SD*FS", "Hi")); + assertThat(violation.message()).isEqualTo("Invalid MyKey"); + + assertThat(one(new MyCustomPattern("S", "Hi")).message()).isEqualTo("Invalid MyKey"); + assertThat(one(new MyCustomPattern("", "Hi")).message()).isEqualTo("Invalid MyKey"); + assertThat(one(new MyCustomPattern("123456789", "Hi")).message()).isEqualTo("Invalid MyKey"); + } + + @Test + void notValid_DE() { + var violation = one(new MyCustomPattern("SD*FS", "Hi"), Locale.GERMAN); + assertThat(violation.message()).isEqualTo("darf nicht MyKey"); + } + + ConstraintViolation one(Object any) { + return one(any, Locale.ENGLISH); + } + + ConstraintViolation one(Object any, Locale locale) { + try { + validator.validate(any, locale); + fail("not expected"); + return null; + } catch (ConstraintViolationException e) { + var violations = new ArrayList<>(e.violations()); + assertThat(violations).hasSize(1); + return violations.get(0); + } + } +} From 914c0faee800574ad0a5d4ccc39b5b3cacc84451 Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Tue, 1 Aug 2023 23:52:40 +1200 Subject: [PATCH 2/2] Add another example custom regex with length --- .../example/avaje/composable/MySerial.java | 23 ++++++++ .../avaje/composable/MySerialExample.java | 10 ++++ .../example/avaje/CustomMessages.properties | 1 + .../avaje/composable/MySerialTest.java | 58 +++++++++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 blackbox-test/src/main/java/example/avaje/composable/MySerial.java create mode 100644 blackbox-test/src/main/java/example/avaje/composable/MySerialExample.java create mode 100644 blackbox-test/src/test/java/example/avaje/composable/MySerialTest.java diff --git a/blackbox-test/src/main/java/example/avaje/composable/MySerial.java b/blackbox-test/src/main/java/example/avaje/composable/MySerial.java new file mode 100644 index 00000000..e4bab1af --- /dev/null +++ b/blackbox-test/src/main/java/example/avaje/composable/MySerial.java @@ -0,0 +1,23 @@ +package example.avaje.composable; + +import io.avaje.validation.constraints.Constraint; +import io.avaje.validation.constraints.Length; +import io.avaje.validation.constraints.Pattern; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +@Pattern(regexp = "[A-Z]+") +@Length(max = 5) +@Constraint +@Retention(SOURCE) +@Target({METHOD, FIELD, ANNOTATION_TYPE, PARAMETER, TYPE_USE}) +public @interface MySerial { + + String message() default "{example.avaje.MySerial.message}"; + + Class[] groups() default {}; +} diff --git a/blackbox-test/src/main/java/example/avaje/composable/MySerialExample.java b/blackbox-test/src/main/java/example/avaje/composable/MySerialExample.java new file mode 100644 index 00000000..129a7742 --- /dev/null +++ b/blackbox-test/src/main/java/example/avaje/composable/MySerialExample.java @@ -0,0 +1,10 @@ +package example.avaje.composable; + +import io.avaje.validation.constraints.NotBlank; +import io.avaje.validation.constraints.Valid; + +@Valid +public record MySerialExample( + @MySerial String key, + @NotBlank String value) { +} diff --git a/blackbox-test/src/main/resources/example/avaje/CustomMessages.properties b/blackbox-test/src/main/resources/example/avaje/CustomMessages.properties index 8d175a97..58fe813c 100644 --- a/blackbox-test/src/main/resources/example/avaje/CustomMessages.properties +++ b/blackbox-test/src/main/resources/example/avaje/CustomMessages.properties @@ -1 +1,2 @@ example.avaje.MyKey.message=Invalid MyKey +example.avaje.MySerial.message=Invalid my serial diff --git a/blackbox-test/src/test/java/example/avaje/composable/MySerialTest.java b/blackbox-test/src/test/java/example/avaje/composable/MySerialTest.java new file mode 100644 index 00000000..24a6d4e1 --- /dev/null +++ b/blackbox-test/src/test/java/example/avaje/composable/MySerialTest.java @@ -0,0 +1,58 @@ +package example.avaje.composable; + +import io.avaje.validation.ConstraintViolation; +import io.avaje.validation.ConstraintViolationException; +import io.avaje.validation.Validator; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; + +class MySerialTest { + + final Validator validator = Validator.builder() + .addResourceBundles("example.avaje.CustomMessages") + .addLocales(Locale.GERMAN) + .build(); + + @Test + void valid() { + validator.validate(new MySerialExample("A", "Hi")); + validator.validate(new MySerialExample("ABCDE", "Hi")); + } + + @Test + void notValid() { + var violation = one(new MySerialExample("*", "Hi")); + assertThat(violation.message()).isEqualTo("Invalid my serial"); + + assertThat(one(new MySerialExample("ABCDEF", "Hi")).message()).isEqualTo("Invalid my serial"); + assertThat(one(new MySerialExample("", "Hi")).message()).isEqualTo("Invalid my serial"); + assertThat(one(new MySerialExample("123456789", "Hi")).message()).isEqualTo("Invalid my serial"); + } + + @Test + void notValid_DE() { + var violation = one(new MySerialExample("*", "Hi"), Locale.GERMAN); + assertThat(violation.message()).isEqualTo("Invalid my serial"); // not translated for DE + } + + ConstraintViolation one(Object any) { + return one(any, Locale.ENGLISH); + } + + ConstraintViolation one(Object any, Locale locale) { + try { + validator.validate(any, locale); + fail("not expected"); + return null; + } catch (ConstraintViolationException e) { + var violations = new ArrayList<>(e.violations()); + assertThat(violations).hasSize(1); + return violations.get(0); + } + } +}