Package org.jboss.jopr.jsfunit

Source Code of org.jboss.jopr.jsfunit.EmbjoprTestCase

/*
* 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.*;
import java.io.IOException;
import java.util.*;
import org.jboss.logging.*;
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;
//import org.jboss.jmx.adaptor.rmi.RMIAdaptor; // Needs dependency: jmx-adaptor-plugin
import java.util.regex.Pattern;
import org.jboss.profileservice.spi.ProfileService;
import org.jboss.profileservice.spi.NoSuchDeploymentException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.commons.lang.StringUtils;
import org.jboss.deployers.spi.management.ManagementView;
import org.jboss.managed.api.*;
import org.jboss.metatype.api.values.MetaValue;
import org.jboss.metatype.api.values.SimpleValueSupport;
import org.jboss.jopr.jsfunit.exceptions.EmbJoprTestException;
import org.jboss.jopr.jsfunit.exceptions.HtmlElementNotFoundException;
import org.jboss.jopr.jsfunit.util.EmbJoprTestToolkit;
import org.jboss.jopr.jsfunit.util.jaas.SecuredProfileServiceAccess;


/**
* 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 Ondrej Zizka
* @author Stan Silvert
*/
public abstract class EmbjoprTestCase extends ServletTestCase implements EmbJoprTestConstants {

    protected final Logger log = Logger.getLogger(this.getClass().getName());

    protected EmbJoprTestToolkit ejtt;

    protected boolean isJBoss4;

    protected WebClient webClient;

    protected JSFClientSession client;
    protected JSFServerSession server;

    public static final String LOGIN_USERNAME = "admin";
    public static final String LOGIN_PASSWORD = "admin";

    public String getLoginUser() {    return LOGIN_USERNAME;  }
    public String getLoginPass() {    return LOGIN_PASSWORD;  }



   
    // Tab Menu IDs
    public static final String SUMMARY_TAB = "summaryTab";
    public static final String METRICS_TAB = "metricsTab";
    public static final String CONFIGURATION_TAB = "configurationTab";
    public static final String CONTROL_TAB = "controlTab";
    public static final String CONTENT_TAB = "contentTab";
   
    public static final String RESOURCE_CONFIGURATION_FORM = "resourceConfigurationForm";

    public JSFClientSession getClient() { return client; }
    public JSFServerSession getServer() { return server; }

    private long testStartTime;

    /**
     * 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.
     */
    @Override
    public void setUp() throws IOException, EmbJoprTestException
    {

        // Announce this test in the JBoss log.
        log.info("========================================================================================");
        log.info("  Setting up test "+this.getClass().getName()+"#"+this.getName());
        log.info("========================================================================================");

        // Save the startup time.
        this.testStartTime = System.currentTimeMillis();


        // JVM version
        log.info("Java version: "+System.getProperty("java.version") + "," +
                 " vendor: "     +System.getProperty("java.vendor"));
        log.info("Java home:  "  +System.getProperty("java.home"));

        // JBoss AS version
        String version = Package.getPackage("org.jboss.system.server")
                         .getImplementationVersion();
        log.info("Detected AS version: " + version);
        isJBoss4 = version.startsWith("4");


        // Browser branch and version

        BrowserVersion browserVersion = BrowserVersion.FIREFOX_3;

        String browserProp = System.getProperty("htmlunit.browser");
        if( "ff3".equals(browserProp) || "firefox3".equals(browserProp) ){
          browserVersion = BrowserVersion.FIREFOX_3;
        }else
        if( "ff2".equals(browserProp) || "firefox2".equals(browserProp) ){
          browserVersion = BrowserVersion.FIREFOX_2;
        }else
        if( "ie7".equals(browserProp) || "internetexplorer7".equals(browserProp) ){
          browserVersion = BrowserVersion.INTERNET_EXPLORER_7_0;
        }else
        if( "ie6".equals(browserProp) || "internetexplorer6".equals(browserProp) ){
          browserVersion = BrowserVersion.INTERNET_EXPLORER_6_0;
        }
       
        log.info("Simulating browser: "+browserVersion.getNickName() + "('htmlunit.browser' sysprop: "+browserProp+")");


       
       
        // Initial JSF request
        WebClientSpec wcSpec = new WebClientSpec("/", browserVersion);


        // This is temporary because embedded Jopr can't find /js/rhq.js
        wcSpec.getWebClient().setThrowExceptionOnFailingStatusCode(true);

        // Always press OK for confirm dialogs
        wcSpec.getWebClient().setConfirmHandler(new SimpleConfirmHandler(true));

        wcSpec.setInitialRequestStrategy(new JoprLoginStrategy( this.getLoginUser(), this.getLoginPass())); // logs in

        this.webClient = wcSpec.getWebClient();
       
        JSFSession jsfSession = new JSFSession(wcSpec);
        this.client = jsfSession.getJSFClientSession();
        this.server = jsfSession.getJSFServerSession();

        this.ejtt = new EmbJoprTestToolkit(client, server);
        this.ejtt.setCurrentTest(this);
    }

    @Override
    protected void tearDown() throws Exception {

      // Clean up.
      this.webClient.closeAllWindows();
      this.webClient.getCache().clear();
      this.webClient.getCookieManager().clearCookies();
      this.webClient = null;
      this.client = null;
      this.server = null;

      // Denounce this test in the JBoss log.
      log.info("------  END OF TEST "+this.getName()+" - took "+((System.currentTimeMillis() - this.testStartTime)/1000)+" seconds. -------");
    }


   
    /**
     * 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];
      // resourceSummaryForm:dataTable:2:removeButton
      return (HtmlButtonInput)client.getElement(formId + ":dataTable:" + 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();

          linkText = linkText.trim(); // ignore any leading or trailing spaces
          if (linkText.equals(linkLabel)) return link;
      }

      throw new IllegalStateException("Link for '"+ linkLabel +"' not found in form #"+formId);
    }
   
    /**
     * 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 ClickableElement getNavTreeArrow(String resourceName) throws EmbJoprTestException {

        // Tree.Item JS object can be still loading.
        ejtt.navTree.waitUntilReady(100, 15);
        // After expanding some node, it's children are loaded using AJAX.
        // Here, we wait for the node with given label to appear in the nav tree.
        ejtt.navTree.waitUntilNodeLoadedByAjax(resourceName, 200, 10);

        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(0, index) + ":handle";
        return (ClickableElement)client.getElement(id);
    }
   
    /**
     * Expand the nav tree arrow for the given resource.
     */
    public void expandNavTreeArrow(String resourceName) throws IOException, EmbJoprTestException {
       
        // Expand the tree node
        ClickableElement resourceArrow = getNavTreeArrow(resourceName);
        resourceArrow.click();
    }
   
    /**
     * Click on the given nav tree link.
     */
    public void clickNavTreeLink(String resourceName) throws IOException {
        HtmlAnchor resourceLink = getNavTreeLink(resourceName);
        resourceLink.click();
    }
   
    /**
     * 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);
        if( null == metricsTable )
          throw new IllegalStateException("Metrics table with ID '"+tableId+"' not found.");
        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
                // We would need: dataTable:0:j_id118:2:measurementValue
                return ((HtmlTableCell)client.getElement(id.substring(0, id.lastIndexOf(":"))
                                       + ":measurementValue")).asText();
               
            }
        }
       
        throw new IllegalStateException("Value of '"+metricName+"' not found.");
    }



    /**
     * Takes a Properties object, takes their names
     * and calls getFormPropertiesValues( Collection<String> ).
     */
    public Properties getFormPropertiesValues( Properties propsTemplate ){
      return getFormPropertiesValues(EmbJoprTestToolkit.stringPropertyNames(propsTemplate));
    }

    /**
     * Takes a list of properties to load
     * and returns a Properties object filled with their values.
     */
    public Properties getFormPropertiesValues( Collection<String> propsToLoad ){

      Properties props = new Properties();

      //for( String propName : EmbJoprTestToolkit.stringPropertyNames(propsToLoad) )
      for( String propName : propsToLoad )
      {
        HtmlInput input = getConfigFormInput(propName);
        String propValue = getFormInputValueAsText(input);
        props.setProperty(propName, propValue);
      }

      return props;
     
    }

   
    /**
     * 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, String formName) {
        Iterator itr = properties.keySet().iterator();
       
        // Set each property
        while(itr.hasNext()) {
            String propertyName = (String)itr.next();

            // Make sure the input is enabled
            HtmlInput input = enableOrDisableFormInput(propertyName,
                                                       Boolean.TRUE,
                                                       formName);
           
            assertFalse("Could not enable: " + propertyName, input.isDisabled());
           
            setFormInput(input, properties.get(propertyName));
        }
    }

    /** Convert Properties to Map and call fillOutForm(Map). */
    public void fillOutForm(Properties props) {
      Map<String,String> map = new HashMap<String,String>(props.size());
      for( String propName : EmbJoprTestToolkit.stringPropertyNames(props) ) {
        map.put(propName, props.getProperty(propName));
      }
      fillOutForm(map, RESOURCE_CONFIGURATION_FORM);
    }

    /** Check if the form is filled according to given Properties. */
    public void checkForm(Properties props)
    {
      boolean foundNonMatching = false;
      StringBuilder sb = new StringBuilder("Non-matching properties: \n");

      for( String propName : EmbJoprTestToolkit.stringPropertyNames(props) ) {
        HtmlInput input = getConfigFormInput(propName);
        String expected = props.getProperty(propName);
        String actual = getFormInputValueAsText(input);
        if( StringUtils.equals(expected, actual) ) continue;
        foundNonMatching = true;
        sb.append( propName+": expected '"+expected+"', found '"+actual+"'\n");
      }
      if( foundNonMatching ){
        fail( sb.toString() );
      }
    }

    /** Looks for a form input of given property. */
    public HtmlInput getConfigFormInput( String propertyName )
    {
      HtmlForm form = (HtmlForm)client.getElement("resourceConfigurationForm");
      HtmlInput input = (HtmlInput)form.getFirstByXPath(".//input[@ondblclick='//"
                        + propertyName + "']");

      assertNotNull("Form input for property '"+ propertyName +"' not found.", input);
      return input;
    }

    /** Looks for an enable/disable checkbox corresponding to this input element. */
    public HtmlCheckBoxInput getCheckBoxForInput( HtmlInput input ){
      boolean isRadioButton = input.getTypeAttribute().equals("radio");
      String id = input.getId();
      String xpath;
      if(isRadioButton) {
        xpath = ".//input[@onclick=\"setInputUnset(document.getElementById('"+ id
                + "'), this.checked);setInputUnset(document.getElementById('"
                + id.substring(0, id.lastIndexOf(":")) + ":1'), this.checked);\"]";
      } else {
        xpath = ".//input[@onclick=\"setInputUnset(document.getElementById('"
                + id + "'), this.checked);\"]";
      }

      HtmlCheckBoxInput checkBox = (HtmlCheckBoxInput)input.getEnclosingForm().getFirstByXPath(xpath);
      return (HtmlCheckBoxInput) checkBox;
    }
   

    /**
     * Attempt to enable or disable the given input box or "Yes/No" radio button
     * that corresponds to the given property name on a resource configuration
     * page. Return the enabled/disabled input element.
     * If the input box/radio button does not have an enable/disable checkbox,
     * return the input element as is.
     */
    public HtmlInput enableOrDisableFormInput(String propertyName, Boolean enableInput, String formName) {
     
        HtmlForm form = (HtmlForm)client.getElement(formName);
       
        if( null == form ){
            // Wrapped. Don't want to add "throws Html..." all over the project.
            throw new RuntimeException(new HtmlElementNotFoundException(
                                       "Element " + formName + " not found. Page dumped.", this));
        }

        HtmlInput input = (HtmlInput)form.getFirstByXPath(".//input[@ondblclick='//"
                          + propertyName + "']");

        assertNotNull("Form input for property '" + propertyName + "' not found.", input);
       
        boolean isRadioButton = input.getTypeAttribute().equals("radio");
        String id = input.getId();
        String xpath;

        // Look for an enable/disable checkbox corresponding to this
        // input element.
        if(isRadioButton) {
            List<HtmlInput> propertyButtons = (List<HtmlInput>)form.getByXPath(".//input[@ondblclick='//" + propertyName
                                              + "' and @type='radio']");
           
            int numButtons = propertyButtons.size();
           
            xpath = ".//input[@onclick=\"";
           
            for(int i = 0; i < numButtons; i++) {
                xpath = xpath + "setInputUnset(document.getElementById('"
                        + id.substring(0, id.lastIndexOf(":")) + ":" + i + "'), this.checked);";
            }
           
            xpath = xpath + "\"]";

        } else {
            xpath = ".//input[@onclick=\"setInputUnset(document.getElementById('"
                    + id + "'), this.checked);\"]";
        }

        HtmlInput checkBox = (HtmlInput)form.getFirstByXPath(xpath);

        if(checkBox != null) {
            //checkBox.setChecked(!enableInput);
           
            boolean isChecked = checkBox.isChecked();
           
            if(isChecked == enableInput) {
                try {
                    checkBox.click();
                } catch (Exception e) {
                    log.error("Could not click on the checkbox for: " + 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");
        if(isRadioButton) {
           
            // Check the appropriate button
            if(propertyValue.equals("false")) {
               
                // Get the "No" radio button.
                String id = input.getId();
                input = (HtmlInput)client.getElement(
                        id.substring(0, id.lastIndexOf(":")) + ":1");
            }
            else{

              // Multiple choices - find the appropriate radio button.
              String inputName = input.getNameAttribute();
              DomNode node = input.getFirstByXPath(
                  "./ancestor::form//input[@name='"+inputName+"' and @value='"+propertyValue+"']");
              //DomNode node = input.getOneHtmlElementByAttribute("input", "value", propertyValue);

              if( null == node ){
                throw new IllegalArgumentException(
                  "HTML Radio input of name '"+inputName+"' and value '"+propertyValue+"' not found.");
              }

              input = (HtmlInput)node;

            }
           
            input.setChecked(Boolean.TRUE);
        } else {
            input.setValueAttribute(propertyValue);
        }
    }
   

    /**
     * Returns the value of HTML input.
     * @returns
     * If the input is marked as unset, returns "unset".
     * For radios, returns the value of the checked radio.
     * For others, simply returns value attribute.
     */
    public String getFormInputValueAsText(HtmlInput input) {
   
      HtmlCheckBoxInput checkbox = getCheckBoxForInput(input);
      if( checkbox.isChecked() )
        return "unset";

      boolean isRadioButton = input.getTypeAttribute().equals("radio");
      if(!isRadioButton){
        return input.getValueAttribute();
      }
      else {

        HtmlRadioButtonInput radio = (HtmlRadioButtonInput)input;

        // Multiple choices - find the appropriate radio button.
        String inputName = input.getNameAttribute();
        String xPath = ".//input[@name='"+ inputName +"']";
        List<HtmlInput> radios = (List<HtmlInput>) input.getEnclosingForm().getByXPath(xPath);

        for (HtmlInput htmlInput : radios) {
          if( htmlInput.isChecked() ){
            return htmlInput.getValueAttribute();
          }
        }
        return null;

      }
    }


    /**
     * Check that the given messages occur on the client side and server side.
     * Uses checkClientAndServerMessages( String, String, FacesMessage.Severity ),
     * kept for backwards compat.
     */
    public void checkClientAndServerMessages(String expectedClientMsg,
                                             String expectedServerMsg,
                                             boolean isErrorMsg)
    {
        FacesMessage.Severity expectedSeverity;

        if(isErrorMsg) {
            expectedSeverity = FacesMessage.SEVERITY_ERROR;
        } else {
            expectedSeverity = FacesMessage.SEVERITY_INFO;
        }
       
        checkClientAndServerMessages(expectedClientMsg, expectedServerMsg, expectedSeverity);
    }

    /**
     * Check that the given messages with given severity
     * occur on the client side and server side.
     */
    public void checkClientAndServerMessages(String expectedClientMsg,
                                             String expectedServerMsg,
                                             FacesMessage.Severity expectedSeverity ) {

        // Check that the expected message appears on the server side
        assertTrue("Expected message not found in faces messages (no messages in Faces)",
                    server.getFacesMessages().hasNext());
       
        FacesMessage message = server.getFacesMessages().next();

        assertTrue("Expected message: " + expectedServerMsg + " Actual: "+ message.getDetail(),
                   message.getDetail().contains(expectedServerMsg));
        if( ! message.getDetail().contains(expectedServerMsg) ){
          //throw new EmbJoprTestException( "Expected message: " + expectedServerMsg + " Actual: "+ message.getDetail(), this);
          String fileName = this.getName() + "-msgCheck.html";
          try {
            ejtt.dumpPage( fileName );
          } catch (IOException ex) { log.error(ex.toString()); }
          fail( "\nExpected message: [" + expectedServerMsg + "]\nActual: ["+ message.getDetail() + "]\nPage dumped to '"+fileName+"'." );
        }

        assertEquals("Incorrect message severity. Message: "+message.getSummary(), expectedSeverity, message.getSeverity());


        // Check that the expected message appears on the client side
        assertTrue("This expected message was not found on the page: " + expectedClientMsg,
                   client.getPageAsText().contains(expectedClientMsg));

    }


    /**
     * Check that the given messages occur on the client side and server side.
     * Given strings are treated as regular expressions to match.
     */
    public void checkClientAndServerMessagesRegExp(String expectedClientMsgRE,
                                                   String expectedServerMsgRE,
                                                   boolean isErrorMsg)
    {
        // In Faces
        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( Pattern.matches( expectedServerMsgRE, message.getDetail() ) );

        // On page

        String pageText = client.getPageAsText();
        assertTrue( Pattern.matches(expectedClientMsgRE, pageText) );

    }


    /**
     * Refresh the content under the given nav tree node.
     */
    public void refreshTreeNode(String nodeName) throws EmbJoprTestException {
       try {
           // Collapse and then expand the nav tree node
           ClickableElement nodeArrow = getNavTreeArrow(nodeName);
           nodeArrow.click();
      
           nodeArrow = getNavTreeArrow(nodeName);
           nodeArrow.click();
       } catch (IOException e) {
           throw new EmbJoprTestException("An error occurred when trying " +
                                         "to collapse and then expand the nav tree " +
                                         "arrow for " + nodeName, e);
       }
    }
   
    /**
     * Finds a row in the "details table" using the text in the Name column
     * and returns the text from the Value column.
     * @param name
     * @return
     */
    public String getDetailsRowValue(String name) throws EmbJoprTestException {
        HtmlDivision contentDiv = (HtmlDivision) client.getElement("content");
        List<?> valueTDs = contentDiv.getByXPath(
                ".//div[@class='tabmenubox']//td[contains(text(),'"+name+"']/following-sibling::td[1]");
        //assertTrue( name + " row not found.", valueTDs.size() == 1 );
        if( valueTDs.size() == 1 )
            throw new EmbJoprTestException( name + " row not found." );
        String value = ((HtmlTableCell) valueTDs).getTextContent();
        return value;
    }

    /**
     * Returns the content element - &lt;div id="content"> - which contains whole page.
     * Good as a start point for XPath queries - other elements usually have generated IDs.
     * Assertion fails if the element is not found.
     * @return
     */
    public HtmlElement getContentElement() throws EmbJoprTestException {
        HtmlElement contentElement = (HtmlElement)client.getElement("content");
        //assertNotNull("Content <div> not found.", contentElement);
        if( null == contentElement )
            throw new EmbJoprTestException( "Content <div> not found." );
        return contentElement;
    }

    /**
     * Convenience method, calls getElementsByXPath() with content element.
     * @param sXPath
     * @return
     */
    public List<? extends HtmlElement> getElementsByXPath(String sXPath ) throws EmbJoprTestException {
        //return (List<? extends HtmlElement>) getContentElement().getByXPath(sXPath);
        return getElementsByXPath( getContentElement(), sXPath );
    }

    /**
     * Retuns a list of elements chosen by XPath, with the given element as context node.
     * @param xPathContextElement
     * @param sXPath
     * @return
     */
    public List<? extends HtmlElement> getElementsByXPath(
            HtmlElement xPathContextElement, String sXPath )
            throws EmbJoprTestException
    {
        if( null == xPathContextElement ){
            throw new EmbJoprTestException("Given XPath context element is null.");
        }

        return (List<? extends HtmlElement>) xPathContextElement.getByXPath(sXPath);
    }

    /**
     * Returns the first element in the list returned by getElementsByXPath(String sXPath ).
     * @param sXPath
     * @returns The first of elements found, or null when XPath expr. found none.
     */
    public HtmlElement findFirstElementByXPath( HtmlElement xPathContext, String sXPath ) throws EmbJoprTestException {

        List<? extends HtmlElement> elementsByXPath = getElementsByXPath(xPathContext, sXPath);
        if( elementsByXPath.size() == 0 ){
            //
            // Exception is better - will get the stack trace.
            //fail("XPath expression found no elements: "+sXPath);
            return null;
        }
        return elementsByXPath.get(0);
    }

    /**
     * The same as findFirstElementByXPath(), only throws an exception when no element was found.
     * Returns the first element in the list returned by getElementsByXPath(String sXPath ).
     * @param sXPath
     * @returns The first of elements found.
     * @throws XPathException when the expression found no elements.
     */
    public HtmlElement getFirstElementByXPath( HtmlElement xPathContext, String sXPath )
            throws EmbJoprTestException
    {
      HtmlElement e = findFirstElementByXPath(xPathContext, sXPath);
      if( null == e ){
        throw new EmbJoprTestException("XPath expression found no elements: "+sXPath);
      }
      return e;
    }

    /**
     * Convenience method - calls getFirstElementByXPath() with content div as context.
     * @param sXPath
     * @return
     */
    public HtmlElement getFirstElementByXPath( String sXPath ) throws EmbJoprTestException{
        return getFirstElementByXPath( getContentElement(), sXPath );
    }

    /**
     * Retrieves an input element from a named row of a table in a form.
     * Supposes that the form is in the "tabmenubox" or "notabmenubox" div.
     * @param sRowName
     * @return
     * @throws org.jboss.jopr.jsfunit.AssertException
     */
    public HtmlInput getFormInputByRowName(String sRowName) throws EmbJoprTestException {
        try {
            HtmlInput input = (HtmlInput) getFirstElementByXPath(
                    getTabMenuBoxElement(),
                    ".//td[contains(text(),'"+sRowName+"')]/following-sibling::td[@class='property-value-cell']//input"
            );
            if( null == input ){
                throw new EmbJoprTestException("Input for value "+sRowName+" not found.");
            }
            return input;
        }
        catch(EmbJoprTestException ex){
            //throw new AssertException("Row with name \""+sRowName+"\" not found.", ex);
            throw ex;
        }
    }


    /**
     * Retrieves a named row of a table in the "right side of the page".
     * Supposes that the table is in the "tabmenubox" or "notabmenubox" div.
     * Uses getTabMenuBoxElement() to get that div.
     * @param sRowName
     * @return
     * @throws org.jboss.jopr.jsfunit.AssertException
     */
    public HtmlTableRow getRowByName(String sRowName) throws EmbJoprTestException {

        HtmlTableRow row = (HtmlTableRow) getFirstElementByXPath(
                getTabMenuBoxElement(),
                ".//td[contains(string(),'"+sRowName+"')]/ancestor::tr" );
       
        if( null == row ){
          throw new EmbJoprTestException("Row with label "+sRowName+" not found.");
        }
        return row;
    }


    /**
     * Returns the element which contains the "right side of the page".
     * <div class="tabmenubox"> element exists on each page that shows resource's details.
     * <div class="notabmenubox"> element exists on each page with form for resource's properties editation.
     * @return
     * @throws org.jboss.jopr.jsfunit.AssertException
     */
    public HtmlElement getTabMenuBoxElement() throws EmbJoprTestException {
        return getFirstElementByXPath(".//div[@class='tabmenubox' or @class='notabmenubox']");
    }


    /**
     * Returns an integer part of the beginning of the given string.
     * @param s
     * @return Integer with the value of numerical part of the string,
     *         or null if there are no digits at the beginning.
     */
    public Integer integerFromString(String s) {
        int pos;
        for( pos = 0; pos < s.length(); pos++ ){
            char ch = s.charAt(0);
            if'0' > ch || ch > '9' )
                break;
        }

        if( pos == 0 )
            return null;

        try{
            int val = Integer.parseInt( s.substring( 0, pos ) );
            return val;
        }catch( NumberFormatException ex ){
            return null;
        }

    }
   
    /**
     * Checks whether given string looks like a double in terms of Java's Double,
     * i.e. /<digit>+(\.<digit>+)?/
     * @param value  The string to check.
     * @returns true if the
     */
    public static boolean looksLikeDouble(String value) {
        try{
            Double.parseDouble(value);
        }catch(NumberFormatException ex){
            return false;
        }
        return true;
    }

    /**
     * Returns true if the string looks like a double with unit, i.e. 123.45kg
     */
    public static boolean looksLikeDoubleWithUnit(String value) {
        return value.matches("([0-9]+\\.[0-9]+)[a-zA-Z]{0,3}");
    }

    /**
     * If both expected and actual string look like a double,
     * returns normalized double (with a decimal dot);
     * Otherwise, returns original actual value.
     * @param expected
     * @param actual
     */
    public static String normalizeIfDoubleExpected(String expected, String actual) {
        //return looksLikeDouble(expected) ? actual.replace(',', '.') : actual;

        if( !looksLikeDouble(expected) )
            return actual;

        String converted = actual.replace(',', '.');
        return looksLikeDouble(converted) ? converted : actual;
    }



    /**  Converts a decimal number in either english or german notation to Java-like double. */
    public static String normalizeIfNumber( String val ){
      if( null == val )
        return null;

      boolean isNumeric = val.matches("([0-9][0-9\\., ]+[0-9])[a-zA-Z]{0,3}");
      if( !isNumeric )
        return val;

      // TODO: Normalize numbers with units (1.5m)

      String val2 = val.replace(",", "");
      // English notation - 1,322.51
      if( EmbjoprTestCase.looksLikeDoubleWithUnit(val2) )
        return val2;

      // Still can be numbe: 1 358,84
      val2 = val.replace(" ", "");
      val2 = val.replace(" ", "").replace(',', '.');
      if( EmbjoprTestCase.looksLikeDoubleWithUnit(val2) )
        return val2;

      return val;
    }





   
    /**
     * Transform the given map of Strings to MetaValues into a
     * map of Strings to Strings.
     */
    protected static Map<String, String> formatPropertiesMap(Map<String, MetaValue> propertiesMap) {
        Map<String, String> formattedPropertiesMap = new HashMap<String, String>();
       
        for(String propertyName : propertiesMap.keySet()) {
            SimpleValueSupport propertyMetaValue = (SimpleValueSupport)propertiesMap.get(propertyName);
            String propertyStringValue = propertyMetaValue.getValue().toString();
            formattedPropertiesMap.put(propertyName, propertyStringValue);
        }
       
        return formattedPropertiesMap;
    }


    /**
     * Check the properties for a particular managed component.
     *
     * @param expectedProperties maps property names to expected values
     * @param componentName - the name of the ManagedComponent
     * @param type - the component type
     */
    protected void checkComponentProperties(Map<String, MetaValue> expectedProperties, String componentName,
            ComponentType type) throws Exception {
      checkComponentProperties(expectedProperties, componentName, type, true);
    }
   
    /**
     * Check the properties for a particular managed component.
     *
     * @param expectedProperties maps property names to expected values
     * @param componentName - the name of the ManagedComponent
     * @param type - the component type
     */
    protected void checkComponentProperties(Map<String, MetaValue> expectedProperties, String componentName,
            ComponentType type, boolean secured) throws Exception {
       
        Map<String, MetaValue> actualProperties = getComponentProperties(componentName, type, secured);
       
        // Verify that the property values are correct
        for(String propertyName : expectedProperties.keySet()) {
            assertEquals("Incorrect value for '" + propertyName + "'",
                         expectedProperties.get(propertyName),
                         actualProperties.get(propertyName));
        }
    }

   
    /**
     * Create a map of property names to property values for a particular component. Unsecured.
     */
    protected Map<String, MetaValue> getComponentProperties(String componentName,
                                                            ComponentType type) throws Exception {
      return getComponentProperties(componentName, type, true);
    }

    /**
     * Create a map of property names to property values for a particular component.
     */
    protected Map<String, MetaValue> getComponentProperties(String componentName,
                                                            ComponentType type, boolean secured) throws Exception
    {
        ManagedComponent component = getManagedComponent(componentName, type, secured);
        assertNotNull("The returned component was null; Name: "+componentName, component);
        assertEquals(componentName, component.getName());
       
        Map<String, ManagedProperty> actualProperties = component.getProperties();
        Map<String, MetaValue> propertiesMap = new HashMap<String, MetaValue>();
        ManagedProperty prop;
       
        // Create a map of Strings to MetaValues
        for(String propertyName : actualProperties.keySet()) {
            prop = actualProperties.get(propertyName);
            propertiesMap.put(propertyName, prop.getValue());
        }
       
        return propertiesMap;
    }

   
    /**
     * Create a map of property names to property values for a particular
     * component. The desired property names are given by specificProperties.
     * (This is useful when we need to check the values of some specific properties
     * only - eg. the configuration tests)
     */
    protected Map<String, MetaValue> getSpecificComponentProperties(String componentName,
                                                                    ComponentType type,
                                                                    String specificProperties[]) throws Exception {
      return getSpecificComponentProperties(componentName, type, specificProperties, true);
    }
   
    /**
     * Create a map of property names to property values for a particular
     * component. The desired property names are given by specificProperties.
     * (This is useful when we need to check the values of some specific properties
     * only - eg. the configuration tests)
     */
    protected Map<String, MetaValue> getSpecificComponentProperties(String componentName,
                                                                    ComponentType type,
                                                                    String specificProperties[],
                                                                    boolean secured) throws Exception {
        ManagedComponent component = getManagedComponent(componentName, type, secured);
        assertNotNull("The returned component was null", component);
        assertEquals(componentName, component.getName());
       
        Map<String, ManagedProperty> actualProperties = component.getProperties();
        Map<String, MetaValue> propertiesMap = new HashMap<String, MetaValue>();
        ManagedProperty prop;
       
        // Create a map containing only the specified properties
        for(int i = 0; i < specificProperties.length; i++) {
            String propertyName = specificProperties[i];
            prop = actualProperties.get(propertyName);
            propertiesMap.put(propertyName, prop.getValue());
        }
       
        return propertiesMap;
    }
   
    /**
     * Return a ManagedComponent, given the component name and type.
     */
    protected ManagedComponent getManagedComponent(String componentName,
                                                   ComponentType type) throws Exception {
      return getManagedComponent(componentName, type, true);
    }
       
    /**
     * Return a ManagedComponent, given the component name and type.
     * @param secured  If true, uses JAAS secured access to ProfileService etc.
     */
    protected ManagedComponent getManagedComponent(String componentName,
                                                   ComponentType type, boolean secured) throws Exception {

        // Get the ManagedComponent
        ManagementView mgtView = getCurrentProfileView( secured );
        ManagedComponent component = mgtView.getComponent(componentName, type);
       
        return component;
    }
   
    /**
     * Return whether or not the given deployment is deployed.
     *
     * @param deployment - the deployment we are interested in
     */
    protected boolean isDeployed(String deployment) throws Exception {
      return isDeployed(deployment, true);
    }
    /**
     * Return whether or not the given deployment is deployed.
     *
     * @param deployment - the deployment we are interested in
     * @param secured   If true, JAAS secured ManagementView is used.
     */
    protected boolean isDeployed(String deployment, boolean secured) throws Exception {
   deployment = deployment.replace("/", System.getProperty("file.separator"));

        ManagementView currentProfileView = getCurrentProfileView(secured);
        ManagedDeployment managedDeployment = null;
       
        try {
            managedDeployment = currentProfileView.getDeployment(deployment);
        } catch (NoSuchDeploymentException e) {
            return false;
        }
       
        return managedDeployment != null;
    }
      
    /**
     * Get the profile service.
     */
    protected ProfileService getProfileService( boolean secured ){
      return secured ? getProfileServiceSecured() : getProfileService();
    }

    protected ProfileService getProfileServiceSecured()
    {
      try {
        return SecuredProfileServiceAccess.getInstance().getProfileService();
      } catch (NamingException ex) {
        // Farah's methods don't propagate exceptions -> report and swallow.
        log.error("Can't get secured ProfileService: " + ex.toString(), ex);
        return null;
      }
    }
   
    protected ProfileService getProfileService()
    {
        ProfileService profileService = null;
        InitialContext initialContext;
       
        try {
            initialContext = new InitialContext();
        } catch (NamingException e) {
            log.error("Unable to get an InitialContext to JBoss AS 5", e);
            return null;
        }

        try {
            profileService = (ProfileService) initialContext.lookup("ProfileService");
        } catch (NamingException e) {
            log.error("Could not find ProfileService Name on JBoss AS 5", e);
        } catch (Exception e) {
            log.error("Exception thrown when looking up ProfileService on JBoss AS 5", e);
        }
       
        return profileService;
    }

    /**
     * Get the current profile view.
     * @param secured  If true, returns JAAS profile view of secured profile service.
     */
    protected ManagementView getCurrentProfileView( boolean secured ){
      return secured ? getCurrentProfileView() : getCurrentProfileViewUnsecured();
    }

    /**
     * Get the current profile view.
     */
    protected ManagementView getCurrentProfileView(){
      try {
        ManagementView view = SecuredProfileServiceAccess.getInstance().getManagementView();
        view.load();
        return view;
      } catch (NamingException ex) {
        log.error("Can't get ManagementView: "+ex);
        return null;
      }
    }

    protected ManagementView getCurrentProfileViewUnsecured()
    {
        ProfileService profileService = getProfileService();
        ManagementView currentProfileView = profileService.getViewManager();
      
        try {
            currentProfileView.load();
        } catch (Exception e) {
            log.error("Could not find default Profile in Current Profile View", e);
        }

        return currentProfileView;
    }
}


TOP

Related Classes of org.jboss.jopr.jsfunit.EmbjoprTestCase

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.