开发者

problem writing HTMLUnit script for YUI form submit

开发者 https://www.devze.com 2023-04-02 09:14 出处:网络
I want to write a simple HTMLUnit test script for Jenkins (former Hudson). INFO: Jenkins uses the YUI Javascript library. The YUI library replaces the form submit with a custom button. The script just

I want to write a simple HTMLUnit test script for Jenkins (former Hudson). INFO: Jenkins uses the YUI Javascript library. The YUI library replaces the form submit with a custom button. The script just creates a new job in Jenkins.

start Jenkins: java -jar jenkins.war

Current versions of HTMLUnit do not support form.submit any more and require you to use button.click() for form submitting. Unfortunately this does not work for Jenkins (the sample below does not advance the page and create the job but stays on the new job page)

I tried for some hours now to find a solution or workaround but so far I could not get the form submitted. Hopefully somebody has found a solution and let me know.

Here is my sample code:

package example;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlButton;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;

public class jenkins3 {
     public static void main(String args[]) {
        // create a new job in jenkins
        // home
        final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6);
        try {
            final HtmlPage page1 = webClient.getPage("http://localhost:8080");
            //assertEquals("Dashboard [Jenkins]", page1.getTitleText());

            // new job
            final HtmlAnchor new_job = page1.getAnchorByText("New Job");
            final HtmlPage page2 = new_job.click();

            // job name
            HtmlTextInput name_field开发者_JAVA百科 = (HtmlTextInput) page2.getElementById("name");
            name_field.type("new job by htmlunit");

            // radio button
            final HtmlInput radio_freestyle = (HtmlInput) page2.getByXPath("//input[@value='hudson.model.FreeStyleProject']").get(0);
            radio_freestyle.click();
            Thread.sleep(10000);

            // OK button (submit form)
            final HtmlForm form = page2.getFormByName("createItem");
            //final HtmlSubmitInput button = (HtmlSubmitInput) form.getByXPath("//button").get(0);
            final HtmlButton button = (HtmlButton) form.getByXPath("//button").get(0);

            final HtmlPage page3 = button.click(); // !!!!! Form submit does not workstacko
            //assertEquals("Dashboard [Jenkins]", page3.getTitleText());
        }

        catch( Exception e ) {
            System.out.println( "General exception thrown:" + e.getMessage() );
            e.printStackTrace();
        }

        webClient.closeAllWindows();
    }
}


Although this may be completely out of the question in your senerio: i would suggest giving up on HTMLUnit. I've had bug after bug, mainly because of the pages I've been automating tests for aren't always 100% valid html (3rd party piggybacked requests). I finally went looking elsewhere and found PhantomJS (js bindings to the WebKit engine) much better suited. For me the advantages were evident: - no need for another app server - much simpler and faster to script JS than Java - a "real"-world engine is more realistic than a buggy emulator one Thats my advice, Cheers


HTMLUnit doesn't include support for testing javascript actions. You might not want to switch your testing framework at this point, but I would recommend using Selenium for this kind of testing. It runs a mock browser and executes javascript, making it possible to do this sort of thing.


I have found this little trick to work. Navigate to the Jenkins login page using HtmlUnit. Add a Submit button to the login form. Set appropriate attributes to Submit element, including an "onclick" value. Click on this new button and viola! You're logged in.

Note, if you're not concerned about security, you can also do this:

webClient.getPage("https://yourdomain:8443/jenkins/j_acegi_security_check?j_username=yourUsername&j_password=yourPassword");

See below for first method.

Enjoy, Nick.

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;

public class JenkinsLogin {

  final String urlValue = "https://<yourdomain>:8443/jenkins";
  private final String userName = "yourUsername";
  private final String password = "yourPassword";
  protected static final BrowserVersion BROWSER_VERSION_FIREFOX = new BrowserVersion(
          "Netscape", "5.0 (Windows)",
          "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0) Gecko/20100101 Firefox/8.0",
          (float) 1.2);
  private final WebClient webClient = new WebClient(BROWSER_VERSION_FIREFOX);

  public static void main(final String[] args) throws Exception {
    final JenkinsLogin jenkinsLogin = new JenkinsLogin();
    jenkinsLogin.login();
  }

  private void login() throws Exception {

    this.webClient.setThrowExceptionOnScriptError(false);

    HtmlPage page = this.webClient.getPage(this.urlValue + "/login");

    final HtmlForm form = page.getFormByName("login");
    form.getInputByName("j_username").setValueAttribute(this.userName);
    form.getInputByName("j_password").setValueAttribute(this.password);

    final HtmlElement createdElement = page.createElement("input");
    createdElement.setAttribute("type", "submit");
    createdElement.setAttribute("name", "submitIt");
    createdElement.setAttribute("onclick", "login.submit();");
    form.appendChild(createdElement);

    final HtmlElement submitButton = form.getInputByName("submitIt");
    page = submitButton.click();

    final HtmlElement loginField = page.getFirstByXPath("id('login-field')");
    if (loginField == null || !loginField.getTextContent().contains(this.userName))
      throw new RuntimeException("Unable to log on to Jenkins. ");
    System.out.println("Logged in! ");
  }
}


Does replacing

final HtmlButton button = (HtmlButton) form.getByXPath("//button").get(0);
final HtmlPage page3 = button.click()

with

form.submit((HtmlButton)last(form.getHtmlElementsByTagName("button")));

work?

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号