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

org.bithill.selenium.resolving.Find Maven / Gradle / Ivy

There is a newer version: 1.0
Show newest version
package org.bithill.selenium.resolving;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;

import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;

import static org.bithill.selenium.resolving.FieldOfResolvable.isGroupMember;
import static org.bithill.selenium.resolving.FieldOfResolvable.isList;
import static org.bithill.selenium.resolving.FieldOfResolvable.isResolvable;
import static org.bithill.selenium.resolving.FieldOfResolvable.isResolvedByAnnotated;
import static org.bithill.selenium.resolving.FieldOfResolvable.isSelect;
import static org.bithill.selenium.resolving.FieldOfResolvable.isWebElement;
import static org.bithill.selenium.resolving.Reflection.getClassFields;
import static org.bithill.selenium.resolving.Reflection.getFieldValue;


/**
 * Searching in RESOLVED {@link WebElement}s.
 */
public class Find
{
    private Find() {}

    /* Create a new search. */
    public static QueryEngine in(Resolvable resolvable)
    {
        return new QueryEngine(resolvable);
    }

    /* Search implementation. */
    public static class QueryEngine
    {
        /** Resolvable that serves as the root for searching. */
        private Resolvable searchRoot;

        public QueryEngine(Resolvable resolvable)
        {
            this.searchRoot = resolvable;
        }

        /**
         * Search for WebElements that have been resolved and belong to a given set of groups.
         *
         * @param groups list of groups for whose members we are looking
         * @return list of WebElements under a search root
         */
        public List groupMembers(String... groups)
        {
            return new ArrayList<>(groupMembers(searchRoot, groups));
        }

        /**
         * Search for WebElements that have been resolved and belong to a given set of groups.
         *
         * @param groups            list of groups for whose members we are looking
         * @param currentSearchRoot the search root used for this search, it is excluded from the search
         * @return list of WebElements under a search root
         */
        private LinkedHashSet  groupMembers(Resolvable currentSearchRoot, String... groups)
        {
            LinkedHashSet  result = new LinkedHashSet<>();

            if (currentSearchRoot != null)
            {
                // breadth-first search
                //
                // annotatedGroupMember = "annotated by ResolveBy and belongs to one of the groups"
                // 1. for each field that is annotatedGroupMember of the currentSearchRoot :
                //     1.1 if WebElement, add it to the result
                //     1.2 if List, add its all elements to the result
                //     1.3 if Resolvable, add it field's self-reference to the result
                for (Field field : getClassFields(currentSearchRoot, Resolvable.class))
                {
                    if ( getFieldValue(currentSearchRoot, field) != null && isResolvedByAnnotated(field) && isGroupMember(field, groups) )
                    {
                        if (isWebElement(field))
                        {
                            result.add((WebElement) getFieldValue(currentSearchRoot, field));
                        }
                        if (isSelect(field))
                        {
                            // Select's internal element is not accessible via API, let's use reflection to get it
                            try
                            {
                                Select select = (Select) getFieldValue(currentSearchRoot, field);
                                Field elementField = select.getClass().getField("element");
                                WebElement element = (WebElement) getFieldValue(select, elementField);
                                result.add(element);
                            }
                            catch (NoSuchFieldException ex)
                            {
                                throw new RuntimeException(ex);
                            }
                        }
                        else if (isList(field))
                        {
                            @SuppressWarnings("unchecked")
                            List elementList = (List) getFieldValue(currentSearchRoot, field);
                            result.addAll(elementList);
                        }
                        else if (isResolvable(field))
                        {
                            Resolvable resolvable = (Resolvable) getFieldValue(currentSearchRoot, field);
                            if (resolvable.getSelf() != null)
                            {
                                result.add(resolvable.getSelf());
                            }
                        }
                    }
                }

                // 2. for each of Resolvable field of the currentSearchRoot:
                //     add all elements in groupMembers(field, groups) to the result,
                //     i.e. use the field as new search root and drill down
                for (Field field : getClassFields(currentSearchRoot, Resolvable.class))
                {
                    if (getFieldValue(currentSearchRoot, field) != null && isResolvable(field))
                    {
                        Resolvable resolvable = (Resolvable) getFieldValue(currentSearchRoot, field);
                        result.addAll( groupMembers(resolvable, groups) );
                    }
                }
            }

            return result;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy