So I am facing a problem interacting with this HTML below. I am unable to open the pop up and close it using different Selenium Webdriver commands. Although I am looking for a specific solution here, any general tips on dealing with Angular JS would also be appreciated. I believe that the root cause of the problem is that I do not know a good way to automate Angular using Selenium Webdriver.
I'm using C#, but I will take any helpful information from any programming language as I can always retrofit the solution.
I am trying to interact with this pop up button, unsuccessfully: uib-popover-template="'/app/student/assessment/directives/templates/shortTextPopupTemplate.html'"
<div class="line ttsBorder">“<span style="font-style:italic;">And be it further enacted</span><span style="display: inline;">, That in all that territory ceded</span><span short-text-popup="" accession-number="VH209006" class="ng-isolate-scope" ng-non-bindable=""><a uib-popover-template="'/app/student/assessment/directives/templates/shortTextPopupTemplate.html'" popover-is-open="ctrl.isVisible" popover-trigger="none" popover-placement="auto top" tabindex="0" title="Shows more information." ng-click="buttonOnClick($event)" ng-keydown="buttonOnKeydown($event)" ng-class="['stpu-button', {disabled: ctrl.isDisabled, active: ctrl.isVisible}]" class="ng-scope stpu-button" style="z-index: 3;"></a></span> by France to the United States . . . which lies north of thirty‑six degrees and thirty minutes north latitude . . . slavery . . . shall be, and is hereby, forever prohibited.”</div>
Here is what I tried unsuccessfully:
//attempt 1
var elements = Driver.FindElements(By.XPath("//*[@class='line ttsBorder']"));
//attempt 2 - UserInteractions = new Actions(Driver);
UserInteractions.MoveToElement(PopUpButton).Click().Perform();
//attempt 3
Driver.FindElement(By.XPath("//[@title='Shows more information.']")).Click();
//attempt 4
//Driver.FindElement(By.XPath("//a[@uib-popover-template]"));
PopUpButton.Click();
//attempt 5
//Working, but seems dirty - JavaExecutor.ExecuteScript("arguments[0].click();", PopUpButton);
I had to result to tabbing through the UI to find the element that I want. I'm really unhappy with such a brittle solution and was hoping that you can offer some advice.
Thanks in advance!
There is a library called ngWebDriver that is designed to automate AngularJS and Angular Web Applications using Selenium with Java. This library is developed by having all the JavaScript created for a Protractor Project.
Various Unit testing frameworks for Selenium automation like Angular are available making it easy for developers to write their own Unit tests cases. Angular is considered to be one of the best web development frameworks. It comes with in-built Unit testing tools like Jasmine and Karma for automated Unit testing.
The Protractor is an automation testing tool for web applications testing; combining powerful technologies such as Jasmine, Selenium Webdriver, Node. js etc. The Protractor testing tool is an end to end behavior-driven testing framework designed keeping Angular JS applications in mind.
Selenium is an open-source automation testing tool that supports a number of scripting languages like C#, Java, Perl, Ruby, JavaScript, etc. Depending on the application to be tested, one can choose the script accordingly.
The quick fix is to create a CssSelector to access your element like this: Driver.FindElement(By.CssSelector("a[ng-click='buttonOnClick($event)']"));
A good fix is to create a class for each page you are testing and reach the elements of your page like so:
class LoginPageObject
{
public LoginPageObject()
{
PageFactory.InitElements(TestBase.driver, this);
}
[FindsBy(How = How.Id, Using = "UserName")]
public IWebElement TxtUsername { get; set; }
[FindsBy(How = How.Id, Using = "Password")]
public IWebElement TxtPassword { get; set; }
[FindsBy(How = How.Id, Using = "submit")]
public IWebElement BtnLogin { get; set; }
}
For accessing Angular elements using ng properties, It is better to use Protractor-Net which exposes NgBy class to explore angular elements in the DOM like this:
var ngDriver = new NgWebDriver(driver);
ngDriver.Navigate().GoToUrl("http://www.angularjs.org");
var elements = ngDriver.FindElements(NgBy.Repeater("todo in todoList.todos"));
The complete source code for the code snippet above can be found in here. Also, you can create your own custom decorators for angular elements from protractor API like this:
public class NgByRepeaterFinder : By
{
public NgByRepeaterFinder(string locator)
{
FindElementsMethod = context => context.FindElements(NgBy.Repeater(locator));
}
}
internal class NgByModelFinder : By
{
public NgByModelFinder(string locator)
{
FindElementMethod = context => context.FindElement(NgBy.Model(locator));
}
}
And then use them in your page class like this:
class YourPageObject
{
public YourPageObject()
{
PageFactory.InitElements(TestBase.ngWebDriver, this);
}
[FindsBy(How = How.CssSelector, Using = "a[ng-click='addNewTrack()']")]
public IWebElement BtnAddNewTrack { get; set; }
[FindsBy(How = How.Custom, CustomFinderType = typeof(NgByModelFinder), Using = "trackSearch")]
public IWebElement TxtSearchTrack { get; set; }
[FindsBy(How = How.Custom, CustomFinderType = typeof(NgByRepeaterFinder), Using = "track in models.tracks | filter: trackSearch")]
public IList<IWebElement> BtnListTracks { get; set; }
}
the complete guide for how to create and you custom finder annotators for angularjs can be found in here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With