5

I have been struggling to set up a simple automated test on an angular (5) app using atata as the framework which simply wraps the selenium web driver to do its tests. For the life of me I can't get it to find the elements i need in a log on page. I've tried finding by xpath, css, id, and name. None of which work. Please could someone help me understand if I'm doing something wrong?

I have made sure that id's are in place for the controls i'm trying to manage and they display when i inspect the element. Is there something that I should be doing so that the webdriver accesses the dom and not the websites html source (as there is a difference due to it being an spa)? I have also tried waiting 10 seconds before continuing to search for the control.

Versions of all packages are up to date.

AtataSettings.cs

using Atata;

[assembly: Culture("en-us")]
[assembly: VerifyTitleSettings(Format = "Login")]

SignInPage.cs

using Atata;

namespace PortalTests2
{
    using _ = SignInPage;

    [Url("auth/login")]
    [VerifyTitle]
    public class SignInPage : Page<_>
    {
        [FindById("email")]
        public TextInput<_> Email { get; set; }

        [FindById("password")]
        public TextInput<_> Password { get; set; }

        [FindById("login_button")]
        public Button<_> SignIn { get; set; }

        [FindById]
        public Select<_> selectedClientId { get; set; }

        [FindById("continue_button")]
        public Button<_> ContinueButton { get; set; }
    }
}

SignInTests.cs

using Atata;
using NUnit.Framework;

namespace PortalTests2
{
    [TestFixture]
    public class SignInTests
    {
        [SetUp]
        public void SetUp()
        {
            AtataContext.Configure().
                UseChrome().
                WithFixOfCommandExecutionDelay().
                WithLocalDriverPath().
                UseBaseUrl($"http://localhost:4300/").
                UseNUnitTestName().
                AddNUnitTestContextLogging().
                AddScreenshotFileSaving().
                LogNUnitError().
                TakeScreenshotOnNUnitError().
                Build();
        }

        [TearDown]
        public void TearDown()
        {
            AtataContext.Current?.CleanUp();
        }

        [Test]
        public void SignIn()
        {
            Go.To<SignInPage>().
                Email.Set("root").
                Password.Set("r00t").
                SignIn.Click();
        }
    }
}

Edit:

I managed to get it to find the element if I use the plain selenium setup as follows. Why would this work but Atata's wrapping doesn't?

using (var driver = new ChromeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)))
            {
                driver.Navigate().GoToUrl(@"http://localhost:4300/");
                var link = driver.FindElement(By.Id("email"));
                link.SendKeys("hello");
            }

edit 2:

I found someone that had a similar issue but it was constrained to a file input field. Can someone maybe confirm if there is a lingering bug with regards to the setup I'm using?

https://github.com/atata-framework/atata/issues/188

edit 3:

Html snippet of the email field input control:

<input autocomplete="off" class="form-control ng-pristine ng-valid ng-touched" id="email" name="email" placeholder="Email address" type="email" ng-reflect-name="email" ng-reflect-is-disabled="false" style="background-image: url(&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAAAXNSR0IArs4c6QAAAPhJREFUOBHlU70KgzAQPlMhEvoQTg6OPoOjT+JWOnRqkUKHgqWP4OQbOPokTk6OTkVULNSLVc62oJmbIdzd95NcuGjX2/3YVI/Ts+t0WLE2ut5xsQ0O+90F6UxFjAI8qNcEGONia08e6MNONYwCS7EQAizLmtGUDEzTBNd1fxsYhjEBnHPQNG3KKTYV34F8ec/zwHEciOMYyrIE3/ehKAqIoggo9inGXKmFXwbyBkmSQJqmUNe15IRhCG3byphitm1/eUzDM4qR0TTNjEixGdAnSi3keS5vSk2UDKqqgizLqB4YzvassiKhGtZ/jDMtLOnHz7TE+yf8BaDZXA509yeBAAAAAElFTkSuQmCC&quot;); background-repeat: no-repeat; background-attachment: scroll; background-size: 16px 18px; background-position: 98% 50%; cursor: auto;" xpath="1">
ian_stagib
  • 148
  • 12
  • Have you looked at the page source in the browser by right clicking and checking that the id is as you expect. – bilpor Nov 22 '18 at 10:44
  • yes, the page source only shows a very limited amount of the document whereas inspecting an element shows the full dom with all the controls and the id as expected. This is the reason I asked if i'm supposed to be doing something different in order for webdriver to see the dom as opposed to just the source as seen when you right click and say "show source". – ian_stagib Nov 22 '18 at 10:49
  • I've never used atata, but as long as you have installed and referenced the correct driver for the browser that you are testing with, I've not had this problem. Selenium is a very stable product. Would it be too much to remove atata for now and just work directly with Selenium just to prove a point. If it works, then you will know the issue is with Atata – bilpor Nov 22 '18 at 10:53
  • I gave it a try and edited my question above. I guess you wouldn't have any ideas as to why it works with the plain webdriver setup vs atata's setup right? – ian_stagib Nov 22 '18 at 11:27
  • I'm afraid not. But at least you know to focus on the Atata product – bilpor Nov 22 '18 at 12:49
  • Could you please share HTML snippet of your input elements? `TextInput` has `[ControlDefinition("input[@type='text' or not(@type)]")]` by default. Control definition is taken into account during element search, but it is configurable. – Yevgeniy Shunevych Nov 22 '18 at 13:16
  • snippet added, Yevgeniy – ian_stagib Nov 22 '18 at 13:25

1 Answers1

5

The issue is in wrong controls usage. Atata has unique ControlDefinition feature which specifies base XPath of control's element. It makes element search more accurate by filtering out wrong elements. For TextInput<TOwner> it is [ControlDefinition("input[@type='text' or not(@type)]")].

You email element is <input type="email"> which does not match base XPath of TextInput<TOwner>. The same should be with password control.

Just change types of controls to EmailInput<TOwner> and PasswordInput<TOwner>:

public class SignInPage : Page<_>
{
    [FindById("email")]
    public EmailInput<_> Email { get; set; }

    [FindById("password")]
    public PasswordInput<_> Password { get; set; }

    //...
}

Here is the link to input controls docs: https://atata-framework.github.io/components/#inputs

As an option you can also change both control types to Input<string, TOwner>. It will also work as Input has less strict ControlDefinition.

By the way, if you need to override some default ControlDefinition for specific control globally:

[assembly: ControlDefinition("input", ComponentTypeName = "text input", TargetType = typeof(TextInput<>))]

Or put even "*" to match any element.

[assembly: ControlDefinition("*", ComponentTypeName = "text input", TargetType = typeof(TextInput<>))]
Yevgeniy Shunevych
  • 1,136
  • 6
  • 11