BaseWicketTester's simulated AJAX form submissions don't include Radio values
-----------------------------------------------------------------------------

                 Key: WICKET-1451
                 URL: https://issues.apache.org/jira/browse/WICKET-1451
             Project: Wicket
          Issue Type: Bug
            Reporter: David Shepherdson


When submitting a form by AJAX, the BaseWicketTester goes through all the form 
components to make sure their values are stored in the request. However, 
because Radios are not instances of FormComponent, and because the code skips 
RadioGroups, the values for radio buttons are not stored in the request. This 
is particularly a problem if the form contains radio buttons marked as 
required, because in that case validation will fail and the onSubmit() method 
will not be called.

The problem lies in BaseWicketTester.submitAjaxFormSubmitBehavior(). If the 
visitor in this method were changed so that, instead of skipping RadioGroups, 
it instead did something like the constructor of FormTester does (see 
WICKET-1411) to extract the actual value for the group and set that in the 
request, the problem would be prevented.

For anyone else affected by this issue, we're working around it by overriding 
the clickLink(String, boolean) method (since submitAjaxFormSubmitBehavior() is 
private) in a subclass of WicketTester like this:

        @Override
        public void clickLink(String path, boolean isAjax) {
                // Workaround for bug in BaseWicketTester: doexn't cope with 
RadioGroups properly.
                Component linkComponent = 
getComponentFromLastRenderedPage(path);
                if (linkComponent instanceof AjaxSubmitLink) {
                        // Code borrowed from BaseWicketTester.
                        AjaxSubmitLink link = (AjaxSubmitLink)linkComponent;

                        // We cycle through the attached behaviors and select 
the
                        // LAST matching behavior as the one we handle.
                        List behaviors = link.getBehaviors();
                        AjaxFormSubmitBehavior behaviour = null;
                        for (Iterator iter = behaviors.iterator(); 
iter.hasNext();)
                        {
                                Object behavior = iter.next();
                                if (behavior instanceof AjaxFormSubmitBehavior)
                                {
                                        AjaxFormSubmitBehavior submitBehavior = 
(AjaxFormSubmitBehavior)behavior;
                                        behaviour = submitBehavior;
                                }
                        }
                        if (behaviour != null) {
                                // More code borrowed from BaseWicketTester.
                                Form form = null;
                                try {
                                        Field formField = 
AjaxFormSubmitBehavior.class.getDeclaredField("form");
                                        formField.setAccessible(true);
                                        form = (Form)formField.get(behaviour);
                                } catch (Exception e) {
                                        s_log.error("Caught exception in 
workaround for BaseWicketTester bug.", e);
                                }
                                if (form != null) {
                                        form.visitFormComponents(new 
FormComponent.AbstractVisitor()
                                        {
                                                public void 
onFormComponent(FormComponent formComponent)
                                                {
                                                        if (formComponent 
instanceof RadioGroup) {
                                                                final String 
name = formComponent.getInputName();
                                                        final String value = 
formComponent.getValue();
                                                        Object choiceValue = 
formComponent.visitChildren(Radio.class, new IVisitor()
                                                        {

                                                            public Object 
component(Component component)
                                                            {
                                                                // O-P Preserve 
old escaping value, then turn escaping off
                                                                // so that 
values aren't escaped unnecessarily.
                                                                
@SuppressWarnings("hiding")
                                                                boolean 
oldEscaping = component.getEscapeModelStrings();
                                                                
component.setEscapeModelStrings(false);
                                                                Radio radio = 
(Radio)component;
                                                                String 
radioValue = radio.getValue();
                                                                // O-P Restore 
the previous escaping setting.
                                                                
component.setEscapeModelStrings(oldEscaping);
                                                                if 
(radio.getModelObject().toString().equals(value))
                                                                {
                                                                    return 
radioValue;
                                                                }
                                                                return 
CONTINUE_TRAVERSAL;
                                                            }

                                                        });
                                                        if (choiceValue != 
null) {
                                                                Map 
requestParams = getParametersForNextRequest();
                                                                if 
(requestParams.get(name) == null) {
                                                                        
requestParams.put(name, (String) choiceValue);
                                                                }
                                                        }
                                                        }
                                                }
                                        });
                                }
                        }
                }
                super.clickLink(path, isAjax);
        }


-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to