All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.axway.ats.uiengine.elements.html.HtmlElementLocatorBuilder Maven / Gradle / Ivy

/*
 * Copyright 2017 Axway Software
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.axway.ats.uiengine.elements.html;

import java.util.Arrays;

import org.apache.log4j.Logger;

import com.axway.ats.uiengine.elements.ElementsMap;
import com.axway.ats.uiengine.elements.UiElementProperties;

/**
 * Builds paths for referring an HTML element
 */
public class HtmlElementLocatorBuilder {

    private static final Logger   log                      = Logger.getLogger( HtmlElementLocatorBuilder.class );

    public static final String PROPERTY_ELEMENT_LOCATOR = "htmlElementLocator";

    public static final String XPATH                    = "xpath";

    private static final String[] INTERNAL_ATTRIBUTES      = new String[]{ "_text",
            "_partText",
            "_inputType",
            "_css"                                        };

    /**
     * Returns the element's XPath
     *
     * @param properties
     * @param htmlType
     * @param isInput
     * @return
     */
    public static String buildXpathLocator(
                                            String[] rules,
                                            UiElementProperties properties,
                                            String[] htmlTypes,
                                            String htmlNodeName ) {

        /*if( Arrays.asList( rules ).contains( XPATH ) && properties.getProperty( XPATH ) != null ) {
        
            return properties.getProperty( XPATH ).trim();
        }*/

        if( properties.getProperty( XPATH ) != null ) {
            return properties.getProperty( XPATH ).trim();
        }

        StringBuilder xpath = new StringBuilder( "//" );

        final String formId = properties.getProperty( ElementsMap.ATT_ELEMENT_FORMID );
        final String formName = properties.getProperty( ElementsMap.ATT_ELEMENT_FORMNAME );
        if( formId != null ) {
            xpath.append( "form[@id='" );
            xpath.append( formId );
            xpath.append( "']/" );
        } else if( formName != null ) {
            xpath.append( "form[@name='" );
            xpath.append( formName );
            xpath.append( "']/" );
        }

        xpath.append( htmlNodeName );

        if( "input".equals( htmlNodeName ) || "button".equals( htmlNodeName ) ) {

            // to convert the value of 'type' attribute to lower case we are using this function:
            // translate(@type, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')
            // NOTE: there is another function to lower case 'lower-case()', but it's not in XPath 1.0
            // which is the version of XPath used in Firefox
            xpath.append( "[translate(@type, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')=" );
            boolean firstTime = true;
            for( String htmlType : htmlTypes ) {
                if( firstTime ) {
                    firstTime = false;
                } else {
                    xpath.append( "or" );
                }
                xpath.append( "'" );
                xpath.append( htmlType.toLowerCase() );
                xpath.append( "'" );
            }
            xpath.append( "]" );
        }

        // adding rules to xpath
        for( String rule : rules ) {

            boolean foundRule = true;
            // split if rule is to use several attributes combined like "name and value" ("name,value" in RULES)
            String[] ruleAttributes = rule.split( "[\\s\\,]+" );
            for( String ruleAttribute : ruleAttributes ) {
                if( properties.getProperty( ruleAttribute ) == null ) {
                    foundRule = false;
                }

                if( foundRule ) {
                    
                    // ignore attributes starting with double underscore
                    if( ruleAttribute.startsWith( "__" ) ) {
                        log.debug( "Ignoring attribute " + ruleAttribute + " as a helper one" );
                        continue;
                    }

                    if( ruleAttribute.startsWith( "_" ) ) {
                        if( !Arrays.asList( INTERNAL_ATTRIBUTES ).contains( ruleAttribute ) ) {
                            log.warn( "Found HTML property [" + ruleAttribute + " = "
                                      + properties.getProperty( ruleAttribute )
                                      + "] , which starts with underscore , but is not known by ATS. "
                                      + "It will be used to locate HTML element " + htmlNodeName );
                        }
                    }

                    if( "_text".equals( ruleAttribute ) ) {
                        xpath.append( "[" );
                        xpath.append( "text()" );
                        xpath.append( "='" );
                        xpath.append( properties.getProperty( ruleAttribute ) );
                        xpath.append( "']" );
                    } else if( "_partText".equals( ruleAttribute ) ) {
                        xpath.append( "[" );
                        xpath.append( "contains(text()" );
                        xpath.append( ", '" );
                        xpath.append( properties.getProperty( ruleAttribute ) );
                        xpath.append( "')]" );
                    } else if( "_inputType".equals( ruleAttribute ) ) {
                        xpath.append( "[@" );
                        xpath.append( "type" );
                        xpath.append( "='" );
                        xpath.append( properties.getProperty( ruleAttribute ) );
                        xpath.append( "']" );
                    } else if( "_css".equals( ruleAttribute ) ) {
                        // do nothing
                    } else {
                        xpath.append( "[@" );
                        xpath.append( ruleAttribute );
                        xpath.append( "='" );
                        xpath.append( properties.getProperty( ruleAttribute ) );
                        xpath.append( "']" );
                    }

                    if( !"href".equalsIgnoreCase( rule ) ) { //if the rule is 'href' don't stop and append another rules
                        break;
                    }
                    
                }

            }
        }

        if( "button".equals( htmlNodeName ) )

        {

            // we have to search for input elements too eg. //button[@type="button" or ...] | //input[@type="button" or ...]
            xpath.append( " | " + xpath.toString().replace( "//button[", "//input[" ) );
        } else if( "a".equals( htmlNodeName ) ) {

            // link title is the text of the "a" node (link), we need to do the following replace
            // here we are using normalize-space() function to trim the text of the link, because
            // text() = ' someText ' does't work. This is a problem with spaces in at the beginning and/or at the end.
            return xpath.toString().replace( "@title", "normalize-space(text())" );
        }

        return xpath.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy