提交 16c30cdc 编写于 作者: T Tom Fennelly 提交者: Oliver Gondža

Merge pull request #1774 from tfennelly/upgrade-htmlunit

Upgrade HtmlUnit to v2.18 (from forked version)
(cherry picked from commit f552d48f)
上级 acd341d5
......@@ -64,6 +64,16 @@ THE SOFTWARE.
<groupId>${project.groupId}</groupId>
<artifactId>maven-plugin</artifactId>
<version>${maven-plugin.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
......@@ -127,16 +137,9 @@ THE SOFTWARE.
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci</groupId>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.6-jenkins-6</version>
<exclusions>
<exclusion>
<!-- hides JDK DOM classes in Eclipse -->
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
</exclusions>
<version>2.18</version>
</dependency>
<dependency><!-- we exclude this transient dependency from htmlunit, which we actually need in the test -->
<groupId>xalan</groupId>
......
# Overview
Jenkins used to maintain a forked version of HtmlUnit and use it via `JenkinsRule` (and `HudsonTestCase`). Moving
away from the forked version has allowed Jenkins GUI to start using more modern JavaScript libraries than were
possible through the forked version.
Moving away from the forked version also means that some tests in plugins may no longer compile due to the
fact that they were using some methods that were added to the fork, but not available in the mainstream HtmlUnit.
To help with that, the test harness now provides static utilities for all of this functionality.
# WebClientUtil
The `WebClientUtil` class provides static utilities for interacting asynchronously with HtmlUnit's `WebClient`,
supporting `waitForJSExec` calls to allow your test code wait for background (asynchronous) JavaScript code to complete
before the test continues. Calling these methods are not required in many cases as they are called for you from
other static utilities (e.g. `HtmlFormUtil.submit`), but sometimes it is required to call them directly.
Because HtmlUnit executes JavaScript asynchronously, it's usually not possible to block and catch exceptions. For
that reason, `WebClientUtil` provides the `addExceptionListener` utility as a way of registering an exception listener.
This typically needs to be used in conjunction with the `waitForJSExec` method e.g.
```java
WebClient webClient = jenkinsRule.createWebClient();
WebClientUtil.ExceptionListener exceptionListener = WebClientUtil.addExceptionListener(webClient);
// Interact with Jenkins UI as normal in a test...
// Make sure all background JavaScript has completed so as expected exceptions have been thrown.
WebClientUtil.waitForJSExec(webClient);
// Now we can check for exceptions etc...
exceptionListener.assertHasException();
ScriptException e = exceptionListener.getScriptException();
Assert.assertTrue(e.getMessage().contains("simulated error"));
```
# HtmlElementUtil, HtmlFormUtil and DomNodeUtil
These classes provide static utility methods to replace functionality that was added to the forked HtmlUnit e.g.
for triggering `<form>` submit, triggering a click event on an element etc.
Use your IDE to access these utility classes and the static methods available.
\ No newline at end of file
/*
* The MIT License
*
* Copyright (c) 2015, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.gargoylesoftware.htmlunit;
import com.gargoylesoftware.htmlunit.javascript.JavaScriptErrorListener;
import org.junit.Assert;
import java.net.MalformedURLException;
import java.net.URL;
/**
* {@link WebClient} helper methods.
* @author <a href="mailto:tom.fennelly@gmail.com">tom.fennelly@gmail.com</a>
*/
public class WebClientUtil {
/**
* Wait for all async JavaScript tasks associated with the supplied {@link WebClient} instance
* to complete.
* <p>
* Waits for 10 seconds before timing out.
* @param webClient The {@link WebClient} instance.
*/
public static void waitForJSExec(WebClient webClient) {
waitForJSExec(webClient, 10000);
}
/**
* Wait for all async JavaScript tasks associated with the supplied {@link WebClient} instance
* to complete.
* @param webClient The {@link WebClient} instance.
* @param timeout The timeout in milliseconds.
*/
public static void waitForJSExec(WebClient webClient, long timeout) {
webClient.getJavaScriptEngine().processPostponedActions();
webClient.waitForBackgroundJavaScript(timeout);
}
/**
* Create and add an {@link ExceptionListener} to the {@link WebClient} instance.
* @param webClient The {@link WebClient} instance.
* @return The {@link ExceptionListener}.
*/
public static ExceptionListener addExceptionListener(WebClient webClient) {
ExceptionListener exceptionListener = new ExceptionListener(webClient);
webClient.setJavaScriptErrorListener(exceptionListener);
return exceptionListener;
}
/**
* JavaScript Exception listener.
* @see #addExceptionListener(WebClient)
*/
public static class ExceptionListener implements JavaScriptErrorListener {
private final WebClient webClient;
private ScriptException scriptException;
private ExceptionListener(WebClient webClient) {
this.webClient = webClient;
}
/**
* Get the last {@link ScriptException}.
* @return The last {@link ScriptException}, or {@code null} if none happened.
*/
public ScriptException getScriptException() {
return scriptException;
}
/**
* Get the last {@link ScriptException}.
* <p>
* Performs a call to {@link #assertHasException()}.
* @return The last {@link ScriptException}.
*/
public ScriptException getExpectedScriptException() {
assertHasException();
return scriptException;
}
/**
* {@inheritDoc}
*/
@Override
public void scriptException(InteractivePage htmlPage, ScriptException scriptException) {
this.scriptException = scriptException;
}
/**
* Assert that a {@link ScriptException} occurred within the JavaScript executing
* on the associated {@link WebClient}.
*/
public void assertHasException() {
WebClientUtil.waitForJSExec(webClient);
Assert.assertNotNull("A JavaScript Exception was expected.", scriptException);
}
/**
* {@inheritDoc}
*/
@Override
public void timeoutError(InteractivePage htmlPage, long allowedTime, long executionTime) {
}
/**
* {@inheritDoc}
*/
@Override
public void malformedScriptURL(InteractivePage htmlPage, String url, MalformedURLException malformedURLException) {
}
/**
* {@inheritDoc}
*/
@Override
public void loadScriptError(InteractivePage htmlPage, URL scriptUrl, Exception exception) {
}
}
}
package com.gargoylesoftware.htmlunit;
import org.junit.Assert;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @author <a href="mailto:tom.fennelly@gmail.com">tom.fennelly@gmail.com</a>
*/
public interface WebResponseListener {
void onLoadWebResponse(WebRequest webRequest, WebResponse webResponse) throws IOException;
public final class StatusListener implements WebResponseListener {
private final int statusCode;
private final List<WebResponse> responses = new CopyOnWriteArrayList<>();
public StatusListener(final int statusCode) {
this.statusCode = statusCode;
}
@Override
public void onLoadWebResponse(WebRequest webRequest, WebResponse webResponse) throws IOException {
if (webResponse.getStatusCode() == statusCode) {
responses.add(webResponse);
}
}
public void assertHasResponses() {
Assert.assertTrue(!responses.isEmpty());
}
public List<WebResponse> getResponses() {
return responses;
}
}
}
/*
* The MIT License
*
* Copyright (c) 2015, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.gargoylesoftware.htmlunit.html;
import com.gargoylesoftware.htmlunit.WebClientUtil;
import com.gargoylesoftware.htmlunit.html.xpath.XPathUtils;
import java.util.List;
/**
* {@link DomNode} helper methods.
*
* @author <a href="mailto:tom.fennelly@gmail.com">tom.fennelly@gmail.com</a>
*/
public class DomNodeUtil {
/**
* Evaluates an XPath expression from the specified node, returning the resultant nodes.
* <p>
* Calls {@link WebClientUtil#waitForJSExec(com.gargoylesoftware.htmlunit.WebClient)} before
* executing the query.
*
* @param domNode the node to start searching from
* @param xpathExpr the XPath expression
* @return the list of objects found.
*/
public static <E> List<E> selectNodes(final DomNode domNode, final String xpathExpr) {
WebClientUtil.waitForJSExec(domNode.getPage().getWebClient());
return (List) XPathUtils.getByXPath(domNode, xpathExpr, null);
}
/**
* Evaluates the specified XPath expression from this node, returning the first matching element,
* or <tt>null</tt> if no node matches the specified XPath expression.
* <p>
* Calls {@link WebClientUtil#waitForJSExec(com.gargoylesoftware.htmlunit.WebClient)} before
* executing the query.
*
* @param domNode the node to start searching from
* @param xpathExpr the XPath expression
* @return the first element matching the specified XPath expression
*/
public static <X> X selectSingleNode(final DomNode domNode, final String xpathExpr) {
WebClientUtil.waitForJSExec(domNode.getPage().getWebClient());
return domNode.<X>getFirstByXPath(xpathExpr);
}
}
/*
* The MIT License
*
* Copyright (c) 2015, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.gargoylesoftware.htmlunit.html;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebClientUtil;
import java.io.IOException;
/**
* {@link HtmlElement} helper methods.
* @author <a href="mailto:tom.fennelly@gmail.com">tom.fennelly@gmail.com</a>
*/
public class HtmlElementUtil {
/**
* Click on the supplied element.
* <p>
* Waits for all executing JavaScript tasks to complete before returning.
*
* @param element The element to click.
* @return The page resulting from the click
* @throws IOException if an IO error occurs
*/
public static Page click(HtmlElement element) throws IOException {
if (element == null) {
return null;
}
try {
return element.click();
} finally {
// The JS script execution tasks are added to a queue and executed
// async. Wait for all to finish executing.
WebClient webClient = element.getPage().getWebClient();
WebClientUtil.waitForJSExec(webClient);
}
}
}
/*
* The MIT License
*
* Copyright (c) 2015, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.gargoylesoftware.htmlunit.html;
import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebClientUtil;
import java.io.IOException;
import java.util.List;
/**
* {@link HtmlForm} helper functions.
* <p>
* In many cases, the methods defined here replace methods of the same name that were
* added to the {@link HtmlForm} class on the old forked version of HtmlUnit.
*
* @author <a href="mailto:tom.fennelly@gmail.com">tom.fennelly@gmail.com</a>
*/
public class HtmlFormUtil {
/**
* Submit the supplied {@link HtmlForm}.
* <p>
* Locates the submit element/button on the form.
* @param htmlForm The {@link HtmlForm}.
* @return The submit result page.
* @throws IOException Error performing submit.
*/
public static Page submit(final HtmlForm htmlForm) throws IOException {
HtmlElement submitElement = getSubmitButton(htmlForm);
return submit(htmlForm, submitElement);
}
/**
* Submit the supplied {@link HtmlForm} via the supplied submit element.
* @param htmlForm The {@link HtmlForm}.
* @param submitElement The element through which the submit should be performed.
* @return The submit result page.
* @throws IOException Error performing submit.
*/
public static Page submit(HtmlForm htmlForm, HtmlElement submitElement) throws IOException {
final HtmlPage htmlPage = (HtmlPage) htmlForm.getPage();
final WebClient webClient = htmlPage.getWebClient();
try {
if (submitElement != null && !(submitElement instanceof SubmittableElement)) {
// Just click and return
return submitElement.click();
}
try {
htmlForm.submit((SubmittableElement) submitElement);
} finally {
// The HtmlForm submit doesn't really do anything. It just adds a "LoadJob"
// to an internal queue. What we are doing here is manually forcing the load of
// the response for that submit LoadJob and then getting the enclosing page
// from the current window on the WebClient, allowing us to return the correct
// HtmlPage object to the test.
webClient.loadDownloadedResponses();
Page resultPage = webClient.getCurrentWindow().getEnclosedPage();
if (resultPage == htmlPage) {
return HtmlElementUtil.click(submitElement);
} else {
return resultPage;
}
}
} finally {
// Make sure all background JS has executed.
WebClientUtil.waitForJSExec(webClient);
}
}
/**
* Returns all the &lt;input type="submit"> elements in this form.
*/
public static List<HtmlElement> getSubmitButtons(final HtmlForm htmlForm) throws ElementNotFoundException {
final List<HtmlElement> list = htmlForm.getElementsByAttribute("input", "type", "submit");
// collect inputs from lost children
for (final HtmlElement elt : htmlForm.getLostChildren()) {
list.add(elt);
}
return list;
}
/**
* Gets the first &lt;input type="submit"> element in this form.
*/
public static HtmlElement getSubmitButton(final HtmlForm htmlForm) throws ElementNotFoundException {
List<HtmlElement> submitButtons = getSubmitButtons(htmlForm);
if (!submitButtons.isEmpty()) {
return submitButtons.get(0);
}
for (HtmlElement element : htmlForm.getHtmlElementsByTagName("button")) {
if(element instanceof HtmlButton) {
return element;
}
}
return null;
}
/**
* Get the form button having the specified text/caption.
* @param htmlForm The form containing the button.
* @param caption The button text/caption being searched for.
* @return The button if found.
* @throws ElementNotFoundException Failed to find the button on the form.
*/
public static HtmlButton getButtonByCaption(final HtmlForm htmlForm, final String caption) throws ElementNotFoundException {
for (HtmlElement b : htmlForm.getHtmlElementsByTagName("button")) {
if(b instanceof HtmlButton && b.getTextContent().trim().equals(caption)) {
return (HtmlButton) b;
}
}
throw new ElementNotFoundException("button", "caption", caption);
}
}
......@@ -28,8 +28,10 @@ import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.WebWindow;
import com.gargoylesoftware.htmlunit.PageCreator;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
/**
......@@ -46,5 +48,16 @@ public class HudsonPageCreator extends DefaultPageCreator {
return super.createPage(webResponse, webWindow);
}
@Override
protected String determineContentType(String contentType, InputStream contentAsStream) throws IOException {
// Need to sidestep HtmlUnit default behaviour here. It defaults the response type to
// being text/plain (and so creates a TextPage) if the content type in the response is
// blank + is an empty response.
if (StringUtils.isEmpty(contentType)) {
return "text/html";
}
return super.determineContentType(contentType, contentAsStream);
}
public static final HudsonPageCreator INSTANCE = new HudsonPageCreator();
}
......@@ -25,6 +25,10 @@
package org.jvnet.hudson.test;
import com.gargoylesoftware.htmlunit.AlertHandler;
import com.gargoylesoftware.htmlunit.WebClientUtil;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.html.HtmlFormUtil;
import com.gargoylesoftware.htmlunit.html.HtmlImage;
import com.google.inject.Injector;
......@@ -120,6 +124,7 @@ import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
......@@ -175,7 +180,6 @@ import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.DefaultCssErrorHandler;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.html.DomNode;
import com.gargoylesoftware.htmlunit.html.HtmlButton;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
......@@ -1042,7 +1046,7 @@ public abstract class HudsonTestCase extends TestCase implements RootAction {
*/
public void assertXPath(HtmlPage page, String xpath) {
assertNotNull("There should be an object that matches XPath:" + xpath,
page.getDocumentElement().selectSingleNode(xpath));
DomNodeUtil.selectSingleNode(page.getDocumentElement(), xpath));
}
/** Asserts that the XPath matches the contents of a DomNode page. This
......@@ -1098,7 +1102,7 @@ public abstract class HudsonTestCase extends TestCase implements RootAction {
* (By default, HtmlUnit doesn't load images.)
*/
public void assertAllImageLoadSuccessfully(HtmlPage p) {
for (HtmlImage img : p.<HtmlImage>selectNodes("//IMG")) {
for (HtmlImage img : DomNodeUtil.<HtmlImage>selectNodes(p, "//IMG")) {
try {
img.getHeight();
} catch (IOException e) {
......@@ -1160,7 +1164,7 @@ public abstract class HudsonTestCase extends TestCase implements RootAction {
* Plain {@link HtmlForm#submit()} doesn't work correctly due to the use of YUI in Hudson.
*/
public HtmlPage submit(HtmlForm form) throws Exception {
return (HtmlPage)form.submit((HtmlButton)last(form.getHtmlElementsByTagName("button")));
return (HtmlPage) HtmlFormUtil.submit(form, last(form.getHtmlElementsByTagName("button")));
}
/**
......@@ -1172,24 +1176,15 @@ public abstract class HudsonTestCase extends TestCase implements RootAction {
public HtmlPage submit(HtmlForm form, String name) throws Exception {
for( HtmlElement e : form.getHtmlElementsByTagName("button")) {
HtmlElement p = (HtmlElement)e.getParentNode().getParentNode();
if(p.getAttribute("name").equals(name)) {
// To make YUI event handling work, this combo seems to be necessary
// the click will trigger _onClick in buton-*.js, but it doesn't submit the form
// (a comment alluding to this behavior can be seen in submitForm method)
// so to complete it, submit the form later.
//
// Just doing form.submit() doesn't work either, because it doesn't do
// the preparation work needed to pass along the name of the button that
// triggered a submission (more concretely, m_oSubmitTrigger is not set.)
((HtmlButton)e).click();
return (HtmlPage)form.submit((HtmlButton)e);
if (e instanceof HtmlButton && p.getAttribute("name").equals(name)) {
return (HtmlPage)HtmlFormUtil.submit(form, (HtmlButton) e);
}
}
throw new AssertionError("No such submit button with the name "+name);
}
protected HtmlInput findPreviousInputElement(HtmlElement current, String name) {
return (HtmlInput)current.selectSingleNode("(preceding::input[@name='_."+name+"'])[last()]");
return DomNodeUtil.selectSingleNode(current, "(preceding::input[@name='_."+name+"'])[last()]");
}
protected HtmlButton getButtonByCaption(HtmlForm f, String s) {
......@@ -1629,19 +1624,19 @@ public abstract class HudsonTestCase extends TestCase implements RootAction {
* for accessing Hudson.
*/
public class WebClient extends com.gargoylesoftware.htmlunit.WebClient {
private static final long serialVersionUID = 5808915989048338267L;
private static final long serialVersionUID = 8720028298174337333L;
public WebClient() {
// default is IE6, but this causes 'n.doScroll('left')' to fail in event-debug.js:1907 as HtmlUnit doesn't implement such a method,
// so trying something else, until we discover another problem.
super(BrowserVersion.FIREFOX_2);
super(BrowserVersion.FIREFOX_38);
setPageCreator(HudsonPageCreator.INSTANCE);
clients.add(this);
// make ajax calls run as post-action for predictable behaviors that simplify debugging
setAjaxController(new AjaxController() {
private static final long serialVersionUID = -5844060943564822678L;
public boolean processSynchron(HtmlPage page, WebRequestSettings settings, boolean async) {
private static final long serialVersionUID = 6730107519583349963L;
public boolean processSynchron(HtmlPage page, WebRequest settings, boolean async) {
return false;
}
});
......@@ -1689,7 +1684,7 @@ public abstract class HudsonTestCase extends TestCase implements RootAction {
// avoid a hang by setting a time out. It should be long enough to prevent
// false-positive timeout on slow systems
setTimeout(60*1000);
//setTimeout(60*1000);
}
/**
......@@ -1701,7 +1696,7 @@ public abstract class HudsonTestCase extends TestCase implements RootAction {
HtmlForm form = page.getFormByName("login");
form.getInputByName("j_username").setValueAttribute(username);
form.getInputByName("j_password").setValueAttribute(password);
form.submit(null);
HtmlFormUtil.submit(form, null);
return this;
}
......@@ -1767,7 +1762,7 @@ public abstract class HudsonTestCase extends TestCase implements RootAction {
HtmlPage top = goTo("");
HtmlForm search = top.getFormByName("search");
search.getInputByName("q").setValueAttribute(q);
return (HtmlPage)search.submit(null);
return (HtmlPage)HtmlFormUtil.submit(search, null);
}
/**
......@@ -1821,7 +1816,11 @@ public abstract class HudsonTestCase extends TestCase implements RootAction {
@SuppressWarnings("unchecked")
@Override
public Page getPage(String url) throws IOException, FailingHttpStatusCodeException {
return super.getPage(url);
try {
return super.getPage(url);
} finally {
WebClientUtil.waitForJSExec(this);
}
}
/**
......@@ -1845,6 +1844,7 @@ public abstract class HudsonTestCase extends TestCase implements RootAction {
Page p;
try {
p = super.getPage(getContextPath() + relative);
WebClientUtil.waitForJSExec(this);
} catch (IOException x) {
if (x.getCause() != null) {
x.getCause().printStackTrace();
......@@ -1895,12 +1895,10 @@ public abstract class HudsonTestCase extends TestCase implements RootAction {
/**
* Adds a security crumb to the quest
*/
public WebRequestSettings addCrumb(WebRequestSettings req) {
NameValuePair crumb[] = { new NameValuePair() };
crumb[0].setName(jenkins.getCrumbIssuer().getDescriptor().getCrumbRequestField());
crumb[0].setValue(jenkins.getCrumbIssuer().getCrumb( null ));
public WebRequest addCrumb(WebRequest req) {
com.gargoylesoftware.htmlunit.util.NameValuePair crumb = new com.gargoylesoftware.htmlunit.util.NameValuePair(
jenkins.getCrumbIssuer().getDescriptor().getCrumbRequestField(),
jenkins.getCrumbIssuer().getCrumb( null ));
req.setRequestParameters(Arrays.asList( crumb ));
return req;
}
......
......@@ -30,8 +30,10 @@ import com.gargoylesoftware.htmlunit.DefaultCssErrorHandler;
import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.WebClientUtil;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.WebResponseListener;
import com.gargoylesoftware.htmlunit.html.DomNode;
import com.gargoylesoftware.htmlunit.html.HtmlButton;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
......@@ -41,6 +43,7 @@ import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.javascript.HtmlUnitContextFactory;
import com.gargoylesoftware.htmlunit.javascript.host.xml.XMLHttpRequest;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import com.gargoylesoftware.htmlunit.xml.XmlPage;
import hudson.ClassicPluginStrategy;
import hudson.CloseProofOutputStream;
......@@ -99,6 +102,7 @@ import hudson.slaves.CommandLauncher;
import hudson.slaves.ComputerConnector;
import hudson.slaves.ComputerListener;
import hudson.slaves.DumbSlave;
import hudson.slaves.OfflineCause;
import hudson.slaves.RetentionStrategy;
import hudson.tasks.Ant;
import hudson.tasks.BuildWrapper;
......@@ -173,7 +177,6 @@ import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.io.FileUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.AbstractArtifactResolutionException;
......@@ -191,6 +194,8 @@ import org.junit.runner.Description;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import java.nio.channels.ClosedByInterruptException;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.html.HtmlFormUtil;
import org.jvnet.hudson.test.recipes.Recipe;
import org.jvnet.hudson.test.rhino.JavaScriptDebugger;
import org.kohsuke.stapler.ClassDescriptor;
......@@ -793,6 +798,31 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
return env.temporaryDirectoryAllocator.allocate();
}
public DumbSlave createSlave(boolean waitForChannelConnect) throws Exception {
DumbSlave slave = createSlave();
if (waitForChannelConnect) {
long start = System.currentTimeMillis();
while (slave.getChannel() == null) {
if (System.currentTimeMillis() > (start + 10000)) {
throw new IllegalStateException("Timed out waiting on DumbSlave channel to connect.");
}
Thread.sleep(200);
}
}
return slave;
}
public void disconnectSlave(DumbSlave slave) throws Exception {
slave.getComputer().disconnect(new OfflineCause.ChannelTermination(new Exception("terminate")));
long start = System.currentTimeMillis();
while (slave.getChannel() != null) {
if (System.currentTimeMillis() > (start + 10000)) {
throw new IllegalStateException("Timed out waiting on DumbSlave channel to disconnect.");
}
Thread.sleep(200);
}
}
public DumbSlave createSlave() throws Exception {
return createSlave("",null);
}
......@@ -1180,8 +1210,9 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
* Asserts that the XPath matches.
*/
public void assertXPath(HtmlPage page, String xpath) {
HtmlElement documentElement = page.getDocumentElement();
assertNotNull("There should be an object that matches XPath:" + xpath,
page.getDocumentElement().selectSingleNode(xpath));
DomNodeUtil.selectSingleNode(documentElement, xpath));
}
/** Asserts that the XPath matches the contents of a DomNode page. This
......@@ -1237,7 +1268,7 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
* (By default, HtmlUnit doesn't load images.)
*/
public void assertAllImageLoadSuccessfully(HtmlPage p) {
for (HtmlImage img : p.<HtmlImage>selectNodes("//IMG")) {
for (HtmlImage img : DomNodeUtil.<HtmlImage>selectNodes(p, "//IMG")) {
try {
img.getHeight();
} catch (IOException e) {
......@@ -1300,7 +1331,7 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
* Plain {@link com.gargoylesoftware.htmlunit.html.HtmlForm#submit()} doesn't work correctly due to the use of YUI in Hudson.
*/
public HtmlPage submit(HtmlForm form) throws Exception {
return (HtmlPage) form.submit((HtmlButton) last(form.getHtmlElementsByTagName("button")));
return (HtmlPage) HtmlFormUtil.submit(form);
}
/**
......@@ -1312,24 +1343,15 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
public HtmlPage submit(HtmlForm form, String name) throws Exception {
for( HtmlElement e : form.getHtmlElementsByTagName("button")) {
HtmlElement p = (HtmlElement)e.getParentNode().getParentNode();
if(p.getAttribute("name").equals(name)) {
// To make YUI event handling work, this combo seems to be necessary
// the click will trigger _onClick in buton-*.js, but it doesn't submit the form
// (a comment alluding to this behavior can be seen in submitForm method)
// so to complete it, submit the form later.
//
// Just doing form.submit() doesn't work either, because it doesn't do
// the preparation work needed to pass along the name of the button that
// triggered a submission (more concretely, m_oSubmitTrigger is not set.)
((HtmlButton)e).click();
return (HtmlPage)form.submit((HtmlButton)e);
if(e instanceof HtmlButton && p.getAttribute("name").equals(name)) {
return (HtmlPage)HtmlFormUtil.submit(form, (HtmlButton) e);
}
}
throw new AssertionError("No such submit button with the name "+name);
}
public HtmlInput findPreviousInputElement(HtmlElement current, String name) {
return (HtmlInput)current.selectSingleNode("(preceding::input[@name='_."+name+"'])[last()]");
return DomNodeUtil.selectSingleNode(current, "(preceding::input[@name='_."+name+"'])[last()]");
}
public HtmlButton getButtonByCaption(HtmlForm f, String s) {
......@@ -1839,20 +1861,22 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
* for accessing Hudson.
*/
public class WebClient extends com.gargoylesoftware.htmlunit.WebClient {
private static final long serialVersionUID = 5808915989048338267L;
private static final long serialVersionUID = -7944895389154288881L;
private List<WebResponseListener> webResponseListeners = new ArrayList<>();
public WebClient() {
// default is IE6, but this causes 'n.doScroll('left')' to fail in event-debug.js:1907 as HtmlUnit doesn't implement such a method,
// so trying something else, until we discover another problem.
super(BrowserVersion.FIREFOX_2);
super(BrowserVersion.FIREFOX_38);
// setJavaScriptEnabled(false);
setPageCreator(HudsonPageCreator.INSTANCE);
clients.add(this);
// make ajax calls run as post-action for predictable behaviors that simplify debugging
setAjaxController(new AjaxController() {
private static final long serialVersionUID = -5844060943564822678L;
public boolean processSynchron(HtmlPage page, WebRequestSettings settings, boolean async) {
private static final long serialVersionUID = -76034615893907856L;
public boolean processSynchron(HtmlPage page, WebRequest settings, boolean async) {
return false;
}
});
......@@ -1897,7 +1921,23 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
// avoid a hang by setting a time out. It should be long enough to prevent
// false-positive timeout on slow systems
setTimeout(60*1000);
//setTimeout(60*1000);
}
public void addWebResponseListener(WebResponseListener listener) {
webResponseListeners.add(listener);
}
@Override
public WebResponse loadWebResponse(final WebRequest webRequest) throws IOException {
WebResponse webResponse = super.loadWebResponse(webRequest);
if (!webResponseListeners.isEmpty()) {
for (WebResponseListener listener : webResponseListeners) {
listener.onLoadWebResponse(webRequest, webResponse);
}
}
return webResponse;
}
/**
......@@ -1907,6 +1947,14 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
return login(username,password,false);
}
public boolean isJavaScriptEnabled() {
return getOptions().isJavaScriptEnabled();
}
public void setJavaScriptEnabled(boolean enabled) {
getOptions().setJavaScriptEnabled(enabled);
}
/**
* Logs in to Jenkins.
*/
......@@ -1923,7 +1971,7 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
// remember me not available is OK so long as the caller didn't ask for it
assert !rememberMe;
}
form.submit(null);
HtmlFormUtil.submit(form, null);
return this;
}
......@@ -1935,7 +1983,7 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
* and passwords. All the test accounts have the same user name and password.
*/
public WebClient login(String username) throws Exception {
login(username,username);
login(username, username);
return this;
}
......@@ -1989,7 +2037,7 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
HtmlPage top = goTo("");
HtmlForm search = top.getFormByName("search");
search.getInputByName("q").setValueAttribute(q);
return (HtmlPage)search.submit(null);
return (HtmlPage)HtmlFormUtil.submit(search, null);
}
/**
......@@ -2018,7 +2066,7 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
}
public HtmlPage getPage(Node item) throws IOException, SAXException {
return getPage(item,"");
return getPage(item, "");
}
public HtmlPage getPage(Node item, String relative) throws IOException, SAXException {
......@@ -2043,7 +2091,11 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
@SuppressWarnings("unchecked")
@Override
public Page getPage(String url) throws IOException, FailingHttpStatusCodeException {
return super.getPage(url);
try {
return super.getPage(url);
} finally {
WebClientUtil.waitForJSExec(this);
}
}
/**
......@@ -2075,6 +2127,7 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
Page p;
try {
p = super.getPage(getContextPath() + relative);
WebClientUtil.waitForJSExec(this);
} catch (IOException x) {
Throwable cause = x.getCause();
if (cause instanceof SocketTimeoutException) {
......@@ -2131,15 +2184,13 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
/**
* Adds a security crumb to the request.
* Use {@link #createCrumbedUrl} instead if you intend to call {@link WebRequestSettings#setRequestBody}, typical of a POST request.
* Use {@link #createCrumbedUrl} instead if you intend to call {@link WebRequest#setRequestBody}, typical of a POST request.
*/
public WebRequestSettings addCrumb(WebRequestSettings req) {
NameValuePair crumb[] = { new NameValuePair() };
crumb[0].setName(jenkins.getCrumbIssuer().getDescriptor().getCrumbRequestField());
crumb[0].setValue(jenkins.getCrumbIssuer().getCrumb( null ));
req.setRequestParameters(Arrays.asList( crumb ));
public WebRequest addCrumb(WebRequest req) {
NameValuePair crumb = new NameValuePair(
jenkins.getCrumbIssuer().getDescriptor().getCrumbRequestField(),
jenkins.getCrumbIssuer().getCrumb( null ));
req.setRequestParameters(Arrays.asList(crumb));
return req;
}
......
......@@ -51,4 +51,4 @@ public class FailedTest extends TestCase {
if (problem!=null)
throw problem;
}
}
}
\ No newline at end of file
......@@ -25,18 +25,13 @@ package hudson.model;
import com.gargoylesoftware.htmlunit.ElementNotFoundException
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebRequestSettings
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.security.*
import com.gargoylesoftware.htmlunit.HttpMethod
import com.gargoylesoftware.htmlunit.WebRequest;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.BuildTrigger
import hudson.tasks.Publisher
import hudson.tasks.Recorder;
import com.gargoylesoftware.htmlunit.html.HtmlPage
import hudson.maven.MavenModuleSet;
import hudson.security.*;
import hudson.tasks.BuildTrigger;
import hudson.tasks.Shell;
import hudson.scm.NullSCM;
import hudson.scm.SCM
......@@ -53,17 +48,12 @@ import hudson.triggers.TriggerDescriptor;
import hudson.util.StreamTaskListener;
import hudson.util.OneShotEvent
import jenkins.model.Jenkins;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder
import org.jvnet.hudson.test.HudsonTestCase
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.MemoryAssert
import org.jvnet.hudson.test.SequenceLock;
import org.jvnet.hudson.test.TestExtension;
import org.jvnet.hudson.test.recipes.PresetData;
import org.jvnet.hudson.test.recipes.PresetData.DataSet
import org.apache.commons.io.FileUtils;
import java.lang.ref.WeakReference
import org.jvnet.hudson.test.MockFolder
......@@ -127,10 +117,10 @@ public class AbstractProjectTest extends HudsonTestCase {
def webClient = createWebClient();
HtmlPage page = webClient.getPage(jenkins.getItem("test0"));
page = (HtmlPage)page.getFirstAnchorByText("Workspace").click();
page = (HtmlPage)page.getAnchorByText("Workspace").click();
try {
String wipeOutLabel = ResourceBundle.getBundle("hudson/model/AbstractProject/sidepanel").getString("Wipe Out Workspace");
page.getFirstAnchorByText(wipeOutLabel);
page.getAnchorByText(wipeOutLabel);
fail("shouldn't find a link");
} catch (ElementNotFoundException e) {
// OK
......@@ -393,7 +383,7 @@ public class AbstractProjectTest extends HudsonTestCase {
private String deleteRedirectTarget(String job) {
def wc = createWebClient();
String base = wc.getContextPath();
String loc = wc.getPage(wc.addCrumb(new WebRequestSettings(new URL(base + job + "/doDelete"), HttpMethod.POST))).getWebResponse().getUrl().toString();
String loc = wc.getPage(wc.addCrumb(new WebRequest(new URL(base + job + "/doDelete"), HttpMethod.POST))).getUrl().toString();
assert loc.startsWith(base): loc;
return loc.substring(base.length());
}
......
......@@ -9,7 +9,7 @@ import org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices
import org.acegisecurity.userdetails.User
import org.acegisecurity.userdetails.UserDetails
import org.acegisecurity.userdetails.UsernameNotFoundException
import org.apache.commons.httpclient.Cookie
import com.gargoylesoftware.htmlunit.util.Cookie
import org.junit.After
import org.junit.Before
import org.junit.Rule
......
package jenkins.bugs
import com.gargoylesoftware.htmlunit.WebClientUtil
import hudson.Launcher
import hudson.model.AbstractBuild
import hudson.model.AbstractProject
......@@ -40,10 +41,12 @@ class Jenkins19124Test {
def wc = j.createWebClient();
def c = wc.getPage(p, "configure");
c.getElementByName("_.alpha").valueAttribute = "hello";
WebClientUtil.waitForJSExec(wc);
assert d.alpha=="hello";
assert d.bravo=="2";
c.getElementByName("_.bravo").setSelectedAttribute("1",true);
WebClientUtil.waitForJSExec(wc);
assert d.alpha=="hello";
assert d.bravo=="1";
}
......
package hudson;
import com.gargoylesoftware.htmlunit.ScriptException;
import com.gargoylesoftware.htmlunit.WebClientUtil;
import org.junit.Assert;
import org.jvnet.hudson.test.HudsonTestCase;
/**
......@@ -11,14 +13,12 @@ public class ExceptionTest extends HudsonTestCase {
* Makes sure that an AJAX handler error results in a fatal problem in the unit test.
*/
public void testAjaxError() throws Exception {
try {
createWebClient().goTo("/self/ajaxError");
fail("should have resulted in a ScriptException");
} catch (ScriptException e) {
if (e.getMessage().contains("simulated error"))
return; // as expected
throw e;
WebClient webClient = createWebClient();
WebClientUtil.ExceptionListener exceptionListener = WebClientUtil.addExceptionListener(webClient);
webClient.goTo("/self/ajaxError");
}
// Check for the error.
ScriptException e = exceptionListener.getExpectedScriptException();
Assert.assertTrue(e.getMessage().contains("simulated error"));
}
}
......@@ -74,7 +74,7 @@ public class JnlpAccessWithSecuredHudsonTest extends HudsonTestCase {
// parse the JNLP page into DOM to list up the jars.
XmlPage jnlp = (XmlPage) wc.goTo("computer/test/slave-agent.jnlp","application/x-java-jnlp-file");
URL baseUrl = jnlp.getWebResponse().getUrl();
URL baseUrl = jnlp.getUrl();
Document dom = new DOMReader().read(jnlp.getXmlDocument());
for( Element jar : (List<Element>)dom.selectNodes("//jar") ) {
URL url = new URL(baseUrl,jar.attributeValue("href"));
......
......@@ -24,6 +24,7 @@
package hudson.bugs;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlFormUtil;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import java.net.HttpURLConnection;
import org.jvnet.hudson.test.Issue;
......@@ -47,15 +48,14 @@ public class LoginRedirectTest extends HudsonTestCase {
public void testRedirect() throws Exception {
WebClient wc = new WebClient();
// Hudson first causes 403 FORBIDDEN error, then redirect the browser to the page
wc.setThrowExceptionOnFailingStatusCode(false);
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
HtmlPage p = wc.goTo("/");
System.out.println(p.getDocumentURI());
assertEquals(200, p.getWebResponse().getStatusCode());
HtmlForm form = p.getFormByName("login");
form.getInputByName("j_username").setValueAttribute("alice");
form.getInputByName("j_password").setValueAttribute("alice");
p = (HtmlPage) form.submit(null);
p = (HtmlPage) HtmlFormUtil.submit(form, null);
System.out.println(p);
}
......
......@@ -2,7 +2,8 @@ package hudson.console;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.TextPage;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.FilePath;
import hudson.Launcher;
......@@ -62,7 +63,7 @@ public class ConsoleAnnotatorTest {
// make sure we see the annotation
HtmlPage rsp = r.createWebClient().getPage(b, "console");
assertEquals(1,rsp.selectNodes("//B[@class='demo']").size());
assertEquals(1, DomNodeUtil.selectNodes(rsp, "//B[@class='demo']").size());
// make sure raw console output doesn't include the garbage
TextPage raw = (TextPage)r.createWebClient().goTo(b.getUrl()+"consoleText","text/plain");
......@@ -112,7 +113,7 @@ public class ConsoleAnnotatorTest {
// make sure we see the annotation
HtmlPage rsp = r.createWebClient().getPage(b, "console");
assertEquals(1,rsp.selectNodes("//A[@href='http://infradna.com/']").size());
assertEquals(1, DomNodeUtil.selectNodes(rsp, "//A[@href='http://infradna.com/']").size());
// make sure raw console output doesn't include the garbage
TextPage raw = (TextPage)r.createWebClient().goTo(b.getUrl()+"consoleText","text/plain");
......@@ -138,7 +139,8 @@ public class ConsoleAnnotatorTest {
}
String next() throws IOException {
WebRequestSettings req = new WebRequestSettings(new URL(r.getURL() + run.getUrl() + "/logText/progressiveHtml"+(start!=null?"?start="+start:"")));
WebRequest req = new WebRequest(new URL(r.getURL() + run.getUrl() + "/logText/progressiveHtml"+(start!=null?"?start="+start:"")));
req.setEncodingType(null);
Map headers = new HashMap();
if (consoleAnnotator!=null)
headers.put("X-ConsoleAnnotator",consoleAnnotator);
......
......@@ -24,7 +24,7 @@
package hudson.diagnosis;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.WebRequest;
import java.net.URL;
import org.junit.Test;
import org.junit.Rule;
......@@ -35,7 +35,8 @@ public class ReverseProxySetupMonitorTest {
@Rule public JenkinsRule r = new JenkinsRule();
@Test public void normal() throws Exception {
WebRequestSettings wrs = new WebRequestSettings(new URL(r.getURL(), r.jenkins.getAdministrativeMonitor(ReverseProxySetupMonitor.class.getName()).getUrl() + "/test"));
WebRequest wrs = new WebRequest(new URL(r.getURL(), r.jenkins.getAdministrativeMonitor(ReverseProxySetupMonitor.class.getName()).getUrl() + "/test"));
wrs.setEncodingType(null);
wrs.setAdditionalHeader("Referer", r.getURL() + "manage");
r.createWebClient().getPage(wrs);
}
......
......@@ -55,7 +55,7 @@ public class TooManyJobsButNoViewTest {
assertNotNull(f);
// this should take us to the new view page
URL url = r.submit(f,"yes").getWebResponse().getUrl();
URL url = r.submit(f,"yes").getUrl();
assertTrue(url.toExternalForm(),url.toExternalForm().endsWith("/newView"));
// since we didn't create a view, if we go back, we should see the warning again
......
......@@ -25,7 +25,7 @@
package hudson.model;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import static org.junit.Assert.*;
import org.junit.Rule;
......@@ -53,7 +53,7 @@ public class AsynchPeopleTest {
}
assertEquals(0, wc.waitForBackgroundJavaScript(120000));
boolean found = false;
for (HtmlElement table : page.getElementsByTagName("table")) {
for (DomElement table : page.getElementsByTagName("table")) {
if (table.getAttribute("class").contains("progress-bar")) {
found = true;
assertEquals("display: none;", table.getAttribute("style"));
......
......@@ -30,6 +30,7 @@ import java.net.URL;
import javax.annotation.Nonnull;
import com.gargoylesoftware.htmlunit.WebRequest;
import org.hamcrest.Matchers;
import org.junit.Rule;
import org.junit.Test;
......@@ -39,7 +40,6 @@ import org.jvnet.hudson.test.MockFolder;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.WebResponse;
public class DirectlyModifiableViewTest {
......@@ -186,8 +186,8 @@ public class DirectlyModifiableViewTest {
private Page doPost(View view, String path) throws Exception {
WebClient wc = j.createWebClient();
wc.setThrowExceptionOnFailingStatusCode(false);
WebRequestSettings req = new WebRequestSettings(
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
WebRequest req = new WebRequest(
new URL(j.jenkins.getRootUrl() + view.getUrl() + path),
HttpMethod.POST
);
......
package hudson.model;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.gargoylesoftware.htmlunit.WebResponseListener;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.html.HtmlElementUtil;
import hudson.tasks.BuildStepMonitor;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
......@@ -48,16 +51,22 @@ public class HelpLinkTest {
private void clickAllHelpLinks(AbstractProject p) throws Exception {
// TODO: how do we add all the builders and publishers so that we can test this meaningfully?
clickAllHelpLinks(j.createWebClient().getPage(p, "configure"));
clickAllHelpLinks(j.createWebClient(), p);
}
private void clickAllHelpLinks(JenkinsRule.WebClient webClient, AbstractProject p) throws Exception {
// TODO: how do we add all the builders and publishers so that we can test this meaningfully?
clickAllHelpLinks(webClient.getPage(p, "configure"));
}
private void clickAllHelpLinks(HtmlPage p) throws Exception {
List<?> helpLinks = p.selectNodes("//a[@class='help-button']");
List<?> helpLinks = DomNodeUtil.selectNodes(p, "//a[@class='help-button']");
assertTrue(helpLinks.size()>0);
System.out.println("Clicking "+helpLinks.size()+" help links");
for (HtmlAnchor helpLink : (List<HtmlAnchor>)helpLinks)
helpLink.click();
for (HtmlAnchor helpLink : (List<HtmlAnchor>)helpLinks) {
HtmlElementUtil.click(helpLink);
}
}
public static class HelpNotFoundBuilder extends Publisher {
......@@ -92,13 +101,15 @@ public class HelpLinkTest {
try {
FreeStyleProject p = j.createFreeStyleProject();
p.getPublishersList().add(new HelpNotFoundBuilder());
clickAllHelpLinks(p);
fail("should detect a failure");
} catch(AssertionError e) {
if(e.getMessage().contains(d.getHelpFile()))
; // expected
else
throw e;
JenkinsRule.WebClient webclient = j.createWebClient();
WebResponseListener.StatusListener statusListener = new WebResponseListener.StatusListener(404);
webclient.addWebResponseListener(statusListener);
clickAllHelpLinks(webclient, p);
statusListener.assertHasResponses();
String contentAsString = statusListener.getResponses().get(0).getContentAsString();
Assert.assertTrue(contentAsString.contains(d.getHelpFile()));
} finally {
Publisher.all().remove(d);
}
......
......@@ -28,9 +28,10 @@ import static org.junit.Assert.*;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.model.Node.Mode;
......@@ -128,7 +129,7 @@ public class HudsonTest {
FreeStyleProject p = j.createFreeStyleProject();
Page jobPage = j.search(p.getName());
URL url = jobPage.getWebResponse().getUrl();
URL url = jobPage.getUrl();
System.out.println(url);
assertTrue(url.getPath().endsWith("/job/"+p.getName()+"/"));
}
......@@ -139,8 +140,8 @@ public class HudsonTest {
@Test
public void breadcrumb() throws Exception {
HtmlPage root = j.createWebClient().goTo("");
HtmlElement navbar = root.getElementById("breadcrumbs");
assertEquals(1,navbar.selectNodes("LI/A").size());
DomElement navbar = root.getElementById("breadcrumbs");
assertEquals(1, DomNodeUtil.selectNodes(navbar, "LI/A").size());
}
/**
......@@ -165,7 +166,7 @@ public class HudsonTest {
assertFalse(a.getHrefAttribute(),a.getHrefAttribute().endsWith("delete"));
// try to delete it by hitting the final URL directly
WebRequestSettings req = new WebRequestSettings(new URL(wc.getContextPath()+"computer/(master)/doDelete"), HttpMethod.POST);
WebRequest req = new WebRequest(new URL(wc.getContextPath()+"computer/(master)/doDelete"), HttpMethod.POST);
try {
wc.getPage(wc.addCrumb(req));
fail("Error code expected");
......
......@@ -25,6 +25,7 @@ package hudson.model;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.WebAssert;
import com.gargoylesoftware.htmlunit.html.HtmlFormUtil;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.TextPage;
......@@ -211,7 +212,7 @@ public class JobTest {
// But it posts invalid data so we expect 500 if we have permission, 403 if not
HtmlPage page = wc.goTo("userContent/post.html");
try {
page.getForms().get(0).submit();
HtmlFormUtil.submit(page.getForms().get(0));
fail("Expected exception: " + msg);
} catch (FailingHttpStatusCodeException expected) {
assertEquals(msg, status, expected.getStatusCode());
......
......@@ -25,6 +25,7 @@ package hudson.model;
import static org.junit.Assert.assertTrue;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.junit.Rule;
......@@ -47,7 +48,7 @@ public class ManagementLinkTest {
@Test
public void links() throws Exception {
HtmlPage page = j.createWebClient().goTo("manage");
List<?> anchors = page.selectNodes("id('management-links')//*[@class='link']/a[not(@onclick)]");
List<?> anchors = DomNodeUtil.selectNodes(page, "id('management-links')//*[@class='link']/a[not(@onclick)]");
assertTrue(anchors.size()>=8);
for(HtmlAnchor e : (List<HtmlAnchor>) anchors) {
e.click();
......
......@@ -2,6 +2,8 @@ package hudson.model;
import static org.junit.Assert.*;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.html.HtmlFormUtil;
import org.junit.Rule;
import org.junit.Test;
......@@ -42,38 +44,38 @@ public class ParametersTest {
project.getBuildersList().add(builder);
WebClient wc = j.createWebClient();
wc.setThrowExceptionOnFailingStatusCode(false);
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
HtmlPage page = wc.goTo("job/" + project.getName() + "/build?delay=0sec");
HtmlForm form = page.getFormByName("parameters");
HtmlElement element = (HtmlElement) form.selectSingleNode("//tr[td/div/input/@value='string']");
HtmlElement element = (HtmlElement) DomNodeUtil.selectSingleNode(form, "//tr[td/div/input/@value='string']");
assertNotNull(element);
assertEquals("string description", ((HtmlElement) element.getNextSibling().getNextSibling().selectSingleNode("td[@class='setting-description']")).getTextContent());
assertEquals("string description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "td[@class='setting-description']")).getTextContent());
HtmlTextInput stringParameterInput = (HtmlTextInput) element.selectSingleNode(".//input[@name='value']");
HtmlTextInput stringParameterInput = (HtmlTextInput) DomNodeUtil.selectSingleNode(element, ".//input[@name='value']");
assertEquals("defaultValue", stringParameterInput.getAttribute("value"));
assertEquals("string", ((HtmlElement) element.selectSingleNode("td[@class='setting-name']")).getTextContent());
assertEquals("string", ((HtmlElement) DomNodeUtil.selectSingleNode(element, "td[@class='setting-name']")).getTextContent());
stringParameterInput.setAttribute("value", "newValue");
element = (HtmlElement) form.selectSingleNode("//tr[td/div/input/@value='boolean']");
element = (HtmlElement) DomNodeUtil.selectSingleNode(form, "//tr[td/div/input/@value='boolean']");
assertNotNull(element);
assertEquals("boolean description", ((HtmlElement) element.getNextSibling().getNextSibling().selectSingleNode("td[@class='setting-description']")).getTextContent());
Object o = element.selectSingleNode(".//input[@name='value']");
assertEquals("boolean description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "td[@class='setting-description']")).getTextContent());
Object o = DomNodeUtil.selectSingleNode(element, ".//input[@name='value']");
System.out.println(o);
HtmlCheckBoxInput booleanParameterInput = (HtmlCheckBoxInput) o;
assertEquals(true, booleanParameterInput.isChecked());
assertEquals("boolean", ((HtmlElement) element.selectSingleNode("td[@class='setting-name']")).getTextContent());
assertEquals("boolean", ((HtmlElement) DomNodeUtil.selectSingleNode(element, "td[@class='setting-name']")).getTextContent());
element = (HtmlElement) form.selectSingleNode(".//tr[td/div/input/@value='choice']");
element = (HtmlElement) DomNodeUtil.selectSingleNode(form, ".//tr[td/div/input/@value='choice']");
assertNotNull(element);
assertEquals("choice description", ((HtmlElement) element.getNextSibling().getNextSibling().selectSingleNode("td[@class='setting-description']")).getTextContent());
assertEquals("choice", ((HtmlElement) element.selectSingleNode("td[@class='setting-name']")).getTextContent());
assertEquals("choice description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "td[@class='setting-description']")).getTextContent());
assertEquals("choice", ((HtmlElement) DomNodeUtil.selectSingleNode(element, "td[@class='setting-name']")).getTextContent());
element = (HtmlElement) form.selectSingleNode(".//tr[td/div/input/@value='run']");
element = (HtmlElement) DomNodeUtil.selectSingleNode(form, ".//tr[td/div/input/@value='run']");
assertNotNull(element);
assertEquals("run description", ((HtmlElement) element.getNextSibling().getNextSibling().selectSingleNode("td[@class='setting-description']")).getTextContent());
assertEquals("run", ((HtmlElement) element.selectSingleNode("td[@class='setting-name']")).getTextContent());
assertEquals("run description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "td[@class='setting-description']")).getTextContent());
assertEquals("run", ((HtmlElement) DomNodeUtil.selectSingleNode(element, "td[@class='setting-name']")).getTextContent());
j.submit(form);
Queue.Item q = j.jenkins.getQueue().getItem(project);
......@@ -96,15 +98,15 @@ public class ParametersTest {
project.getBuildersList().add(builder);
WebClient wc = j.createWebClient();
wc.setThrowExceptionOnFailingStatusCode(false);
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
HtmlPage page = wc.goTo("job/" + project.getName() + "/build?delay=0sec");
HtmlForm form = page.getFormByName("parameters");
HtmlElement element = (HtmlElement) form.selectSingleNode(".//tr[td/div/input/@value='choice']");
HtmlElement element = (HtmlElement) DomNodeUtil.selectSingleNode(form, ".//tr[td/div/input/@value='choice']");
assertNotNull(element);
assertEquals("choice description", ((HtmlElement) element.getNextSibling().getNextSibling().selectSingleNode("td[@class='setting-description']")).getTextContent());
assertEquals("choice", ((HtmlElement) element.selectSingleNode("td[@class='setting-name']")).getTextContent());
HtmlOption opt = (HtmlOption)element.selectSingleNode("td/div/select/option[@value='Choice <2>']");
assertEquals("choice description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "td[@class='setting-description']")).getTextContent());
assertEquals("choice", ((HtmlElement) DomNodeUtil.selectSingleNode(element, "td[@class='setting-name']")).getTextContent());
HtmlOption opt = (HtmlOption)DomNodeUtil.selectSingleNode(element, "td/div/select/option[@value='Choice <2>']");
assertNotNull(opt);
assertEquals("Choice <2>", opt.asText());
opt.setSelected(true);
......@@ -183,7 +185,7 @@ public class ParametersTest {
project.addProperty(pdp);
WebClient wc = j.createWebClient();
wc.setThrowExceptionOnFailingStatusCode(false);
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
HtmlPage page = wc.goTo("job/" + project.getName() + "/build?delay=0sec");
HtmlForm form = page.getFormByName("parameters");
......@@ -206,12 +208,12 @@ public class ParametersTest {
p.addProperty(pdb);
WebClient wc = j.createWebClient();
wc.setThrowExceptionOnFailingStatusCode(false); // Ignore 405
wc.getOptions().setThrowExceptionOnFailingStatusCode(false); // Ignore 405
HtmlPage page = wc.getPage(p, "build");
// java.lang.IllegalArgumentException: No such parameter definition: <gibberish>.
wc.setThrowExceptionOnFailingStatusCode(true);
wc.getOptions().setThrowExceptionOnFailingStatusCode(true);
final HtmlForm form = page.getFormByName("parameters");
form.submit(form.getButtonByCaption("Build"));
HtmlFormUtil.submit(form, HtmlFormUtil.getButtonByCaption(form, "Build"));
}
}
......@@ -25,6 +25,7 @@ package hudson.model;
import com.gargoylesoftware.htmlunit.html.HtmlFileInput;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlFormUtil;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.xml.XmlPage;
import hudson.Launcher;
......@@ -284,7 +285,7 @@ public class QueueTest {
HtmlForm f = p.getFormByName("main");
HtmlFileInput input = (HtmlFileInput) f.getInputByName("test");
input.setData(testData);
f.submit();
HtmlFormUtil.submit(f);
} finally {
server.stop();
}
......
......@@ -25,6 +25,7 @@
package hudson.model;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.ScriptException;
import com.gargoylesoftware.htmlunit.WebAssert;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
......@@ -51,11 +52,12 @@ import org.acegisecurity.context.SecurityContextHolder;
import static org.junit.Assert.*;
import static org.junit.Assume.*;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.FakeChangeLogSCM;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.TestExtension;
import org.jvnet.hudson.test.recipes.LocalData;
......@@ -452,6 +454,7 @@ public class UserTest {
}
catch(FailingHttpStatusCodeException e){
//ok exception should be thrown
Assert.assertEquals(400, e.getStatusCode());
}
assertTrue("User should not delete himself from memory.", User.getAll().contains(user));
assertTrue("User should not delete his persistent data.", user.getConfigFile().exists());
......
......@@ -23,6 +23,7 @@
*/
package hudson.model;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlLabel;
import hudson.model.Descriptor.FormException;
......@@ -42,7 +43,7 @@ public class ViewPropertyTest extends HudsonTestCase {
// make sure it renders as optionalBlock
HtmlForm f = createWebClient().getPage(foo, "configure").getFormByName("viewConfig");
((HtmlLabel)f.selectSingleNode(".//LABEL[text()='Debug Property']")).click();
((HtmlLabel) DomNodeUtil.selectSingleNode(f, ".//LABEL[text()='Debug Property']")).click();
submit(f);
ViewPropertyImpl vp = foo.getProperties().get(ViewPropertyImpl.class);
assertEquals("Duke",vp.name);
......
......@@ -23,11 +23,12 @@
*/
package hudson.model;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import jenkins.model.Jenkins;
import org.jvnet.hudson.test.Issue;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlLabel;
......@@ -48,9 +49,7 @@ import hudson.slaves.DumbSlave;
import hudson.util.HudsonIsLoading;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.*;
import org.junit.Ignore;
import org.junit.Rule;
......@@ -100,7 +99,7 @@ public class ViewTest {
WebClient wc = j.createWebClient();
HtmlPage userPage = wc.goTo("user/me");
HtmlAnchor privateViewsLink = userPage.getFirstAnchorByText("My Views");
HtmlAnchor privateViewsLink = userPage.getAnchorByText("My Views");
assertNotNull("My Views link not available", privateViewsLink);
HtmlPage privateViewsPage = (HtmlPage) privateViewsLink.click();
......@@ -157,7 +156,7 @@ public class ViewTest {
@Test public void allImagesCanBeLoaded() throws Exception {
User.get("user", true);
WebClient webClient = j.createWebClient();
webClient.setJavaScriptEnabled(false);
webClient.getOptions().setJavaScriptEnabled(false);
j.assertAllImageLoadSuccessfully(webClient.goTo("asynchPeople"));
}
......@@ -196,8 +195,9 @@ public class ViewTest {
String xml = wc.goToXml("view/v/config.xml").getContent();
assertTrue(xml, xml.contains("<description>one</description>"));
xml = xml.replace("<description>one</description>", "<description>two</description>");
WebRequestSettings req = new WebRequestSettings(wc.createCrumbedUrl("view/v/config.xml"), HttpMethod.POST);
WebRequest req = new WebRequest(wc.createCrumbedUrl("view/v/config.xml"), HttpMethod.POST);
req.setRequestBody(xml);
req.setEncodingType(null);
wc.getPage(req);
assertEquals("two", view.getDescription());
xml = new XmlFile(Jenkins.XSTREAM, new File(j.jenkins.getRootDir(), "config.xml")).asString();
......@@ -401,7 +401,7 @@ public class ViewTest {
View view = listView("foo");
Thread.sleep(100000);
HtmlForm f = j.createWebClient().getPage(view, "configure").getFormByName("viewConfig");
((HtmlLabel)f.selectSingleNode(".//LABEL[text()='Test property']")).click();
((HtmlLabel) DomNodeUtil.selectSingleNode(f, ".//LABEL[text()='Test property']")).click();
j.submit(f);
assertNotNull("View should contains ViewPropertyImpl property.", view.getProperties().get(PropertyImpl.class));
}
......
......@@ -118,7 +118,7 @@ public class SearchTest {
assertNotNull(result);
j.assertGoodStatus(result);
URL resultUrl = result.getWebResponse().getUrl();
URL resultUrl = result.getUrl();
assertTrue(resultUrl.toString().equals(j.getInstance().getRootUrl() + myFreeStyleProject.getUrl()));
}
......@@ -134,7 +134,7 @@ public class SearchTest {
assertNotNull(result);
j.assertGoodStatus(result);
URL resultUrl = result.getWebResponse().getUrl();
URL resultUrl = result.getUrl();
assertTrue(resultUrl.toString().equals(j.getInstance().getRootUrl() + myFreeStyleProject.getUrl()));
}
......
......@@ -6,6 +6,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import com.gargoylesoftware.htmlunit.html.HtmlFormUtil;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlCheckBoxInput;
......@@ -40,7 +41,7 @@ public class LoginTest {
private void verifyNotError(WebClient wc) throws IOException, SAXException {
HtmlPage p = wc.goTo("loginError");
URL url = p.getWebResponse().getUrl();
URL url = p.getUrl();
System.out.println(url);
assertFalse(url.toExternalForm().contains("login"));
}
......@@ -84,7 +85,7 @@ public class LoginTest {
public void loginRememberMe() throws Exception {
WebClient wc = j.createWebClient();
prepareLoginFormWithRememberMeChecked(wc).submit(null);
HtmlFormUtil.submit(prepareLoginFormWithRememberMeChecked(wc), null);
assertNotNull(getRememberMeCookie(wc));
}
......@@ -100,7 +101,7 @@ public class LoginTest {
HtmlForm form = prepareLoginFormWithRememberMeChecked(wc);
j.jenkins.setDisableRememberMe(true);
form.submit(null);
HtmlFormUtil.submit(form, null);
assertNull(getRememberMeCookie(wc));
}
......
......@@ -60,6 +60,6 @@ public class SignupPage {
}
public void assertErrorContains(String msg) {
assertThat(signupForm.getElementById("main-panel").getTextContent(),containsString(msg));
assertThat(signupForm.getPage().getElementById("main-panel").getTextContent(),containsString(msg));
}
}
......@@ -137,7 +137,7 @@ public class JNLPLauncherTest extends HudsonTestCase {
private String getJnlpLink(Computer c) throws Exception {
HtmlPage p = new WebClient().goTo("computer/"+c.getName()+"/");
String href = ((HtmlAnchor) p.getElementById("jnlp-link")).getHrefAttribute();
href = new URL(new URL(p.getDocumentURI()),href).toExternalForm();
href = new URL(new URL(p.getUrl().toExternalForm()),href).toExternalForm();
return href;
}
......
......@@ -6,6 +6,7 @@ import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlLabel;
import hudson.model.Descriptor.FormException;
......@@ -63,7 +64,7 @@ public class NodePropertyTest {
public void basicConfigRoundtrip() throws Exception {
DumbSlave s = j.createSlave();
HtmlForm f = j.createWebClient().goTo("computer/" + s.getNodeName() + "/configure").getFormByName("config");
((HtmlLabel)f.selectSingleNode(".//LABEL[text()='Some Property']")).click();
((HtmlLabel)DomNodeUtil.selectSingleNode(f, ".//LABEL[text()='Some Property']")).click();
j.submit(f);
PropertyImpl p = j.jenkins.getNode(s.getNodeName()).getNodeProperties().get(PropertyImpl.class);
assertEquals("Duke",p.name);
......
......@@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlFormUtil;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.tools.JDKInstaller.DescriptorImpl;
import org.junit.Before;
......@@ -74,7 +75,7 @@ public class JDKInstallerTest {
HtmlForm form = p.getFormByName("postCredential");
form.getInputByName("username").setValueAttribute("foo");
form.getInputByName("password").setValueAttribute("bar");
form.submit(null);
HtmlFormUtil.submit(form, null);
DescriptorImpl d = j.jenkins.getDescriptorByType(DescriptorImpl.class);
assertEquals("foo",d.getUsername());
......
......@@ -25,11 +25,13 @@ package hudson.util;
import static org.junit.Assert.fail;
import com.gargoylesoftware.htmlunit.WebResponseListener;
import hudson.model.FreeStyleProject;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Publisher;
import hudson.util.FormFieldValidatorTest.BrokenFormValidatorBuilder.DescriptorImpl;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
......@@ -83,13 +85,16 @@ public class FormFieldValidatorTest {
try {
FreeStyleProject p = j.createFreeStyleProject();
p.getPublishersList().add(new BrokenFormValidatorBuilder());
j.createWebClient().getPage(p, "configure");
fail("should have failed");
} catch(AssertionError e) {
if(e.getMessage().contains("doCheckXyz is broken"))
; // expected
else
throw e;
JenkinsRule.WebClient webclient = j.createWebClient();
WebResponseListener.StatusListener statusListener = new WebResponseListener.StatusListener(500);
webclient.addWebResponseListener(statusListener);
webclient.getPage(p, "configure");
statusListener.assertHasResponses();
String contentAsString = statusListener.getResponses().get(0).getContentAsString();
Assert.assertTrue(contentAsString.contains("doCheckXyz is broken"));
} finally {
Publisher.all().remove(d);
}
......
......@@ -58,7 +58,7 @@ import org.kohsuke.stapler.StaplerRequest;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.WebRequest;
public class RobustReflectionConverterTest {
......@@ -201,10 +201,11 @@ public class RobustReflectionConverterTest {
r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
WebClient wc = r.createWebClient();
wc.login("test", "test");
WebRequestSettings req = new WebRequestSettings(
WebRequest req = new WebRequest(
wc.createCrumbedUrl(String.format("%s/config.xml", p.getUrl())),
HttpMethod.POST
);
req.setEncodingType(null);
req.setRequestBody(String.format(CONFIGURATION_TEMPLATE, "badvalue", AcceptOnlySpecificKeyword.ACCEPT_KEYWORD));
wc.getPage(req);
......@@ -233,10 +234,11 @@ public class RobustReflectionConverterTest {
r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
WebClient wc = r.createWebClient();
wc.login("test", "test");
WebRequestSettings req = new WebRequestSettings(
WebRequest req = new WebRequest(
wc.createCrumbedUrl(String.format("%s/config.xml", p.getUrl())),
HttpMethod.POST
);
req.setEncodingType(null);
req.setRequestBody(String.format(CONFIGURATION_TEMPLATE, AcceptOnlySpecificKeyword.ACCEPT_KEYWORD, "badvalue"));
try {
......
......@@ -35,7 +35,7 @@ import static org.junit.Assert.fail;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
......@@ -287,11 +287,11 @@ public class JenkinsTest {
wc.goTo("script");
wc.assertFails("script?script=System.setProperty('hack','me')", HttpURLConnection.HTTP_BAD_METHOD);
assertNull(System.getProperty("hack"));
WebRequestSettings req = new WebRequestSettings(new URL(wc.getContextPath() + "script?script=System.setProperty('hack','me')"), HttpMethod.POST);
WebRequest req = new WebRequest(new URL(wc.getContextPath() + "script?script=System.setProperty('hack','me')"), HttpMethod.POST);
wc.getPage(wc.addCrumb(req));
assertEquals("me", System.getProperty("hack"));
wc.assertFails("scriptText?script=System.setProperty('hack','me')", HttpURLConnection.HTTP_BAD_METHOD);
req = new WebRequestSettings(new URL(wc.getContextPath() + "scriptText?script=System.setProperty('huck','you')"), HttpMethod.POST);
req = new WebRequest(new URL(wc.getContextPath() + "scriptText?script=System.setProperty('huck','you')"), HttpMethod.POST);
wc.getPage(wc.addCrumb(req));
assertEquals("you", System.getProperty("huck"));
wc.login("bob");
......@@ -333,7 +333,8 @@ public class JenkinsTest {
}
}
private String eval(WebClient wc) throws Exception {
WebRequestSettings req = new WebRequestSettings(wc.createCrumbedUrl("eval"), HttpMethod.POST);
WebRequest req = new WebRequest(wc.createCrumbedUrl("eval"), HttpMethod.POST);
req.setEncodingType(null);
req.setRequestBody("<j:jelly xmlns:j='jelly:core'>${1+2}</j:jelly>");
return wc.getPage(req).getWebResponse().getContentAsString();
}
......@@ -393,7 +394,7 @@ public class JenkinsTest {
assertTrue(!Jenkins.getInstance().getACL().hasPermission(Jenkins.ANONYMOUS,Jenkins.READ));
WebClient wc = j.createWebClient();
wc.setThrowExceptionOnFailingStatusCode(false);
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
HtmlPage p = wc.goTo("error/reportError");
assertEquals(p.asText(), 400, p.getWebResponse().getStatusCode()); // not 403 forbidden
......@@ -436,13 +437,15 @@ public class JenkinsTest {
@Test
public void runScriptOnOfflineComputer() throws Exception {
DumbSlave slave = j.createSlave();
DumbSlave slave = j.createSlave(true);
j.disconnectSlave(slave);
URL url = new URL(j.getURL(), "computer/" + slave.getNodeName() + "/scriptText?script=println(42)");
WebClient wc = j.createWebClient();
wc.setThrowExceptionOnFailingStatusCode(false);
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
WebRequestSettings req = new WebRequestSettings(url, HttpMethod.POST);
WebRequest req = new WebRequest(url, HttpMethod.POST);
Page page = wc.getPage(wc.addCrumb(req));
WebResponse rsp = page.getWebResponse();
......
......@@ -5,24 +5,45 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import com.gargoylesoftware.htmlunit.DownloadedContent;
import com.gargoylesoftware.htmlunit.HttpWebConnection;
import com.gargoylesoftware.htmlunit.WebConnection;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.WebResponseData;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import com.gargoylesoftware.htmlunit.util.UrlUtils;
import hudson.Util;
import hudson.model.User;
import jenkins.model.Jenkins;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScheme;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
import org.apache.commons.httpclient.auth.CredentialsProvider;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.JenkinsRule.WebClient;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
/**
......@@ -53,23 +74,10 @@ public class ApiTokenPropertyTest {
assertSame(t, u.getProperty(ApiTokenProperty.class));
WebClient wc = j.createWebClient();
wc.setCredentialsProvider(new CredentialsProvider() {
public Credentials getCredentials(AuthScheme scheme, String host, int port, boolean proxy) throws CredentialsNotAvailableException {
return new UsernamePasswordCredentials("foo", token);
}
});
wc.setWebConnection(new HttpWebConnection(wc) {
@Override
protected HttpClient getHttpClient() {
HttpClient c = super.getHttpClient();
c.getParams().setAuthenticationPreemptive(true);
c.getState().setCredentials(new AuthScope("localhost", AuthScope.ANY_PORT, AuthScope.ANY_REALM), new UsernamePasswordCredentials("foo", token));
return c;
}
});
configureWebConnection(wc, token);
// test the authentication
assertEquals(u,wc.executeOnServer(new Callable<User>() {
assertEquals(u, wc.executeOnServer(new Callable<User>() {
public User call() throws Exception {
return User.current();
}
......@@ -98,4 +106,71 @@ public class ApiTokenPropertyTest {
u.addProperty(t);
assertTrue(t.getApiToken().equals(Util.getDigestOf(historicalInitialValue+"somethingElse")));
}
private void configureWebConnection(final WebClient wc, final String token) throws IOException {
// See https://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html
final UsernamePasswordCredentials fooCreds = new UsernamePasswordCredentials("foo", token);
URL hostUrl = j.getURL();
final HttpHost targetHost = new HttpHost(hostUrl.getHost(), hostUrl.getPort(), hostUrl.getProtocol());
CredentialsProvider credsProvider = new BasicCredentialsProvider() {
@Override
public Credentials getCredentials(AuthScope authscope) {
return fooCreds;
}
};
credsProvider.setCredentials(
new AuthScope("localhost", AuthScope.ANY_PORT, AuthScope.ANY_REALM),
fooCreds);
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local auth cache
AuthScheme authScheme = new BasicScheme();
authCache.put(targetHost, authScheme);
// Add AuthCache to the execution context
final HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);
wc.setCredentialsProvider(credsProvider);
// Need to create our own WebConnection that gives us control of HttpClient execution,
// allowing us to pass our own HttpClientContext etc. HttpWebConnection has its own
// private HttpClientContext instance, which means we can't authenticate properly.
wc.setWebConnection(new WebConnection() {
@Override
public WebResponse getResponse(WebRequest request) throws IOException {
try {
long startTime = System.currentTimeMillis();
HttpClientBuilder builder = HttpClientBuilder.create();
CloseableHttpClient httpClient = builder.build();
URL url = UrlUtils.encodeUrl(request.getUrl(), false, request.getCharset());
HttpGet method = new HttpGet(url.toURI());
CloseableHttpResponse response = httpClient.execute(targetHost, method, context);
HttpEntity httpEntity = response.getEntity();
DownloadedContent responseBody = HttpWebConnection.downloadContent(httpEntity.getContent(), wc.getOptions().getMaxInMemory());
String statusMessage = response.getStatusLine().getReasonPhrase();
if (statusMessage == null) {
statusMessage = "Unknown status message";
}
int statusCode = response.getStatusLine().getStatusCode();
List<NameValuePair> headers = new ArrayList<>();
for (final Header header : response.getAllHeaders()) {
headers.add(new NameValuePair(header.getName(), header.getValue()));
}
WebResponseData responseData = new WebResponseData(responseBody, statusCode, statusMessage, headers);
return new WebResponse(responseData, request, (System.currentTimeMillis() - startTime));
} catch (Exception e) {
throw new AssertionError("Failed to execute WebRequest.", e);
}
}
});
}
}
......@@ -5,7 +5,7 @@ import static org.junit.Assert.fail;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.WebRequest;
import hudson.model.UnprotectedRootAction;
import hudson.model.User;
import hudson.util.HttpResponses;
......@@ -81,7 +81,8 @@ public class BasicHeaderProcessorTest {
}
private void makeRequestWithAuthAndVerify(String userAndPass, String username) throws IOException, SAXException {
WebRequestSettings req = new WebRequestSettings(new URL(j.getURL(),"test"));
WebRequest req = new WebRequest(new URL(j.getURL(),"test"));
req.setEncodingType(null);
if (userAndPass!=null)
req.setAdditionalHeader("Authorization","Basic "+Scrambler.scramble(userAndPass));
Page p = wc.getPage(req);
......
......@@ -5,7 +5,7 @@ import static org.junit.Assert.assertNull;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.apache.commons.httpclient.NameValuePair;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
......
package jenkins.security;
import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.html.HtmlButton;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
......@@ -100,8 +101,8 @@ public class RekeySecretAdminMonitorTest extends HudsonTestCase {
// should be no warning/error now
HtmlPage manage = wc.goTo("manage");
assertEquals(0,manage.selectNodes("//*[class='error']").size());
assertEquals(0,manage.selectNodes("//*[class='warning']").size());
assertEquals(0, DomNodeUtil.selectNodes(manage, "//*[class='error']").size());
assertEquals(0, DomNodeUtil.selectNodes(manage, "//*[class='warning']").size());
// and the data should be rewritten
verifyRewrite(jenkins.getRootDir());
......@@ -140,8 +141,8 @@ public class RekeySecretAdminMonitorTest extends HudsonTestCase {
// should be no warning/error now
HtmlPage manage = wc.goTo("/manage");
assertEquals(0,manage.selectNodes("//*[class='error']").size());
assertEquals(0,manage.selectNodes("//*[class='warning']").size());
assertEquals(0, DomNodeUtil.selectNodes(manage, "//*[class='error']").size());
assertEquals(0, DomNodeUtil.selectNodes(manage, "//*[class='warning']").size());
}
private String encryptOld(String str) throws Exception {
......
......@@ -20,7 +20,7 @@ public class Security177Test {
@Test
public void nosniff() throws Exception {
WebClient wc = jenkins.createWebClient();
wc.setThrowExceptionOnFailingStatusCode(false);
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
URL u = jenkins.getURL();
verifyNoSniff(wc.getPage(new URL(u, "adjuncts/507db12b/nosuch/adjunct.js")));
......
......@@ -59,14 +59,14 @@ public class BuildListTableTest {
assertEquals(0, wc.waitForBackgroundJavaScript(120000));
HtmlAnchor anchor = page.getAnchorByText("d » d2 » p");
String href = anchor.getHrefAttribute();
URL target = URI.create(page.getDocumentURI()).resolve(href).toURL();
URL target = URI.create(page.getUrl().toExternalForm()).resolve(href).toURL();
wc.getPage(target);
assertEquals(href, r.getURL() + "view/v1/job/d/view/v2/job/d2/job/p/", target.toString());
page = wc.goTo("job/d/view/All/builds?suppressTimelineControl=true");
assertEquals(0, wc.waitForBackgroundJavaScript(120000));
anchor = page.getAnchorByText("d » d2 » p");
href = anchor.getHrefAttribute();
target = URI.create(page.getDocumentURI()).resolve(href).toURL();
target = URI.create(page.getUrl().toExternalForm()).resolve(href).toURL();
wc.getPage(target);
assertEquals(href, r.getURL() + "job/d/job/d2/job/p/", target.toString());
}
......
package lib.form;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlFormUtil;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.util.FormValidation;
import net.sf.json.JSONObject;
......@@ -17,7 +18,7 @@ public class AdvancedButtonTest extends HudsonTestCase {
public void testNestedOptionalBlock() throws Exception {
HtmlPage p = createWebClient().goTo("self/testNestedOptionalBlock");
HtmlForm f = p.getFormByName("config");
f.getButtonByCaption("Advanced...").click();
HtmlFormUtil.getButtonByCaption(f, "Advanced...").click();
f.getInputByName("c").click();
submit(f);
}
......
......@@ -25,7 +25,7 @@ package lib.form;
import static com.gargoylesoftware.htmlunit.HttpMethod.POST;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.HudsonTestCase;
......@@ -53,7 +53,8 @@ public class ExpandableTextboxTest extends HudsonTestCase {
protected HtmlPage evaluateAsHtml(String jellyScript) throws Exception {
HudsonTestCase.WebClient wc = new WebClient();
WebRequestSettings req = new WebRequestSettings(wc.createCrumbedUrl("eval"), POST);
WebRequest req = new WebRequest(wc.createCrumbedUrl("eval"), POST);
req.setEncodingType(null);
req.setRequestBody("<j:jelly xmlns:j='jelly:core' xmlns:st='jelly:stapler' xmlns:l='/lib/layout' xmlns:f='/lib/form'>"+jellyScript+"</j:jelly>");
Page page = wc.getPage(req);
return (HtmlPage) page;
......
......@@ -24,6 +24,7 @@
package lib.form;
import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import com.gargoylesoftware.htmlunit.html.HtmlFormUtil;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlSelect;
......@@ -33,7 +34,6 @@ import java.util.ArrayList;
import java.util.List;
import com.gargoylesoftware.htmlunit.javascript.background.JavaScriptJob;
import com.gargoylesoftware.htmlunit.javascript.background.JavaScriptJobManagerImpl;
import hudson.DescriptorExtensionList;
import hudson.Extension;
import hudson.ExtensionPoint;
......@@ -68,11 +68,11 @@ public class RepeatableTest extends HudsonTestCase {
private void doTestSimple() throws Exception {
HtmlPage p = createWebClient().goTo("self/testSimple");
HtmlForm f = p.getFormByName("config");
f.getButtonByCaption("Add").click();
HtmlFormUtil.getButtonByCaption(f, "Add").click();
f.getInputByValue("").setValueAttribute("value one");
f.getButtonByCaption("Add").click();
HtmlFormUtil.getButtonByCaption(f, "Add").click();
f.getInputByValue("").setValueAttribute("value two");
f.getButtonByCaption("Add").click();
HtmlFormUtil.getButtonByCaption(f, "Add").click();
f.getInputByValue("").setValueAttribute("value three");
f.getInputsByName("bool").get(2).click();
submit(f);
......@@ -201,10 +201,10 @@ public class RepeatableTest extends HudsonTestCase {
public void testRadio() throws Exception {
HtmlPage p = createWebClient().goTo("self/testRadio");
HtmlForm f = p.getFormByName("config");
f.getButtonByCaption("Add").click();
HtmlFormUtil.getButtonByCaption(f, "Add").click();
f.getInputByValue("").setValueAttribute("txt one");
f.getElementsByAttribute("INPUT", "type", "radio").get(1).click();
f.getButtonByCaption("Add").click();
HtmlFormUtil.getButtonByCaption(f, "Add").click();
f.getInputByValue("").setValueAttribute("txt two");
f.getElementsByAttribute("INPUT", "type", "radio").get(3).click();
submit(f);
......@@ -224,7 +224,7 @@ public class RepeatableTest extends HudsonTestCase {
list.add(new FooRadio("three", "one"));
HtmlPage p = createWebClient().goTo("self/testRadio");
HtmlForm f = p.getFormByName("config");
f.getButtonByCaption("Add").click();
HtmlFormUtil.getButtonByCaption(f, "Add").click();
f.getInputByValue("").setValueAttribute("txt 4");
f.getElementsByAttribute("INPUT", "type", "radio").get(7).click();
submit(f);
......@@ -238,12 +238,12 @@ public class RepeatableTest extends HudsonTestCase {
public void testRadioBlock() throws Exception {
HtmlPage p = createWebClient().goTo("self/testRadioBlock");
HtmlForm f = p.getFormByName("config");
f.getButtonByCaption("Add").click();
HtmlFormUtil.getButtonByCaption(f, "Add").click();
f.getInputByValue("").setValueAttribute("txt one");
f.getInputByValue("").setValueAttribute("avalue do not send");
f.getElementsByAttribute("INPUT", "type", "radio").get(1).click();
f.getInputByValue("").setValueAttribute("bvalue");
f.getButtonByCaption("Add").click();
HtmlFormUtil.getButtonByCaption(f, "Add").click();
f.getInputByValue("").setValueAttribute("txt two");
f.getElementsByAttribute("INPUT", "type", "radio").get(2).click();
f.getInputByValue("").setValueAttribute("avalue two");
......@@ -303,11 +303,11 @@ public class RepeatableTest extends HudsonTestCase {
public void testDropdownList() throws Exception {
HtmlPage p = createWebClient().goTo("self/testDropdownList");
HtmlForm f = p.getFormByName("config");
f.getButtonByCaption("Add").click();
HtmlFormUtil.getButtonByCaption(f, "Add").click();
waitForJavaScript(p);
f.getInputByValue("").setValueAttribute("17"); // seeds
f.getInputByValue("").setValueAttribute("pie"); // word
f.getButtonByCaption("Add").click();
HtmlFormUtil.getButtonByCaption(f, "Add").click();
waitForJavaScript(p);
// select banana in 2nd select element:
((HtmlSelect)f.getElementsByTagName("select").get(1)).getOption(1).click();
......@@ -367,7 +367,7 @@ public class RepeatableTest extends HudsonTestCase {
}
private void clickButton(HtmlPage p, HtmlForm f, String caption) throws IOException {
f.getButtonByCaption(caption).click();
HtmlFormUtil.getButtonByCaption(f, caption).click();
waitForJavaScript(p);
}
......@@ -377,10 +377,10 @@ public class RepeatableTest extends HudsonTestCase {
try {
clickButton(p, f, "Add");
f.getElementsByAttribute("input", "type", "radio").get(1).click(); // outer=two
f.getButtonByCaption("Add Moo").click();
HtmlFormUtil.getButtonByCaption(f, "Add Moo").click();
waitForJavaScript(p);
f.getElementsByAttribute("input", "type", "radio").get(2).click(); // inner=inone
f.getButtonByCaption("Add").click();
HtmlFormUtil.getButtonByCaption(f, "Add").click();
waitForJavaScript(p);
f.getElementsByAttribute("input", "type", "radio").get(4).click(); // outer=one
Thread.sleep(500);
......
package lib.form;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlOption;
......@@ -42,9 +43,9 @@ public class RowVisibilityGroupTest extends HudsonTestCase implements Describabl
public void test1() throws Exception {
HtmlPage p = createWebClient().goTo("self/test1");
HtmlElement outer = (HtmlElement)p.selectSingleNode("//INPUT[@name='outer']");
HtmlElement inner = (HtmlElement)p.selectSingleNode("//INPUT[@name='inner']");
HtmlInput field = (HtmlInput)p.selectSingleNode("//INPUT[@type='text'][@name='_.field']");
HtmlElement outer = (HtmlElement)DomNodeUtil.selectSingleNode(p, "//INPUT[@name='outer']");
HtmlElement inner = (HtmlElement)DomNodeUtil.selectSingleNode(p, "//INPUT[@name='inner']");
HtmlInput field = (HtmlInput)DomNodeUtil.selectSingleNode(p, "//INPUT[@type='text'][@name='_.field']");
// outer gets unfolded, but inner should be still folded
outer.click();
......@@ -67,7 +68,7 @@ public class RowVisibilityGroupTest extends HudsonTestCase implements Describabl
public void test2() throws Exception {
HtmlPage p = createWebClient().goTo("self/test2");
HtmlSelect s = (HtmlSelect)p.selectSingleNode("//SELECT");
HtmlSelect s = (HtmlSelect)DomNodeUtil.selectSingleNode(p, "//SELECT");
List<HtmlOption> opts = s.getOptions();
// those first selections will load additional HTMLs
......@@ -78,13 +79,13 @@ public class RowVisibilityGroupTest extends HudsonTestCase implements Describabl
s.setSelectedAttribute(opts.get(0),true);
// make sure that the inner control is still hidden
List<HtmlInput> textboxes = p.selectNodes("//INPUT[@name='_.textbox2']");
List<HtmlInput> textboxes = DomNodeUtil.selectNodes(p, "//INPUT[@name='_.textbox2']");
assertEquals(2,textboxes.size());
for (HtmlInput e : textboxes)
assertTrue(!e.isDisplayed());
// reveal the text box
List<HtmlInput> checkboxes = p.selectNodes("//INPUT[@name='inner']");
List<HtmlInput> checkboxes = DomNodeUtil.selectNodes(p, "//INPUT[@name='inner']");
assertEquals(2,checkboxes.size());
checkboxes.get(0).click();
assertTrue(textboxes.get(0).isDisplayed());
......
......@@ -23,6 +23,9 @@
*/
package lib.form;
import com.gargoylesoftware.htmlunit.html.HtmlButton;
import com.gargoylesoftware.htmlunit.html.HtmlElementUtil;
import com.gargoylesoftware.htmlunit.html.HtmlFormUtil;
import org.jvnet.hudson.test.HudsonTestCase;
import org.kohsuke.stapler.QueryParameter;
import hudson.model.Describable;
......@@ -41,7 +44,8 @@ public class ValidateButtonTest extends HudsonTestCase implements Describable<Va
DescriptorImpl d = getDescriptor();
d.test1Outcome = new Exception(); // if doValidateTest1() doesn't get invoked, we want to know.
HtmlPage p = createWebClient().goTo("self/test1");
p.getFormByName("config").getButtonByCaption("test").click();
HtmlButton button = HtmlFormUtil.getButtonByCaption(p.getFormByName("config"), "test");
HtmlElementUtil.click(button);
if (d.test1Outcome!=null)
throw d.test1Outcome;
}
......
......@@ -2,6 +2,7 @@ package lib.hudson;
import static org.junit.Assert.assertTrue;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.html.HtmlOption;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSelect;
......@@ -41,7 +42,7 @@ public class ListScmBrowsersTest {
private void check(Item p) throws IOException, SAXException {
HtmlPage page = j.createWebClient().getPage(p, "configure");
List<HtmlSelect> selects = page.selectNodes("//select");
List<HtmlSelect> selects = DomNodeUtil.selectNodes(page, "//select");
assertTrue(selects.size()>0);
for (HtmlSelect select : selects) {
Set<String> title = new HashSet<String>();
......
......@@ -23,9 +23,7 @@
*/
package lib.layout;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.google.common.collect.Lists;
......@@ -53,8 +51,8 @@ public class IconTest extends HudsonTestCase {
public void testIcons() throws Exception {
HtmlPage p = createWebClient().goTo("self/01_testIcons");
HtmlElement iconsBlock = p.getElementById("iconsBlock");
List<HtmlElement> icons = Lists.newArrayList(iconsBlock.getChildElements());
DomElement iconsBlock = p.getElementById("iconsBlock");
List<DomElement> icons = Lists.newArrayList(iconsBlock.getChildElements());
assertIconToImageOkay(icons.get(0), "/images/16x16/aborted.png", "icon-aborted icon-sm");
assertIconToImageOkay(icons.get(1), "/images/24x24/aborted.png", "icon-aborted icon-md");
......@@ -72,12 +70,12 @@ public class IconTest extends HudsonTestCase {
public void testBallColorTd() throws Exception {
HtmlPage p = createWebClient().goTo("self/02_testBallColorTd");
HtmlElement ballColorAborted = p.getElementById("ballColorAborted");
List<HtmlElement> ballIcons = Lists.newArrayList(ballColorAborted.getChildElements());
DomElement ballColorAborted = p.getElementById("ballColorAborted");
List<DomElement> ballIcons = Lists.newArrayList(ballColorAborted.getChildElements());
assertIconToImageOkay(ballIcons.get(0), "/images/32x32/aborted.png", "icon-aborted icon-lg");
HtmlElement statusIcons = p.getElementById("statusIcons");
List<HtmlElement> statusIconsList = Lists.newArrayList(statusIcons.getChildElements());
DomElement statusIcons = p.getElementById("statusIcons");
List<DomElement> statusIconsList = Lists.newArrayList(statusIcons.getChildElements());
assertIconToImageOkay(statusIconsList.get(0), "/images/32x32/folder.png", "icon-folder icon-lg");
assertIconToImageOkay(statusIconsList.get(1), "/plugin/12345/icons/s2.png");
......@@ -86,8 +84,8 @@ public class IconTest extends HudsonTestCase {
public void testTasks() throws Exception {
HtmlPage p = createWebClient().goTo("self/03_testTask");
HtmlElement tasksDiv = p.getElementById("tasks");
List<HtmlElement> taskDivs = Lists.newArrayList(tasksDiv.getChildElements());
DomElement tasksDiv = p.getElementById("tasks");
List<DomElement> taskDivs = Lists.newArrayList(tasksDiv.getChildElements());
assertIconToImageOkay(taskDivs.get(0).getElementsByTagName("img").get(0), "/images/24x24/up.png", "icon-up icon-md");
assertIconToImageOkay(taskDivs.get(1).getElementsByTagName("img").get(0), "/images/24x24/folder.png", "icon-folder icon-md");
......@@ -120,11 +118,11 @@ public class IconTest extends HudsonTestCase {
};
}
private void assertIconToImageOkay(HtmlElement icon, String imgPath) {
private void assertIconToImageOkay(DomElement icon, String imgPath) {
assertIconToImageOkay(icon, imgPath, null);
}
private void assertIconToImageOkay(HtmlElement icon, String imgPath, String classSpec) {
private void assertIconToImageOkay(DomElement icon, String imgPath, String classSpec) {
assertEquals("img", icon.getTagName());
assertTrue(icon.getAttribute("src").endsWith(imgPath));
if (classSpec != null) {
......
......@@ -24,7 +24,7 @@
package lib.layout;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.HtmlLink;
import org.junit.Rule;
import org.junit.Test;
......@@ -41,7 +41,7 @@ public class LayoutTest {
@Test public void rejectedLinks() throws Exception {
JenkinsRule.WebClient wc = r.createWebClient();
String prefix = r.contextPath + '/';
for (HtmlElement e : wc.goTo("login").getElementsByTagName("link")) {
for (DomElement e : wc.goTo("login").getElementsByTagName("link")) {
String href = ((HtmlLink) e).getHrefAttribute();
if (!href.startsWith(prefix)) {
System.err.println("ignoring " + href);
......
......@@ -24,6 +24,8 @@
package lib.layout;
import com.gargoylesoftware.htmlunit.ScriptResult;
import com.gargoylesoftware.htmlunit.WebClientUtil;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.jvnet.hudson.test.HudsonTestCase;
......@@ -41,9 +43,11 @@ public class RenderOnDemandTest extends HudsonTestCase {
HtmlPage p = createWebClient().goTo("self/testBehaviour");
p.executeJavaScript("renderOnDemand(document.getElementsBySelector('.lazy')[0])");
WebClientUtil.waitForJSExec(p.getWebClient());
// all AJAX calls complete before the above method returns
ScriptResult r = p.executeJavaScript("var r=document.getElementsBySelector('DIV.a'); r[0].innerHTML+r[1].innerHTML+r[2].innerHTML");
WebClientUtil.waitForJSExec(p.getWebClient());
assertEquals("AlphaBravoCharlie",r.getJavaScriptResult().toString());
}
......@@ -75,14 +79,17 @@ public class RenderOnDemandTest extends HudsonTestCase {
HtmlPage p = createWebClient().goTo("self/testScript");
assertNull(p.getElementById("loaded"));
p.getElementById("button").click();
((HtmlElement)p.getElementById("button")).click();
WebClientUtil.waitForJSExec(p.getWebClient());
// all AJAX calls complete before the above method returns
assertNotNull(p.getElementById("loaded"));
ScriptResult r = p.executeJavaScript("x");
WebClientUtil.waitForJSExec(p.getWebClient());
assertEquals("xxx",r.getJavaScriptResult().toString());
r = p.executeJavaScript("y");
WebClientUtil.waitForJSExec(p.getWebClient());
assertEquals("yyy",r.getJavaScriptResult().toString());
// if you want to test this in the browser
......
......@@ -29,6 +29,7 @@ import java.io.IOException;
import javax.servlet.ServletException;
import com.gargoylesoftware.htmlunit.html.HtmlElementUtil;
import hudson.model.UnprotectedRootAction;
import org.junit.Rule;
......@@ -49,7 +50,7 @@ public class TaskTest {
@Test public void postLink() throws Exception {
WebClient wc = j.createWebClient();
HtmlPage page = wc.goTo(postLink.getUrlName());
page.getAnchorByText("POST").click();
HtmlElementUtil.click(page.getAnchorByText("POST"));
assertTrue("Action method should be invoked", postLink.called);
}
......
......@@ -62,7 +62,7 @@ public class UseRecipesWithJenkinsRuleTest {
private void verifyNotError(WebClient wc) throws IOException, SAXException {
HtmlPage p = wc.goTo("loginError");
URL url = p.getWebResponse().getUrl();
URL url = p.getUrl();
System.out.println(url);
assertFalse(url.toExternalForm().contains("login"));
}
......
......@@ -29,6 +29,11 @@
// for memory leak patterns and how to prevent them.
//
if (window.isRunAsTest) {
// Disable postMessage when running in test mode (HtmlUnit).
window.postMessage = false;
}
// create a new object whose prototype is the given object
function object(o) {
function F() {}
......
......@@ -1923,13 +1923,7 @@ if (!Node.ELEMENT_NODE) {
}
var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){
try {
var el = document.createElement('<input name="x">');
return el.tagName.toLowerCase() === 'input' && el.name === 'x';
}
catch(err) {
return false;
}
return false;
})();
var element = global.Element;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册