/*
* JBoss, Home of Professional Open Source.
* Copyright 2009, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.jopr.jsfunit;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlButtonInput;
import com.gargoylesoftware.htmlunit.html.HtmlFileInput;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.servlet.http.HttpServletRequest;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.cactus.ServletTestCase;
import org.jboss.jopr.jsfunit.exceptions.EmbJoprTestException;
import org.jboss.jopr.jsfunit.exceptions.HtmlElementNotFoundException;
import org.jboss.jopr.jsfunit.util.EmbJoprTestToolkit;
import org.jboss.jsfunit.framework.WebClientSpec;
import org.jboss.jsfunit.jsfsession.JSFClientSession;
import org.jboss.jsfunit.jsfsession.JSFServerSession;
import org.jboss.jsfunit.jsfsession.JSFSession;
import org.jboss.mx.util.MBeanServerLocator;
/**
* Sample for testing Embedded Jopr. Here I present a fairly complex test
* case to show some of the things that JSFUnit can do.
*
* @author Stan Silvert
*/
public class HelloJoprTest extends ServletTestCase {
private boolean isJBoss4;
private JSFClientSession client;
private JSFServerSession server;
/**
* Start a JSFUnit session by logging in to the main page. Note that
* because setUp() is called before each test, a new HttpSession will be
* created each time a test is run.
*/
public void setUp() throws IOException {
isJBoss4 = Package.getPackage("org.jboss.system.server").getImplementationVersion().startsWith("4");
// Initial JSF request
WebClientSpec wcSpec = new WebClientSpec("/", BrowserVersion.FIREFOX_3);
// This is temporary because embedded Jopr can't find /js/rhq.js
wcSpec.getWebClient().setThrowExceptionOnFailingStatusCode(false);
// Always press OK for confirm dialogs
wcSpec.getWebClient().setConfirmHandler(new SimpleConfirmHandler(true));
wcSpec.setInitialRequestStrategy(new JoprLoginStrategy()); // logs in
JSFSession jsfSession = new JSFSession(wcSpec);
this.client = jsfSession.getJSFClientSession();
this.server = jsfSession.getJSFServerSession();
}
/**
* @return the suite of tests being tested
*/
public static Test suite() {
return new TestSuite(HelloJoprTest.class);
}
public void testDeployWAR() throws IOException, HtmlElementNotFoundException, EmbJoprTestException {
final String DEPLOYABLE_NAME = "hellothere.war";
final EmbJoprTestToolkit ejtt = new EmbJoprTestToolkit(client, server);
// Click the nav tree.
String linkLabel = "Web Application (WAR)s";
//HtmlAnchor warLink = getNavTreeLink(linkLabel);
HtmlAnchor warLink = ejtt.navTree.getNodeLink(linkLabel);
warLink.click();
// click on the "Add new resource" button
DebugUtils.writeFile("target/testDeployWAR-beforeAdd.html", client.getPageAsText());///
client.click("actionHeaderForm:addNewContent"); // 404 if setThrowExceptionOnFailingStatusCode(true) above
// upload hellothere.war
HtmlFileInput fileInput = (HtmlFileInput) client.getElement("createContentForm:file");
fileInput.setContentType("application/war");
fileInput.setValueAttribute(System.getProperty("jsfunit.testdata") + "/war/hellothere.war");
client.click("createContentForm:addButton");
// assert that the success message appeared on the client side
assertTrue(client.getPageAsText().contains("hellothere.war created successfully"));
// assert text and sevrity level for FacesMessage on server side
assertTrue(server.getFacesMessages().hasNext());
FacesMessage successMessage = server.getFacesMessages().next();
assertTrue(FacesMessage.SEVERITY_INFO.equals(successMessage.getSeverity()));
assertTrue(successMessage.getDetail().contains("hellothere.war created successfully"));
// Use JMX to assert that the WAR really did deploy successfully
assertTrue(isWarDeployed(DEPLOYABLE_NAME));
// use HtmlUnit to test the newly deployed war in a new WebClient session
// note that I have full access to the FacesContext and the previous request
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
int port = request.getLocalPort();
WebClient webClient = new WebClient();
HtmlPage page = (HtmlPage) webClient.getPage("http://localhost:" + port + "/hellothere/hello.jsp");
assertTrue(page.asText().contains("HELLO WORLD"));
/* Doesn't work when the WAR is not on first page of listing.
// Undeploy the WAR
HtmlButtonInput deleteButton = getDeleteButton(DEPLOYABLE_NAME);
deleteButton.click();*/
ejtt.deployment.undeployViaEmbJopr(AppConstants.DeployableTypes.WAR, DEPLOYABLE_NAME);
assertFalse(isWarDeployed(DEPLOYABLE_NAME));
}
private boolean isWarDeployed(String warName) {
if (isJBoss4) {
return checkWarDeployment_4_2(warName);
} else {
return checkWarDeployment_5_0(warName);
}
}
/** Query the MBean server to find if WAR is deployed. */
private boolean checkWarDeployment_4_2(String warName) {
try {
MBeanServer jmxServer = MBeanServerLocator.locateJBoss();
ObjectName objName = new ObjectName("jboss.web.deployment:war=" + warName + ",*");
Set mBeans = jmxServer.queryNames(objName, null);
if (mBeans.size() != 1) {
return false;
}
ObjectName deploymentMBean = (ObjectName) mBeans.iterator().next();
String state = (String) jmxServer.getAttribute(deploymentMBean, "StateString");
return "Started".equals(state);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/** Query the MBean server to find if WAR is deployed. */
private boolean checkWarDeployment_5_0(String warName) {
if (warName.endsWith(".war")) {
warName = warName.substring(0, warName.lastIndexOf(".war"));
} else {
warName = warName.substring(0, warName.lastIndexOf(".WAR"));
}
try {
MBeanServer jmxServer = MBeanServerLocator.locateJBoss();
ObjectName objName = new ObjectName("jboss.deployment:id=\"jboss.web.deployment:war=/" + warName + "\",*");
Set mBeans = jmxServer.queryNames(objName, null);
if (mBeans.size() != 1) {
return false;
}
ObjectName deploymentMBean = (ObjectName) mBeans.iterator().next();
// returns org.jboss.deployers.spi.DeploymentState
Object state = jmxServer.getAttribute(deploymentMBean, "State");
return "DEPLOYED".equals(state.toString());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// need a standard JSFUnit API to replace this code
private HtmlAnchor getNavTreeLink(String linkLabel) {
return getLinkInsideForm("navTreeForm", linkLabel);
}
private HtmlButtonInput getDeleteButton(String resourceName) {
HtmlAnchor link = getLinkInsideForm("resourceSummaryForm", resourceName);
// The id will look like "resourceSummaryForm:dataTable:2:resourceName"
// I need the row number. (2 in the above example)
String id = link.getIdAttribute();
String[] idElements = id.split(":");
String row = idElements[idElements.length - 2];
return (HtmlButtonInput) client.getElement(row + ":removeButton");
}
/** Finds a <a> tag inside a form that has a particular label. */
private HtmlAnchor getLinkInsideForm(String formId, String linkLabel) {
HtmlForm form = (HtmlForm) client.getElement(formId);
List links = form.getByXPath(".//a"); // get all <a> tags inside form
for (Iterator i = links.iterator(); i.hasNext();) {
HtmlAnchor link = (HtmlAnchor) i.next();
String linkText = link.getTextContent();
if (linkText.contains(linkLabel)) {
return link;
}
}
throw new IllegalStateException("Nav Tree link for '" + linkLabel + "' not found.");
}
}// class