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))); }
/// <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)); }