private IEnumerable <Element> FindElements(Selector selector, LoggingWebDriver loggingWebdriver) { var wrappers = selector.PrioritizedSearchers.Select(s => new Wrapper { Searcher = s }).ToList(); var loopResults = Parallel.ForEach(wrappers, (wrapper, loopState) => { var searcher = wrapper.Searcher; var results = searcher.SearchIn(loggingWebdriver, Prefixes); SuccessfulSearchers.Add(searcher); loopState.Break(); wrapper.Elements = results; return; }); var r = loopResults.IsCompleted; var index = 0; foreach (var w in wrappers) { if (w.Elements != null) { return(w.Elements); } if (w.Exception != null) { throw new AggregateException($"Error throw on xpath {index}", w.Exception); } index++; } return(null); }
public IEnumerable <Element> SelectMany(Selector selector) => RetryExecutor.RetryFor(() => { var loggingWebdriver = new LoggingWebDriver(Driver, MovieLogger); try { var elements = FindElements(selector, loggingWebdriver); if (elements != null) { return(elements); } //iframes ? var iframes = Driver.FindElements(By.XPath("//iframe")); foreach (var iframe in iframes) { try { loggingWebdriver.Log($"Trying iframe:{iframe}"); Driver.SwitchTo().Frame(iframe); elements = FindElements(selector, loggingWebdriver); if (elements != null) { return(elements); } } catch { } } Driver.SwitchTo().DefaultContent(); return(new List <Element>()); } finally { if (loggingWebdriver.Screenshots.Any()) { Screenshots = loggingWebdriver.Screenshots.Select(x => x.AsByteArray).ToList(); } } }, TimeSpan.FromMilliseconds(SeleniumGridConfiguration.RetryMs));
public Element Select(Selector selector, TimeSpan?retryDuration = null, int?index = null) => RetryExecutor.RetryFor(() => { var loggingWebdriver = new LoggingWebDriver(Driver, MovieLogger); try { var element = FindElement(selector, loggingWebdriver, index); if (element != null) { return(element); } //iframes ? var iframes = Driver.FindElements(By.XPath("//iframe")); foreach (var iframe in iframes) { try { loggingWebdriver.Log($"Trying iframe:{iframe}"); Driver.SwitchTo().Frame(iframe); element = FindElement(selector, loggingWebdriver, index); if (element != null) { return(element); } } catch { } } Driver.SwitchTo().DefaultContent(); throw new Exception($"element was not found; tried:\n{loggingWebdriver.GetLogs()}, maybe try one of these identifiers {GetIdentifiers().Take(10).LogFormat()}"); } finally { if (loggingWebdriver.Screenshots.Any()) { Screenshots = loggingWebdriver.Screenshots.Select(x => x.AsByteArray).ToList(); } } }, retryDuration ?? TimeSpan.FromMilliseconds(SeleniumGridConfiguration.RetryMs));
public TableElement GetTables(IEnumerable <string> headers, StringComparison comparison = StringComparison.CurrentCulture, int?index = null) => RetryExecutor.RetryFor(() => { var loggingWebdriver = new LoggingWebDriver(Driver, MovieLogger); try { var possilbeTables = GetTables(headers.Count()).ToList(); Func <string, string, bool> comparer = (s1, s2) => s1.Equals(s2, comparison); var tableElements = possilbeTables.Where(t => headers.Where(h => !string.IsNullOrEmpty(h)).Except(t.Header.Keys, new Core.EqualityComparer <string>(comparer)).None()); if (tableElements.One()) { return(tableElements.First()); } if (tableElements.Many()) { if (index == null) { throw new Exception($"multiple talbes matched the definition of {headers.LogFormat()}, table headers were {tableElements.LogFormat(t => $"Table: {t.Header.Keys.LogFormat()}")};"); } if (index >= tableElements.Count()) { throw new Exception($"only found {tableElements.Count()} tables, index of {index} is out of range. (zero based)"); } return(tableElements.ToArray()[index.Value]); } //iframes ? var iframes = Driver.FindElements(By.XPath("//iframe")); foreach (var iframe in iframes) { try { loggingWebdriver.Log($"Trying iframe:{iframe}"); Driver.SwitchTo().Frame(iframe); possilbeTables = GetTables(headers.Count() - 1).ToList(); tableElements = possilbeTables.Where(t => headers.Where(h => !string.IsNullOrEmpty(h)).Except(t.Header.Keys, new Core.EqualityComparer <string>(comparer)).None()); if (tableElements.One()) { return(tableElements.First()); } if (tableElements.Many()) { if (index == null) { throw new Exception($"multiple talbes matched the definition of {headers.LogFormat()}, table headers were {tableElements.LogFormat(t => $"Table: {t.Header.Keys.LogFormat()}")};"); } if (index >= tableElements.Count()) { throw new Exception($"only found {tableElements.Count()} tables, index of {index} is out of range. (zero based)"); } return(tableElements.ToArray()[index.Value]); } } catch { } } Driver.SwitchTo().DefaultContent(); throw new Exception($"table was not found"); } finally { if (loggingWebdriver.Screenshots.Any()) { Screenshots = loggingWebdriver.Screenshots.Select(x => x.AsByteArray).ToList(); } } }, TimeSpan.FromMilliseconds(SeleniumGridConfiguration.RetryMs));
private Element FindElement(Selector selector, LoggingWebDriver loggingWebdriver, int?index = null) { var wrappers = selector.PrioritizedSearchers.Select(s => new Wrapper { Searcher = s }).ToList(); var loopResults = Parallel.ForEach(wrappers, //new ParallelOptions { MaxDegreeOfParallelism = 4 }, (wrapper, loopState) => { var searcher = wrapper.Searcher; var results = searcher.SearchIn(loggingWebdriver, Prefixes); if (loopState.ShouldExitCurrentIteration) { return; } else if (results.One()) { SuccessfulSearchers.Add(searcher); loopState.Break(); wrapper.Element = results.First(); return; } else if (results.Many() && index.HasValue) { SuccessfulSearchers.Add(searcher); loopState.Break(); var a = results.ToArray(); if (a.Count() <= index.Value) { wrapper.Exception = new Exception($"Not enough items found, found {a.Count()} and desired index {index}"); } else { wrapper.Element = a[index.Value]; } return; } else if (results.Many()) { //lets make sure none are hidden var filterHidden = results .Select(e => new { e, o = loggingWebdriver.GetElementFromPoint(e.Location.X + 1, e.Location.Y + 1) }) .Where(p => p.e.Tag == p.o?.TagName && p.e.Location == p.o?.Location); if (filterHidden.One()) { SuccessfulSearchers.Add(searcher); loopState.Break(); wrapper.Element = results.First(); return; } //check if they are logical duplicates. if (results.GroupBy(e => e.Id).One()) { SuccessfulSearchers.Add(searcher); loopState.Break(); wrapper.Element = results.First(); return; } //scroll up ? //WebDriver.ExecuteScript("window.scrollTo(0,1)"); var items = results.Select(e => $"{e.Tag}@{e.Location.X},{e.Location.Y}").LogFormat(); loopState.Break(); wrapper.Exception = new Exception($"Multiple results were found using {searcher.LogFormat()}"); return; } }); var r = loopResults.IsCompleted; var wrapperIndex = 0; foreach (var w in wrappers) { if (w.Element != null) { return(w.Element); } if (w.Exception != null) { throw new AggregateException($"Error throw on xpath {wrapperIndex}", w.Exception); } wrapperIndex++; } return(null); }