[
https://issues.apache.org/jira/browse/WICKET-1094?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Igor Vaynberg resolved WICKET-1094.
-----------------------------------
Assignee: Igor Vaynberg
Fix Version/s: 1.4.11
Resolution: Fixed
> Values over-escaped by FormTester
> ---------------------------------
>
> Key: WICKET-1094
> URL: https://issues.apache.org/jira/browse/WICKET-1094
> Project: Wicket
> Issue Type: Bug
> Affects Versions: 1.3.0-beta4
> Reporter: David Shepherdson
> Assignee: Igor Vaynberg
> Fix For: 1.4.11, 1.5-M2
>
>
> FormTester's constructor contains code that visits all components on the form
> and calls setFormComponentValue(formComponent, formComponent.getValue()) (or
> variations thereof), to store the component's value in the servlet request
> parameters. However, by default, FormComponent's getValue() method uses
> Strings.escapeMarkup(...) to encode any special characters, such as angle
> brackets. This is fine in a 'real' environment, where a Web browser will be
> responsible for displaying the escaped characters with their proper values,
> and so the proper value will be the one that comes through when the form is
> submitted; however, in the Wicket test environment, there isn't anything to
> do that extra level of 'un-escaping', meaning there's a danger of the form
> components being given escaped values when the form is submitted.
> For example, we have a form that contains a text area, whose value contains a
> URI enclosed in angle brackets, like so:
> < http://test.com/ >
> When we submit the form with a Web browser, the value set on the model is
> exactly that string -- '< http://test.com/ >'. However, when we test our page
> with FormTester, the FormTester constructor calls getValue() on the
> component, which by default returns the escaped form:
> < http://test.com/ >
> When the form is submitted, this is the value set on the model, and so
> comparisons to the original string fail.
> (Extra spaces inserted into the strings above to make them display properly
> in JIRA.)
> However, if FormTester were to call setEscapeModelStrings(false) on the form
> component before calling getValue() (and then restore the original escaping
> setting afterwards), then the value that ends up being provided to the
> component at the end would be the correct (unescaped) value, matching the
> behaviour when using the page in a browser.
> We have worked around this issue by overriding FormTester with a class that
> performs a second traversal of the form component hierarchy after calling the
> FormTester constructor, replacing the incorrectly escaped values with the
> proper ones (changes marked with '// O-P'):
> public OurFormTester(String path, Form workingForm, BaseWicketTester
> wicketTester, boolean fillBlankString) {
> super(path, workingForm, wicketTester, fillBlankString);
> fixFormParameterValues(workingForm, fillBlankString);
> }
>
> protected void fixFormParameterValues(Form workingForm, final boolean
> fillBlankString) {
> workingForm.visitFormComponents(new FormComponent.AbstractVisitor()
> {
> public void onFormComponent(final FormComponent formComponent)
> {
> // do nothing for invisible component
> if (!formComponent.isVisibleInHierarchy())
> {
> return;
> }
> // O-P Preserve old escaping value, then turn escaping off
> // so that values aren't escaped unnecessarily.
> boolean oldEscaping = formComponent.getEscapeModelStrings();
> formComponent.setEscapeModelStrings(false);
>
> // if component is text field and do not have exist value,
> fill
> // blank String if required
> if (formComponent instanceof AbstractTextComponent)
> {
> if (Strings.isEmpty(formComponent.getValue()))
> {
> if (fillBlankString)
> {
> setFormComponentValue(formComponent, "");
> }
> }
> else
> {
> setFormComponentValue(formComponent,
> formComponent.getValue());
> }
> }
> else if ( (formComponent instanceof DropDownChoice) ||
> (formComponent instanceof RadioChoice) ||
> (formComponent instanceof CheckBox))
> {
> setFormComponentValue(formComponent,
> formComponent.getValue());
> }
> else if (formComponent instanceof ListMultipleChoice)
> {
> final String[] modelValues =
> formComponent.getValue().split(FormComponent.VALUE_SEPARATOR);
> for (int i = 0; i < modelValues.length; i++)
> {
> addFormComponentValue(formComponent, modelValues[i]);
> }
> }
> else if (formComponent instanceof CheckGroup)
> {
> final Collection checkGroupValues = (Collection)
> formComponent.getModelObject();
> formComponent.visitChildren(Check.class, new IVisitor()
> {
> public Object component(Component component)
> {
>
> if
> (checkGroupValues.contains(component.getModelObject()))
> {
> // O-P Preserve old escaping value, then turn
> escaping off
> // so that values aren't escaped
> unnecessarily.
> boolean oldEscaping =
> component.getEscapeModelStrings();
> component.setEscapeModelStrings(false);
>
> addFormComponentValue(formComponent, ((Check)
> component).getValue());
>
> // O-P Restore the previous escaping setting.
> component.setEscapeModelStrings(oldEscaping);
> }
> return CONTINUE_TRAVERSAL;
> }
> });
> }
>
> // O-P Restore the previous escaping setting.
> formComponent.setEscapeModelStrings(oldEscaping);
> }
> });
> }
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.