/**
   * Click the {@link Link} in the last rendered Page.
   *
   * <p>This method also works for {@link AjaxLink}, {@link AjaxFallbackLink} and {@link
   * AjaxSubmitLink}.
   *
   * <p>On AjaxLinks and AjaxFallbackLinks the onClick method is invoked with a valid
   * AjaxRequestTarget. In that way you can test the flow of your application when using AJAX.
   *
   * <p>When clicking an AjaxSubmitLink the form, which the AjaxSubmitLink is attached to is first
   * submitted, and then the onSubmit method on AjaxSubmitLink is invoked. If you have changed some
   * values in the form during your test, these will also be submitted. This should not be used as a
   * replacement for the {@link FormTester} to test your forms. It should be used to test that the
   * code in your onSubmit method in AjaxSubmitLink actually works.
   *
   * <p>This method is also able to simulate that AJAX (javascript) is disabled on the client. This
   * is done by setting the isAjax parameter to false. If you have an AjaxFallbackLink you can then
   * check that it doesn't fail when invoked as a normal link.
   *
   * @param path path to <code>Link</code> component
   * @param isAjax Whether to simulate that AJAX (javascript) is enabled or not. If it's false then
   *     AjaxLink and AjaxSubmitLink will fail, since it wouldn't work in real life.
   *     AjaxFallbackLink will be invoked with null as the AjaxRequestTarget parameter.
   */
  public void clickLink(String path, boolean isAjax) {
    Component linkComponent = getComponentFromLastRenderedPage(path);

    // if the link is an AjaxLink, we process it differently
    // than a normal link
    if (linkComponent instanceof AjaxLink) {
      // If it's not ajax we fail
      if (isAjax == false) {
        Assert.fail(
            "Link "
                + path
                + "is an AjaxLink and will "
                + "not be invoked when AJAX (javascript) is disabled.");
      }

      AjaxLink link = (AjaxLink) linkComponent;

      setupRequestAndResponse();
      RequestCycle requestCycle = createRequestCycle();
      AjaxRequestTarget target = new AjaxRequestTarget();
      requestCycle.setRequestTarget(target);

      link.onClick(target);

      // process the request target
      target.respond(requestCycle);
    }
    // AjaxFallbackLinks is processed like an AjaxLink if isAjax is true
    // If it's not handling of the linkComponent is passed through to the
    // Link.
    else if (linkComponent instanceof AjaxFallbackLink && isAjax) {
      AjaxFallbackLink link = (AjaxFallbackLink) linkComponent;

      setupRequestAndResponse();
      RequestCycle requestCycle = createRequestCycle();
      AjaxRequestTarget target = new AjaxRequestTarget();
      requestCycle.setRequestTarget(target);

      link.onClick(target);

      // process the request target
      target.respond(requestCycle);
    }
    // if the link is an AjaxSubmitLink, we need to find the form
    // from it using reflection so we know what to submit.
    else if (linkComponent instanceof AjaxSubmitLink) {
      // If it's not ajax we fail
      if (isAjax == false) {
        Assert.fail(
            "Link "
                + path
                + "is an AjaxSubmitLink and "
                + "will not be invoked when AJAX (javascript) is disabled.");
      }

      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 ajaxFormSubmitBehavior = null;
      for (Object behavior : behaviors) {
        if (behavior instanceof AjaxFormSubmitBehavior) {
          AjaxFormSubmitBehavior submitBehavior = (AjaxFormSubmitBehavior) behavior;
          ajaxFormSubmitBehavior = submitBehavior;
        }
      }

      String failMessage = "No form submit behavior found on the submit link. Strange!!";
      Assert.assertNotNull(failMessage, ajaxFormSubmitBehavior);

      // We need to get the form submitted, using reflection.
      // It needs to be "submitted".
      Form form = null;
      try {
        Field formField = AjaxFormSubmitBehavior.class.getDeclaredField("form");
        formField.setAccessible(true);
        form = (Form) formField.get(ajaxFormSubmitBehavior);
      } catch (Exception e) {
        Assert.fail(e.getMessage());
      }

      failMessage = "No form attached to the submitlink.";
      Assert.assertNotNull(failMessage, form);

      setupRequestAndResponse();
      RequestCycle requestCycle = createRequestCycle();

      // "Submit" the form
      form.visitFormComponents(
          new FormComponent.IVisitor() {
            public void formComponent(FormComponent formComponent) {
              if (!(formComponent instanceof Button) && !(formComponent instanceof RadioGroup)) {
                String name = formComponent.getInputName();
                String value = formComponent.getValue();

                getServletRequest().setParameter(name, value);
              }
            }
          });

      // Ok, finally we "click" the link
      ajaxFormSubmitBehavior.onRequest();

      // process the request target
      requestCycle.getRequestTarget().respond(requestCycle);
    }
    // if the link is a normal link
    else if (linkComponent instanceof Link) {
      Link link = (Link) linkComponent;
      newRequestToComponent(link);
    } else {
      Assert.fail("Link " + path + " is not a Link, AjaxLink, AjaxFallbackLink or AjaxSubmitLink");
    }
  }