This is an automated email from the ASF dual-hosted git repository. lukaszlenart pushed a commit to branch feature/WW-5695-html5-constraint-validation in repository https://gitbox.apache.org/repos/asf/struts.git
commit 584f4064c2df6fe744fbe129f6f14170c965d6fc Author: Lukasz Lenart <[email protected]> AuthorDate: Mon Aug 24 23:36:39 2026 +0200 WW-5695 test(components): pin the constraint hook's evaluateExtraParams ordering Adds a discriminating test: a stringlength validator on an explicit type="number" control must not emit minlength, since minlength is only legal once TextField.evaluateExtraParams() has resolved the control type. The prior two tests could not tell a correctly-placed hook from one hoisted to the tagNames block, because an untyped field resolves to TEXT either way. Also rewords the javadoc/properties comment for struts.ui.html5.constraints to stop committing to a specific future version number; the release version is chosen at release time, not baked into 7.4.0-SNAPSHOT. Co-Authored-By: Claude Opus 5 <[email protected]> --- .../java/org/apache/struts2/StrutsConstants.java | 2 +- .../org/apache/struts2/default.properties | 3 ++- .../components/ConstraintAttributesTest.java | 27 +++++++++++++++++++--- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java b/core/src/main/java/org/apache/struts2/StrutsConstants.java index 105c02a62..ffc135f0b 100644 --- a/core/src/main/java/org/apache/struts2/StrutsConstants.java +++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java @@ -205,7 +205,7 @@ public final class StrutsConstants { /** * Whether the html5 theme emits HTML5 constraint attributes derived from the action's validators. - * Defaults to false in 7.4.0; the default becomes true in 8.0.0. + * Defaults to {@code false}; the default is expected to flip in a future major release. * * @since 7.4.0 */ diff --git a/core/src/main/resources/org/apache/struts2/default.properties b/core/src/main/resources/org/apache/struts2/default.properties index 956862835..a35001534 100644 --- a/core/src/main/resources/org/apache/struts2/default.properties +++ b/core/src/main/resources/org/apache/struts2/default.properties @@ -173,7 +173,8 @@ struts.ui.templateSuffix=ftl ### Whether the html5 theme emits HTML5 constraint attributes (required, minlength, ### maxlength, pattern, min, max) derived from the action's validators. -### Defaults to false so existing html5-theme forms render unchanged; becomes true in 8.0.0. +### Defaults to false so existing html5-theme forms render unchanged; the default is +### expected to flip in a future major release. struts.ui.html5.constraints=false ### Sets a global flag which will escape html body of Anchor, Submit and Component tag diff --git a/core/src/test/java/org/apache/struts2/components/ConstraintAttributesTest.java b/core/src/test/java/org/apache/struts2/components/ConstraintAttributesTest.java index d596d34e5..10dac32fe 100644 --- a/core/src/test/java/org/apache/struts2/components/ConstraintAttributesTest.java +++ b/core/src/test/java/org/apache/struts2/components/ConstraintAttributesTest.java @@ -33,19 +33,37 @@ public class ConstraintAttributesTest extends AbstractUITagTest { public void testNoConstraintsWhenTheConstantIsOff() throws Exception { initDispatcherWith("false"); - assertNull(renderFieldAndReturnConstraints()); + assertNull(renderFieldAndReturnConstraints(null)); } public void testConstraintsWhenTheConstantIsOn() throws Exception { initDispatcherWith("true"); - Map<String, String> constraints = renderFieldAndReturnConstraints(); + Map<String, String> constraints = renderFieldAndReturnConstraints(null); assertNotNull("expected constraints to be populated", constraints); assertEquals("3", constraints.get("minlength")); } + /** + * Pins the hook to running after {@code evaluateExtraParams()}. A {@code stringlength} validator on + * a control the browser treats as numeric must not emit {@code minlength} at all — that attribute + * is not legal there. This can only resolve correctly if the control type ({@code type="number"}, + * resolved by {@code TextField.evaluateExtraParams()}) is already known when the constraint hook + * fires. Untyped text fields resolve to {@code TEXT} either way, so + * {@link #testConstraintsWhenTheConstantIsOn()} alone cannot distinguish a correctly-placed hook + * from one hoisted up to the {@code tagNames} block. + */ + public void testConstraintsRespectAnExplicitInputType() throws Exception { + initDispatcherWith("true"); + + Map<String, String> constraints = renderFieldAndReturnConstraints("number"); + + assertTrue("expected minlength to be suppressed for a numeric control", + constraints == null || !constraints.containsKey("minlength")); + } + @SuppressWarnings("unchecked") - private Map<String, String> renderFieldAndReturnConstraints() throws Exception { + private Map<String, String> renderFieldAndReturnConstraints(String type) throws Exception { FormTag form = new FormTag(); form.setPageContext(pageContext); form.setAction("constraintAction"); @@ -55,6 +73,9 @@ public class ConstraintAttributesTest extends AbstractUITagTest { TextFieldTag field = new TextFieldTag(); field.setPageContext(pageContext); field.setName("username"); + if (type != null) { + field.setType(type); + } field.doStartTag(); Map<String, Object> attributes =
