[embjopr-commits] EMBJOPR SVN: r74 - in trunk: core/src/main/webapp/secure and 2 other directories.

embjopr-commits at lists.jboss.org embjopr-commits at lists.jboss.org
Tue Dec 16 15:13:35 EST 2008


Author: fjuma
Date: 2008-12-16 15:13:35 -0500 (Tue, 16 Dec 2008)
New Revision: 74

Added:
   trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/DatasourceTest.java
   trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/EmbjoprTestCase.java
Modified:
   trunk/core/src/main/webapp/include/tabMenu.xhtml
   trunk/core/src/main/webapp/secure/categorySummary.xhtml
   trunk/core/src/main/webapp/secure/resourceCreatePage1.xhtml
   trunk/core/src/main/webapp/secure/resourceInstanceConfig.xhtml
   trunk/core/src/main/webapp/secure/resourceInstanceMetrics.xhtml
   trunk/jsfunit/pom.xml
Log:
Added a base test class for Embedded Jopr JSFUnit tests and added a test class that currently contains some preliminary datasource creation tests.

Added ID attributes to tags in some xhtml files.


Modified: trunk/core/src/main/webapp/include/tabMenu.xhtml
===================================================================
--- trunk/core/src/main/webapp/include/tabMenu.xhtml	2008-12-16 20:10:13 UTC (rev 73)
+++ trunk/core/src/main/webapp/include/tabMenu.xhtml	2008-12-16 20:13:35 UTC (rev 74)
@@ -72,7 +72,7 @@
         <h:panelGroup layout="block"
                       rendered="#{activeTab ne 'configuration' and navigationAction.enabledTabs.contains('configuration')}">
             <li>
-                <s:link styleClass="" action="#{resourceConfigurationUIBean.resourceConfiguration()}" propagation="end">
+                <s:link id="configurationTab" styleClass="" action="#{resourceConfigurationUIBean.resourceConfiguration()}" propagation="end">
                     #{messages['tab.menu.configuration']}
                 </s:link>
             </li>
@@ -97,7 +97,7 @@
         <h:panelGroup layout="block"
                       rendered="#{activeTab ne 'metric' and navigationAction.enabledTabs.contains('metric')}">
             <li>
-                <s:link styleClass="" view="/secure/resourceInstanceMetrics.xhtml" propagation="end">
+                <s:link id="metricsTab" styleClass="" view="/secure/resourceInstanceMetrics.xhtml" propagation="end">
                     #{messages['tab.menu.metrics']}
                 </s:link>
             </li>

Modified: trunk/core/src/main/webapp/secure/categorySummary.xhtml
===================================================================
--- trunk/core/src/main/webapp/secure/categorySummary.xhtml	2008-12-16 20:10:13 UTC (rev 73)
+++ trunk/core/src/main/webapp/secure/categorySummary.xhtml	2008-12-16 20:13:35 UTC (rev 74)
@@ -71,7 +71,7 @@
                 </h:selectOneMenu>
             </h:form>
         </div>
-        <h:form>
+        <h:form id="categorySummaryForm">
             <rich:dataTable
                     id="dataTable"
                     rows="#{tableManager.numRows}"
@@ -117,7 +117,8 @@
                     <h:outputText value="#{resourceItem.availability}"/>
                 </rich:column>
                 <rich:column>
-                    <s:button action="#{resourceCRUDAction.removeResourceAction()}" value="Delete"
+                    <s:button id="removeButton"
+                              action="#{resourceCRUDAction.removeResourceAction()}" value="Delete"
                               styleClass="buttonsmall"
                               rendered="#{resourceItem.resource.resourceType.deletable}">
                         <f:param name="resourceId" value="#{resourceItem.resource.id}"/>

Modified: trunk/core/src/main/webapp/secure/resourceCreatePage1.xhtml
===================================================================
--- trunk/core/src/main/webapp/secure/resourceCreatePage1.xhtml	2008-12-16 20:10:13 UTC (rev 73)
+++ trunk/core/src/main/webapp/secure/resourceCreatePage1.xhtml	2008-12-16 20:13:35 UTC (rev 74)
@@ -36,7 +36,7 @@
                 <ui:include src="../include/displayGlobalMessages.xhtml"/>
 
                 <hr/>
-                <h:form>
+                <h:form id="resourceCreateForm">
                     <h:panelGrid styleClass="formstyle">
 
                         <ui:include src="/include/formDropDownComponent.xhtml">
@@ -50,9 +50,10 @@
                         </ui:include>
                     </h:panelGrid>
                     <h:panelGrid columns="2" styleClass="buttons-table" columnClasses="button-cell">
-                        <h:commandButton value="#{messages['resource.add.button.continue']}"
-                                             action="#{templateDropDownPopulator.populateFromTemplate()}"
-                                             styleClass="buttonmed"/>
+                        <h:commandButton id="addButton" 
+                                         value="#{messages['resource.add.button.continue']}"
+                                         action="#{templateDropDownPopulator.populateFromTemplate()}"
+                                         styleClass="buttonmed"/>
                             <s:button value="#{messages['resource.add.button.cancel']}"
                                       view="/secure/summary.xhtml"
                                       styleClass="buttonmed"

Modified: trunk/core/src/main/webapp/secure/resourceInstanceConfig.xhtml
===================================================================
--- trunk/core/src/main/webapp/secure/resourceInstanceConfig.xhtml	2008-12-16 20:10:13 UTC (rev 73)
+++ trunk/core/src/main/webapp/secure/resourceInstanceConfig.xhtml	2008-12-16 20:13:35 UTC (rev 74)
@@ -71,12 +71,14 @@
                                 nullConfigurationStyle="infoBlock"/>
 
                     <h:panelGrid columns="2" styleClass="buttons-table" columnClasses="button-cell">
-                        <h:commandButton type="submit"
+                        <h:commandButton id="saveButton"
+                                         type="submit"
                                          action="#{resourceConfigurationUIBean.saveConfiguration()}"
                                          value="Save"
                                          alt="Click to Save Changes"
                                          styleClass="buttonmed"/>
-                        <s:button value="#{messages['resource.add.button.cancel']}"
+                        <s:button id="cancelButton"
+                                  value="#{messages['resource.add.button.cancel']}"
                                   view="/secure/summary.xhtml"
                                   styleClass="buttonmed"
                                   propagation="end"/>

Modified: trunk/core/src/main/webapp/secure/resourceInstanceMetrics.xhtml
===================================================================
--- trunk/core/src/main/webapp/secure/resourceInstanceMetrics.xhtml	2008-12-16 20:10:13 UTC (rev 73)
+++ trunk/core/src/main/webapp/secure/resourceInstanceMetrics.xhtml	2008-12-16 20:13:35 UTC (rev 74)
@@ -72,6 +72,7 @@
                 <h2>#{messages['metrics.resourceInstance.numericMetricValues']}</h2>
 
                 <rich:dataTable
+                        id="dataTable"
                         value="#{measurementCategoryList}" var="category"
                         rendered="#{measurementCategoryList ne null}"
                         styleClass="controlTable"
@@ -91,7 +92,7 @@
                             rowClasses="oddRow,evenRow"
                             columnClasses="rich-table-cell, rich-table-cell, rich-table-cell-action">
                         <rich:column>#{measurementDefinitionMap[md.measurementData.name].displayName}</rich:column>
-                        <rich:column>#{md.measurementValueAndUnits}</rich:column>
+                        <rich:column id="measurementValue">#{md.measurementValueAndUnits}</rich:column>
                         <rich:column>#{measurementDefinitionMap[md.measurementData.name].description}</rich:column>
                     </rich:subTable>
                     <f:facet name="footer"><h:graphicImage value="images/spacer.gif"/>

Modified: trunk/jsfunit/pom.xml
===================================================================
--- trunk/jsfunit/pom.xml	2008-12-16 20:10:13 UTC (rev 73)
+++ trunk/jsfunit/pom.xml	2008-12-16 20:13:35 UTC (rev 74)
@@ -72,6 +72,11 @@
          <scope>provided</scope>
          <version>2.8.1</version>
       </dependency>
+      <dependency>
+         <groupId>jdom</groupId>
+         <artifactId>jdom</artifactId>
+         <version>1.0</version>
+      </dependency>
    </dependencies>
    <profiles>
       <profile>
@@ -102,6 +107,7 @@
                              result is in server.log 
                            <jsfunit.htmlunitsnooper>enabled</jsfunit.htmlunitsnooper> -->
                            <jsfunit.testdata>${basedir}/testdata</jsfunit.testdata>
+                           <jsfunit.deploy.dir>${basedir}/target/jboss42x/deploy</jsfunit.deploy.dir>
                         </systemProperties>
                      </container>
                   </configuration>
@@ -185,6 +191,7 @@
                            <!-- Snoops request and response from client side. Result is in server.log
                            <jsfunit.htmlunitsnooper>enabled</jsfunit.htmlunitsnooper> -->
                            <jsfunit.testdata>${basedir}/testdata</jsfunit.testdata>
+                           <jsfunit.deploy.dir>${basedir}/target/jboss5x/deploy</jsfunit.deploy.dir>
                         </systemProperties>
                      </container>
                   </configuration>

Added: trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/DatasourceTest.java
===================================================================
--- trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/DatasourceTest.java	                        (rev 0)
+++ trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/DatasourceTest.java	2008-12-16 20:13:35 UTC (rev 74)
@@ -0,0 +1,394 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, 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.html.HtmlAnchor;
+import com.gargoylesoftware.htmlunit.html.HtmlButtonInput;
+import com.gargoylesoftware.htmlunit.html.HtmlForm;
+import com.gargoylesoftware.htmlunit.html.HtmlImage;
+import com.gargoylesoftware.htmlunit.html.HtmlSelect;
+import com.gargoylesoftware.htmlunit.html.HtmlInput;
+import java.io.IOException;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.jboss.mx.util.MBeanServerLocator;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import java.util.Set;
+import java.util.Iterator;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.input.SAXBuilder;
+import org.jdom.JDOMException;
+import java.io.File;
+import java.util.Map;
+import java.util.HashMap;
+import javax.naming.InitialContext;
+import java.sql.Connection;
+import javax.sql.DataSource;
+import javax.naming.Context;
+import java.sql.SQLException;
+import org.jboss.jopr.jsfunit.EmbjoprTestCase;
+
+/**
+ * When complete, this class will contain tests for creating, 
+ * configuring, and deleting various types of datasources. This
+ * test class should be run against JBAS 5.x.
+ * 
+ * @author Farah Juma
+ *
+ */
+public class DatasourceTest extends EmbjoprTestCase {
+    
+    // Datasource types, as they appear in the left nav
+    private final String LOCAL_TX_DATASOURCE="Local TX Datasources";
+    private final String NO_TX_DATASOURCE="No TX Datasources";
+    private final String XA_DATASOURCE="XA Datasources";
+    
+    /**
+     * Create a new datasource using the given type, template, and properties.
+     * 
+     * @param datasourceType must be the name of a datasource type, as it 
+     * appears in the left nav (eg. "Local TX Datasources")
+     */
+    private void createDatasource(String datasourceType, 
+                                  String datasourceTemplate,
+                                  Map<String, String> propertiesMap) throws IOException {
+        
+        // Expand the "Datasources" tree node
+        HtmlImage resourceNodeImage = getNavTreeArrow("Datasources");
+        resourceNodeImage.click();
+        
+        HtmlAnchor datasourceLink = getNavTreeLink(datasourceType);
+        datasourceLink.click();
+        
+        // Add a new datasource 
+        client.click("actionHeaderForm:addNewNotContent");
+        HtmlSelect menu = (HtmlSelect)client.getElement("selectedTemplate");
+        menu.setSelectedAttribute(datasourceTemplate, Boolean.TRUE);
+        client.click("resourceCreateForm:addButton");
+        
+        // Configure the properties associated with this datasource
+        fillOutForm(propertiesMap);  
+    }
+    
+    /**
+     * Delete the datasource given by datasourceName.
+     */
+    private void deleteDatasource(String datasourceName) throws IOException {
+        HtmlAnchor datasourceLink = getNavTreeLink("Datasources");
+        datasourceLink.click();
+        HtmlButtonInput deleteButton = getDeleteButton("categorySummaryForm", 
+                                                       datasourceName);
+        deleteButton.click();
+    }
+    
+    /**
+     * Use JMX to check if the datasource given by datasourceName is 
+     * deployed.
+     */
+    private boolean isDatasourceDeployed(String jndiName, 
+                                         String datasourceType) {
+        try {
+
+            ObjectName deploymentMBean;
+            ObjectName objName;
+            Object state;
+            Set dsMBeans;
+            String service;
+            
+            // One of the MBeans we will need to inspect depends on
+            // the type of datasource
+            if(datasourceType.equals(LOCAL_TX_DATASOURCE)) {
+                service="LocalTxCM";
+            } else if(datasourceType.equals(NO_TX_DATASOURCE)) {
+                service="NoTxCM";
+            } else {
+                service="XATxCM";
+            }
+            
+            String[] dsMBeanServices = {"DataSourceBinding", 
+                                        "ManagedConnectionPool", 
+                                        "ManagedConnectionFactory",
+                                        service};
+                                      
+            // Query the MBean server to check if the datasource is deployed
+            MBeanServer jmxServer = MBeanServerLocator.locateJBoss();
+
+            // Inspect the following MBeans and make sure that the "State" attribute
+            // is "DEPLOYED": 
+            // 1) "jboss.jca:name=TestDS,service=DataSourceBinding",type=Component
+            // 2) "jboss.jca:name=TestDS,service=ManagedConnectionPool",type=Component
+            // 3) "jboss.jca:name=TestDS,service=ManagedConnectionFactory",type=Component
+            // 4) The fourth MBean inspected depends on the type of datasource
+            for(int i = 0; i < dsMBeanServices.length; i++) {
+                
+                objName = new ObjectName("jboss.deployment:id=\"jboss.jca:name=" 
+                        + jndiName + ",service=" 
+                        + dsMBeanServices[i] + "\",type=Component");
+                
+                dsMBeans = jmxServer.queryNames(objName, null);
+                if (dsMBeans.size() != 1)  return false; 
+                
+                deploymentMBean = (ObjectName)dsMBeans.iterator().next();
+                state = jmxServer.getAttribute(deploymentMBean, "State");            
+                if(!("DEPLOYED".equals(state.toString()))) return false;
+            }
+            
+            return true;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    } 
+    
+    
+    /**
+     * checkProperties reads the *-ds.xml file corresponding to the datasource 
+     * given by jndiName and compares the property values in this file to the 
+     * given expected values. checkProperties returns true if all the given 
+     * properties are correctly set in the *-ds.xml file and false otherwise.
+     */
+    private boolean checkProperties(String jndiName,
+                                    String datasourceType, 
+                                    Map<String, String> expectedValuesMap) {
+        
+        Map<String, String> actualValuesMap = new HashMap<String, String>();
+        String datasourceElementName;
+        
+        try {
+            
+            // Parse the *-ds.xml file
+            File file = new File(System.getProperty("jsfunit.deploy.dir") 
+                                 + "/" + jndiName + "-ds.xml");
+         
+            SAXBuilder builder = new SAXBuilder();
+            Document doc = builder.build(file);
+            
+            Element root = doc.getRootElement();
+            assertTrue(root.getName().equals("datasources"));
+            
+            // Get the datasource element
+            if(datasourceType.equals(LOCAL_TX_DATASOURCE)) {
+                datasourceElementName="local-tx-datasource";
+            } else if(datasourceType.equals(NO_TX_DATASOURCE)) {
+                datasourceElementName="no-tx-datasource";
+            } else {
+                datasourceElementName="xa-datasource";
+            }
+            Element datasource = root.getChild(datasourceElementName);
+            
+            // Create actualValuesMap by mapping property names to 
+            // property values
+            Iterator itr = (datasource.getChildren()).iterator();
+            while(itr.hasNext()) {
+              Element property = (Element)itr.next();
+              actualValuesMap.put(property.getName(), property.getValue());
+            }
+          
+            // Compare the actual values to the expected ones
+            itr = expectedValuesMap.keySet().iterator();
+            while(itr.hasNext()) {
+                String key = (String)itr.next();
+                if(actualValuesMap.containsKey(key)) {
+                    if(!expectedValuesMap.get(key).equals(actualValuesMap.get(key))) {
+                        return false; // incorrect value
+                    } 
+                } else {
+                    return false; // value was not set
+                }
+            }
+            
+            return true;
+            
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+    
+    /**
+     * Connect to the database identified by the given JNDI name,
+     * using the given username and password. Return the Connection
+     * object.
+     */
+    public Connection connectDB(String jndiName, String username, 
+                                String password) throws Exception{
+        Context ctx = new InitialContext();
+        DataSource ds = (DataSource)ctx.lookup(jndiName);
+        return ds.getConnection(username, password);
+    }
+    
+    /**
+     * Disconnect from the database.
+     */
+    public void disconnectDB(Connection con) throws SQLException {
+        if(con != null) {
+            con.close();  
+        } 
+    }
+    
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+       return new TestSuite(DatasourceTest.class);
+    }
+    
+    /*
+     * Some preliminary creation tests
+     */
+    
+    /**
+     * Create a new datasource. Leave some property values that aren't 
+     * required unset.
+     */
+    public void testCreateDatasource() throws IOException {
+        Map<String, String> propertiesMap = new HashMap<String, String>();
+        
+        // The properties we want to configure
+        propertiesMap.put("jndi-name", "TestDS");
+        propertiesMap.put("user-name", "testUser");
+        propertiesMap.put("password", "password");
+        propertiesMap.put("min-pool-size", "5");
+        propertiesMap.put("driver-class", "org.hsqldb.jdbcDriver");
+        propertiesMap.put("connection-url", "jdbc:hsqldb:.");
+        propertiesMap.put("idle-timeout-minutes", "20");
+        propertiesMap.put("query-timeout", "180");
+        propertiesMap.put("prepared-statement-cache-size", "2");
+        propertiesMap.put("valid-connection-checker-class-name", 
+                          "org.jboss.resource.adapter.jdbc.CheckValidConnectionSQL");
+        propertiesMap.put("stale-connection-checker-class-name",
+                          "org.jboss.resource.adapter.jdbc.StaleConnectionChecker");
+        propertiesMap.put("exception-sorter-class-name", 
+                          "org.jboss.resource.adapter.jdbc.ExceptionSorter");
+        propertiesMap.put("allocation-retry", "10000");
+        propertiesMap.put("allocation-retry-wait-millis", "10000");
+        propertiesMap.put("background-validation-millis", "15000");
+        propertiesMap.put("use-try-lock", "61000");
+        propertiesMap.put("prefill", "true"); 
+        propertiesMap.put("share-prepared-statements", "false");        
+
+        createDatasource(LOCAL_TX_DATASOURCE, 
+                         "default__Local TX Datasource", 
+                         propertiesMap);
+        client.click("resourceConfigurationForm:saveButton");
+        
+        // Check for the appropriate success messages
+        String expectedMessage = "Successfully added new Local TX Datasource";
+        checkClientAndServerMessages(expectedMessage, expectedMessage, false);
+        
+        assertTrue(isDatasourceDeployed(propertiesMap.get("jndi-name"), 
+                                        LOCAL_TX_DATASOURCE)); 
+        assertTrue(checkProperties(propertiesMap.get("jndi-name"), 
+                                   LOCAL_TX_DATASOURCE, 
+                                   propertiesMap));
+        
+        // TODO: need to verify that appropriate default values were
+        // set for properties that were not specified above
+       
+        // Clean up
+        deleteDatasource(propertiesMap.get("jndi-name")); 
+        expectedMessage = "Successfully deleted Local TX Datasource '" 
+                          + propertiesMap.get("jndi-name") + "'";
+        checkClientAndServerMessages(expectedMessage, expectedMessage, false);
+    }
+    
+    /**
+     * Attempt to create a new datasource but leave at least one required
+     * value unset. An error should occur.
+     */
+    public void testCreateDatasourceMissingRequiredValues() throws IOException {
+        
+        // Leave jndi-name and connection-url unset
+        Map<String, String> propertiesMap = new HashMap<String, String>();
+        propertiesMap.put("user-name", "testUser");
+        propertiesMap.put("max-pool-size", "10");
+        propertiesMap.put("prefill", "true");
+        propertiesMap.put("idle-timeout-minutes", "20");
+        propertiesMap.put("set-tx-query-timeout", "true");
+        propertiesMap.put("query-timeout", "1800");
+        
+        createDatasource(NO_TX_DATASOURCE, "default__No TX Datasource", 
+                         propertiesMap);
+        client.click("resourceConfigurationForm:saveButton");
+        
+        // Check for the appropriate error messages
+        checkClientAndServerMessages("An invalid value was specified for one " 
+                                     + "or more properties",
+                                     "Value is required",
+                                     true);  
+    } 
+    
+    /**
+     * Attempt to create a new datasource but set a property value
+     * beyond its expected range of values. An error should occur.
+     */
+    public void testCreateDatasourcePropertyOutOfRange() throws IOException {
+        Map<String, String> propertiesMap = new HashMap<String, String>();
+        propertiesMap.put("jndi-name", "InvalidDS");
+        propertiesMap.put("user-name", "testUser");
+        propertiesMap.put("password", "password");
+        propertiesMap.put("xa-datasource-class", "org.postgresql.xa.PGXADataSource");
+        propertiesMap.put("xa-resource-timeout", "36000");
+        
+        // This number is too big
+        propertiesMap.put("max-pool-size", "100000000000000"); 
+
+        createDatasource(XA_DATASOURCE, "default__XA Datasource", 
+                         propertiesMap);
+        client.click("resourceConfigurationForm:saveButton");
+
+        // Check for the appropriate error messages      
+        checkClientAndServerMessages("An invalid value was specified for one or more properties",
+                                     "Specified attribute is not between the expected values",
+                                     true);
+    }
+    
+    /**
+     * Attempt to create a new datasource but set a property value
+     * to an invalid type. An error should occur.
+     */
+    public void testCreateDatasourceInvalidPropertyType() throws IOException {
+        Map<String, String> propertiesMap = new HashMap<String, String>();
+        propertiesMap.put("jndi-name", "InvalidDS");
+        propertiesMap.put("min-pool-size", "10");
+        propertiesMap.put("max-pool-size", "20");
+        propertiesMap.put("driver-class", "org.hsqldb.jdbcDriver");
+        propertiesMap.put("connection-url", "jdbc:hsqldb:.");
+        propertiesMap.put("share-prepared-statements", "false"); 
+        
+        // This property value is supposed to be an integer
+        propertiesMap.put("background-validation-millis", "abcde"); 
+        
+        createDatasource(LOCAL_TX_DATASOURCE, 
+                         "default__Local TX Datasource", 
+                         propertiesMap);
+        client.click("resourceConfigurationForm:saveButton");
+        
+        // Check for the appropriate error messages
+        checkClientAndServerMessages("An invalid value was specified for one or more properties", 
+                                     "Value is not a valid integer", 
+                                     true);
+    }
+}
+

Added: trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/EmbjoprTestCase.java
===================================================================
--- trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/EmbjoprTestCase.java	                        (rev 0)
+++ trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/EmbjoprTestCase.java	2008-12-16 20:13:35 UTC (rev 74)
@@ -0,0 +1,307 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, 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.WebClient;
+import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
+import com.gargoylesoftware.htmlunit.html.HtmlButtonInput;
+import com.gargoylesoftware.htmlunit.html.HtmlForm;
+import com.gargoylesoftware.htmlunit.html.HtmlImage;
+import com.gargoylesoftware.htmlunit.html.HtmlTable;
+import com.gargoylesoftware.htmlunit.html.HtmlTableRow;
+import com.gargoylesoftware.htmlunit.html.HtmlTableCell;
+import com.gargoylesoftware.htmlunit.html.HtmlInput;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.cactus.ServletTestCase;
+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 javax.faces.application.FacesMessage;
+
+/**
+ * This is the base test class for Embedded Jopr test cases. 
+ * It supplies access to a JSFClientSession object and a JSFServerSession 
+ * object. It also provides methods that make it easier to access some 
+ * commonly used UI components.
+ * 
+ * @author Farah Juma
+ * @author Stan Silvert
+ */
+public class EmbjoprTestCase extends ServletTestCase {
+
+    protected boolean isJBoss4;
+
+    protected JSFClientSession client;
+    protected 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("/");
+
+        // 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(); 
+
+    }	
+
+    /**
+     * Need a standard JSFUnit API to replace this code
+     */
+    public HtmlAnchor getNavTreeLink(String linkLabel)
+    {
+        return getLinkInsideForm("navTreeForm", linkLabel);
+    }
+
+    /**
+     * Get the "Delete" button in the resources data table that corresponds
+     * to the resource given by resourceName.
+     */
+    public HtmlButtonInput getDeleteButton(String formId, String resourceName)
+    {
+        HtmlAnchor link = getLinkInsideForm(formId, 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.
+     */
+    public 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.");
+    }
+    
+    /**
+     * Finds the arrow icon in the nav tree that corresponds to the resource
+     * given by resourceName. This method is used to expand tree nodes 
+     * (eg. "Web Applications (WAR)", "Datasources", etc.) in the 
+     * navigation tree.
+     */
+    public HtmlImage getNavTreeArrow(String resourceName) {
+        HtmlAnchor link = getNavTreeLink(resourceName);
+        String id = link.getIdAttribute();
+        
+        // An example id is: "navTreeForm:navTree:81:82:83:84::typeSummaryLink"
+        // The icon's id would be: "81:82:83:84::typeSummary:handle:img:collapsed"
+        int index = id.lastIndexOf("Link");
+        id = id.substring("navTreeForm:navTree:".length(), index) 
+             + ":handle:img:collapsed";
+        return (HtmlImage)client.getElement(id);
+    }
+    
+    /**
+     * Finds the value of the given metric in the given metrics
+     * data table.
+     */
+    public String getMetricValueFromTable(String metricName, 
+                                          String tableId) {
+        
+        // Get the metrics data table
+        HtmlTable metricsTable = (HtmlTable)client.getElement(tableId);
+        List<HtmlTableRow> rows = metricsTable.getRows();
+        
+        // Find the appropriate metric and return its value
+        for(Iterator i = rows.iterator(); i.hasNext();) {
+            
+            HtmlTableRow row = (HtmlTableRow)i.next();
+            HtmlTableCell metric = row.getCell(0);
+                   
+            if(metric.asText().equals(metricName)) {
+                String id = metric.getIdAttribute();
+                   
+                // An example id is: dataTable:0:j_id118:2:j_id119
+                String[] idElements = id.split(":");
+                String rowNum = idElements[idElements.length - 2];
+                return ((HtmlTableCell)client.getElement(rowNum 
+                                                         + ":measurementValue")).asText();
+                
+            }
+        }
+        
+        throw new IllegalStateException("Value of '" + metricName 
+                                        + "' not found.");
+    } 
+    
+    /**
+     * fillOutForm sets the values of input boxes and "Yes/No" radio 
+     * buttons on a resource configuration page using the given values. 
+     * 
+     * @param properties maps property names (eg. "jndi-name", 
+     * "min-pool-size", etc.) to property values 
+     */
+    public void fillOutForm(Map<String, String> properties) {
+        Iterator itr = properties.keySet().iterator();
+        
+        // Set each property
+        while(itr.hasNext()) {
+            String propertyName = (String)itr.next();
+            
+            // Enable the input if it is currently disabled
+            HtmlInput input = enableFormInput(propertyName);
+            assertFalse(input.isDisabled());
+            
+            setFormInput(input, properties.get(propertyName));
+        }
+    }
+    
+    /**
+     * Enable the given input box or "Yes/No" radio button that corresponds 
+     * to the given property name on a resource configuration page. If the 
+     * input box/radio button is already enabled, do nothing.
+     * 
+     * @return the enabled input element
+     */
+    public HtmlInput enableFormInput(String propertyName) {
+        HtmlForm form = (HtmlForm)client.getElement("resourceConfigurationForm");
+        HtmlInput input = (HtmlInput)form.getFirstByXPath(".//input[@ondblclick='//" 
+                + propertyName + "']");
+        
+        boolean isRadioButton = input.getTypeAttribute().equals("radio");
+        String id = input.getId();
+        String xpath;
+
+        if(input.isDisabled()) {
+            
+            // Find the enable/disable checkbox corresponding to this
+            // input element. 
+            if(isRadioButton) {
+
+                xpath = ".//input[@onchange=\"setInputUnset(document.getElementById('" 
+                        + id 
+                        + "'), this.checked);setInputUnset(document.getElementById('"
+                        + id.substring(0, id.lastIndexOf(":")) + ":1'), this.checked);\"]";
+            } else {
+                xpath = ".//input[@onchange=\"setInputUnset(document.getElementById('" 
+                        + id + "'), this.checked);\"]";
+            }
+
+            HtmlInput checkBox = (HtmlInput)form.getFirstByXPath(xpath);
+            checkBox.setChecked(Boolean.FALSE);
+            input = (HtmlInput)form.getFirstByXPath(".//input[@ondblclick='//" 
+                    + propertyName + "']");
+        }
+ 
+        return input;
+    }
+    
+    /**
+     * Set the given input box or "Yes/No" radio button to the given value. 
+     */
+    public void setFormInput(HtmlInput input, String propertyValue) {
+        boolean isRadioButton = input.getTypeAttribute().equals("radio");
+        String id = input.getId();
+        
+        if(isRadioButton) {
+            
+            // Check the appropriate button
+            if(propertyValue.equals("false")) {
+                
+                // Get the "No" radio button
+                input = (HtmlInput)client.getElement(id.substring(0, 
+                        id.lastIndexOf(":")) 
+                        + ":1");
+            }
+            
+            input.setChecked(Boolean.TRUE); 
+        } else {
+            input.setValueAttribute(propertyValue);
+        }
+    }
+    
+    
+    /**
+     * Check that the given messages occur on the client side
+     * and server side.
+     */
+    public void checkClientAndServerMessages(String expectedClientMsg,
+                                             String expectedServerMsg,
+                                             boolean isErrorMsg) {
+        assertTrue(client.getPageAsText().contains(expectedClientMsg));
+        
+        assertTrue(server.getFacesMessages().hasNext());
+        FacesMessage message = server.getFacesMessages().next();
+        
+        if(isErrorMsg) {
+            assertTrue(FacesMessage.SEVERITY_ERROR.equals(message.getSeverity()));
+        } else {
+            assertTrue(FacesMessage.SEVERITY_INFO.equals(message.getSeverity()));
+        }
+       
+        assertTrue(message.getDetail().contains(expectedServerMsg));
+    } 
+    
+    /**
+     * This just checks that the JSFServerSession object was created.
+     */
+    public void testServerSessionCreated() {
+        assertTrue(server != null);
+    }
+    
+    /**
+     * This just checks that the JSFClientSession object was created.
+     */
+    public void testClientSessionCreated() {
+        assertTrue(client != null);
+    }
+}
+




More information about the embjopr-commits mailing list