private IList <HtmlElement> FindAll(HtmlElementFindParams findParams, int timeoutInSeconds, bool stopAfterFirstFind)
        {
            List <HtmlElement> elements     = new List <HtmlElement>();
            bool     canUseTagIndexToLocate = (this.ParentElement == null ? true : false);
            DateTime timeout  = DateTime.Now.AddSeconds(timeoutInSeconds);
            int      attempts = 0;

            /*
             * Design:
             *  1) First try to locate element in in-memory collection.
             *  2) If that fails, refresh the collection from the browser and try again (regardless of timeout)
             *  3) If that fails, keep refreshing and searching until timeout is met
             */

            do
            {
                if (this._testPage != null && _timeoutWaitingToFind > 0 &&
                    (attempts > 0 || findParams.Attributes.Count > 0))
                {
                    // after first attempt (or if we want to find by Attributes)
                    //refresh the collection from client before trying again.
                    Thread.Sleep(100);
                    this.Refresh(findParams.Attributes.ConvertAll <string>(
                                     delegate(HtmlAttributeFindParams attrMatch) { return(attrMatch.Name); })
                                 );
                }

                findParams.IndexInternal = findParams.Index;
                this.FindAllInternal(findParams, elements, stopAfterFirstFind, canUseTagIndexToLocate);
                attempts++;
            } while (elements.Count == 0 && (attempts < 2 || DateTime.Now < timeout) && timeoutInSeconds != 0);

            return(elements);
        }
        private void FindAllInternal(HtmlElementFindParams findParams, ICollection <HtmlElement> collection, bool stopAfterFirstFind, bool canUseTagIndexToLocate)
        {
            if (stopAfterFirstFind && collection.Count > 0)
            {
                return;
            }

            foreach (HtmlElement element in this.Items)
            {
                if (findParams.DoesElementMatch(element))
                {
                    if (findParams.IndexInternal == 0)
                    {
                        element.CanUseTagIndexToLocate = canUseTagIndexToLocate;
                        collection.Add(element);
                        if (stopAfterFirstFind)
                        {
                            return;
                        }
                    }
                    else
                    {
                        findParams.IndexInternal--;
                    }
                }

                element.ChildElements.FindAllInternal(findParams, collection, stopAfterFirstFind, canUseTagIndexToLocate);
            }
        }
        /// <summary>
        /// Recursively finds all the elements with the determined tagName and innerText
        /// </summary>
        /// <param name="tagName">Tag name of the element to find (case insensitive).</param>
        /// <param name="innerText">The innerText of the element to find (case insensitive).</param>
        /// <returns>A collection of HtmlElements that have the given tag name and inner text.</returns>
        public ReadOnlyCollection <HtmlElement> FindAll(string tagName, string innerText)
        {
            HtmlElementFindParams findParams = new HtmlElementFindParams();

            findParams.TagName   = tagName;
            findParams.InnerText = innerText;
            return(this.FindAll(findParams));
        }
 /// <summary>
 /// Returns the first occurence of an element that matches the findParams and that occurs after
 /// the specified element.
 /// </summary>
 /// <param name="precedingElement">The element that must come before the what we are looking for</param>
 /// <param name="findParams">The find params for the element we are looking for</param>
 /// <returns>The element that is found.  An exception is thrown if an element is not found</returns>
 public HtmlElement FindAfter(HtmlElement precedingElement, HtmlElementFindParams findParams)
 {
     if (IsElementUnderThisCollection(precedingElement))
     {
         return(FindAfterRecursive(precedingElement, findParams));
     }
     else
     {
         throw new ArgumentException("The 'precedingElement' argument was not itself a member of the collection.", "precedingElement");
     }
 }
        /// <summary>
        /// Returns whether an element that satisfies the given parameters exists within this collection (recursive)
        /// </summary>
        /// <param name="findParams">HtmlElementFindParams object that encapsulates the find parameters</param>
        /// <param name="timeoutInSeconds">Seconds to keep searching the collection if element not found</param>
        /// <returns>True if an element is found, otherwise false</returns>
        public bool Exists(HtmlElementFindParams findParams, int timeoutInSeconds)
        {
            IList <HtmlElement> list = FindAll(findParams, timeoutInSeconds, true);

            if (list.Count > 0)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
        /// <summary>
        /// Recursively find the first element that satisfies the given parameters and keep trying for the specified time
        /// </summary>
        /// <param name="findParams">HtmlElementFindParams object that encapsulates the find parameters</param>
        /// <param name="timeoutInSeconds">Seconds to keep searching the collection if element not found</param>
        /// <returns>The first HtmlElement in this collection that satisfies the given find parameters</returns>
        /// <exception cref="ElementNotFoundException">Thrown if element not found</exception>
        public HtmlElement Find(HtmlElementFindParams findParams, int timeoutInSeconds)
        {
            IList <HtmlElement> list = FindAll(findParams, timeoutInSeconds, true);

            if (list.Count > 0)
            {
                return(list[0]);
            }
            else
            {
                throw BuildElementNotFoundException(findParams, timeoutInSeconds);
            }
        }
        private ElementNotFoundException BuildElementNotFoundException(HtmlElementFindParams findParams, int timeout)
        {
            string message = @"Control not found in HtmlElementCollection after {0} seconds. HtmlElemntFindParams:
<br />TagName:'{1}'.
<br />Id:'{2}'.
<br />InnerText:'{3}'.
<br />Index:'{4}'. 
If control is taking too long to appear in browser's DOM, use 'Find(HtmlElementFindParams,int)' method overload to wait until control appears.";

            return(new ElementNotFoundException(String.Format(message,
                                                              timeout,
                                                              findParams.TagName,
                                                              findParams.IdAttributeFindParams.Value,
                                                              findParams.InnerText,
                                                              findParams.Index)));
        }
Exemple #8
0
        /// <summary>
        /// Returns whether the current page is an Asp.Net server error page.
        /// </summary>
        /// <returns>True if current page is an Asp.Net server error page, false otherwise</returns>
        public virtual bool IsServerError()
        {
            HtmlElementFindParams findParams = new HtmlElementFindParams("h1", 0);

            if (this.Elements.Exists(findParams, 0))
            {
                if (_aspnetErrorRegexPattern == null)
                {
                    WebResourceReader reader = new WebResourceReader();
                    string            aspnetErrorStringFormatter = reader.GetString("System.Web", "System.Web", "Error_Formatter_ASPNET_Error"); //Server Error in '{0}' Application.
                    _aspnetErrorRegexPattern = String.Format(aspnetErrorStringFormatter, ".+?");
                }

                HtmlElement h1 = this.Elements.Find(findParams, 0);
                return(Regex.IsMatch(h1.CachedInnerText, _aspnetErrorRegexPattern, RegexOptions.Singleline));
            }
            return(false);
        }
        private HtmlElement FindAfterRecursive(HtmlElement precedingElement, HtmlElementFindParams findParams)
        {
            var parentOfElement = precedingElement.ParentElement;

            // Stop if we are at the root element
            if (parentOfElement == null)
            {
                throw BuildElementNotFoundException(findParams, 0);
            }

            // Stop if we are looking outside of this collection's parent (only possible if the collection belongs
            // to an element, not to the page).
            if (this.ParentElement != null && this.ParentElement.ParentElement == parentOfElement)
            {
                throw BuildElementNotFoundException(findParams, 0);
            }

            int indexOfThisElement = parentOfElement.ChildElements.IndexOf(precedingElement);

            for (int i = indexOfThisElement + 1; i < parentOfElement.ChildElements.Count; i++)
            {
                if (findParams.DoesElementMatch(parentOfElement.ChildElements[i]))
                {
                    return(parentOfElement.ChildElements[i]);
                }
                else
                {
                    var matchedElements = parentOfElement.ChildElements[i].ChildElements.FindAll(findParams, 0);
                    if (matchedElements.Count > 0)
                    {
                        return(matchedElements[0]);
                    }
                }
            }

            return(this.FindAfterRecursive(parentOfElement, findParams));
        }
 /// <summary>
 /// Returns whether an element that satisfies the given parameters exists within this collection (recursive)
 /// </summary>
 /// <param name="findParams">HtmlElementFindParams object that encapsulates the find parameters</param>
 /// <returns>True if an element is found, otherwise false</returns>
 public bool Exists(HtmlElementFindParams findParams)
 {
     return(Exists(findParams, _timeoutWaitingToFind));
 }
        /// <summary>
        /// Recursively finds all the elements that satisfy the given parameters and keep trying for the specified time
        /// </summary>
        /// <param name="findParams">HtmlElementFindParams object that encapsulates the find parameters</param>
        /// <param name="timeoutInSeconds">Seconds to keep searching the collection if element not found</param>
        /// <returns>A collection of HtmlElements that satisfy the given find parameters</returns>
        public ReadOnlyCollection <HtmlElement> FindAll(HtmlElementFindParams findParams, int timeoutInSeconds)
        {
            IList <HtmlElement> list = FindAll(findParams, timeoutInSeconds, false);

            return(new ReadOnlyCollection <HtmlElement>(list));
        }
 /// <summary>
 /// Recursively finds all the elements that satisfy the given parameters
 /// </summary>
 /// <param name="findParams">HtmlElementFindParams object that encapsulates the find parameters</param>
 /// <returns>A collection of HtmlElements that satisfy the given find parameters</returns>
 public ReadOnlyCollection <HtmlElement> FindAll(HtmlElementFindParams findParams)
 {
     return(FindAll(findParams, _timeoutWaitingToFind));
 }
 /// <summary>
 /// Recursively find the first element that satisfies the given parameters
 /// </summary>
 /// <param name="findParams">HtmlElementFindParams object that encapsulates the find parameters</param>
 /// <returns>The first HtmlElement in this collection that satisfies the given find parameters</returns>
 /// <exception cref="ElementNotFoundException">Thrown if element not found</exception>
 public HtmlElement Find(HtmlElementFindParams findParams)
 {
     return(Find(findParams, _timeoutWaitingToFind));
 }