Exemplo n.º 1
0
        /// <summary>
        /// This method evaluates if one IWebElement contains a child selected by the predicate. It can be used to select
        /// one container element based on its child elements.
        /// </summary>
        /// <param name="element">The container element to be evaludated.</param>
        /// <param name="childEnum">Enum Identifier of the child element, which carries the CSS selector.</param>
        /// <param name="predicate">Function to see if the child element meets predefined criteria.</param>
        /// <returns>"true": The container IWebElement contains the expected child IWebElement, otherwise "false".</returns>
        public static bool HasChildOf(this IWebElement element, Enum childEnum, Func <IWebElement, bool> predicate)
        {
            string      childLocatorCss = childEnum.Css();
            IWebElement child           = null;

            try
            {
                //child = GenericWait<IWebElement>.Until(() =>
                //    element.FindElementByCss(childLocatorCss), null, 1000);
                ReadOnlyCollection <IWebElement> candidates = null;
                candidates = GenericWait <ReadOnlyCollection <IWebElement> > .Until(
                    () => candidates = element.FindElementsByCss(childLocatorCss),
                    x => x.Count != 0,
                    200
                    );

                var  qualified = candidates.Where(predicate).ToList();
                bool result    = qualified.Count != 0;
                return(result);
            }
            catch (Exception)
            {
                return(false);
            }
        }
Exemplo n.º 2
0
 /// <summary>
 /// Assuming Elements can be found with CSS selector within time specified by waitInMills, keep executing the
 /// FindElementsByCssSelector() of either Driver or a specific IWebElement until timeout.
 /// </summary>
 /// <param name="findFunc">The FindElementsByCssSelector() of either Driver or a specific IWebElement.</param>
 /// <param name="css">CSS Selector string.</param>
 /// <param name="waitInMills">Maximum time to wait when the findFunc returns 0-length collection.</param>
 /// <returns>The non-empty collection immediately or empty collection after time is out.</returns>
 public ReadOnlyCollection <IWebElement> WaitToFindElements(Func <string, ReadOnlyCollection <IWebElement> > findFunc,
                                                            string css,
                                                            int waitInMills)
 {
     return(GenericWait <ReadOnlyCollection <IWebElement> > .Until(
                () => findFunc(css), collction => collction.Count != 0, waitInMills
                ));
 }
Exemplo n.º 3
0
        //Stores the last calling of FindElement() to avoid InvalidElementStateException or StaleElementReferenceException.
        //private long lastTick = Int64.MinValue;
        #endregion

        /// <summary>
        /// Retrieve the IWebElement based on the CSS associated with the Enum Identifier, and optional
        /// the filters when Enum Identifier selects a collection.
        /// </summary>
        /// <param name="filters">
        /// ByIndex to select one IWebElement from a collection of them, would be used by this Locator and its parents.
        ///     For Locator of a single IWebElement whose IsCollection=="false", filters is always neglected.
        ///     For Locator of multiple IWebElements whose IsCollection=="true",
        ///         filters is used to choose from a Collection returned by FindElementsByCssSelector().
        /// Noticeably, the filters is sticky. That is, if one Locator uses a filters, then it and its parent would store
        /// it for following calling of FindElement(null).
        /// The defintion of filters is similar to Queryable.Where<TSource> Method (IQueryable<TSource>, Expression<Func<TSource, Int32, Boolean>>)
        /// <seealso cref="http://msdn.microsoft.com/en-us/library/vstudio/bb548547(v=vs.100).aspx"/>
        /// </param>
        /// <returns>
        /// The IWebElement chosen by the CSS selector and the filters, and casted to IWebElement.
        /// </returns>
        public virtual IWebElement FindElement(Func <IWebElement, bool> filters = null, int waitInMills = DefaultWaitToFindElement)
        {
            //TODO: if it is necessary to validate the lastSelectedELement or regard it as valid within a limited time?
            //*/ Perform some simple operation to validate that the lastFoundElement is still valid
            if (lastFoundElement != null && (filters == null || filters == lastFilters) &&
                lastFoundElement.IsValid())
            {
                return(lastFoundElement);
            }

            /*/
             * //Otherwise, using the Environment.Ticks to make sure each Element is valid for a limited time (1 second)
             * if (lastFoundElement != null && (filters == null || filters == lastFilters)
             *  //&& (Environment.TickCount-lastTick<ValidElementStatePeriodInTicks)
             *  )
             *  return lastFoundElement;
             * //*/

            IWebElement parentElement = null;

            if (Parent != null && !Parent.Identifier.Equals(HtmlByCustom.Root))
            {
                parentElement = Parent.FindElement(filters, waitInMills);
                if (parentElement == null || !parentElement.IsValid())
                {
                    return(null);
                }
            }

            string css = Identifier.Css();

            //When CSS matches multiple IWebElements, further selection shall be applied by filters
            //Or, When selection is based on ByText mechanism, then EnumMember.Value is used
            if (Identifier.IsCollection() || Identifier.Mechanism().Equals(Mechanisms.ByText))
            {
                Func <string, ReadOnlyCollection <IWebElement> > findFunc = (parentElement == null) ?
                                                                            (Func <string, ReadOnlyCollection <IWebElement> >)DriverManager.FindElementsByCssSelector : parentElement.FindElementsByCss;

                //Select the candidate element by calling FindElementsByCssSelector(css) of either the parentElement or the Driver
                var candidates = WaitToFindElements(findFunc, css, waitInMills);

        #if (STEP_BY_STEP)
                Console.WriteLine("There are {0} candidates selected by '{1}'", candidates.Count, css);
        #endif

                if (Identifier.IsCollection())
                {
                    //Store the filters if it is not null, otherwise use the last filters
                    lastFilters = filters ?? lastFilters;

                    if (lastFilters == null)
                    {
                        throw new NullReferenceException();
                    }

                    var filtered = candidates.Where(lastFilters);

                    lastFoundElement = filtered.FirstOrDefault();
                }
                else
                {
                    lastFoundElement = candidates.FirstOrDefault(item => item.Text.Equals(Identifier.Value()));
                }
            }
            //When CSS select one IWebElement, then filter is ignored
            //Notice the GenericWait.Until() would keeps running until timeout or no Exception is thrown
            else
            {
                Func <string, IWebElement> find = (parentElement == null)
                    ? (Func <string, IWebElement>)DriverManager.FindElementByCssSelector
                    : parentElement.FindElementByCss;

                lastFoundElement = GenericWait <IWebElement> .TryUntil(() => find(css),
                                                                       x => x != null& x.IsValid(), ImmediateWaitToFindElement);
            }

            //if(lastFoundElement == null)
            //    throw new NoSuchElementException("Failed to find Element by CSS: " + css);

            //Keeps the moment of this opertion
            //lastTick = Environment.TickCount;
            return(lastFoundElement);
        }