/// <summary> /// Creates a dynamic element that uses the parent element as the base of the search /// </summary> /// <param name="page"></param> /// <param name="displayName"></param> /// <param name="parentElement"></param> public DynamicElement(IPageObject page, string displayName, DynamicElement parentElement) { ParentElement = parentElement; this.Driver = page.Driver; this.ParentPage = page.DisplayName; this.DisplayName = displayName; }
public static Control <TOwner> GetActiveControl <TOwner>(this IPageObject <TOwner> pageObject) where TOwner : PageObject <TOwner> { return(pageObject.Controls.Create <Control <TOwner> >( "<Active>", new DynamicScopeLocator(so => AtataContext.Current.Driver.SwitchTo().ActiveElement()))); }
private static T To <T>(T pageObject, GoOptions options) where T : PageObject <T> { if (AtataContext.Current == null) { AtataContext.Build().SetUp(); } if (AtataContext.Current.PageObject == null) { pageObject = pageObject ?? ActivatorEx.CreateInstance <T>(); AtataContext.Current.PageObject = pageObject; if (!string.IsNullOrWhiteSpace(options.Url)) { ToUrl(options.Url); } pageObject.NavigateOnInit = options.Navigate; pageObject.Init(); return(pageObject); } else { IPageObject currentPageObject = (IPageObject)AtataContext.Current.PageObject; T newPageObject = currentPageObject.GoTo(pageObject, options); AtataContext.Current.PageObject = newPageObject; return(newPageObject); } }
private T To <T>(T pageObject, GoOptions options) where T : PageObject <T> { if (context.PageObject is null) { pageObject = pageObject ?? ActivatorEx.CreateInstance <T>(); context.PageObject = pageObject; if (!string.IsNullOrWhiteSpace(options.Url)) { ToUrl(options.Url); } pageObject.NavigateOnInit = options.Navigate; pageObject.Init(); return(pageObject); } else { IPageObject currentPageObject = (IPageObject)context.PageObject; T newPageObject = currentPageObject.GoTo(pageObject, options); context.PageObject = newPageObject; return(newPageObject); } }
public void SetupTest() { pageObject = new VeeamPageObject(driver); steps = new CareersVeeamSteps(pageObject); driver.Navigate().GoToUrl(@"https://careers.veeam.com/"); driver.Manage().Window.Maximize(); }
/// <summary> /// Gets the test classes associated with this page object. /// </summary> /// <param name="source">The source page object.</param> /// <returns>The test classes associated with this page object.</returns> internal static IEnumerable <Type> TestClasses(this IPageObject source) { var interfaces = source.GetType().GetInterfaces(); var pageObjectInterfaces = interfaces.Where(e => e.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IPageObject))); var matchingTypes = pageObjectInterfaces.Union(new[] { source.GetType() }); var result = TestClassTypes.Where(type => type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPageObjectTestClass <>) && matchingTypes.Contains(i.GenericTypeArguments.First()))).ToArray(); return(result); }
public static IQueryable <T> ApplyPaging <T>(this IQueryable <T> query, IPageObject pageObj) { var page = pageObj.Page <= 0 ? 1 : pageObj.Page; var pageSize = pageObj.PageSize <= 0 ? 10 : pageObj.PageSize; return(query.Skip((page - 1) * pageSize) .Take(pageSize)); }
/// <summary> /// Gets the page object statistic for a certain page object type. /// </summary> /// <param name="pageObject">The page object.</param> /// <returns>The page object statistic.</returns> internal static PageObjectStatistic PageObjectStatistic(IPageObject pageObject) { var t = pageObject.GetType(); if (!pageObjectStatistic.ContainsKey(t)) { pageObjectStatistic[t] = new PageObjectStatistic(); } return(pageObjectStatistic[t]); }
/// <summary> /// Add page object statistics. /// </summary> /// <param name="source">The page object</param> /// <param name="testClassStatistic">The statistics to add.</param> internal void Add(IPageObject source, TestClassStatistic testClassStatistic) { var t = source.GetType(); if (!pageObjectStatistic.ContainsKey(t)) { pageObjectStatistic[t] = new PageObjectStatistic(); } pageObjectStatistic[t] += testClassStatistic; }
/// <summary> /// Initializes a new <see cref="UIPageObject" /> with a <see cref="TextSequence" />. /// </summary> /// <param name="pageObject">A <see cref="PageObject" /> to use to populate and style this control.</param> /// <param name="storyData">The <see cref="Data" /> that corresponds to the loaded story.</param> /// <param name="style">A <see cref="Style" /> object describing how this object should be drawn.</param> protected UIPageObject(IPageObject pageObject, Data storyData, Style style) { TextBlock = new TextBlock { FontFamily = new FontFamily("Cambria"), FontSize = 24.0, TextWrapping = TextWrapping.WrapWithOverflow }; FormattedText = pageObject.DisplayText(storyData); PageObjectStyle = style; }
/// <summary> /// Register the page object type with the given object. /// </summary> /// <typeparam name="TPageObject">The page object type.</typeparam> /// <param name="target">The object to register.</param> public void Register <TPageObject>(IPageObject target) { if (typeToPageObjectMap.TryGetValue(typeof(TPageObject), out HashSet <IPageObject> o)) { o.Add(target as IPageObject); } else { typeToPageObjectMap.Add(typeof(TPageObject), new HashSet <IPageObject>(new IPageObjectEqualityComparer())); Register <TPageObject>(target); } }
public static TOwner ThrowSoftAsserts <TOwner>(this IPageObject <TOwner> page) where TOwner : PageObject <TOwner> { AtataContext.Current.Log.Info($"ThrowSoftAssert: Exceptions count is {ExceptionResults.Count}"); if (ExceptionResults.Count > 0) { Exception ex = new Exception(ExceptionResults.Count.ToString() + " exceptions: \n" + ExceptionResults.Aggregate((i, j) => i + "\n" + j)); ExceptionResults.Clear(); throw ex; } return(page.Owner); }
/// <summary> /// Find a page object in the page object tree. /// </summary> /// <param name="condition">The condition that must evaluate true for the resulting page object.</param> /// <param name="result">The result page object.</param> /// <typeparam name="TPageObject">The page object type to search for.</typeparam> /// <returns>The page object.</returns> private bool TryFind <TPageObject>(Predicate <TPageObject> condition, out TPageObject result) where TPageObject : IPageObject { Queue <IPageObject> q = new Queue <IPageObject>(); if (TryGet(out IEnumerable <TPageObject> registeredObjects)) { foreach (var a in registeredObjects) { q.Enqueue(a); } } q.Enqueue(rootObject); while (q.Count > 0) { IPageObject current = q.Dequeue(); // interface types match any implementation, whereas classes must match exactly var match = typeof(TPageObject).IsInterface ? current is TPageObject : current.GetType().Equals(typeof(TPageObject)); if (match) { TPageObject page = (TPageObject)current; Register <TPageObject>(page); if ((page as ITreeObject).OnCondition && condition(page)) { var parent = (IPageObject)page.Parent; result = parent == null ? page : (TPageObject)(Activator.CreateInstance(page.GetType()) as IUIObjectInternal).Init(parent, true); return(true); } } // traverse children var c = ((ITreeObject)current).Children <TPageObject>(); foreach (IPageObject childPageObject in c) { // generic page object must be child-less if (current.GetType().IsGenericType) { Trace.TraceWarning($"Ignoring children of generic page object type <{current.GetType().Name}>"); continue; } q.Enqueue(childPageObject); } } result = default(TPageObject); return(false); }
/// <summary> /// Run all tests with the <c>PageTestAttribute</c>. /// </summary> /// <param name="source">The source page object.</param> /// <param name="pageObjectStatistics">Whether to write the result tree.</param> /// <param name="filter">The test method filter predicate.</param> /// <param name="writeTree">Whether to write the result tree.</param> /// <returns>This page object.</returns> private static Tree TestBottomUp(this IPageObject source, Func <MethodInfo, Type, bool> filter, bool writeTree, PageObjectStatistics pageObjectStatistics) { Trace.WriteLine($"Run tests for {source.GetType().FullName}"); // run tests for every child foreach (var child in source.Children()) { TestBottomUp(child, filter, false, pageObjectStatistics); } // run tests for this page object return(Test(source, filter, writeTree, pageObjectStatistics)); }
/// <summary> /// Run all tests with the <c>PageTestAttribute</c>. /// </summary> /// <param name="source">The source page object.</param> /// <param name="methodFilter">The test method filter predicate.</param> /// <param name="pageTestClassFilter">The page test class filter predicate.</param> /// <returns>This page object.</returns> public static IPageObject TestBottomUp(this IPageObject source, Predicate <MethodInfo> methodFilter = null, Predicate <IPageObjectTests> pageTestClassFilter = null) { Trace.WriteLine("Run tests for " + source.GetType().FullName); // run tests for every child foreach (var child in source.Children()) { child.TestBottomUp(methodFilter, pageTestClassFilter); } // run tests for this page object source.Test(methodFilter, pageTestClassFilter); return(source); }
/// <summary> /// Gets the page object types. /// </summary> /// <param name="parentToFind">The parent page object.</param> /// <returns>The child types.</returns> internal static IEnumerable <Type> ChildTypes(IPageObject parentToFind) { var notMatchingTypeYetMatchingQualifiedName = ChildToParent.Where(childAndParents => !childAndParents.Value.Contains(parentToFind.GetType()) && childAndParents.Value.Select(parent => parent.AssemblyQualifiedName).Contains(parentToFind.GetType().AssemblyQualifiedName)); if (notMatchingTypeYetMatchingQualifiedName.Any()) { var similarParents = notMatchingTypeYetMatchingQualifiedName.First().Value; var similarParent = similarParents.First(parent => parent.AssemblyQualifiedName == parentToFind.GetType().AssemblyQualifiedName); var childOfSimilarParent = notMatchingTypeYetMatchingQualifiedName.First().Key; throw new AmbiguousParentObjectFoundException(parentToFind, similarParent, childOfSimilarParent); } var resultByEquality = ChildToParent.Where(e => e.Value.Contains(parentToFind.GetType())).Select(e => e.Key); return(resultByEquality); }
public DynamicElement(IPageObject page, string displayName) : this(page, displayName, null) { }
public UIParagraph(IPageObject pageObject, Data storyData, Style style) : base(pageObject, storyData, style) { Content = TextBlock; }
/// <summary> /// Gets the page object types. /// </summary> /// <param name="pageObject">The parent page object.</param> /// <returns>The child types.</returns> internal static IEnumerable <Type> ChildTypes(IPageObject pageObject) => ParentToChildMap.Where(e => e.Value.Contains(pageObject.GetType())).Select(e => e.Key);
/// <summary> /// Run tests for this page object. /// </summary> /// <param name="source">The source page object.</param> /// <param name="filter">The test method filter predicate.</param> /// <param name="writeTree">Whether to write the result tree.</param> /// <param name="pageObjectStatistics">The page object statistics.</param> /// <returns>This page object.</returns> private static Tree Test(this IPageObject source, Func <MethodInfo, Type, bool> filter, bool writeTree, PageObjectStatistics pageObjectStatistics) { filter = filter ?? ((e, f) => true); Tree result = null; bool success = true; try { foreach (Type classWithTests in source.TestClasses()) { Trace.WriteLine($"Found page test class for current class {source.GetType().ToString()}: {classWithTests.ToString()}"); // create and initialize page test class var instance = (IPageObjectTestsInternal)Activator.CreateInstance(classWithTests); instance.Init(source); // check if tests should be executed if (instance.Runnable) { Trace.WriteLine("Runnable returned true; running tests..."); } else { Trace.WriteLine("Runnable returned false; skipping tests"); continue; } // get page test methods, and order them from top to bottom // ordering does not respect inheritance var methods = classWithTests.GetMethods().Where(m => m.GetCustomAttributes(typeof(PageTestAttribute), false).Length > 0); var methodsByLine = methods.OrderBy(asd => asd.GetCustomAttribute <PageTestAttribute>(true).Line); var matchingMethodsByLine = methodsByLine.Where(f => filter(f, classWithTests)); int testMethodsCount = matchingMethodsByLine.Count(); if (testMethodsCount > 0) { Trace.WriteLine($"Found {testMethodsCount} test methods"); } else { Trace.WriteLine("No test method found; skipping test class"); continue; } Trace.WriteLine($"Execute function {nameof(IPageObjectTests.BeforeFirstTest)}..."); instance.BeforeFirstTest(); // check if tests should be executed if (!instance.ReadyToRun) { throw new TestNotReadyToRunException(classWithTests.FullName); } else { Trace.WriteLine("Tests are ready to run..."); } // create class statistics object TestClassStatistic testClassStatistic = new TestClassStatistic(classWithTests); // execute test methods try { foreach (var testMethod in matchingMethodsByLine) { Test(testClassStatistic, instance, testMethod); } Trace.WriteLine($"Execute function {nameof(IPageObjectTests.AfterLastTest)}..."); instance.AfterLastTest(); } finally { success = false; pageObjectStatistics.Add(source, testClassStatistic); } } } finally { result = Root(source).Tree; foreach (var pair in pageObjectStatistics.Stats) { // merge trees result += pair.Value; result += new Edge { To = pair.Value.Root.Id, From = new Node() { Id = pair.Key.FullName }.Id }; } if (!success || writeTree) { result.WriteGraph(); } } return(result); }
/// <summary> /// Get the root a page object. /// </summary> /// <param name="source">The page object.</param> /// <returns>The root.</returns> private static ITreeObject Root(IPageObject source) => (ITreeObject)((IUIObjectInternal)source).Root;
/// <summary> /// Run all tests with the <c>PageTestAttribute</c>. /// </summary> /// <param name="source">The source page object.</param> /// <param name="writeTree">Whether to write the result tree.</param> /// <param name="filter">The test method filter predicate.</param> /// <returns>This page object.</returns> public static void TestBottomUp(this IPageObject source, bool writeTree = false, Func <MethodInfo, Type, bool> filter = null) => TestBottomUp(source, filter, writeTree, new PageObjectStatistics());
/// <summary> /// Equalses the specified page object. /// </summary> /// <param name="pageObject">The page object.</param> /// <returns></returns> /// <exception cref="ArgumentNullException">pageObject</exception> public virtual bool Equals(IPageObject pageObject) { return(GetHashCode() == (pageObject?.GetHashCode() ?? 0)); }
/// <summary> /// Initialize the page object. /// </summary> /// <param name="pageUnderTest">The page object to drive the test.</param> void IPageObjectTestsInternal.Init(IPageObject pageUnderTest) { Configuration = new Lazy <Configuration>(() => (Page as IUIObjectInternal).Root.Configuration); Page = (TPageUnderTest)pageUnderTest; }
/// <summary> /// Run all tests with the <c>PageTestAttribute</c>. /// </summary> /// <param name="source">The source page object.</param> /// <param name="filter">The test method filter predicate.</param> /// <param name="writeTree">Whether to write the result tree.</param> /// <returns>This page object.</returns> internal static Tree TestBottomUpInternal(this IPageObject source, Func <MethodInfo, Type, bool> filter = null, bool writeTree = false) => TestBottomUp(source, filter, writeTree, new PageObjectStatistics());
public PageFluentAsserts(IPageObject pageobject) { _pageObject = pageobject; }
/// <summary> /// Initializes a new instance of the <see cref="AmbiguousParentObjectFoundException"/> class. /// </summary> public AmbiguousParentObjectFoundException(IPageObject parentToFind, Type similarParent, Type childOfSimilarParent) : base($"Error when searching for page object '{parentToFind.GetType().Name}' in location '{parentToFind.GetType().Assembly.Location}' in the page object tree: Found the same class in location {similarParent.Assembly.Location}' with child '{childOfSimilarParent}'. Ensure that page objects are only loaded once. Check https://stackoverflow.com/a/3624044 for ideas on how to solve this issue.") { }
/// <summary> /// Clear the page object statistic. /// </summary> /// <param name="pageObject">The page object.</param> internal static void ClearPageObjectStatistic(IPageObject pageObject) { pageObjectStatistic[pageObject.GetType()] = new PageObjectStatistic(); }
/// <summary> /// /// </summary> /// <param name="page"></param> /// <param name="displayName"></param> /// <param name="rootElement"></param> public DynamicElement(IPageObject page, string displayName, IWebElement rootElement) { this.RootElement = rootElement; this.Driver = page.Driver; this.DisplayName = "Unknown"; }
/// <summary> /// Run tests for this page object. /// </summary> /// <param name="source">The source page object.</param> /// <param name="methodFilter">The test method filter predicate.</param> /// <param name="pageTestClassFilter">The page test class filter predicate.</param> /// <returns>This page object.</returns> public static IPageObject Test(this IPageObject source, Predicate <MethodInfo> methodFilter = null, Predicate <IPageObjectTests> pageTestClassFilter = null) { methodFilter = methodFilter ?? (_ => true); pageTestClassFilter = pageTestClassFilter ?? (_ => true); foreach (Type classWithTests in source.TestClasses()) { Trace.WriteLine("Found page test class for current class " + source.GetType().ToString() + ": " + classWithTests.ToString()); // create and initialize page test class IPageObjectTestsInternal instance; var root = ((IUIObjectInternal)source).Root; try { var configuration = root.Configuration; configuration .DependencyRegistrator .RegisterType(classWithTests); instance = (IPageObjectTestsInternal)configuration.resolver.Resolve(classWithTests); } catch (Stashbox.Exceptions.ResolutionFailedException exception) { throw new TypeResolutionFailedException(exception, $"Configure the resolver via '{nameof(Configuration.DependencyRegistrator)}' in class '{root.GetType().FullName}'."); } // init page test class instance.Init(source); // check if tests should be executed according to the page test filter if (pageTestClassFilter(instance)) { Trace.WriteLine("Page test class filter returned true; running tests..."); } else { Trace.WriteLine("Page test class filter returned true; skipping tests..."); continue; } // check if tests should be executed according to the runnable predicate if (instance.Runnable) { Trace.WriteLine("Runnable returned true; running tests..."); } else { Trace.WriteLine("Runnable returned false; skipping tests"); continue; } // get page test methods, and order them from top to bottom // ordering does not respect inheritence var methods = classWithTests.GetMethods().Where(method => method.GetCustomAttributes(typeof(PageTestAttribute), false).Length > 0); var methodsByLine = methods.OrderBy(method => method.GetCustomAttribute <PageTestAttribute>(true).Line); var matchingMethodsByLine = methodsByLine.Where(method => methodFilter(method)); int testMethodsCount = matchingMethodsByLine.Count(); if (testMethodsCount > 0) { Trace.WriteLine("Found " + testMethodsCount + " test methods"); } else { Trace.WriteLine("No test method found; skipping test class"); continue; } Trace.WriteLine($"Execute function {nameof(IPageObjectTests.BeforeFirstTest)}..."); instance.BeforeFirstTest(); // check if tests should be executed if (!instance.ReadyToRun) { throw new TestNotReadyToRunException(classWithTests.FullName); } else { Trace.WriteLine("Tests are ready to run..."); } // create class statistics object TestClassStatistic testClassStatistic = new TestClassStatistic(classWithTests); // execute test methods try { foreach (var testMethod in matchingMethodsByLine) { if (instance.IsTestRunnable(testMethod)) { Test(testClassStatistic, instance, testMethod); } else { Trace.WriteLine($"Skipping test: '{nameof(instance.IsTestRunnable)}' returned false for test method '{testMethod.Name}'."); } } Trace.WriteLine($"Execute function {nameof(IPageObjectTests.AfterLastTest)}..."); instance.AfterLastTest(); } finally { var pageObjectStatistic = PageObjectStatistic(source); pageObjectStatistic += testClassStatistic; } } return(source); }