public class SomeControl<TOwner> : Control<TOwner>
where TOwner : PageObject<TOwner>
{
protected override void OnHover()
{
Driver.ExecuteScript("var mouseenterEvent = document.createEvent('MouseEvents'); mouseenterEvent.initEvent('mouseenter', true, true); arguments[0].dispatchEvent(mouseenterEvent);", Scope);
}
}
Hi, I am having issues on navigation. Currently, the website has a navigation bar, each containing its own list of items. However, <div> for those items would only show up on mouse hovers. I have something like this,
public class Header<TOwner> :
Control<TOwner>
where TOwner : Page<TOwner>
{
public class HeaderMenu:
Control<TOwner>
{
[FindByXPath("/div/nav/span/ul/li[1]")]
public Menu1<TOwner> Example1 { get; set;}
}
[FindByXPath("//*[contains(@class,'BottomHeaderRow')]")]
public HeaderMenu Menu {get; set;}
}
public class Menu1<TOwner> :
Control<TOwner>
where TOwner : PageObject<TOwner>
{
[FindByXPath("//a[@href='/example1']")]
public Link<Page1, TOwner> ToPage1 {get; set;}
[FindByXPath("//a[@href='/example2']")]
public Link<Page2, TOwner> ToPage2{get; set;}
}
And I call it by usingHeader.Menu.Menu1.Hover().Header.Menu.Menu1.Click()
But I am currently getting a NoSuchElementException : Unable to located element: By.XPath
error. I was able to locate the item directly from the web page using the XPath but somehow unable to with this method.
Hey. The first thing I see that might be wrong is XPath:
[FindByXPath("/div/nav/span/ul/li[1]")]
public Menu1<TOwner> Example1 { get; set;}`
Don't use single slash at the beggining of XPath. Use either //
, .//
or ./
.
You can also take a look at HoverParent trigger that can do hovering automatically.
Thanks! I was able to resolve that issue but now I'm facing another ): I have a select property and my test would randomizes the option I get from that select. Is there a way to use
property.SetRandom()
so that it will set to a random option from the list? And I didn't want to create a Enum for the property because the list of options might change over time and hard coding it wouldn't be ideal.
Hey. Implemented few extension methods for Select
. You can add this class to your project:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Atata
{
public static class SelectExtensions
{
public static TOwner SetRandomAvailable<T, TOwner>(this Select<T, TOwner> select)
where TOwner : PageObject<TOwner>
{
return select.SetRandomAvailable(filter: null);
}
public static TOwner SetRandomAvailableExcept<T, TOwner>(this Select<T, TOwner> select, params T[] exceptValues)
where TOwner : PageObject<TOwner>
{
return select.SetRandomAvailable(values => values.Where(x => !exceptValues.Contains(x)));
}
public static TOwner SetRandomAvailableExceptFirst<T, TOwner>(this Select<T, TOwner> select)
where TOwner : PageObject<TOwner>
{
return select.SetRandomAvailable(values => values.Skip(1));
}
public static TOwner SetRandomAvailable<T, TOwner>(this Select<T, TOwner> select, Func<IEnumerable<T>, IEnumerable<T>> filter)
where TOwner : PageObject<TOwner>
{
T randomValue = select.GetRandomOptionValue(filter);
return select.Set(randomValue);
}
public static T GetRandomOptionValue<T, TOwner>(this Select<T, TOwner> select, Func<IEnumerable<T>, IEnumerable<T>> filter = null)
where TOwner : PageObject<TOwner>
{
IEnumerable<T> allOptionValues = select.Options.Select(x => x.Value);
T[] filteredOptionValues = (filter?.Invoke(allOptionValues) ?? allOptionValues).ToArray();
int indexToUse = Randomizer.GetInt(0, filteredOptionValues.Length - 1);
return filteredOptionValues[indexToUse];
}
}
}
Usage in test:
Go.To<SelectPage>().
TextSelect.SetRandomAvailable().
TextSelect.SetRandomAvailableExceptFirst().
TextSelect.SetRandomAvailableExcept("Option B");
I will later think how to move this thing to Atata itself.
Hey. Unfortunately, I don't have an example project, at least for now. We used Atata with SpecFlow 2 a year ago for one project and it was OK. I haven't tried Atata with SpecFlow 3, but I almost sure that it should be fine. If you know both frameworks well, I guess it should not be a big deal.
Honestly, I try to avoid SpecFlow for automated testing as it makes overhead unless the business really wants the feature files, and all team members want and ready to play by the BDD rules. In this case, the overhead is reasonable. But unfortunately, in most projects, SpecFlow feature files are written and used only by automated testers (SDETs), which is not BDD.
Anyway, you can try it yourself and ask for questions when you have some issues.
Hey @lewcianci.
1) Multi-driver tests.
Take a look at Multi-Browser Configuration via Fixture Arguments tutorial. There local drivers are used but I guess you will get an idea:
AtataContext.GlobalConfiguration.
UseRemoteDriver().
WithAlias("chrome_remote").
// Other properties...
UseRemoteDriver().
WithAlias("firefox_remote").
// Other properties...
2) Table headers issue.
Take a look at Table with Row-Spanned Cells sample. There is custom FindByColumnHeaderInTableWithRowSpannedCellsStrategy
implemented there. It's a bit complex, but you can get the idea abou the way it can be implemented.
Another option is to inherit FindByColumnHeaderStrategy and override some parts of it.
If you will have difficulties implementing it, let me know and please provide a sample of HTML table then.
Hey! I came back to write more functional testing and there was an issue that I had previously that I was not able to resolve. So I tried Custom Trigger Wait for Loading Indicator but I'm still having issues if the loading indicator appears multiple times within the same page and if different buttons/action can trigger it once/multiple times. I could use wait after every action but I was wondering if there's a better way to resolve this issue.
Also, another issue I'm currently facing is I'm not sure how to open up a different browser during a test. Currently, my tests run in chrome but there's a site that still lives in the stone age and does not support chrome, only internet explorer. Is there a way to do that? Or should I initialize two browsers at startup, one for chrome, one for IE and switch between the browsers? Thanks in advance!
AppliesTo = TriggerScope.Children
:// To wait for busy indicator during page load:
[WaitForElement(WaitBy.Class, "some-class", Until.VisibleThenMissingOrHidden, TriggerEvents.Init)]
// To wait for busy indicator after any click or set action within the page. Applies to all children:
[WaitForElement(WaitBy.Class, "some-class", Until.VisibleThenMissingOrHidden, TriggerEvents.AfterClick | TriggerEvents.AfterSet, AppliesTo = TriggerScope.Children)]
public class SomePage : Page<_>
{
// ...
}