Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Atata selenium web driver can't find controls by id on angular app

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">
like image 223
ian_stagib Avatar asked Nov 22 '18 10:11

ian_stagib


1 Answers

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<>))]
like image 184
Yevgeniy Shunevych Avatar answered Nov 19 '22 09:11

Yevgeniy Shunevych