diff --git a/CONVENTIONS.md b/CONVENTIONS.md index 2eadf3ff..58769be8 100644 --- a/CONVENTIONS.md +++ b/CONVENTIONS.md @@ -52,8 +52,12 @@ with `isValid()` rather than refusing the value at set time. Refuse a value only when the real control physically cannot produce it: a slider clamps to its range and snaps to its step, so `RangeInputTester` and -`NumberSliderTester` do reject out-of-range and off-step values. Structural -refusals stay too, such as `null` on a field whose empty value is not `null`. +`NumberSliderTester` do reject out-of-range and off-step values, and a text +input truncates at `maxLength` and filters the keystrokes `allowedCharPattern` +does not match, so `TextFieldTester` and `TextAreaTester` reject a value that +breaks either one. `minLength`, `pattern` and required are validation-only and +keep committing an invalid value. Structural refusals stay too, such as `null` +on a field whose empty value is not `null`. Read-only state counts towards usability. `isUsable()` is enabled + attached + effectively visible + not inert + not read-only, and effective visibility walks diff --git a/guidelines/testers.md b/guidelines/testers.md index f5865e1c..7e0faf9d 100644 --- a/guidelines/testers.md +++ b/guidelines/testers.md @@ -81,9 +81,20 @@ for it — not enforced at set time. The exception is a control that physically cannot produce the value: a slider clamps to its range and snaps to its step, so `RangeInputTester` and -`NumberSliderTester` do refuse out-of-range and off-step values. Structural +`NumberSliderTester` do refuse out-of-range and off-step values. A text input +truncates what is over `maxLength` and filters out the keystrokes +`allowedCharPattern` does not match, so `TextFieldTester` and `TextAreaTester` +refuse a value that breaks either one — while `minLength`, `pattern` and +required stay validation-only and keep committing an invalid value. Structural refusals stay too, such as `null` on a field whose empty value is not `null`. +Where the line falls is a question about the control, not about the constraint: +ask whether a user sitting in front of the component could hand the field that +value at all. When they could not, refuse it with an `IllegalArgumentException` +whose message says what the browser does instead, rather than silently +correcting the value — a test that asks for the impossible has a bug in it, and +truncating or clamping behind its back would hide it. + `isValid()` means "not marked invalid, and the current value passes the component's own default validator" — it delegates to `getDefaultValidator()` rather than re-checking required / `min` / `max` / `step` by hand. Re-checking diff --git a/junit6/src/test/java/com/vaadin/flow/component/textfield/TextAreaTesterTest.java b/junit6/src/test/java/com/vaadin/flow/component/textfield/TextAreaTesterTest.java index 43f007b2..3960ecf3 100644 --- a/junit6/src/test/java/com/vaadin/flow/component/textfield/TextAreaTesterTest.java +++ b/junit6/src/test/java/com/vaadin/flow/component/textfield/TextAreaTesterTest.java @@ -93,26 +93,33 @@ public void nonInteractableField_throwsOnSetValue() { @Test void textAreaWithValidation_doNotPreventInvalid_doNotThrow() { // Only accept numbers - view.textArea.setAllowedCharPattern("\\d*"); + view.textArea.setPattern("\\d*"); final TextAreaTester