You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wicket.apache.org by Marek Gilbert <gi...@tacitknowledge.com> on 2007/07/20 04:12:58 UTC
Ajax + FormTester
Greetings.
I've been trying to figure out how to do a WicketTester based test of
an Ajax-enabled form sequence. The basic idea of the code under test
is to have a bunch of panels on a single page, where navigation
between panels is gated by server-side validation implemented as Ajax
calls triggered from a submit button on each panel.
I'm using wicket 1.3 beta 1.
My first attempt at this was to do the obvious thing where I fill in
the form using a FormTester and then call submit on the FormTester.
This is almost right except that it doesn't end up calling the
onSubmit or onError methods of my AjaxFormSubmitBehavior. I now
realize calling submit() here does an actual form submission, which
is not what I want to test.
Then I noticed that there was an executeAjaxEvent method on
WicketTester. I then tried to fill in the form using a FormTester
and then execute the "onclick" behavior associated with my button and
this almost worked again. This time all the ajax behavior events
were being called but there were no values for my form parameters in
the request. This seems to be because
BaseWicketTester.submitAjaxFormSubmitBehavior() pulls all the values
out of the actual underlying form and sets parameters in the request
based on them, in effect undoing the work I did with the FormTester
(recall that FormTester sets up a request and then sets parameters on
the request for each call to setValue or the like).
Similarly, I could forget using FormTester and instead call
BaseWicketTester.setParameterForNextRequest() for each form value I
care about, but using executeAjaxEvent again cancels this work out.
Then I tried using BaseWicketTester.executeBehavior(), but because
this calls getServletRequest().setRequestToRedirectString(...) again
the parameters that I've filled in with the FormTester get overwritten.
At this point, I have this almost working, but I feel like what I've
done is an abomination. I've subclassed FormTester and added
ajaxSubmit methods, effectively an amalgamation of the
FormTester.submit and the BaseWicketTester.executeAjaxEvent methods:
public void ajaxSubmit()
{
ajaxSubmit(findSubmitButton(), "onclick");
}
public void ajaxSubmit(Component component, String event)
{
try
{
MockHttpServletRequest servletRequest =
ajaxWicketTester.getServletRequest();
WebRequestCycle requestCycle =
ajaxWicketTester.createRequestCycle();
servletRequest.setRequestToComponent(getForm());
// handle hasUploadedFiles()
AjaxEventBehavior behavior = findAjaxEventBehavior
(component, event);
// handle behavior not found
behavior.onRequest();
requestCycle.getRequestTarget().respond(requestCycle);
}
catch (FileUploadException e)
{
throw new WicketRuntimeException(e);
}
}
This gets me really close, except that I'm now finding behavioral
differences between the site running in a container vs the unit
test. For example, when under test, error messages aren't being
cleared between pages: once an error is generated it never goes
away. I could try to reach into RequestCycle.detach() for myself but
this is going way outside the bounds of a reasonable solution to this
problem.
So my questions come down to these:
- Am I crazy for wanting to write these kinds of tests? I figure
a few tests like these running through critical site functionality
should be integrated into our CI build with every commit.
WicketTester tests are way more palatable than doing something like
Selenium here. When the forms weren't Ajax enabled the FormTester
approach worked really well. We don't have a whole lot of Javascript
besides that which Wicket supplies so hooking up the ajax-based
version of this test would seem to be just what the doctor ordered.
- Why are executeBehavior and executeAjaxEvent implemented so
differently? executeBehavior uses setRequestToRedirectString then
calls processRedirectCycle (which in turn calls detach and cleans up
rendered error messages). executeAjaxEvent calls onRequest on the
behavior directly, and then calls requestCycle.getRequestTarget
().respond(requestCycle) bypassing the detach step in the
RedirectCycle, leaving error messages present forever.
- Similarly, how could I effectively use executeAjaxEvent when
submitAjaxFormSubmitBehavior pulls parameters from the underlying
form? Writing test code that reaches out and grabs the actual form
to set fields, to have submitAjaxFormSubmitBehavior read these and
set request parameters, to set my actual form fields seems really
contorted.
- All the Ajax-related calls in WicketTester are calling
setupRequestAndResponse, which seems to be fundamentally at adds with
what the FormTester is trying to do (it calls setupRequestAndResponse
for itself and then manipulates parameters on the *current*
request). Would it possibly be better to have FormTester call
setParameterForNextRequest?
- (more of a question for wicket-user, but I've already got your
attention) given all this, am I just missing something fundamental in
how would I go about writing a test that fills in a form and clicks
an AjaxSubmitButton?
If this issue is bugging other people I'd be happy to start hacking
on FormTester and friends myself and submit patches but I was pretty
sure that I didn't have the whole picture in my head yet and wanted
to see if there were any obvious ways of doing this that I'm just
missing.
Many thanks in advance and best regards for a killer tool!
-Gil
Re: Ajax + FormTester
Posted by Timo Rantalaiho <Ti...@ri.fi>.
Hello Gil,
That's a long email -- sorry if I missed something :) And
anyway I skipped the parts on Wicket internals as I don't
know about that.
On Thu, 19 Jul 2007, Marek Gilbert wrote:
> I'm using wicket 1.3 beta 1.
Immediately upgrade to beta2, or better yet, to the
snapshots to get this
http://issues.apache.org/jira/browse/WICKET-254
on board.
> Then I noticed that there was an executeAjaxEvent method on
> WicketTester. I then tried to fill in the form using a FormTester
> and then execute the "onclick" behavior associated with my button and
> this almost worked again. This time all the ajax behavior events
This is how it's supposed to be done, as far as I know.
> were being called but there were no values for my form parameters in
> the request. This seems to be because
> BaseWicketTester.submitAjaxFormSubmitBehavior() pulls all the values
> out of the actual underlying form and sets parameters in the request
> based on them, in effect undoing the work I did with the FormTester
> (recall that FormTester sets up a request and then sets parameters on
> the request for each call to setValue or the like).
Yep. If I understand correctly, at least some of this is
fixed in WICKET-254.
Wicket and its built-in ajax support are excellent, and so
is WicketTester, but when doing heavy ajax we have faced a
lot of problems with WicketTester. At least a part of them
were solved by the above test.
> - Am I crazy for wanting to write these kinds of tests? I figure
Of course not :)
> WicketTester tests are way more palatable than doing something like
> Selenium here. When the forms weren't Ajax enabled the FormTester
> approach worked really well. We don't have a whole lot of Javascript
> besides that which Wicket supplies so hooking up the ajax-based
> version of this test would seem to be just what the doctor ordered.
I think that WicketTester tests are more unit-test like
(even though they are not unit tests in the strictest
sense). Whatever you test with WicketTester, there's no
telling on how the code will behave in different browsers.
And sometimes it can be difficult to get something to work
realistically in the test.
That's why it's a very good idea to complement your
WicketTester tests with Selenium. This is most easily done
with Selenium RC (remote control) which you can nicely use
on a per-component basis, if you're on Java 5 (or above) and
can use WicketBenchTestCase from Wicket Bench:
http://svn.laughingpanda.org/svn/wicket-bench/trunk/wicket-bench-test/src/test/java/test/DictionaryPanelTest.java
> If this issue is bugging other people I'd be happy to start hacking
> on FormTester and friends myself and submit patches but I was pretty
> sure that I didn't have the whole picture in my head yet and wanted
> to see if there were any obvious ways of doing this that I'm just
> missing.
Probably providing patches and quickstarts to Jira would get
stuff fixed quickly (maybe for 1.4 if 1.3 is starting to get
frozen), if you still have problems after the fix of
WICKET-254.
In general, it's a great idea to search the wiki
http://cwiki.apache.org/WICKET/
and Nabble
http://www.nabble.com/Wicket-f13974.html
before asking:
http://www.catb.org/~esr/faqs/smart-questions.html#before
Best wishes,
Timo
--
Timo Rantalaiho
Reaktor Innovations Oy <URL: http://www.ri.fi/ >