JDI Light Framework
JDI Light is a powerful Test Automation Framework that helps to make your tests fast, sustainable and provides obvious and predictable test run results.
JDI Light is powered by Selenium and has simple integration with Selenium-based projects.
Highlights
- Has simple integration with any Selenium-based project, allowing to increase overall project stability, add user action logs and enrich standard WebElement capabilities with new features in just minutes.
- Complements the Page Object pattern with powerful pre-made UI Elements: Buttons, TextFields, Forms, Tables and many others.
- Enables you to write stable and predictable tests that fail only because of business logic or layout changes. No more waits, thread sleeps and other flaky stuff.
- Increases your overall test execution speed, especially for complex cases like searching huge tables, selecting dropdown items out of a hundred or entering text containing thousands of lines.
- Provides detailed logs and well-readable reports of all user actions with no additional effort.
- All UI Elements have assertions/matchers powered by Hamcrest and a wait with expected condition during timeout.
- Easy integration with all modern automation tools: CI (Jenkins, TC etc.), logging (Log4j or any other slf4j-based logs), reporting (Allure or Report Portal); browser/device farms (Selenium Grid, BrowserStack, Selenoid etc.), test runners (TestNG, JUnit) etc.
Navigation
Introduction provides examples of common test automation tasks solved with JDI Light.
Tutorial walks you through adding JDI Light to your project, implementing test scenarios and using UI Elements. You also get to see how much JDI Light reduces the needed effort, compared to pure Selenium.
Theory addresses the key principles behind JDI Light framework and the tools it offers to put these principles into practice.
Documentation contains technical description of JDI Light features/settings and UI Element sets.
Introduction
Simple JDI examples
Create a simple Login test
First of all, let's see how JDI solves typical problems. Let's start with Login, since most tests start with signing in.
You can find a Java code example here.
Test Scenario
@Test
public void loginTest() {
homePage.open();
userIcon.click();
loginForm.loginAs(DEFAULT_USER);
homePage.checkOpened();
}
- Open Home Page (https://jdi-testing.github.io/jdi-light/index.html)
- Click on User Icon (to open login dialog)
- Log in as a default user:
- Enter 'Roman' in login text field
- Enter 'Jdi1234' in password text field
- Press 'Enter'
- Verify that Home Page has been opened
[22:17.102 STEP] : Open 'Home Page'(url=>https://jdi-testing.github.io/jdi-light/index.html)
[22:23.617 STEP] : Click on 'User Icon'
[22:23.727 STEP] : Login as User (userName:epam; password:1234)
[22:24.516 STEP] : Check that 'Home Page' is opened (url CONTAINS '/index.html'; title EQUALS 'Home Page')
So simple! But there's more to it. Try to run this test in your IDE and see what you get...
- A detailed log in the console output (pictured to the right; nice, isn't it?)
- Log file containing the same log (src/test/.logs/) in case you'd like to view the test execution results separately. (requires log4j2.xml file in src/test/resources)
- A neat Allure report of your test execution. (requires proper Allure settings in pom.xml)
Just move the allure-results folder to your local folder and run Maven > Plugins > Allure > allure:serve (see picture below).
@JSite("https://jdi-testing.github.io/jdi-light/")
public class JdiTestSite {
public static HomePage homePage;
}
@BeforeSuite(alwaysRun = true)
public static void setUp() {
initElements(JdiTestSite.class);
}
@Url("/index.html") @Title("Home Page")
public class HomePage extends WebPage {
@Css("form") public static LoginForm loginForm;
@Css("img#user-icon") public static Icon userIcon;
}
public class LoginForm extends Form<User> {
@Css("#name") TextField userName;
@Css("#password") TextField password;
@Css("[type=submit]") Button enter;
}
UI Page Objects
Now let's have a look at Page Objects in JDI. For example, we used the following objects in the login test above:
Site — your application entity. It contains all the Pages of your application and can be initiated with a single method call.
HomePage — Pages contain UI elements: common, complex and composite. Pages also carry meta-information about their URLs and titles and allow executing common actions like
open
,checkOpened
,getUrl
,getTitle
,zoom
,scroll
etc.LoginForm — Forms and Sections are logical parts of pages; they can include other sections or just UI elements. Forms also offer additional actions like
fill
,submit
,check
etc.UI elements (typified elements) —
Button
,TextField
,Checkbox
,Icon
etc. are simple elements representing the elements of an actual UI.
Below you can find a common JDI project structure:
@Test
public void nonPageObjectTest() {
WebPage.openUrl("https://jdi-testing.github.io/jdi-light/index.html");
$("img#user-icon").click();
$("form #name").input("Roman");
$("form #password").input("Jdi1234");
$("form [type=submit]").click();
Assert.assertEquals(WebPage.getUrl(), "https://jdi-testing.github.io/jdi-light/index.html");
}
public class LoginForm extends Form<User> {
TextField userName = $("#name");
TextField password = $("#password");
Button enter = $("[type=submit]");
}
Short term non-Page Object style
If you need a quick test (i.e. you don't need Page Objects), you can simply use jQuery/Selenide style without any additional code.
You can also directly initialize UI elements defined in your Page Objects if you don't like annotations.
Smart Test locators
See details and examples for Smart locators in the documentation
@Test
public void assertTest{
title.is().text(containsString("jdi"));
name.assertThat().text(is("Roman"));
color.has().attr("color", is("red"))
}
@Test
public void chainAssertTest{
title.assertThat()
.text(containsString("jdi"))
.attr("color", is("red"))
.tag(is("h1"))
}
@Test
public void listAssertTest{
searchResults.is().notEmpty();
searchResults.assertThat()
.size(equalTo(10))
.any(e -> e.name.equals("Jdi intro 2"))
.each(e -> e.name.toLowerCase().contains("jdi"))
.onlyOne(e -> e.name.contains("Jdi intro 1"))
.noOne(e -> e.name.contains("Selenide"));
}
@Test
public void tableChainTest() {
users.assertThat()
.displayed().size(6).size(greaterThan(3))
.notEmpty().row(d -> d.user.contains("Ivan"))
.allRows(d -> d.user.length() > 4)
.atLeast(3).rows(d -> d.type.contains("User"))
.row(SPIDER_MAN)
.exact(2).rows(d -> d.description.contains(":VIP"))
.exact(1).rows(SPIDER_MAN);
}
Asserts/Matchers integrated with elements
JDI has a really flexible set of matchers integrated into it.
- To access element matchers, you can use the following methods:
is()
assertThat()
has()
waitFor()
shouldBe()
All these methods are equivalent. Different names just help making code more descriptive and human-readable. - JDI matchers are powered by Hamcrest, the most popular matcher library in the Java world.
And you can chain these matchers to verify multiple conditions.
- With JDI you won't have to struggle with waits or execute sloppy tests.
JDI matchers handle most kinds of problems. They will pass when you expect them to and fail whenever there is a real error.
Really useful, don't you agree?
Custom elements
public class Checklist extends HtmlElement {
@Override
public boolean isSelected() {
return find("<<").hasClass("active");
}
}
public class Checklist extends HtmlChecklist {
@Override
public boolean isSelected(HtmlElement value) {
return hasClass("active") && attr("ui").equals("label");
}
}
public class ContactForm extends Form<Contacts> {
TextField name, lastName, position, passportNumber, passportSeria;
...
@UI("['Submit']") public Button submit;
@Override
public void fillAction(Field field, Object element, Object parent, String setValue) {
if (isInterface(field, TextField.class))
((TextField)element).higlight();
super.fillAction(field, element, parent, setValue);
}
}
JDI HTML elements can handle typical standard cases, but each application has its unique culture of layout development.
So if your developers are not following common standards, you can easily create a pack of elements specific to your application and use them with JDI. You can create your own elements or simply extend the existing ones, overriding a couple of methods.
Check these examples:
Start a new project with JDI
You can start a new test automation project with JDI in mere seconds!
Just download one of the templates at Github JDI template repository.
Java + Allure + TestNg (recommended)
Java + Allure + JUnit
CSharp + NUnit
How to improve your Selenium project with new capabilities in just a few minutes
Logging and Reporting
Tutorial
In this tutorial we’ll take a glance at JDI Light, a library that simplifies test automation, makes test run results stable, predictable and easy to maintain.
- Quick Start — a short instruction on how to add JDI Light to your project and perform its basic configuration.
- JDI Light at a glance — a few simple test examples with and without Page Objects. Typified UI Elements and logs in JDI Light.
- JDI Light Forms — a small complex element example that showcases the primary benefits of using JDI Light.
- UI Elements and optimization — a more sophisticated example elaborating on types of elements in JDI Light and demonstrating their capabilities.
- Reduce the amount of code with JDI Light — a concise example of how JDI Light can decrease the amount of code threefold compared to Selenium.
Demonstrates that you can write clear and stable tests with 3 times less effort.
1. Quick Start
- Adding JDI Light to your projects
- A brief configuration overview
Let’s start from the beginning by adding JDI Light to our test project and going through the setup step by step.
Note: JDI Light ships with a template project that helps to save setup time.
Maven Dependencies
<dependency>
<groupId>com.epam.jdi</groupId>
<artifactId>jdi-light-html</artifactId>
<version>RELEASE</version>
</dependency>
First, we need to add JDI Light to the dependency section of our pom.xml file:
The latest version can be found in the Maven Central Repository.
Configuration
That’s all! We don’t need to explicitly configure anything else to start working. By default, JDI Light will download Chrome driver automatically, set it up and run it as soon as we try to access the first page.
We can change the default settings by altering the test.properties file (located within src/test/resources directory).
src/test/resources/test.properties
driver=chrome
#driver.version=2.23 | LATEST
#timeout.wait.element=10
#timeout.wait.page=30
domain=https://jdi-testing.github.io/jdi-light/
#page.load.strategy=normal | eager | none
#browser.size=MAXIMIZE | 1024x762
...
Let’s have a detailed look at some options:
- driver — we can specify the driver used to run our tests. Common options include
chrome
,firefox
,ie
; we can also just put${driver}
here and read the driver name from the command line. - driver.version — by default, JDI Light will download the latest version of a driver for us, but if we need a specific version we can put it here (in which case the framework will find and download exactly this version).
- timeout.wait.element — the maximum amount of time in seconds that will be spent waiting for an element on the opened page to load. The default element loading timeout is 10 seconds.
- timeout.wait.page — JDI Light automatically defines a newly opened page and uses this value as page loading timeout (it is usually greater than the element loading timeout). The default is 30 seconds.
- domain — web application root URL (used when our tests work with a single application). Can also be read from the command line if set up as
${domain}.
- page.load.strategy — similarly to Selenium, page loading strategies are:
normal
,eager
,none
. - browser.size — browser window size. By default, JDI Light will maximize the browser window, but we can set the exact size.
- screenshot.strategy =
off
|on failure
|on assert
|new page
— determines when screenshots are taken; it's used by AllureLogger.class and its sub/superclasses. Can be overwritten in test project. - html.code.strategy =
off
|on failure
|on assert
|new page
— logs the last processed element HTML code. - requests.strategy =
off
|on failure
|on assert
|new page
— logs 4ХХ, 5ХХ errors in the console. - allure.steps =
true
— turn on the steps for Allure.
Note: you can find more examples in the documentation.
2. JDI Light at a glance
- Simple Open page test
- No Page Objects test example
- Page Objects test example
Let's start
@Test
public void openJDITestSite() {
openUrl("https://jdi-testing.github.io/jdi-light/");
}
OK, now let’s write our first test case. We can open the JDI test site by using a static method openUrl()
of the WebPage
class.
WebPage
provides essential methods to work with a browser: getUrl()
, getTitle()
, back()
, forward()
, getHtml()
, refresh()
. It also provides methods that allow to scroll up / down / left / right / to page top / to page bottom or zoom the page.
Simple test scenario
@Test
public void loginSimpleTest() {
openUrl("https://jdi-testing.github.io/jdi-light/");
$("img#user-icon").click();
$("#name").sendKeys("Roman");
$("#password").sendKeys("Jdi1234");
$("#login-button").click();
$("#user-name").is().displayed();
}
Now we can write a more involved typical test: log in to a page.
Every test should contain an assertion, so let’s add it to our test.
Code like this is easy to write. However, it will inevitably become hard to maintain as the number of tests grows and elements used get repeated throughout the tests.
For example, if we have an element found by $(".menu-about a")
locator in more than 10 tests and its locator gets changed, we must go through all the tests and adjust the locator.
Page Objects are here to help us!
See the examples above on Github
Page Objects
public class HomePage extends WebPage {
@FindBy(css = "img#user-icon") public WebElement userIcon;
@FindBy(id = "name") public WebElement name;
@FindBy(id = "password") public WebElement password;
@FindBy(id = "login-button") public WebElement loginButton;
@FindBy(id = "user-name") public WebElement userName;
}
public class HomePage extends WebPage {
@UI("img#user-icon") public static Link userIcon;
@UI("#name") public static TextField name;
@UI("#password") public static TextField password;
@UI("#login-button") public static Button loginButton;
@UI("#user-name") public static Text userName;
}
Let’s develop our first simple Page Object and see how the test case will look like. We have our Home Page with several elements on it:
- user icon — clicking on it opens the login form.
- name, password — two text fields in the login form.
- login button — clicking on it starts a login attempt.
- user name — element that will appear after a successful login.
In order to make the code simple, in JDI Light we can use a unified annotation, @UI("...")
. It handles both CSS and XPath locators, thus reducing the amount of code.
It's also a good use case for one of the main JDI Light features: typified elements like TextField
, Button
and Text
.
The other great news is that we can make our Page Object elements static
and keep tests clearer and more obvious.
@JSite("https://jdi-testing.github.io/jdi-light/")
public class SiteJdi {
@Url("/") public static HomePage homePage;
@Url("/contacts") @Title("Contact Form")
public static ContactsPage contactPage;
}
Page Objects in JDI Light are called UI Objects and extend standard Selenium Page Objects' capabilities with typified elements like TextField
, Button
, Text
etc. They also carry additional meta-information about a page, like URL and title.
Pretty simple and obvious, isn’t it?
Page URLs are relative to the site domain specified in the @JSite
annotation or in test.properties file.
Note: We won't be calling ContactsPage
methods in this example; it is put here to demonstrate the usage of @Url
and @Title
annotations.
public interface TestsInit {
@BeforeSuite(alwaysRun = true)
static void setUp() {
initElements(SiteJdi.class);
}
}
And the last thing to consider before writing a test: all UI Objects of our application are initialized at once. We can do it with just a single line of code in the setup method that runs before all tests.
Note: in other frameworks we have to call initElements()
for each Page Object.
public class PageObjectExample implements TestsInit {
@Test
public void loginTest() {
homePage.open();
userIcon.click();
name.sendKeys("Roman");
password.sendKeys("Jdi1234");
loginButton.click();
userName.assertThat().displayed();
}
}
[ STEP 09:30.825] : Open 'Home Page'(url=https://jdi-testing.github.io/jdi-light/) (SiteJdi.homePage (url=https://jdi-testing.github.io/jdi-light/; title=))
[ STEP 09:37.188] : Click on 'User Icon' (HomePage.userIcon (css='img#user-icon'))
[ STEP 09:37.291] : Input 'Roman' in 'Name' (HomePage.name (css='#name'))
[ STEP 09:37.539] : Input 'Jdi1234' in 'Password' (HomePage.password (css='#password'))
[ STEP 09:37.756] : Click on 'Login Button' (HomePage.loginButton (css='#login-button'))
[ STEP 09:37.860] : Assert that 'User Name' is displayed (HomePage.userName (css='#user-name'))
[ STEP 11:16.923] : Open 'Home Page'(url=https://jdi-testing.github.io/jdi-light/)
[ STEP 11:22.983] : Click on 'User Icon'
[ STEP 11:23.088] : Input 'Roman' in 'Name'
[ STEP 11:23.369] : Input 'Jdi1234' in 'Password'
[ STEP 11:23.598] : Click on 'Login Button'
[ STEP 11:23.688] : Assert that 'User Name' is displayed
Now we can write our test using these UI Objects and execute it.
- This test scenario is pretty clear and references the actual UI elements.
- We can easily update elements placed in UI Objects without going through all the tests.
- We have all metadata about pages in one place and can open and validate pages without URL and title duplication in the test code.
- JDI Light tests are stable and will not fail in cases where Selenium throws exceptions (like StaleElementException or NoSuchElementException)
- We get the following text in the log:
It lists exactly what we do in our test with all the details and without any extra effort on our part. Fabulous!
We can change the log level to STEP
(just add logger.setLogLevel(STEP)
to the setUp()
method) and remove the details. The resulting log will be fit to share with a Customer, a Business Analyst or a Manual QA to let them know what our automated tests verify.
See PageObject examples in PageObjectExample.java on Github
3. JDI Light Forms
- Simple login test example. DataClass example
- Login Form in Data Driven Test approach
- Page Objects test example
Standard Login form
public class LoginForm extends Form<User> {
@UI("#name") TextField name;
@UI("#password") TextField password;
@UI("#login-button") Button loginButton;
}
public class JDISite {
@Url("/") public static HomePage homePage;
public static LoginForm loginForm;
...
}
@Test
public void loginTest() {
userIcon.click();
loginForm.loginAs(ROMAN);
userName.is().displayed();
}
public class User extends DataClass<User> {
public String name, password;
}
Now we will optimize the previous example using forms.
Let's move the login form elements to a separate UI Object — LoginForm
.
Then we'll set LoginForm
as a root UI Object in our JDISite
class.
Now we can rewrite our test in the following way:
ROMAN
is a business entity of class User
associated with Login Form. User
class is a simple data class with two String
fields that have the same names as TextField
elements in LoginForm
.
Aligning data class field names with form field names works for every kind of form field that supports fill-like interaction: TextField
, TextArea
, Checkbox
, DropDown
etc.
This gets covered more in depth in Contact Form example.
User ROMAN = new User().set(c -> {
c.name = "Roman"; c.password = "Jdi1234";
} );
Output: ROMAN.toString() --> User(name:Roman; password:Jdi1234)
new User().equals(new User());
Any class can be used as data class, but extending it from DataClass (User extends DataClass<User>
in this case) gives us additional benefits:
- It won't be necessary to keep the same order of fields in the data class and the form.
- Two data class instances will be compared by equality of their fields and not by reference (so NOT like it would have been with the
equals()
method). - There will be a good-looking
toString()
representation of the data class instance based on its fields.
See this example in LoginExample.java on Github
Cover Login Form with Data-Driven tests
public class UsersDataProvider {
public static User NO_PASSWORD = new User().set(c -> c.name = "Roman");
public static User NO_CREDENTIALS = new User().set(c -> {
c.name = ""; c.password = "";}
);
public static User WRONG_CREDENTIALS = new User().set(c -> {
c.name = "Alex"; c.password = "Password";}
);
...
}
public class LoginExample implements TestsInit {
@BeforeMethod
public void before() {
loggedOut();
loginFormShown();
}
@Test
public void failedLoginTest1() {
loginForm.loginAs(NO_PASSWORD);
userName.is().hidden();
}
@Test
public void failedLoginTest2() {
loginForm.loginAs(WRONG_CREDENTIALS);
userName.is().hidden();
}
@Test
public void failedLoginTest3() {
loginForm.loginAs(NO_CREDENTIALS);
userName.is().hidden();
}
...
}
This lets us easily increase the amount of different tests.
Let's cover login functionality with tests checking the following cases:
1) No password; 2. Wrong credentials; 3. No credentials.
In order to do this we will create a separate file (UsersDataProvider.java) for our test data and put User
entities with the corresponding field values there.
Note: if you leave some fields null
, this data will not be provided.
Since we would like to validate empty values in fields for NO_CREDENTIALS
user we'll have to set them as empty strings.
Now we can write our tests:
Note: we don't need to write any other code except test scenarios. Already written UI Objects will be enough.
Note: In order to be sure that the user is logged out and login form is opened before each test we can add these conditions as loggedOut()
and loginFormShown()
States in @BeforeMethod
.
See this example in LoginExample.java on Github
Failed Login Form tests with Data Provider
public class UsersDataProvider {
...
@DataProvider(name = "failedUsers")
public static Object[][] failedUsers() {
return new User[][]{{NO_PASSWORD}, {NO_CREDENTIALS}, {WRONG_CREDENTIALS}};
}
But the scenarios in previous example are pretty much the same. The only difference is the test data. We can simplify our tests using DataProvider.
Let's add failedUsers()
method that returns test data for our cases as a 2D array of User
instances to our UsersDataProvider.java file, then mark this method with @DataProvider(name = "failedUsers")
.
public class UsersDataProvider {
...
@Test(dataProvider = "failedUsers", dataProviderClass = UsersDataProvider.class)
public void dataFailedLoginTest(User user) {
loginForm.loginAs(user);
userName.is().hidden();
}
As a next step, we will create one common test scenario that accepts User
instance as a parameter.
And the last step is just to link our test to the data provider method using @Test
annotation attributes.
That's it! If we run this scenario, it will execute 3 tests that validate different cases of login failure. This way you can easily manage same scenarios with different test data, increase testing coverage, add new data sets or update them without changing the actual tests. It's that simple!
I Like it!
See this example in LoginExample.java on Github
4. UI Elements and optimization
- Main UI Element types in JDI Light and a few examples.
- Complex Contact Form example.
- Check and verify Form methods. Errors in logs.
- 5 Ways to describe Form with a complex Selenium example (17 lines) to 1 line Form
UI Elements on Contact Form
We've had a quick look at JDI Light; now let's look closer at UI Elements. In JDI we have 3 kinds of elements:
- Common Elements:
Button
,TextField
,Text
,Checkbox
etc. Some of them we have already used in Login Form. All of these elements have simple structure and can be described using one locator or Selenium element. Note: See the full list and more details in Documentation - Complex elements like
Dropdown
,Checklist
,RadioButtons
,MultiSelect
,DataList
etc. They represent actual UI elements that encompass the functionality of multiple Common Elements. For example,Dropdown
may be regarded as combination of elements that represent value, caret (expand dropdown) arrow and list of options;Checklist
is basically a list ofCheckbox
elements.
Note: See the full list and more details in Documentation - Composite elements are typified Page Objects. These are
WebPage
,Form
,Section
: classes having Common, Complex Elements or sub-sections as their fields.
Note: See the full list and more details in Documentation
Let's look at an example: Contact Form on Contacts page.
This form, compared to the Login Form, has more different UI elements. Let's describe it.
public class ContactForm extends Form<ContactInfo> {
@UI("#passport") Checkbox passport;
@UI("#name") TextField name;
@UI("#last-name") TextField lastName;
@UI("#position") TextField position;
@UI("#passport-number") TextField passportNumber;
@UI("#passport-seria") TextField passportSeria;
@UI("#accept-conditions") public Checkbox acceptConditions;
@UI("#description") TextArea description;
@UI("button[type=submit]") Button submit;
...
}
Here we have Common elements:
5 TextField
elements (name
, lastName
, position
, passportNumber
, passportSeria
)
2 Checkbox
elements (passport
, acceptConditions
)
1 TextArea
(description
)
1 Button
(submit
)
public class ContactForm extends Form<ContactInfo> {
...
@UI("#gender") Dropdown gender;
@UI("#religion") Combobox religion;
@UI("#weather") MultiDropdown weather;
}
// Selenium implementation that takes 21 lines of code instead of 1 line in JDI Light, namely:
// @UI("#weather") MultiDropdown weather
@FindBy(css ="#weather .caret") WebElement weatherExpand;
@FindBy(css ="#weather label") List<WebElement> weatherList;
@FindBy(css ="#weather button") WebElement weatherValue;
@FindBy(css ="#weather ul") WebElement weatherIsExpanded;
private boolean weatherIsExpanded() {
return weatherIsExpanded.getAttribute("style").equals("display: block;");
}
public void select(String value) {
if (!weatherIsExpanded())
weatherExpand.click();
String[] values = value.split(", ");
for (String val : values) {
for (WebElement listOption : weatherList) {
if (listOption.getText().trim().equals(val))
listOption.click();
}
}
}
public String getValue() {
return weatherValue.getText();
}
And Complex elements:
Dropdown
(gender) — An element with one selectable value, expand arrow and a list of options.
Combobox
(religion) — Mix of Dropdown
and TextField
. You can select a value from a list of options or enter your own value.
MultiDropdown
(weather) — Dropdown that allows selection of multiple options. We also provide an example of Selenium implementation of equivalent functionality for comparison.
@Url("/contacts") @Title("Contact Form")
public class ContactPage extends WebPage {
@UI("#contact-form") public static ContactForm contactForm;
}
And the Contact Form itself is a Composite UI Object (PageObject with additional capabilities in JDI).
We will call the Contact Form placed on another Composite Page Object a Contact Page.
Pay attention to the fact that Contact Form and Contact Page have the additional meta-information:
@Url
and@Title
for Contact Page.- Locator for Contact Form specified with the
@UI
annotation. It ensures that all elements that belong to Contact Form Page Object are searched only within the context of Contact Form: in case when there are multiple elements with a locator like"button[type=submit]"
on the webpage (for example, this locator is valid for the logout button on Contact Page), it will be the element belonging to Contact Form that gets found.
public class ContactInfo extends DataClass<ContactInfo> {
public String passport, name, lastName, position, passportNumber,
passportSeria, gender, religion, weather, acceptConditions, description;
}
The next important points of attention are ContactPage extends WebPage
and ContactForm extends Form<ContactInfo>
inheritance declarations. They grant these Page Objects webpage and form functionality and allow access to their meta-information.
ContactInfo
, the data class to be used with ContactForm
, looks pretty much the same as the data class for Login Form. Each field that is used when filling the form is a String
.
@UI("img#user-icon") public static Link userIcon;
@UI("#user-name") public static Text userName;
@UI(".sidebar-menu span") public static Menu sideMenu;
We also have a few Common elements that are placed directly in Site:
Link
elementuserIcon
andText
elementuserName
; we have already been using them in earlier tests.- One new Complex element,
Menu
, representing the list of links in the left sidebar. This element is also found by one locator but contains 16 menu items, and you can also select the item you need by its name defined inMenuOptions
enum (found in src/main/java/jdisite/enums).
Contact Form test scenario
@Test
public void simpleContactFormTest() {
sideMenu.select("Contact form");
contactPage.checkOpened();
contactForm.submit(FULL_CONTACT);
contactForm.check(FULL_CONTACT);
}
Now let's write a complex test that:
- Opens the Contacts Page by selecting a corresponding menu option
- Verifies that this page has the correct URL and title
- Fills all 11 different elements in the Contact Form with some values
- And verifies that the form has been filled correctly
This is just as simple as filling the Login Form!
Amazing!
public static ContactInfo FULL_CONTACT = new ContactInfo().set(c -> {
c.name = "Roman"; c.lastName = "Full Contact"; c.position = "ChiefQA";
c.passportNumber = 4321; c.passportSeria = 123456;
c.description = "JDI - awesome UI automation tool";
c.gender = "Female"; c.religion = "Other"; c.weather = "Sun, Snow";
c.acceptConditions = true; c.passport = true;
}
);
The most complicated part is creating the test data that we would like to utilize:
public static ContactInfo SIMPLE_CONTACT = new ContactInfo().set(c -> {
c.name = "Roman"; c.lastName = "Iovlev"; c.position = "ChiefQA";
c.passportNumber = 4321; c.passportSeria = 123456; }
);
@Test
public void simpleContactFormTest() {
sideMenu.select(ContactForm);
contactPage.checkOpened();
contactForm.submit(SIMPLE_CONTACT);
contactForm.check(SIMPLE_CONTACT);
}
Now if we would like to fill only the TextField
elements, we only need to change our test data.
Note: In the second example we use MenuOptions
enum value (ContactForm
) to select a sideMenu
item. It reduces the chance of making a mistake by limiting the choice of options. The enum is found at src/main/java/jdisite/enums.
See this example in ContactFormExamples.java on Github
Failed form example in logs
@Test
public void failCheckExample() {
sideMenu.select(ContactForm);
contactPage.checkOpened();
contactForm.fill(FULL_CONTACT);
contactForm.acceptConditions.uncheck();
contactForm.submit();
List<String> result = contactForm.verify(FULL_CONTACT);
assertThat(result, Matchers.hasSize(1));
assertThat(result, hasItem("Field 'acceptConditions' (Actual: 'false' <> Expected: 'true')"));
}
Now let's fail the validation of our form and see how JDI Light will display the failure results. We can build upon the previous example and just change some field before the check. Let's write a test that does this, execute it and observe the results.
Forms in JDI have two methods which verify the entered data:
check
— commonly used verification that validates a form, then throws an exception indicating all the incorrect values if there are any.verify
— has the same behavior ascheck
, but instead of throwing an exception this method returns a string list containing messages with expected/actual values for each incorrectly filled field, so it's up to you to decide how to manage the result.
In our example we revert one field, acceptConditions
, to an unchecked state, and the resulting exception gets presented in a clear way (pictured to the right):
"Field 'acceptConditions' (Actual: 'false' <> Expected: 'true')"
You can find this example in ContactFormExamples.java on Github
Using Forms in different ways
@BeforeMethod
public void before() {
loggedOut();
if (loginForm.isHidden())
userIcon.click();
}
We've had a first look at UI Elements in JDI Light and at the capabilities of Forms, and now we can look deeper at Form initialization and see how it can help you write less code.
Let's start with a simple Form — Login.
We're planning to have a lot of tests with the preconditions "User is logged out" and "Login form is opened", so let's write a corresponding @BeforeMethod
state for this set of test cases.
//Example 1
public class SeleniumLoginForm {
@FindBy(id = "name") public WebElement name;
@FindBy(id = "password") public WebElement password;
@FindBy(id = "login-button") public WebElement loginButton;
public void loginAs(User user) {
name.sendKeys(user.name);
password.sendKeys(user.password);
loginButton.click();
}
}
//Example 2
public class SeleniumLoginForm {
...
// 3 lines for Elements
public void loginAs(User user) {
if (user.name != null) {
name.clear();
name.sendKeys(user.name);
}
if (user.password != null) {
password.clear();
password.sendKeys(user.password);
}
loginButton.click();
}
}
//now we should add the class SeleniumLoginForm on JDISite.java:
public static SeleniumLoginForm seleniumLoginForm;
public class SelenideLoginForm {
UIElement name = $("#name"),
password = $("#password"),
loginButton = $("#login-button");
// + Same 11 rows for methods like in Selenium
...
}
//now we should add the class SelenideLoginForm on JDISite.java:
public static SelenideLoginForm selenideLoginForm;
public class LoginForm extends Form<User> {
@UI("#name") TextField name;
@UI("#password") TextField password;
@UI("#login-button") Button loginButton;
}
//now we should add the class LoginForm on JDISite.java:
public static LoginForm loginForm;
public class LoginFormSmart extends Form<User> {
TextField name, password;
Button loginButton;
}
//now we should add the class LoginFormSmart on JDISite.java:
public static LoginFormSmart loginFormSmart;
In JDI Light we can describe a Form in different styles:
Selenium — a typical Page Object with WebElement
s and @FindBy
annotations, Selenium actions upon Web Elements and no inheritance from JDI Light classes. Code like that will still work in pure Selenium projects without JDI.
See Example 1
But for cases where we would like to fill a form with different values, but it's not guaranteed that all form fields are empty, we need to extend our loginAs
method and make it more complex and stable.
See Example 2
See the example in Selenium LoginForm.java on Github
JQuery/Selenide — Selenide or jQuery-like style, where instead of @FindBy
annotations you can use direct initialization.
See the example in SelenideLoginForm.java on Github
Regular JDI Light Form — typical JDI Forms with typified elements, @UI
annotations, extending from Form without overriding fill
/check
methods.
See the example in LoginForm.java on Github
JDI Light Form with smart locators — If it's possible to align field names with locators, you can use smart locators for elements and remove locator annotations from Forms. This also allows you to declare form fields with the same type in one line, separated by commas.
See more details and examples for Smart locators in documentation
See example in LoginFormSmart.java on Github
on JDISite.java >> public static Form<User> lightLoginForm;
If your Form has only TextField
elements and buttons, instead of describing a UI object you can simply write a single line in the corresponding page class or in the root Site class:
This allows us to construct Login Forms in 1 line instead of 17!
5. Reduce the amount of code with JDI Light
- Initialize Driver in Selenium and JDI Light
- Page Objects code
- Compare Login Form code
- Reduce Complex Contact Form Page Object code from 97 lines (Selenium) to 8 lines of code (JDI Light)
- Test Data in Selenium and JDI Light
- Discuss example results
Now we know enough about Forms, so let's see how this can help us write code faster (by writing less code).
Let's try to code in Selenium the same Fill Contact Form test scenario that we have already covered with JDI Light:
- Open Home Page by URL.
- Open Contact Page by selecting a menu item.
- Validate that this Page has the correct URL and title.
- Fill all 11 different elements in the contact form with values.
- And verify that the form is filled correctly.
Note: You can find all the Selenium code here.
The same scenario with JDI Light is found here.
In this example I will develop Selenium code solution as effectively as possible while trying to keep the same look and feel of the test scenario.
At the same time, we will see how this code can be optimized using knowledge we got from Use Forms in different ways topic.
I will list the amount of lines of code we wrote for each action in brackets.
1. Set up and run Chrome driver
public static WebDriver DRIVER;
public static void runChromeDriver() {
System.setProperty("webdriver.chrome.driver", "C:\\Selenium\\chromedriver.exe");
DRIVER = new ChromeDriver();
DRIVER.manage().window().maximize();
}
Selenium: (6 lines of code)
Here it is done with a simple method, runChromeDriver()
.
Note: To run the driver in Selenium you need to download the latest version from the official site and put it in Selenium folder.
JDI Light: (0 lines of code)
You don't need to write any code for this. By default, the latest version of ChromeDriver will be downloaded automatically.
2. Create Page Objects for Home and Contact pages
public class HomePage {
public static final String URL = "https://jdi-testing.github.io/jdi-light/";
@FindBy(id ="user-icon") public static WebElement userIcon;
@FindBy(id ="user-name") public static WebElement userName;
}
public static HomePage homePage = initElements(DRIVER, HomePage.class);
public class ContactPage {
public static final String URL = "https://jdi-testing.github.io/jdi-light/contacts.html";
public static final String TITLE = "Contact Form";
public static ContactForm contactForm = initElements(DRIVER, ContactForm.class);
}
public static ContactPage contactPage = initElements(DRIVER, ContactPage.class);
Selenium: (12 lines of code)
Using PageFactory.initElements()
, we can create simple Page Objects with minimum code like in the example.
If you want to have cool pages in Selenium, you can use BasePage, which handles all the standard stuff related to opening and checking pages.
Note: I hope this "BasePage" approach will be useful for your Selenium projects.
@Url("/")
public class HomePage extends WebPage {
@UI("#user-icon") public static Link userIcon;
@UI("#user-name") public static Text userName;
}
public static HomePage homePage;
@Url("/contacts") @Title("Contact Form")
public class ContactPage extends WebPage {
@UI("#contact-form") public static ContactForm contactForm;
}
public static ContactPage contactPage;
JDI Light: (11 lines of code)
In JDI Light we already have all the functions related to webpages. You can find them in the WebPage
class, so you just need to extend your Page Object from it and use @Url
and @Title
annotations to set page metadata.
The code for UI Objects in Selenium and JDI Light in this case looks pretty much the same.
However, there are several points worth noting:
- Locators are a little bit shorter thanks to
@UI
annotations.
- Forms can have root locators, so their sub-element locators can be simplified.
- We don't have to initialize each page with the
PageFactory.initElements()
method, like Selenium does it.
public class LoginForm {
@FindBy(id = "name") WebElement name;
@FindBy(id = "password") WebElement password;
@FindBy(id = "login-button") WebElement loginButton;
public void loginAs(User user) {
if (user.name != null) {
name.clear();
name.sendKeys(user.name);
}
if (user.password != null) {
password.clear();
password.sendKeys(user.password);
}
loginButton.click();
}
public boolean isHidden() {
return !name.isDisplayed();
}
}
public static LoginForm loginForm = initElements(DRIVER, LoginForm.class);
3. Create a simple Login Form
Selenium: (21 lines of code)
This form contains WebElements (name
, password
, loginButton
) and actions like loginAs()
and isHidden()
.
JDI Light(1 line of code)
public static Form<User> loginForm;
In JDI Light you don't need to create a UI Object for such a simple form. Just declare it in your site class.
Note: And, of course, you don't need to initialize this form.
4. Creating a complex Contact Form
In total, we have 97 lines of code for Selenium and only 8 lines of code in JDI Light, but let's go step by step and see the difference in details.
Selenium Contact Form code (97)
JDI Light Contact Form code (8)
Note: Unfortunately, we can't use one-liner Form in this case because the form has elements of different kinds, but we still can use short form descriptions with Smart locators. Just describe element types and names and use one-line initialization with your root "#contact-form"
locator.
@FindBy(css ="#contact-form #name") WebElement name;
// +4 more TextFields
@FindBy(css ="#contact-form #accept-conditions") WebElement acceptConditionsCheckbox;
@FindBy(css ="#contact-form #passport") WebElement passportCheckbox;
@FindBy(css ="#contact-form #description") WebElement descriptionText;
@FindBy(css ="#contact-form [type=submit]") WebElement submitButton;
Selenium: (9 lines of code)
In Selenium we have to describe all elements of the form. This is easy to do for simple elements like TextField
, Checkbox
, TextArea
and buttons.
Note: You must add #contact-form to some element locators.
And because WebElement
doesn't give us any clues about the type of element, it is a good practice to denote an element type in a variable name.
TextField name, lastName, position, passportNumber, passportSeria;
Checkbox passport, acceptConditions;
TextArea description;
JDI Light: (3 lines of code)
In JDI Light we just need to describe the types of elements and list them for each type. In this example, locators align with field names, so we can utilize Smart locators without writing explicit ones.
// Dropdown
@FindBy(id = "gender") WebElement gender;
private Select gender() {
return new Select(gender);
}
// Combobox
@FindBy(id = "religion") WebElement religion;
// MultiDropdown
@FindBy(css ="#weather .caret") WebElement weatherExpand;
@FindBy(css ="#weather label") List<WebElement> weatherList;
@FindBy(css ="#weather button") WebElement weatherValue;
@FindBy(css ="#weather ul") WebElement weatherIsExpanded;
private boolean weatherIsExpanded() {
return weatherIsExpanded.getAttribute("style").equals("display: block;");
}
private void selectWeather(String value) {
if (!weatherIsExpanded())
weatherExpand.click();
String[] values = value.split(", ");
for (String val : values) {
for (WebElement listOption : weatherList) {
if (listOption.getText().trim().equals(val))
listOption.click();
}
}
}
Selenium: (23 lines of code)
The situation with Complex elements is more interesting:
Instead of Dropdown
we can use Select
class from selenium-support package and WebElement
+ gender()
method. These are enough to handle all actions.
Instead of Combobox
we can use a one-line WebElement
(just using it as a standard TextField
).
But instead of MultiDropdown
we'll need to add 4 WebElements and a few methods: select
and isExpanded
.
The general problem with Complex elements in standard Selenium approach is that we have to create methods like these for every equivalent of Dropdown
, MultiDropdown
etc. JDI Light allows to define an element once (or pick one from element library) and then just use it in one line in all Page Objects.
Dropdown gender;
Combobox religion;
MultiDropdown weather;
JDI Light: (3 lines of code)
In JDI Light it is as simple as for Common elements.
Note: They are so short that we could write them in one line, but let's keep each on its own line.
public void submit(ContactInfo contact) {
if (contact.name != null) {
nameTextField.clear();
nameTextField.sendKeys(contact.name);
}
// +6 more elements, 4 lines each including Combobox and TextArea
// Dropdown
if (contact.gender != null) {
gender().selectByVisibleText(contact.gender);
}
// MultiDropdown
if (contact.weather != null) {
selectWeather(contact.weather);
}
// Checkboxes
if (contact.passport && !passportCheckbox.isSelected() ||
!contact.passport && passportCheckbox.isSelected())
passportCheckbox.click();
if (contact.acceptConditions && !acceptConditionsCheckbox.isSelected() ||
!contact.acceptConditions && acceptConditionsCheckbox.isSelected())
acceptConditionsCheckbox.click();
submitButton.click();
}
public void check(ContactInfo contact) {
// 20 lines to validate contact
}
Selenium: (65(37) lines of code)
We'll need to write two methods: submit
and check
.
Like with the Login Form, in order to manage different test data fed into the Contact Form we'll have to check values for null
. We can avoid this check in only one case (for example, just fill all fields with null
and save a few lines of code).
Using a flexible approach, we need 43 + 22 = 65 lines of code.
We can improve this code by using a common method that clears and sends keys to an abstract WebElement: this will reduce our code to 55 lines.
If we remove null
validations, it will make our methods less universal, but will save additional 18 lines and reduce the code to 37 lines for Form methods.
Selenium Contact Form code (97)
Short Selenium Contact Form code (69)
JDI Light: (0 lines of code)
In JDI Light we don't need methods for these typical actions. Standard Form actions are flexible and allow to operate with any kind of data.
JDI Light Contact Form code (8)
5. Test Data
public class User {
public String name, password;
// + 3 lines constructor
// + 8 lines set methods
// + 16 lines to Override equals, hashCode and toString
}
public class ContactInfo {
public String name, lastName, position, gender, religion, weather, description;
public int passportNumber, passportSeria;
public boolean passport, acceptConditions;
// + 16 lines constructor
// + 44 lines set methods
// + 30 lines to Override equals, hashCode and toString
}
public static User ROMAN = new User("Roman", "Jdi1234");
public static ContactInfo SIMPLE_CONTACT = new ContactInfo()
.setName("Roman").setLastName("Iovlev").setPosition("ChiefQA")
.setPassportNumber(4321).setPassportSeria(123456)
.setDescription("JDI - awesome UI autoamtion tool");
public static ContactInfo FULL_CONTACT = new ContactInfo(
"Roman", "Full Contact", "ChiefQA", "Female", "Other",
"Sun, Snow", "JDI - awesome UI automation tool",
4321, 123456, true, false
);
Selenium: (134 lines of code)
For a simple User
entity with two fields we should have at least one constructor, but it would be nice to override equals()
, hashCode()
and toString()
methods in order to have a log-friendly representation of an entity and ability to compare the actual and expected results by class fields. Additionally, if we want to have the ability to set up different data, we have to create setter methods for each field.
You can generate all of these methods using "Generate" option in IntelliJ IDEA (right-click the data class and select "Generate").
We need at least 7 lines of code, but for a reusable entity we should write 31 lines of code.
The same holds true for ContactInfo
and for any Data entity in the standard approach. For ContactInfo
the full declaration is more important because we plan to make use of more fields, and it will take more lines of code.
After these manipulations, we can create transparent test data.
User data
ContactInfo data
User Roman
Full and Simple Contact info
public class User extends DataClass<User> {
public String name, password;
}
public class ContactInfo extends DataClass<ContactInfo> {
public String name, lastName, position, gender, religion, weather, description;
public int passportNumber, passportSeria = -1;
public boolean passport, acceptConditions;
}
public static User ROMAN = new User().set(c -> {
c.name = "Roman"; c.password = "Jdi1234";}
);
public static ContactInfo SIMPLE_CONTACT = new ContactInfo().set(c -> {
c.name = "Roman"; c.lastName = "Iovlev"; c.position = "ChiefQA";
c.passportNumber = 4321; c.passportSeria = 123456;
c.description = "JDI - awesome UI autoamtion tool"; }
);
public static ContactInfo FULL_CONTACT = new ContactInfo().set(c -> {
c.name = "Roman"; c.lastName = "Full Contact"; c.position = "ChiefQA";
c.religion = "Other"; c.weather = "Sun, Snow"; c.acceptConditions = true;
c.gender = "Female"; c.passportNumber = 4321; c.passportSeria = 123456;
c.passport = true; c.description = "JDI - awesome UI automation tool"; }
);
JDI Light: (22 lines of code)
To create Test Data in JDI Light, we can use DataClass
. It allows us to create different test data, compare data entities, print their meaningful representations and at the same preserve code clearness.
No constructors, no method overriding and with all functions in place thanks to DataClass
.
User data
ContactInfo data
Test Data
6. Conclusion
// Selenium Init
@BeforeSuite(alwaysRun = true)
static void setUp() {
runChromeDriver();
DRIVER.navigate().to(HomePage.URL);
}
// JDI Light Init
@BeforeSuite(alwaysRun = true)
static void setUp() {
initElements(JDISite.class);
homePage.open();
}
// Selenium Test Scenarios
@BeforeMethod
public void before() {
loggedIn();
selectInMenu("Contact form");
}
@Test
public void submitContactDataTest() {
assertEquals(DRIVER.getCurrentUrl(), ContactPage.URL);
assertEquals(DRIVER.getTitle(), ContactPage.TITLE);
contactForm.submit(FULL_CONTACT);
contactForm.check(FULL_CONTACT);
}
@Test
public void submitContactSimpleDataTest() {
assertEquals(DRIVER.getCurrentUrl(), ContactPage.URL);
assertEquals(DRIVER.getTitle(), ContactPage.TITLE);
contactForm.submit(SIMPLE_CONTACT);
contactForm.check(SIMPLE_CONTACT);
}
// JDI Test Scenarios
@BeforeMethod
public void before() {
loggedIn();
sideMenu.select("Contact form");
}
@Test
public void submitContactFormTest() {
contactPage.checkOpened();
contactForm.submit(FULL_CONTACT);
contactForm.check(FULL_CONTACT);
}
@Test
public void simpleContactFormTest() {
contactPage.checkOpened();
contactForm.submit(SIMPLE_CONTACT);
contactForm.check(SIMPLE_CONTACT);
}
As a result, we have test scenarios that look pretty much the same in Selenium and JDI Light, but the amount of code and time spent writing the code is significantly different.
You can find the complete project code in the "result" branch of Selenium and JDI Light example repositories.
Statistical results:
In our example, we wrote 3 times less amount of code with JDI Light.
This means that if a regular Test Automation engineer writes these tests using Selenium, it will take about 1 working day, while using JDI Light this work will only take 2-3 hours. In other words, an engineer can automate 3 times more test cases in the same period of time.
Note: You can try to automate this test scenario by yourself from scratch without clues and check how much time this will take in your case.
But JDI Light does not only save your time. Less amount of code increases code clearness.
In addition, if you run test scenarios with JDI Light, you will get logs of all your actions in a readable format. If you would like to have the same format of logs in Selenium, you need to write additional 30-50 lines of code for this example and spend 5-10% of your total effort on logs.
Note: JDI Light removes only waste code and keeps all the business-relevant parts in place.
Lesser amount of code, stable tests and clear logs will reduce maintenance effort during regression testing and increase the credibility of your tests, because with JDI Light, once tests are written, they will only fail in case of real application changes or performance issues, but not because of test instability.
JDI Light in BDD Style (even for Manual QA)
TBD
Create Custom controls
TBD
JDI settings at a glance
TBD
Test Framework structure
TBD
Theory
UI Elements
In order to effectively utilize Page Objects pattern we need to place elements on pages. Instead of Selenium WebElement
objects that basically represent HTML tags, in JDI we introduce UI Elements that represent UI elements interacted with by an actual user.
JDI provides the ability to create your own elements or use standard elements from a rich collection.
Common elements
@UI("input[type=text].name") public TextField name;
@UI("h1") public Label label;
@UI("//div[@name='disclamer']") public Text disclaimer;
@UI("textarea[ui=description]") public TextArea description;
@UI("//*[text()='Submit']") public Button submit;
- Are used to make your Page Objects more intuitive and clear.
- An element's type and name is displayed in JDI logs and reports, which simplifies test maintenance.
- And, of course, we expect that the actions each UI element provides are specific to its type (for example,
Button
won't allow you tosendKeys
, unlikeWebElement
orSelenideElement
).
In JDI we have the following Common elements:
Label, Button, Checkbox, ColorPicker, DateTimeSelector, FileInput, Icon, Image, Link, Menu, NumberSelector, ProgressBar, Range, Text, TextField, TextArea, Title.
Complex elements
@UI(".colors") public Dropdown colors;
@UI("input[type=checkbox].conditions") public Checklist acceptConditions;
@JDropdown(root = ".colors", value = ".dropdown-value", list = "li", expand = ".caret")
public Dropdown colors;
@UI("[ui=label] li") public JList<Labels> tabs;
@UI("//button[text()='%s']") public JList<Button> buttons;
In addition to Common elements, JDI Light features Complex elements: they represent UI elements encompassing the functionality of multiple Common elements.
Some Complex elements may be regarded as sets of similar Common elements (something you would likely implement as List<WebElement>
in Selenium). Typical examples of such Complex elements are Menu
, Checklist
, RadioButtons
, or Tabs
.
Note: You can still use lists of Common elements like List<Button>
or List<Label>
if need be.
Other Complex elements may be regarded as made up of different Common elements. Typical examples would be Dropdown
or Combobox
.
In JDI we have the following Complex elements:
RadioButtons, Table, DataTable, Dropdown, MultiDropdown, DataList, Checklist, MultiSelector, Combobox.
Composite elements
public class LoginForm extends Form<User> {
public TextField name, password;
@UI("//*[text()='Submit']") public Button submit;
...
}
public class TopPanel extends Section {
@UI("form.login") public LoginForm loginForm;
@UI("h1") public Label label;
@UI(".colors") public Dropdown colors;
...
}
@Url("/login.html") @Title("Login to JDI")
public class LoginPage extends WebPage {
@UI(".top-panel") public TopPanel topPanel;
...
}
Composite elements represent webpages or webpage sections and are mainly used as containers for elements and actions.
Typical examples of Composite elements are WebPage
and Section
.
Composite elements can also have a locator that defines a context for all elements within them. This means that all elements in a composite element will be searched relatively under this locator.
Composite elements might have predefined actions like fill
, submit
and check
for Form
, or open()
, checkOpened()
for WebPage
.
Remember that you can create your own Composite elements with JDI Light when you need to describe sections like Header, Navigation Bar, Footer, Sidebar, Advertisement Section or the main section of a page.
In JDI we have the following Composite elements:
UI Objects
public class AwesomeApplication {
public LoginPage loginPage;
@UI(".nav li") public Menu navigation;
}
@Url("/login.html") @Title("Login to JDI")
public class LoginPage extends WebPage {
@UI(".top-panel") public TopPanel topPanel;
...
}
public class TopPanel extends Section {
@UI("form.login") public LoginForm loginForm;
@UI("h1") public Label label;
@UI(".colors") public Dropdown colors;
...
}
UI Objects extend the standard Page Objects pattern with UI Elements and allow users to split pages into sections.
A typical UI object structure consists of:
- A Site class that contains all the pages of an application and its common parts like header, footer or navigation panel.
- Page Objects extending
WebPage
and representing respective application pages. - Composite elements (typically represented by
Section
objects or other Composite elements), acting as containers for other elements and smaller sections. - UI Elements representing functional elements on a page utilized by the end user.
Entity Driven Testing
(1)
public class LoginForm extends Form<User> {
public TextField name, password;
@UI("//*[text()='Submit']") public Button submit;
...
}
public class User extends DataClass<User> {
public String name, password;
}
@Test(dataProvider = "users")
public void loginTest(User user) {
loginForm.loginAs(user);
}
(2)
@UI("#user-table")
public static DataTable<?, UserInfo> userTable;
public class UserInfo extends DataClass<UserInfo> {
public String number, type, user, description;
}
@Test
public void userInfoTest() {
usersListPage.open();
userTable.has().value(SPIDER_MAN, inRow(2));
userTable.assertThat()
.all().rows(d -> d.user.length() > 4)
.no().rows(d -> isBlank(d.user))
.atLeast(3).rows(d -> d.type.contains("User"))
.exact(1).rows(SPIDER_MAN);
assertEquals(userTable.dataRow("Wolverine").type, "Admin");
}
(3)
@UI(".search-results li") public DataList<?, Result> resultsList;
public class Result extends DataClass<Result> {
public String name, description, link;
}
@Test
public void resultsTest() {
resultsList.assertThat()
.value(containsString("name:JDI FACEBOOK GROUP; description:English Community Facebook group"))
.any(e -> e.description.toLowerCase().contains("jdi"))
.each(e -> e.name.toLowerCase().contains("jdi"))
.onlyOne(e -> e.name.contains("OWNER"))
.noOne(e -> e.name.equalsIgnoreCase("Selenide"));
resultsList.assertThat(not(empty()))
.and(hasSize(greaterThan(2)))
.and(hasItem(CORRECT))
.and(hasItems(CORRECT, CORRECT_2, CORRECT_3))
.and(not(hasItem(CORRUPTED)))
.and(not(hasItems(CORRUPTED, CORRUPTED_2)));
}
Entity Driven Testing (EDT) is an approach that implies utilizing Business Entities instead of unnamed test data in the test scenarios.
EDT can be organically combined with Data Driven Testing that uses Business Entities as input with similar scenarios.
JDI Light natively supports EDT with Form
, Table
and DataList
. See the examples in the right panel:
Example scenario:
> Provide List<User> for test
0. Check that there is a user in the database
1. Log in with user data
2. Submit user data in Contact Us form
3. Get actual opening from vacancy table
4. Assert that actual opening equals to expected opening
Code example:
@Test(dataProvider = “users") //>
public void formTest(User user) {
DB.users.shouldHave(user); //0.
loginForm.loginAs(user); //1.
contactUsForm.submit(user); //2.
Vacancy vacancy = vacancyTable.getEntity(3); //3.
Assert.areEquals(vacancy, expectedVacancy); //4.
}
Smart Locators
Smart locators example
Let's assume you have a uniform method to locate most of the elements (for example, most of the elements involved in UI test automation have a predictable id, or a name, or a special attribute used to locate them.)
Let's assume you have @UI("[ui=last-name]") public TextField lastName
element in JDI. In this case you can simplify it to public TextField lastName
and omit the locator.
Now for more complex example. Suppose you have the following HTML:
<input type="text" ui="name"/>
<input type="text" ui="last-name"/>
<input type="text" ui="pin-code"/>
<input type="text" ui="promo-code"/>
<input type="checkbox" ui="accept-conditions"/>
<a href="..." ui="external-link">External link</a>
<button ui="submit-button">
public class UserCard : Form<User>
{
[FindBy(Css = "#name")] public TextField Name;
[FindBy(Css = "#last-name")] public TextField LastName;
[FindBy(Css = "#submit-button")] public Button SubmitButton;
}
SmartSearchLocator = "#{0}";
SmartSearchName(string name) => StringExtensions.SplitHyphen(name);
public class UserCard : Form<User>
{
TextField name;
TextField LastName;
Button SubmitButton;
}
@FindBy(css = "[ui=name]")
public WebElement name;
@FindBy(css = "[ui=last-name]")
public WebElement lastName;
@FindBy(css = "[ui=pin-ncodeame]")
public WebElement pinCode;
@FindBy(css = "[ui=promo-code]")
public WebElement promoCode;
@FindBy(css = "[ui=accept-conditions]")
public WebElement acceptConditions;
@FindBy(css = "[ui=submit-button]")
public WebElement submitButton;
With pure Selenium, Page Object elements for that will look like this (see on the right panel) =====>
@UI("[ui=name]") public Textfield name;
@UI("[ui=last-name]") public Textfield lastName;
@UI("[ui=pin-code]") public Textfield pinCode;
@UI("[ui=promo-code]") public Textfield promoCode;
@UI("[ui=accept-conditions]") public Checkbox acceptConditions;
@UI("[ui=submit-button]") public Button submitButton;
In JDI Light with standard UI Objects the code gets more descriptive, but there still are duplications in locator and element names (see on the right panel) =====>
public Textfield name, lastName, pinCode, promoCode;
public Checkbox acceptConditions;
public Button submitButton;
But by using smart locators you can write this without any duplications (without locators) in just a few lines. Looks cool, doesn't it?
Define smart locator using test.properties
smart.locators="[ui=%s]"
smart.locators.toName=UPPER_SNAKE_CASE
You can set up your smart locators in the test.properties file the following way.
First, assign a value to the smart.locators
property:
- set it to
#%s
in case your smart locator translates to id - set it to
.%s
for classname - set it to
[name=%s]
for name (or swapname
for any other attribute)
Then, assign a value to the smart.toName
property. Suppose that you have set smart.locators
to [ui=%s]
:
kebab-case
will provide[ui=last-name]
locator for public WebElementlastName
.camelCase
will provide[ui=lastName]
locator for public WebElementlastName
.snake_case
will provide[ui=last_name]
locator for public WebElementlastName
.PascalCase
will provide[ui=LastName]
locator for public WebElementlastName
.UPPER_SNAKE_CASE
will provide[ui=LAST_NAME]
locator for public WebElementlastName
.
...or, if the property looks like smart.locators=//*[text()='%s']
:
First Upper Case
will provide//*[text()='Submit Form']
locator for public WebElementsubmitForm
.ALL UPPER CASE
will provide//*[text()='SUBMIT FORM']
locator for public WebElementsubmitForm
.
Define a Smart Locator using WebSettings
WebSettings.SMART_SEARCH_LOCATORS = asList("#%s");
WebSettings.SMART_SEARCH_NAME = StringUtils::toKebabCase;
// JDI Light style
WebSettings.SMART_SEARCH = el -> {
String locatorName = toKebabCase(el.getName());
UIElement element = $("[auto="+locatorName+"]", el.base().parent));
element.setName(el.getName());
return element.getWebElement();
}
// Selenium style
WebSettings.SMART_SEARCH = el -> {
String locatorName = toKebabCase(el.getName());
return getDriver.findElement(By.cssClass("[auto="+locatorName+"]"));
}
You can also set up Smart Locators in code using WebSettings.SMART_SEARCH_NAME
and WebSettings.SMART_SEARCH_LOCATORS
variables:
Or you can define by yourself what should be done when UI Element has no locator using WebSettings.SMART_SEARCH
.
Smart Annotations
When your locators follow standard patterns you can use Smart Annotations to mark elements:
For @UI("#last-name") TextField lastName;
use @SId TextField lastName;
For @UI(".contact-form") Form<CardData> contactForm;
use @SClass Form<CardData> contactForm;
For @UI("//*[text()='Submit Card']") Button submitCard;
use @SText Button submitCard;
For @UI("[name='accept-conditions']") Checkbox acceptConditions;
use @SName Checkbox acceptConditions;
Or use @Smart
annotation for any specific HTML attribute:
For @UI("[data-type=data-multi-combobox]") MultiCombobox dataMultiCombobox;
use @Smart("data-type") MultiCombobox dataMultiCombobox;
Custom Smart Annotations
You can also always create your own annotation enabling smart behavior.
Let's assume you would like to use smart locators for buttons like //button[text()='Button Text']
.
First, create a new annotation:
SButton.java
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface SButton {
}
Then set up the behavior for this annotation before you call initSite
:
@BeforeSuite(alwaysRun = true)
public static void setUp() {
JDI_ANNOTATIONS.add("Buttons", aRule(SButton.class,
(e, a) -> e.setLocator(format("//button[text()='%s']", splitCamelCase(e.getName())))));
initSite(YourAwesomeSite.class);
That's all. Now we can write:
@SButton public Button logIn, signIn, cancel, useVipAccess;
Instead of:
@FindBy(xpath = "//button[text()='Log In']")
public WebElement logIn;
@FindBy(xpath = "//button[text()='Sign In']")
public WebElement signIn;
@FindBy(xpath = "//button[text()='Cancel']")
public WebElement cancel;
@FindBy(xpath = "//button[text()='Use Vip Access']")
public WebElement useVipAccess;
JDI Annotations
In order to control element behavior in JDI Light you can use the following standard annotations:
@Root — ignores all parent sections locators for this element and uses only locator that specified for element (including smart locators).
@Frame("frame-id") or @Frame({"frame-id", "div[name-adv]"}) — in case you have two or more frames above the element, use driver.switchTo().frame(...)
before searching your element. Or call it multiple times if @Frame
has list of locators. Can be used together with @UI
locator.
@Css("div.dropdown") — if your element has a CSS locator (deprecated, recommended to use universal @UI
locator instead.)
@XPath("//div[text()='Submit']") — if your element has an XPath locator (deprecated, recommended to use universal @UI
locator instead.)
@ByText("Submit") — used to locate elements by text (uses locator ".//*/text()[normalize-space(.) = %s]/parent::*"
.)
@WithText("Navigation") — used to locate elements by text containing given substring (uses locator ".//*/text()[contains(normalize-space(.), %s)]/parent::*"
)
@ClickArea(...) — specifies how click will be performed. Allowed values: SMART_CLICK
(tries to find area where user able to click), TOP_LEFT
(click top left corner of the element), TOP_RIGHT
(click top right corner of the element), BOTTOM_LEFT
(click bottom left corner of the element), BOTTOM_RIGHT
(click bottom right corner of the element), CENTER
(standard Selenium click in the center of the element), JS
(using JS click).
@GetTextAs(...) — specifies how getText will be performed. Allowed values: TEXT
(getText()
), VALUE
(getAttribute("value")
), INNER
(jsExecute("innerText")
), LABEL
(using a label related to the element; good for checkboxes and radio buttons), SMART_TEXT
(tries smart value search).
@SetTextAs(...) — specifies how text input will be performed. Allowed values: SEND_KEYS
(sendKeys(...)
), SET_TEXT
(set value
attribute using JS), CLEAR_SEND_KEYS
(clear()
then sendKeys(...)
).
@NoCache — always get the element from the page. Do not use cache.
@WaitTimeout(sec) — set sec seconds implicit wait for the element.
@NoWait — no element wait timeout; the element won't be found unless it's present on the page.
@Name(“Test”) — sets the name of an element to the provided value.
@GetAny — gets element without validation.
@GetVisible — returns displayed element.
@GetInvisible — returns invisible element.
@GetVisibleEnabled — returns displayed and enabled element.
@GetShowInView — returns displayed and clickable element.
@PageName — sets pageName
variable for the element.
@SId — sets smart ID locator, e.g “By.cssSelector: #Test”
, where “Test” is the element's id
attribute.
@SText — sets smart text locator, e.g. “By.xpath: .//*/text()[normalize-space(.) = "S Text"]/parent::*”
, where “SText” is the name of the element. Be aware that it’s creating a locator with white space for words starting with capital letter.
@SName — sets smart name locator, e.g. for “@Name(“Test”) @SName”
it will be “By.cssSelector: [name='test']”
.
@Smart — sets smart locator, e.g. for “@Name(“Smart”) @Smart(“id”)”
it will be “By.cssSelector: [id=’smart’]”
.
@SClass — sets smart class locator, e.g. for “@Name(“Test”) @SName”
it will be “By.cssSelector: .test”
.
@UI — for list UI locator, e.g. @UI("img")
, see more examples in the previous section.
@FindBy — an annotation that can have attributes such as: css
, tagName
, linkText
, partialLinkText
, xpath
; text
, id
, name
, className
, group
. Could be quickly changed to from Selenium @FindBy
by changing the import line.
@VisualCheck — adds the “(“visualCheck”, “”)”
pair to params.
JDI Locators (as simple as CSS, as powerful as XPath)
@XPath("//div[contains(@class,'btn')]//*[text()='Submit']")
@UI("div.btn['Submit']")
@XPath("//*[contains(@class,'nav-menu')]//*[@data-role='header']//*[contains(text(),'Navigation menu')]")
@UI(".nav-menu [data-role=header][*'Navigation menu']")
@XPath("//label[text()='Gold status']/..//input[@type='checkbox']")
@UI("label['Gold status']<input[type=checkbox]")
@XPath("//*[contains(@class,'nav-menu')]//*[@data-role='header'][3]")
@UI(".nav-menu [data-role=header][3]")
With JDI Light you can use simple and fast CSS-like selectors with the power of XPath locators. Now you can search by text or index with CSS-like syntax or even move up the DOM tree.
See some examples below:
XPath: //div[contains(@class,'btn')]//*[text()='Submit']
JDI Locator: div.btn['Submit']
XPath: //*[contains(@class,'nav-menu')]//*[@data-role='header']//*[contains(text(),'Navigation menu')]
JDI Locator: .nav-menu [data-role=header][*'Navigation menu']
XPath: //label[text()='Gold status']/..//input[@type='checkbox']
JDI Locator: label['Gold status']<input[type=checkbox]
XPath: //*[contains(@class,'nav-menu')]//*[@data-role='header'][3]
JDI Locator: .nav-menu [data-role=header][3]
FAQ
TBD
Documentation
Base information
Base Elements
UIBaseElement
UIElement
@Test
public void click() {
submit.click();
assertEquals(sum.getText(), "Summary: 3");
}
@Test
public void isDisplayed(){
assertTrue(submit.isDisplayed());
}
@Test
public void input(){
description.input("Hello world!");
assertEquals(description.getText(), "Hello world!");
description.clear();
}
@Test
public void hasAttribute() {
assertTrue(submit.hasAttribute("class"));
assertTrue(submit.hasAttribute("type"));
}
Available methods in Java JDI Light:
Method | Description | Return Type |
---|---|---|
check() | Clicks on element if it's not selected | void |
classes() | Gets all element's classes as list | List |
clear() | Clears input field | void |
click() | Clicks on element | void |
click(ElementArea area) | Clicks on element area (possible ElementArea values are SMART_CLICK, TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, CENTER, JS) | void |
click(int x, int y) | Clicks on point (x, y) | void |
doubleClick() | Double clicks on the element | void |
dragAndDropTo(int x, int y) | Drags and drops element to certain coordinates | void |
dragAndDropTo(WebElement to) | Drags and drops element to another element | void |
focus() | Focuses on element | void |
getAllAttributes() | Gets all element attributes | MapArray |
getAttribute(String value) | Gets the value of specified element attribute | String |
getCssValue(String value) | Gets element CSS value | String |
getLocation() | Gets element location as point | Point |
getRect() | Gets element rectangle | Rectangle |
getSize() | Gets element size | Dimension |
getTagName() | Gets element tag name | String |
getText() | Gets element text | String |
getValue() | Gets element text | String |
hasAttribute(String attrName) | Returns true if the element has an expected attribute | boolean |
hasClass(String className) | Returns true if the element has an expected class | boolean |
highlight() | Highlights element with red color | void |
highlight(String color) | Scrolls view to element and highlights it with a border of specified color | void |
hover() | Hovers mouse cursor over the element | void |
input(String value) | Inputs specified value as keys | void |
isDeselected() | Checks that element is deselected | boolean |
isDisabled() | Checks that element is disabled | boolean |
isDisplayed() | Checks that element is displayed | boolean |
isEnabled() | Checks that element exists | boolean |
isHidden() | Checks that element is hidden | boolean |
isNotExist() | Checks that element does not exist | boolean |
isNotVisible() | Checks that element is not visible by user | boolean |
isSelected() | Checks that element is selected | boolean |
isVisible() | Checks that element is visible by user | boolean |
jsExecute(String jsCode) | Executes JavaScript code | String |
labelText() | Gets label text | String |
makePhoto() | Gets a screenshot of the element | File |
placeholder() | Gets element “placeholder” attribute value | String |
printHtml() | Gets element “innerHTML” attribute value | String |
rightClick() | Right clicks on the element | void |
select() | Selects item | void |
select(int index) | Selects item by index | void |
select(String value) | Selects item by value | void |
select(String… names) | Selects items by values | void |
sendKeys(CharSequence… value) | Sends specified value as keys | void |
setAttribute(String name, String value) | Sets value to the specified attribute | void |
setText(String value) | Puts value as text | void |
setValue() | Inputs value | void |
show() | Scrolls screen view to item | void |
uncheck() | Clicks on element if selected | void |
Aliases in Java JDI Light:
Method | Description | Return Type |
---|---|---|
attr(String value) | Gets element attribute | String |
attrs() | Gets all element attributes | MapArray |
css(String prop) | Gets element css value | String |
text() | Gets element text | String |
WebList
Extended Selenium features
Wait After Action
You can annotate a UI element with @WaitAfterAction
. This tells JDI to wait after executing this element's methods.
@WaitAfterAction(value = 3, method = "getText")
would mean that JDI will wait 3 seconds after executing the annotated element's getText()
method.
If the method name is not specified, the wait will be applied to all action methods of the element (like click
, check
or select
, depending on the element), and you can write the annotation like @WaitAfterAction(3)
.
You can also apply the default @WaitAfterAction
which sets the wait to 1 second for all action methods.
@WaitAfterAction(value = 3, method = "getText")
public Text colorValue;
@WaitAfterAction(2)
public Dropdown detailsButton;
@WaitAfterAction
public Dropdown colors;
...
@Test
public void selectColor() {
detailsButton.click() // will wait 2 seconds after click
colors.select("Gold"); // will wait 1 second after select
assertEquals(colorValue.getText(), "Gold") // will wait 3 seconds after getText
}
1. HTML5 elements
1.1 HTML5 Common elements
1.1.1 Label
// @FindBy(xpath = "//label[@for='your-name']")
@UI("//label[@for='your-name']")
public static TextField yourName;
@Test
public void labelTest() {
assertEquals(yourName.label().getText(), "Your name:");
yourName.label().is().text(containsString("Your"));
disabledName.label().is().text(equalToIgnoringCase("Surname:"));
}
In the next test Label is found from NameTextField locator:
[FindBy(Css = "div.main-content #name")]
public TextField NameTextField { get; set; }
By default, Label is found by locator By.CssSelector($"[for={WebElement.GetAttribute("id")}]")
[Test]
public void LabelTest()
{
Assert.AreEqual(TestSite.Html5Page.NameTextField.Label().GetText(), "Your name:");
TestSite.Html5Page.NameTextField.Label().Is.Text(ContainsString("Your"));
Assert.AreEqual(TestSite.Html5Page.SurnameTextField.Label().GetText(), "Surname:");
TestSite.Html5Page.SurnameTextField.Label().Is.Text(ContainsString("Surname:"));
}
[Test]
public void GetLabelTextTest()
{
AreEqual(TestSite.Html5Page.ColorPicker.LabelText(), "Select a color");
}
Label — Defines a label for an <input>
control.
<form>
<input type="radio" name="gender" value="male" id="male">
<label for="male">Male</label>
<input type="radio" name="gender" value="female" id="female">
<label for="female">Female</label>
</form>
Available methods in JDI Light:
Method | Description | Return Type |
---|---|---|
setValue(String) | sets value | void |
getValue() | gets value | String |
getText() | returns value. Overrided method of UIBaseElement | String |
is() | Assert action | TextAssert |
Available methods in C# JDI Light:
Method | Description | Return Type |
---|---|---|
assertThat() | Assert action | TextAssert |
click() | Click the button | void |
getText() | Get button text | String |
is() | Assert action | TextAssert |
Label() | Creates label for element using the element's Id | Label |
LabelText() | Gets the text of a label | string |
1.1.2 Button
@UI("[value*='Red Button']")
// @FindBy(css = "[value*='Red Button']")
public static Button redButton;
@Test
public void clickTest() {
redButton.click();
validateAndAcceptAlert("Red button");
blueButton.click();
validateAndAcceptAlert("Blue button");
}
[FindBy(Css = ".red")]
public Button RedButton;
[Test]
public void ClickTest()
{
RedButton.Click();
Assert.AreEqual(GetAlert().GetAlertText(), "Red button");
GetAlert().AcceptAlert();
}
[Test]
public void GetTextTest()
{
Assert.AreEqual(RedButton.GetText(), "Big Red Button-Input");
}
Button — The <button>
tag is used to create clickable buttons on the web page
Here is an example with provided HTML code:
html
<input type="button" value="Big Red Button-Input" class="uui-button red" onclick="alert('Red button');">
Button is located in the following classes:
- Java: com.epam.jdi.light.ui.html.common.Button
- C#: JDI.Light.Elements.Common.Button
Available methods in Java JDI Light:
Method | Description | Return Type |
---|---|---|
getValue() | Get button's value | String |
is() | Assert action | TextAssert |
Available methods and properties in C# JDI Light:
Method/Property | Description | Return Type |
---|---|---|
AssertThat | Assert action | TextAssert |
Click() | Click the button | void |
GetText() | Get button text | string |
Is | Assert action | TextAssert |
Java test examples
C# test examples
BDD Steps example
1.1.3 Checkbox
Checkbox — Element allows you to select a single value for submission.
Checkbox is located in the following classes:
- Java: com.epam.jdi.light.ui.html.common.Checkbox*
- C#: JDI.Light.Elements.Common.CheckBox*
Here is an example with provided HTML code:
//@FindBy(xpath = "//input[@type='checkbox' and @id='accept-conditions']")
@UI("//input[@type='checkbox' and @id='accept-conditions']")
public static Checkbox acceptConditions;
@Test
public void checkTest() {
acceptConditions.check();
acceptConditions.is().selected();
}
@Test
public void uncheckTest() {
acceptConditions.uncheck();
acceptConditions.is().deselected();
}
@Test
public void getLabelTextTest() {
acceptConditions.label().is().text(labelText);
}
[FindBy(XPath = "//*[@id='elements-checklist']//*[text()='Water']")]
[IsChecked(typeof(CustomCheck), nameof(CustomCheck.CheckFunc))]
public CheckBox CbWater;
[FindBy(Css = "#accept-conditions")]
public CheckBox AcceptConditions { get; set; }
[Test]
public void CheckSingleTest()
{
Assert.DoesNotThrow(() => TestSite.MetalsColorsPage.CbWater.Check(true));
Jdi.Assert.Contains(TestSite.ActionsLog.Texts[0], "Water: condition changed to true");
}
[Test]
public void UncheckSingleTest()
{
TestSite.MetalsColorsPage.CbWater.Click();
TestSite.MetalsColorsPage.CbWater.Uncheck();
Jdi.Assert.Contains(TestSite.ActionsLog.Texts[0], "Water: condition changed to false");
}
[Test]
public void IsCheckTest()
{
Assert.IsFalse(TestSite.MetalsColorsPage.CbWater.IsChecked);
TestSite.MetalsColorsPage.CbWater.Click();
Assert.IsTrue(TestSite.MetalsColorsPage.CbWater.IsChecked);
}
[Test]
public void MultipleUncheckTest()
{
TestSite.MetalsColorsPage.CbWater.Click();
TestSite.MetalsColorsPage.CbWater.Uncheck();
TestSite.MetalsColorsPage.CbWater.Uncheck();
Jdi.Assert.Contains(TestSite.ActionsLog.Texts[0], "Water: condition changed to false");
}
[Test]
public void ClickTest()
{
TestSite.MetalsColorsPage.CbWater.Click();
Jdi.Assert.Contains(TestSite.ActionsLog.Texts[0], "Water: condition changed to true");
TestSite.MetalsColorsPage.CbWater.Click();
var texts = TestSite.ActionsLog.Texts;
Jdi.Assert.Contains(texts[0], "Water: condition changed to false");
}
[Test]
[TestCaseSource(typeof(CheckBoxProvider), nameof(CheckBoxProvider.InputData))]
public void SetValueTest(bool value, bool expected)
{
if (!expected) TestSite.MetalsColorsPage.CbWater.Click();
TestSite.MetalsColorsPage.CbWater.Value = value;
var resultMsg = "Water: condition changed to " + expected.ToString().ToLower();
Jdi.Assert.Contains(TestSite.ActionsLog.Texts[0], resultMsg);
}
[Test]
public void IsValidationTest()
{
TestSite.Html5Page.Open();
TestSite.Html5Page.AcceptConditions.Is.Selected();
TestSite.Html5Page.AcceptConditions.Click();
TestSite.Html5Page.AcceptConditions.Is.Deselected();
TestSite.Html5Page.AcceptConditions.Is.Enabled();
TestSite.Html5Page.AcceptConditions.Is.Displayed();
}
[Test]
public void LabelTest()
{
TestSite.Html5Page.Open();
Assert.AreEqual("Accept terms and conditions", TestSite.Html5Page.AcceptConditions.Label().GetText());
TestSite.Html5Page.AcceptConditions.Label().Is.Text(ContainsString("terms and conditions"));
TestSite.Html5Page.AcceptConditions.Label().Is.Text(EqualTo("accept terms and conditions"));
}
[Test]
public void AssertValidationTest()
{
TestSite.Html5Page.Open();
TestSite.Html5Page.AcceptConditions.AssertThat.Selected();
}
[Test]
public void BaseValidationTest()
{
TestSite.Html5Page.Open();
BaseElementValidation(TestSite.Html5Page.AcceptConditions);
}
<div>
<input type="checkbox" id="accept-conditions" checked="">
<label for="accept-conditions">Accept terms and conditions</label>
</div>
Available methods in Java JDI Light:
Method | Description | Return Type |
---|---|---|
safeGetLabel() | Safely returns label | Label |
check(String) | Set to checked if string value equals "true" (case insensitive), otherwise set to unchecked | void |
check() | Set to checked | void |
uncheck() | Set to unchecked | void |
Available methods in C# JDI Light:
Method | Description | Return Type |
---|---|---|
AssertThat | Gets assert for checkbox | CheckBoxAssert |
Check(bool checkEnabled = true) | Checks a checkbox | void |
Deselected() | Checks whether a checkbox is deselected | CheckBoxAssert |
Displayed() | Checks whether a checkbox is displayed | CheckBoxAssert |
Enabled() | Checks whether a checkbox is enabled | CheckBoxAssert |
Is | Gets assert for checkbox | CheckBoxAssert |
IsChecked | Determines whether a checkbox is checked | bool |
Selected() | Checks whether a checkbox is selected | CheckBoxAssert |
Uncheck(bool checkEnabled = true) | Unhecks a checkbox | void |
1.1.4 ColorPicker
//@FindBy(xpath = "//input[@type='color' and @id='color-picker']")
@UI("//input[@type='color' and @id='color-picker']")
public static ColorPicker colorPicker;
@Test
public void getColorTest() {
assertEquals(disabledPicker.color(), defaultColor);
}
@Test
public void setColorTest() {
colorPicker.setColor("#432376");
assertEquals(colorPicker.color(), "#432376");
disabledPicker.setColor("#432376");
assertEquals(disabledPicker.color(), "#432376");
}
[FindBy(Css = "#color-picker")]
public ColorPicker ColorPicker;
[Test]
public void GetColorTest()
{
Assert.AreEqual(ColorPicker.Color(), "#3fd7a6");
}
[Test]
public void SetColorTest()
{
ColorPicker.SetColor("#432376");
Assert.AreEqual(ColorPicker.Color(), "#432376");
}
ColorPicker — Elements of this type provide a user interface element that lets a user specify a color, either by using a visual color picker interface or by entering the color into a text field in "#rrggbb" hexadecimal format. Only simple colors (with no alpha channel) are allowed. The values are compatible with CSS.
Color Picker is located in the following classes:
- Java: com.epam.jdi.light.ui.html.common.ColorPicker
Here is an example with provided HTML code:
<div>
<input type="color" value="#3fd7a6" id="color-picker">
<label for="color-picker">Select a color</label>
</div>
Here is the list of some available methods in Java:
Methods | Description | Return Type |
---|---|---|
color() | Returns color code in hexadecimal format ("#rrggbb") | String |
setColor(String) | Set color from string hex representation ("#rrggbb") | void |
Here is the list of some available methods in C#:
Methods | Description | Return Type |
---|---|---|
AssertThat() | Assert action | ColorAssert |
Color() | Returns color code in hexadecimal format ("#rrggbb") | string |
Is() | Assert action | ColorAssert |
SetColor(String) | Set color from string hex representation ("#rrggbb") | void |
Java test examp
Test examples in C#
BDD Steps example
1.1.5 DateTimeSelector
DateTimeSelector — Is used for Input Type Date and its derivatives and allows users to set the value of date and/or time.
The list of supported elements:
- Input Type Date
- Input Type Week
- Input Type Month
- Input Type Time
- Input Type DateTime-Local
Input Type Date — A graphical control element that allows user to set value for date.
//@FindBy(css = "#birth-date")
@UI("#birth-date")
public static DateTimeSelector birthDate;
@Test
public void setDateTimeTest() {
birthDate.setDateTime("2018-11-13");
assertEquals(birthDate.value(), "2018-11-13");
}
@Test
public void labelTest() {
assertEquals(birthDate.label().getText(), "Birth date");
birthDate.label().is().text(containsString("Birth"));
}
[FindBy(Css = "#birth-date")]
public IDateTimeSelector BirthDate { get; set; }
[Test]
public void SetBirthDateTest()
{
TestSite.Html5Page.BirthDate.Format = "yyyy-MM-dd";
TestSite.Html5Page.BirthDate.SetDateTime(_dateTime);
TestSite.Html5Page.BirthDate.AssertThat().SelectedTime(Is.EqualToIgnoringCase("2019-04-01"));
}
<div>
<label for="birth-date">Birth date</label>
<input type="date" id="birth-date" value="1985-06-18" min="1970-01-01" max="2030-12-31">
</div>
Type Date test examples in Java
Type Date test examples in C#
Input Type Week — A graphical control element that allows user to set values for week and year.
//@FindBy(css = "#autumn-week")
@UI("#autumn-week")
public static DateTimeSelector autumnWeek;
@Test
public void setDateTimeTest() {
autumnWeek.setDateTime("2018-W12");
autumnWeek.show();
assertEquals(autumnWeek.value(), "2018-W12");
}
@Test
public void labelTest() {
autumnWeek.label().assertThat().text(is("Autumn"));
autumnWeek.label().is().text(equalToIgnoringCase("autumn"));
}
[FindBy(Css = "#autumn-week")]
public IDateTimeSelector AutumnDateTime { get; set; }
[Test]
public void AutumnDateTimeTest()
{
var calendar = new GregorianCalendar();
var weekNum = calendar.GetWeekOfYear(_dateTime, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday);
TestSite.Html5Page.AutumnDateTime.Format = "yyyy-" + $"W{weekNum}";
TestSite.Html5Page.AutumnDateTime.SetDateTime(_dateTime);
var setValue = TestSite.Html5Page.AutumnDateTime.GetValue();
Assert.AreEqual(setValue, "2019-W13");
}
<div>
<label for="autumn-week">Autumn</label>
<input type="week" id="autumn-week" value="2018-W40" min="2018-W35" max="2018-W48" required="">
</div>
Type Week test examples in Java
Type Week test examples in C#
Input Type Month — a graphical control element that allows user to set values for month and year.
//@FindBy(css = "#month-date")
@UI("#month-date")
public static DateTimeSelector monthDate;
@Test
public void setDateTimeTest() {
monthDate.setDateTime("2018-10");
monthDate.show();
assertEquals(monthDate.value(), "2018-10");
}
@Test
public void labelTest() {
monthDate.label().is().text(containsString("Holidays"));
monthDate.label().is().text(equalToIgnoringCase("month of holidays"));
}
[FindBy(Css = "#month-date")]
public IDateTimeSelector MonthOfHolidays { get; set; }
[Test]
public void SetMonthTest()
{
TestSite.Html5Page.MonthOfHolidays.Format = "yyyy-MM";
TestSite.Html5Page.MonthOfHolidays.SetDateTime(_dateTime);
var setValue = TestSite.Html5Page.MonthOfHolidays.GetValue();
Assert.AreEqual(setValue, "2019-04");
}
<div>
<label for="autumn-week">Autumn</label>
<input type="week" id="autumn-week" value="2018-W40" min="2018-W35" max="2018-W48" required="">
</div>
Type Month test examples in C#
Type Month test examples in Java
Input Type Time — A graphical control element that allows user to set time.
//@FindBy(css = "#booking-time")
@UI("#booking-time")
public static DateTimeSelector bookingTime
@Test
public void setDateTimeTest() {
bookingTime.setDateTime("05:00");
bookingTime.show();
assertEquals(bookingTime.value(), "05:00");
}
@Test
public void labelTest() {
assertEquals(bookingTime.label().getText(), "Booking Time:");
bookingTime.label().is().text(equalToIgnoringCase("booking Time:"));
}
[FindBy(Css = "#booking-time")]
public IDateTimeSelector BookingTime { get; set; }
[Test]
public void SetTimeTest()
{
TestSite.Html5Page.BookingTime.Format = "H:mm";
TestSite.Html5Page.BookingTime.SetDateTime(_dateTime);
var setValue = TestSite.Html5Page.BookingTime.GetValue();
Assert.AreEqual(setValue, "15:00");
}
<div>
<label for="booking-time">Booking Time:</label>
<input type="time" id="booking-time" value="11:00" min="9:00" max="18:00">
</div>
Type Time test examples in C#
Type Time test examples in Java
Input Type DateTime-Local — A graphical control element that allows user to set time and date.
//@FindBy(css = "#party-time")
@UI("#party-time")
public static DateTimeSelector partyTime;
@Test
public void setDateTimeTest() {
partyTime.setDateTime("2017-05-10T00:00");
partyTime.show();
assertEquals(partyTime.value(), "2017-05-10T00:00");
}
@Test
public void labelTest() {
partyTime.label().assertThat().text(is("Date/time:"));
partyTime.label().is().text(equalToIgnoringCase("date/time:"));
}
[FindBy(Css = "#party-time")]
public IDateTimeSelector PartyTime { get; set; }
[Test]
public void SetPartyTimeTest()
{
TestSite.Html5Page.PartyTime.Format = "yyyy-MM-ddTHH:mm";
TestSite.Html5Page.PartyTime.SetDateTime(_dateTime);
var setValue = TestSite.Html5Page.PartyTime.GetDateTime();
Assert.AreEqual(setValue, _dateTime);
}
<div>
<label for="party-time">Date/time:</label>
<input type="datetime-local" id="party-time" value="2018-06-12T19:30" min="2018-05-07T00:00" max="2018-06-14T00:00">
</div>
Type DateTime-Local test examples in Java
Type DateTime-Local test examples in C#
There following classes represent this type of element:
- C#: JDI.Light.Elements.Common.DateTimeSelector
- Java: com.epam.jdi.light.ui.html.common.DateTimeSelector
Here is the list of some methods available in C#:
Method | Description | Return Type |
---|---|---|
AssertThat() | Assert action of DateTimeSelector | DateTimeSelectorAssert |
GetDateTime() | Returns the set date or time | DateTime |
Is() | Assert action of DateTimeSelector | DateTimeSelectorAssert |
Max() | Gets attribute with name 'max' | string |
Min() | Gets attribute with name 'min' | string |
SetDateTime(string/DateTime value) | Sets a date or time | void |
Value() | Returns value attribute | string |
And here are some of the methods available in Java:
Method | Description | Return Type |
---|---|---|
value() | Returns the set date or time | String |
max() | Gets attribute with name max | String |
min() | Gets attribute with name min | String |
setDateTime(String) | Sets a date or time | void |
setValue(String) | Sets a date or time | void |
getValue() | Returns the set date or time | String |
is() | Assertion | DateTimeAssert |
In the following sections there are examples of different implementations of such fields.
1.1.6 FileInput
FileInput — A graphical control element that allows user to upload documents to web site.
//@FindBy(id = "avatar")
@UI("#avatar")
public static FileInput avatar;
@Test
public void uploadTest() {
avatar.uploadFile(mergePath(COMMON.projectPath,"/src/test/resources/functional.xml"));
avatar.is().text(containsString("functional.xml"));
assertTrue(avatar.getText().contains("functional.xml"));
assertTrue(avatar.getValue().contains("functional.xml"));
}
@Test
public void labelTest() {
assertEquals(avatar.labelText(), "Profile picture:");
avatar.label().is().text(containsString("picture"));
}
[Test]
public void FileInputTest()
{
FileInput.SelectFile(CreateFile(filename));
}
[Test]
public void DisabledUploadTest()
{
Sleep(2000);
try
{
TestSite.Html5Page.DisabledFileInput.SelectFile(CreateFile(_fileName));
}
catch (Exception e)
{
Logger.Exception(e);
}
Sleep(2000);
TestSite.Html5Page.DisabledFileInput.Is.Text(EqualTo(""));
}
[Test]
public void LabelTest()
{
AreEqual(TestSite.Html5Page.FileInput.LabelText(), "Profile picture:");
TestSite.Html5Page.FileInput.Label().Is.Text(ContainsString("picture"));
}
[Test]
public void BaseValidationTest()
{
BaseElementValidation(TestSite.Html5Page.FileInput);
}
FileInput element is located in JDI Light in:
- Java: com.epam.jdi.light.ui.html.elements.common.FileInput
- C#: JDI.Light.Elements.Composite.FileInput
Here is an example with HTML code provided:
<div class="html-left">
<label for="avatar">Profile picture:</label>
<input type="file" id="avatar" accept="image/png, image/jpeg">
</div>
Available method in Java JDI Light:
Method | Description | Return Type |
---|---|---|
uploadFile(String) | set file path to input | void |
uploadFileRobot(String, long) | set file path to input | void |
setValue(String) | set file path to input | void |
text() | returns text of input field | String |
getValue() | Get file name | String |
is() | property that returns object for work with assertions | TextAssert |
Available method in C# JDI Light:
Method | Description | Return Type |
---|---|---|
CleanupDownloads() | Cleans the directory | void |
HasSize(Matcher |
Checks that a file has a particular size according to the matcher | FileAssert |
IsDownloaded() | Checks whether a file is downloaded | FileAssert |
SelectFile(string filepath) | Select file to upload | void |
Text(Matcher |
Checks whether an occurrence of a text is contained within a text file | FileAssert |
Test examples in Java
Test examples in C#
BDD Steps example
1.1.7 Icon
Icon — Is a simple element type that represents icons and graphic images.
@UI("#jdi-logo")
// same as FindBy(css = "#jdi-logo")
public static Icon userIcon;
@Test
public void loginWithUserToLightLocatorFormTest() {
userIcon.click();
loginAs("#login-form", DEFAULT_USER);
homePage.checkOpened();
}
[FindBy(Css = "#jdi-logo")]
public IIcon Logo
;
[Test]
public void GetSourceTest()
{
Jdi.Assert.AreEquals(LogoImage.GetSource(), Src);
}
[Test]
public void GetTipTest()
{
Jdi.Assert.AreEquals(LogoImage.GetAlt(), Alt);
}
<label for="jdi-logo">JDI Logo:</label>
<img src="/jdi-light/images/jdi-logo.jpg" id="jdi-logo" alt="Jdi Logo 2"
width="101" height="100" onclick="alert('JDI Logo');">
Icon is represented by Image class:
Icon in JDI is a descendant of Image. It inherits all Image's methods and serves as its wrapper. Here are Java methods for Icon, inherited from Image interface:
Method | Description | Return Type |
---|---|---|
alt() | get value of alt attribute | String |
click() | click on the image | void |
height() | get value of height attribute | int |
is() | method for building assertions | ImageAssert |
src() | get value of src attribute | String |
width() | get value of width attribute | int |
fileName() | Get image source path | String |
getValue() | Get image source path | String |
Here is a list of available methods in C#:
Method | Description | Return Type |
---|---|---|
Alt | get value of alt attribute | string |
AssertThat() | method for building assertions | ImageAssert |
Click() | click on the image | void |
Height | get value of height attribute | string |
Is() | method for building assertions | ImageAssert |
Src | get value of src attribute | string |
Width | get value of width attribute | string |
1.1.8 Image
Image — Is a simple element type that represents graphic images.
@UI("#jdi-logo")
// same as FindBy(css = "#jdi-logo")
public static Image jdiLogo;
@Test
public void isValidationTest() {
WebPage.refresh();
jdiLogo.is().src(containsString("jdi-logo.jpg"));
jdiLogo.is().alt(is("Jdi Logo 2"));
jdiLogo.assertThat().height(is(100));
jdiLogo.assertThat().width(is(101));
}
@Test
public void getSrcTest() {
assertEquals(jdiLogo.src(), text);
}
[FindBy(Css = "#jdi-logo")]
public IImage LogoImage;
[Test]
public void GetSourceTest()
{
Jdi.Assert.AreEquals(LogoImage.GetSource(), Src);
}
[Test]
public void GetTipTest()
{
Jdi.Assert.AreEquals(LogoImage.GetAlt(), Alt);
}
<label for="jdi-logo">JDI Logo:</label>
<img src="/jdi-light/images/jdi-logo.jpg" id="jdi-logo" alt="Jdi Logo 2"
width="101" height="100" onclick="alert('JDI Logo');">
Images are represented by the following classes in Java and C#:
- Java: com.epam.jdi.light.ui.html.elements.common.Image
- C#: JDI.Light.Elements.Common.Image
Here is a list of available methods in Java:
Method | Description | Return Type |
---|---|---|
alt() | get value of alt attribute | String |
click() | click on the image | void |
height() | get value of height attribute | int |
is() | method for building assertions | ImageAssert |
src() | get value of src attribute | String |
width() | get value of width attribute | int |
fileName() | Get image source path | String |
getValue() | Get image source path | String |
Here is a list of available methods in C#:
Method | Description | Return Type |
---|---|---|
Alt | get value of alt attribute | string |
AssertThat() | method for building assertions | ImageAssert |
Click() | click on the image | void |
Height | get value of height attribute | string |
Is() | method for building assertions | ImageAssert |
Src | get value of src attribute | string |
Width | get value of width attribute | string |
1.1.9 Link
//@FindBy(css = "[ui=github-link]")
@UI("[ui=github-link]")
public static Link githubLink;
@Test
public void getTextTest() {
assertEquals(githubLink.getText(), text);
}
@Test
public void getRefTest() {
assertEquals(githubLink.ref(), "https://github.com/jdi-testing");
}
[FindBy(Css = "[ui = github-link]")]
public ILink GithubLink;
[Test]
public void GetTextTest()
{
Assert.AreEqual(GithubLink.GetText(), Text);
}
[Test]
public void GetUrlTest()
{
Assert.AreEqual(GithubLink.Url(), "https://epam.github.io/JDI/html5.html");
}
Link — A graphical control element that allows user to link from one page to other web pages, files, locations within the same page, email addresses, or any other URL.
Link are represented by the following class:
- Java: com.epam.jdi.light.ui.html.elements.common.Link
- C#: JDI.Light.Elements.Common.Link
<a ui="github-link" href="https://github.com/jdi-testing" alt="Github JDI Link">Github JDI</a>
Here is the list of available methods in Java:
Method | Description | Return Type |
---|---|---|
alt() | Returns the alternate text | String |
click() | Follow the link | void |
getValue() | Returns the link text | String |
is() | Returns object for work with assertions | LinkAssert |
ref() | Returns the reference | String |
url() | Returns the URL | URL |
Test examples in Java
BDD Steps example
Here is the list of available methods in C#:
Method | Description | Return Type |
---|---|---|
Alt() | Returns the alternate text | string |
AssertThat() | Returns object for work with assertions | LinkAssert |
Click() | Follow the link | void |
GetText() | Returns the link text | string |
Is() | Returns object for work with assertions | LinkAssert |
Ref() | Returns the reference | string |
Url() | Returns the URL | string |
Test examples in C#
BDD Steps example
1.1.10 Menu
Menu — A list of links which lead to different pages or sections of website.
Menu element is located in JDI Light in:
- Java: _com.epam.jdi.light.ui.html.
- C#: JDI.Light.Elements.Composite.Menu
Here is an example with provided HTML code:
@UI(".sidebar-menu [ui=label]")
//@FindBy(css = ".sidebar-menu [ui=label]")
public static Menu leftMenu;
@Test
public void setNullValueTest() {
String optionName = null;
String selectedValue = leftMenu.selected();
leftMenu.select(optionName);
leftMenu.has().text(selectedValue);
}
@Test
public void selectTest() {
leftMenu.select("Contact form");
contactFormPage.checkOpened();
}
[FindBy(Css = "ul.sidebar-menu")]
public Menu SidebarMenu;
[Test]
public void SelectEnumTest()
{
TestSite.SidebarMenu.Select(Navigation.MetalsColors);
TestSite.MetalsColorsPage.CheckOpened();
}
[Test]
public void IsValidationTest()
{
TestSite.SidebarMenu.Select("Elements packs", "HTML 5");
TestSite.SidebarMenu.Is.Selected("HTML 5")
}
[Test]
public void AssertValidationTest()
{
TestSite.SidebarMenu.Select("Elements packs", "HTML 5");
TestSite.SidebarMenu.AssertThat.Selected("HTML 5");
}
<ul class="sidebar-menu left">
<li ui="label" index="1">
<a href="index.html">
<span>Home</span>
</a>
</li>
<li ui="label" index="2">
<a href="contacts.html">
<span>Contact form</span>
</a>
</li>
<li class="menu-title" index="3">
<a ui="label">
<span>Service</span>
<div class="fa fa-caret-down arrow"/>
</a>
<ul class="sub hide-menu">
<li ui="label" index="1">
<a href="support.html">
<p>
<span>Support</span>
</p>
</a>
</li>
<li ui="label" index="2">
<a href="dates.html">
<span>Dates</span>
</a>
</li>
<li ui="label" index="3">
<a href="complex-table.html">
<span>Complex Table </span>
</a>
</li>
<li ui="label" index="4">
<a href="simple-table.html">
<span>Simple Table</span>
</a>
</li>
<li ui="label" index="5">
<a href="search.html">
<span>Search</span>
</a>
</li>
<li ui="label" index="6">
<a href="user-table.html">
<span>User Table</span>
</a>
</li>
<li ui="label" index="7">
<a href="table-pages.html">
<span>Table with pages</span>
</a>
</li>
<li ui="label" index="8">
<a href="different-elements.html">
<span>Different elements</span>
</a>
</li>
<li ui="label" index="9">
<a href="performance.html">
<span>Performance</span>
</a>
</li>
</ul>
</li>
<li ui="label" index="4">
<a href="metals-colors.html">
<span>Metals & Colors</span>
</a>
</li>
<li class="menu-title active" index="5">
<a ui="label">
<span>Elements packs</span>
<div class="fa fa-caret-down arrow"/>
</a>
<ul class="sub">
<li ui="label" index="1" class="active">
<a href="html5.html">
<span>HTML 5</span>
</a>
</li>
<li ui="label" index="2">
<a href="mobile-html5.html">
<span>Mobile and HTML 5</span>
</a>
</li>
<li ui="label" index="3">
<a href="bootstrap-new.html">
<span>Bootstrap</span>
</a>
</li>
<li ui="label" index="4">
<a href="bootstrap_form.html">
<span>Bootstrap form</span>
</a>
</li>
<li ui="label" index="5">
<a href="bootstrap_forms.html">
<span>Bootstrap forms</span>
</a>
</li>
<li ui="label" index="6">
<a href="react-ant.html">
<span>React Ant</span>
</a>
</li>
<li ui="label" index="7">
<a href="angular.html">
<span>Angular</span>
</a>
</li>
<li ui="label" index="8">
<a href="material">
<span>Material UI</span>
</a>
</li>
<li ui="label" index="9">
<a href="vuetify">
<span>Vuetify</span>
</a>
</li>
</ul>
</li>
</ul>
Available methods in Java JDI Light:
Method | Description | Return Type |
---|---|---|
selected() | Returns selected menu item | String |
selected(String/int) | Check is item seleceted | boolean |
values() | Returns selected menu item and subitems | List |
values(TextTypes) | Returns selected menu item and subitems | List |
select(String/String.../int/int.../TEnum/TEnum...) | Select menu element | void |
listEnabled() | Returns all enable menu options | List |
listDisabled() | Returns all disabled menu options | List |
attrs() | Gets all element attributes | List |
getText() | Gets button text | String |
getValue() | Returns the value | String |
setValue(String) | Sets the value | void |
isDisplayed() | Check that menu is displayed | boolean |
isHidden() | Check that menu is hidden | boolean |
size() | Get menu size | int |
isEmpty() | Check that '{name}' menu is empty | boolean |
isNotEmpty() | Check that '{name}' menu is not empty | boolean |
Available methods in C# JDI Light:
Method | Description | Return Type |
---|---|---|
AssertThat | Get select assert | MenuSelectAssert |
Is | Get select assert | MenuSelectAssert |
List |
Gets values of all options | List |
string Selected() | Returns selected menu item | string |
void HoverAndClick(string[]) | Hovers and clicks menu item and subitems | void |
void HoverAndClick(string) | Hovers and clicks menu item | void |
void Select(string[]) | Select menu element and subelements by string values | void |
void Select(string) | Select menu element | void |
void Select(int[]) | Select menu element and subelements by index | void |
void Select(int) | Select menu element and subelements by index | void |
void Select(Enum[]) | Select menu element and subelements by getting values of enum | void |
void Select(Enum) | Select menu element | void |
1.1.11 NumberSelector
NumberSelector — A graphical control element that allows the user to enter a number.
NumberSelector is represented by the following classes:
- Java: com.epam.jdi.light.ui.html.common.NumberSelector
- C#: JDI.Light.Elements.Common.NumberSelector
@UI("#height")
//@FindBy(css = "#height")
public static NumberSelector height;
@Test
public void minTest() {
assertEquals(height.min(), 0.3);
}
@Test
public void maxTest() {
assertEquals(height.max(), 2.5);
}
@Test
public void setNumberTest() {
height.setNumber("1.4");
assertEquals(height.value(), "1.4");
}
@Test
public void stepTest() {
assertEquals(height.step(), 0.2);
}
[FindBy(Css = "#height")]
public INumberSelector numberSelector;
[Test]
public void GetNumberTest()
{
Jdi.Assert.AreEquals(number, numberSelector.Value());
}
<label for="height">Height (metres):</label>
<input type="number" id="height" min="0.3" max="2.5" step="0.2"
placeholder="20 cm increments. Range [0.3,2.5]">
Here is the list of available methods in Java:
Method | Description | Return Type |
---|---|---|
is() | Returns object for work with assertions | NumberAssert |
max() | Returns the max value | double |
min() | Returns the min value | double |
value() | Returns the value | String |
setNumber(String) | Sets the value | void |
setValue(String) | Sets the value | void |
getValue() | Returns the value | String |
step() | Returns the step value | double |
Here is the list of available methods in C#:
Method | Description | Return Type |
---|---|---|
AssertThat() | Returns object for work with assertions | NumberAssert |
Is() | Returns object for work with assertions | NumberAssert |
Max | Returns the max value | double |
Min | Returns the min value | double |
Placeholder | Returns the placeholder text | String |
SetNumber(double) | Sets the value | void |
Step | Returns the step value | double |
Value | Returns the value | double |
1.1.12 ProgressBar
Progress Bar — Element for displaying an indicator showing the completion progress of a task.
ProgressBar is located in the following class:
- Java: com.epam.jdi.light.ui.html.elements.common.ProgressBar
- C#: JDI.Light.Elements.Common.ProgressBar
@UI("#progress")
// @FindBy(id = "progress")
public static ProgressBar progress;
@Test
public void getLabelTextTest() {
assertEquals(progress.labelText(), "File progress");
}
@Test
public void getValueTest() {
assertEquals(progress.value(), 70);
}
@Test
public void maxTest() {
assertEquals(progress.max(), 100);
}
[FindBy(Css = "#progress")]
public ProgressBar Progress;
[Test]
public void GetValueTest()
{
Assert.AreEqual(Progress.Value(), "70");
}
[Test]
public void MaxTest()
{
Assert.AreEqual(Progress.Max(), "100");
}
Here is an example with provided HTML code:
<label for="progress">File progress</label>
<progress id="progress" max="100" value="70"></progress>
Available methods in Java JDI Light:
Method | Description | Return Type |
---|---|---|
getValue() | Get current progress value | String |
is() | Various assert actions for Progress bar | ProgressAssert |
max() | Get progressbar maximum possible value | int |
value() | Get current progress value | int |
Test examples in Java
BDD Steps example
Available methods in C# JDI Light:
Method | Description | Return Type |
---|---|---|
AssertThat() | Various assert actions for Progress bar | ProgressAssert |
Is() | Various assert actions for Progress bar | ProgressAssert |
Max() | Get progressbar maximum possible value | string |
Value() | Get current progress value | string |
Test examples in C#
BDD Steps example
1.1.13 Range
@UI("#volume") //@FindBy(id = "volume")
public static Range volume;
double defaultVolume = 90;
@Test
public void setupValueTest() {
volume.setupValue(10);
assertEquals(volume.value(), 10.0);
defaultRange.setupValue(65);
assertEquals(defaultRange.value(), 65.0);
minMaxRange.setupValue(3);
assertEquals(minMaxRange.value(), 3.0);
fractionalRange.setupValue(3.5);
assertEquals(fractionalRange.value(), 3.5);
}
@Test
public void stepTest() {
assertEquals(volume.step(), 5.0);
assertEquals(defaultRange.step(), 1.0);
assertEquals(minMaxRange.step(), 2.0);
assertEquals(fractionalRange.step(), 0.5);
}
@Test
public void maxTest() {
assertEquals(volume.max(), 100.0);
assertEquals(defaultRange.max(), 100.0);
assertEquals(minMaxRange.max(), 10.0);
assertEquals(fractionalRange.max(), 7.0);
}
[FindBy(Css = "#volume")]
public IRange Volume { get; set; }
[Test]
public void GetValueTest()
{
Assert.AreEqual(TestSite.Html5Page.DisabledRange.Value(), 50);
}
[Test]
public void MinTest()
{
Assert.AreEqual(TestSite.Html5Page.Volume.Min(), 10);
}
[Test]
public void MaxTest()
{
Assert.AreEqual(TestSite.Html5Page.Volume.Max(), 100);
}
[Test]
public void StepTest()
{
Assert.AreEqual(TestSite.Html5Page.Volume.Step(), 5);
}
[Test]
public void SetRangeTest()
{
TestSite.Html5Page.Volume.SetValue(10);
Assert.AreEqual(TestSite.Html5Page.Volume.Value(), 10);
}
[Test]
public void RangeTest()
{
TestSite.Html5Page.Volume.SetValue("30");
Assert.AreEqual(TestSite.Html5Page.Volume.GetValue(), "30");
}
Range — A graphical control element that allows the user to set the value within a range.
<label for="volume">Volume</label>
<input type="text" disabled="" id="volume-value" class="range-value" value="90">
<br>
<span>10</span>
<input type="range" id="volume" min="10" max="100" value="90" step="5" class="range" list="volume-list" oninput="show_val(this)" onchange="show_val(this)">
<span>100</span>
<datalist id="volume-list">
<option value="0">
</option>
<option value="20">
</option>
<option value="40">
</option>
<option value="60">
</option>
<option value="80">
</option>
<option value="100">
</option>
</datalist>
Range is represented by the following class:
- Java: com.epam.jdi.light.ui.html.elements.common.Range
- C#: JDI.Light.Elements.Common.Range
Here is a list of available methods in C#:
Method | Description | Return Type |
---|---|---|
AssertThat() | Returns object for work with assertions | RangeAssert |
GetValue() | Returns the value | String |
Is() | Returns object for work with assertions | RangeAssert |
Max() | Returns the max value | Double |
Min() | Returns the min value | Double |
SetValue(string value) | Sets the value | void |
SetValue(double value) | Sets the value | void |
Step() | Returns the step value | Double |
Value() | Returns the value | Double |
Test examples in C#
BDD Steps example
And here are methods available in Java:
Method | Description | Return Type |
---|---|---|
getValue() | Gets the value | String |
is() | Returns object for work with assertions | RangeAssert |
max() | Returns the max value | double |
min() | Returns the min value | double |
setupValue(double volume) | Sets the value | void |
setValue(String volume) | Sets the value | void |
step() | Returns the step value | double |
value() | Returns the value | double |
Test examples in Java
BDD Steps example
1.1.14 Text
Text — Is a combination of letters and text symbols. Most testing activities involve working with text: text is typed into login fields, buttons get located by their texts, actual text gets compared to expected.
@UI("[ui=jdi-text]")
//@FindBy(css = "[ui=jdi-text]")
public static Text jdiText;
String text = "Powerful Framework for UI Tests Automation. Suitable for any UI project: Web(Html5, Angular, React...), Mobile(Android IOs), Desktop(Win app) etc.";
@Test
public void getTextTest() {
assertEquals(jdiText.getText(), text);
}
@Test
public void getValueTest() {
assertEquals(jdiText.getValue(), text);
}
@Test
public void isValidationTest() {
jdiText.is().enabled();
jdiText.is().text(is(text));
jdiText.is().text(containsString("Powerful Framework for UI"));
}
[FindBy(Css = ".main-txt")]
public TextElement Text;
[Test]
public void GetTextTest()
{
Jdi.Assert.AreEquals(TestSite.HomePage.Text.Value, _expectedText);
}
[Test]
public void GetValueTest()
{
Jdi.Assert.AreEquals(TestSite.HomePage.Text.Value, _expectedText);
}
[Test]
public void SetAttributeTest()
{
var attributeName = "testAttr";
var value = "testValue";
TestSite.HomePage.Text.SetAttribute(attributeName, value);
Jdi.Assert.AreEquals(TestSite.HomePage.Text.GetAttribute(attributeName), value);
}
[Test]
public void WaitSuspendButtonTextTest()
{
TestSite.Html5Page.Open();
TestSite.Html5Page.GhostButton.Is.Displayed();
TestSite.Html5Page.GhostButton.Is.Text(EqualTo("GHOST BUTTON"));
Thread.Sleep(3000);
TestSite.Html5Page.SuspendButton.Is.Displayed();
TestSite.Html5Page.SuspendButton.Is.Text(EqualTo("SUSPEND BUTTON"));
}
[Test]
public void IsValidationTest()
{
TestSite.HomePage.Text.Is.Enabled();
TestSite.HomePage.Text.Is.Text(EqualTo(_expectedText));
TestSite.HomePage.Text.Is.Text(ContainsString(_contains));
}
[Test]
public void AssertValidationTest()
{
TestSite.HomePage.Text.AssertThat.Text(EqualTo(_expectedText));
}
[Test]
public void BaseValidationTest()
{
TestSite.Html5Page.Open();
BaseElementValidation(TestSite.Html5Page.JdiText);
}
<p ui="jdi-text">Powerful Framework for UI Tests Automation. Suitable for any UI project:
Web(Html5, Angular, React...), Mobile(Android IOs), Desktop(Win app) etc.</p>
Text is represented by the following class:
- C#: JDI.Light.Elements.Common.TextElement
- Java: com.epam.jdi.light.ui.html.elements.common.Text
Here is a list of available methods in C#:
Method | Description | Return Type |
---|---|---|
AssertThat | Gets text assert | TextAssert |
Is | Gets text assert | TextAssert |
GetText() | returns text | String |
GetValue() | returns text | String |
WaitFor | Gets text assert | TextAssert |
And here are methods available in Java:
Method | Description | Return Type |
---|---|---|
getValue() | Get current value | String |
is() | Various assert actions for Text | TextAssert |
1.1.15 TextField
@UI("#your-name") //@FindBy(css = "#your-name")
public static TextField yourName;
String defaultText = "TextField";
@Test
public void inputTest() {
yourName.input("New text");
assertEquals(yourName.getText(), "New text");
}
@Test
public void sendKeysTest() {
yourName.sendKeys("Test");
assertEquals(yourName.getValue(), defaultText +"Test");
}
@Test
public void clearTest() {
yourName.clear();
assertEquals(yourName.getText(), "");
}
[FindBy(Id = "name")]
public ITextField NameField;
[Test]
public void InputTest()
{
TestSite.ContactFormPage.NameField.Input(ToAddText);
Jdi.Assert.AreEquals(TestSite.ContactFormPage.NameField.Value, ToAddText);
}
[Test]
public void SendKeyTest()
{
TestSite.ContactFormPage.NameField.SendKeys(ToAddText);
Jdi.Assert.AreEquals(TestSite.ContactFormPage.NameField.Value, _defaultText + ToAddText);
}
[Test]
public void ClearTest()
{
TestSite.ContactFormPage.NameField.Clear();
Jdi.Assert.AreEquals(TestSite.ContactFormPage.NameField.Value, "");
}
TextField — Is a simple element type that allows users to fill in text fields.
<label for="name">Your name:</label>
<input type="text" id="name" placeholder="Input name">
<label for="disabled-name">Surname:</label>
<input type="text" id="disabled-name" placeholder="Iovlev" disabled="">
Text fields are represented by the following classes in Java and C#:
- C#: JDI.Light.Elements.Common.TextField
- Java: com.epam.jdi.light.ui.html.elements.common.TextField
Here is a list of available methods and properties in C#:
Method / Property | Description | Return Type |
---|---|---|
AssertThat | property that returns object for work with assertions | TextAssert |
Clear() | clears the text field | void |
Focus() | places cursor within the text field | void |
GetText() | returns text from the text field | String |
GetValue() | returns text from the text field | String |
Input(string text) | sets new text | void |
Is | property that returns object for work with assertions | TextAssert |
Placeholder | returns value of the placeholder attribute | String |
SendKeys(string value) | adds text to the field | void |
SetText(String value) | sets new text | void |
Test examples in C#
BDD Steps example
And here are methods available in Java:
Method | Description | Return Type |
---|---|---|
getText() | returns text from the text field | String |
getValue() | returns text from the text field | String |
setValue(String) | sets new value | void |
is() | returns object for work with assertions | TextAssert |
Test examples in Java
BDD Steps example
1.1.16 TextArea
TextArea — Is a simple element type that allows users to fill in text areas (unlike TextField, multiple lines of text are allowed).
@UI("#text-area")
// same as FindBy(css = "#text-area")
public static TextArea textArea;
String defaultText = "TextArea";
@Test
public void addNewLineTest() {
textArea.setLines("line1", "line2");
textArea.addNewLine("line3");
assertEquals(textArea.getText(), "line1\nline2\nline3");
}
@Test
public void isValidationTest() {
textArea.is().enabled();
textArea.setText(defaultText);
textArea.is().text(is(defaultText));
textArea.is().text(containsString("Area"));
disabledTextArea.is().disabled();
}
@Test
public void rowsTest() {
assertEquals(textArea.rows(), 3);
assertEquals(textArea.cols(), 33);
assertEquals(textArea.minlength(), 10);
assertEquals(textArea.maxlength(), 200);
textArea.is().rowsCount(is(3));
textArea.is().colsCount(is(33));
textArea.is().minlength(is(10));
textArea.is().maxlength(is(200));
}
[FindBy(Css = "#text-area")]
public ITextArea TextArea;
[Test]
public void GetTextTest()
{
TextArea.SetText(Text);
Assert.AreEqual(TextArea.GetText(), "Text");
}
[Test]
public void AddNewLineTest()
{
TextArea.SetText("line1", "line2");
TextArea.AddNewLine("line3");
Assert.CollectionEquals(TextArea.GetLines(), new[] { "line1", "line2", "line3" });
}
<label for="text-area">Text example:</label>
<textarea id="text-area" rows="3" cols="33" maxlength="200" minlength="10" required="" wrap="hard" placeholder="Input huge text">Textarea with sizing and wrap attribute (try values of hard, soft, and off to see how it affects wrapping). The maximum number of characters is constrained to 200 by the maxlength attribute.
</textarea>
<br>
<textarea disabled="" placeholder="Disabled area"/>
Text areas are represented by the following classes:
- Java: com.epam.jdi.light.ui.html.elements.common.TextArea
- C#: JDI.Light.Elements.Common.TextArea
In Java TextArea is a descendant of UIBaseElement with HasLabel, SetValue, HasPlaceholder, IsInput interfaces parameterized with TextAreaAssert and inherits its methods. But TextArea also has methods of its own.
In C# TextArea is a descendant of TextField and inherits its methods. But TextArea also has methods of its own.
Here is a list of available methods in Java:
Method | Description | Return Type |
---|---|---|
addNewLine(String) | add line to the already existing | void |
cols() | returns value of cols attribute | int |
getLines() | returns lines (text) from the text area | List |
getValue() | calls getText() method | String |
getText() | returns value of attribute "value" | String |
is() | returns object for work with assertions | TextAreaAssert |
maxlength() | returns value of maxlength attribute | int |
minlength() | returns value of minlength attribute | int |
rows() | returns value of rows attribute | int |
setLines(String...) | sets lines (text) | void |
setValue(String) | setting value | void |
Here is a list of available methods in C#:
Method | Description | Return Type |
---|---|---|
AddNewLine(string line) | add line to the already existing ones | void |
AssertThat() | returns object for work with assertions | TextAreaAssert |
Cols() | returns value of cols attribute | int |
GetLines() | returns lines (text) from the text area | string[] |
Is() | returns object for work with assertions | TextAreaAssert |
Maxlength() | returns value of maxlength attribute | int |
Minlength() | returns value of minlength attribute | int |
Rows() | returns value of rows attribute | int |
SetLines(string[] lines) | sets lines (text) | void |
1.1.17 Title
Title — A graphical control element representing document title, which is displayed in the title bar of the browser or tab page.
Title is represented by the following class:
- Java: com.epam.jdi.light.elements.common.Label
- C#: _JDI.Light.Elements.Common.Title
@UI("[ui=jdi-title]")
//@FindBy(css = "[ui=jdi-title]")
public static Label jdiTitle;
@Test
public void getTextTest() {
assertEquals(jdiTitle.getText(), text);
}
@Test
public void getValueTest() {
assertEquals(jdiTitle.getValue(), text);
}
@Test
public void clickTest() {
jdiTitle.click();
assertEquals(getAlertText(), "JDI Title");
acceptAlert();
}
@Test
public void isValidationTest() {
jdiTitle.is().enabled();
jdiTitle.is().text(is(text));
jdiTitle.is().text(equalTo(text));
jdiTitle.is().text(equalToIgnoringCase("jdi TESTING platform"));
}
[FindBy(Css = "[ui=jdi-title]")]
public Title JdiTitle;
[Test]
public void GetTextTest()
{
Assert.AreEqual(JdiTitle.GetText(), "Title text");
}
[Test]
public void ClickTest()
{
JdiTitle.ClickTitle();
}
[Test]
public void IsValidationTest()
{
TestSite.Html5Page.JdiTitle.Is.Enabled();
TestSite.Html5Page.JdiTitle.Is.Text(EqualTo(_text));
TestSite.Html5Page.JdiTitle.Is.Text(Is(_text));
TestSite.Html5Page.JdiTitle.Is.Text(EqualToIgnoringCaseMatcher.EqualTo("jdi TESTING platform"));
}
[Test]
public void AssertValidationTest()
{
TestSite.Html5Page.JdiTitle.AssertThat.Text(EqualTo(_text));
}
[Test]
public void BaseValidationTest()
{
BaseElementValidation(TestSite.Html5Page.JdiTitle);
}
<h1 ui="jdi-title" onclick="alert('JDI Title');">JDI Testing platform</h1>
Here is the list of methods available in C# JDI Light:
Method | Description | Return Type |
---|---|---|
getValue() | Returns | String |
Is | Gets Title's assert | TextAssert |
Here is the list of available methods in Java JDI Light:
Method | Description | Return Type |
---|---|---|
AssertThat() | Gets Title's assert | TitleAssert |
click() | Click title | void |
getText() | Returns title text | String |
Is() | Gets Title's assert | TitleAssert |
1.2 HTML5 Complex elements
1.2.1 RadioButtons
RadioButtons — Interface element that allows user to select a single option from a predefined group.
Radio buttons are represented by the following class:
- Java: com.epam.jdi.light.ui.html.elements.complex.RadioButtons
- C#: JDI.Light.Elements.Complex.RadioButtons
Consider an example where each radio button has a particular color, described by the following HTML code:
//@FindBy(name = "colors")
@UI("[name=colors]")
public static RadioButtons colors;
@Test
public void selectTest() {
colors.select("Green");
assertEquals(colors.getValue(), "Green");
colorsNoLocator.select("Blue");
colorsNoLocator.is().selected("Blue");
}
@Test
public void valuesTest() {
assertEquals(colors.values(), asList("Red", "Green", "Blue", "Yellow"));
}
@Test
public void isValidationTest() {
colors.is().selected("Blue");
colors.is().selected(Blue);
colors.is().values(hasItem("Yellow"));
colors.is().disabled(hasItem("Yellow"));
colors.is().enabled(not(hasItem("Yellow")));
colors.is().enabled(hasItems("Green", "Blue"));
colorsNoLocator.is().selected("Blue");
colorsNoLocator.is().selected(Blue);
}
@Test
public void assertValidationTest() {
colors.assertThat().values(contains("Red", "Green", "Blue", "Yellow"));
}
[FindBy(Css = "#colors")]
public IRadioButtons MyRadioButtons;
[Test]
public void SelectRadioButton()
{
MyRadioButtons.Select("some value");
}
[Test]
public void SelectRadioButtonByIndex()
{
MyRadioButtons.Select(1);
}
[Test]
public void GetSelected()
{
var selected = MyRadioButtons.GetSelected();
Assert.AreEqual(selected, "some value");
MyRadioButtons.Is().Selected(Is.EqualTo("some value"));
MyRadioButtons.AssertThat().Selected(Is.EqualTo("some value"));
}
<input type="radio" id="red" name="colors">
<label for="red">Red</label> <br>
<input type="radio" id="green" name="colors" checked="">
<label for="green">Green</label> <br>
<input type="radio" id="blue" name="colors">
<label for="blue">Blue</label> <br>
<input type="radio" id="yellow" name="colors" disabled="">
<label for="yellow">Yellow</label>
Here is the list of some available methods in Java:
Method | Description | Return Type |
---|---|---|
assertThat() | Returns object for work with assertions | RadioButtonAssert |
is() | Returns object for work with assertions | RadioButtonAssert |
select(String/int/Enum) | Select radiobutton by value/index | void |
selected() | Get selected radiobutton value | string |
values() | Returns list of values | List |
Here is the list of some available methods in C#:
Method | Description | Return Type |
---|---|---|
AssertThat() | Returns object for work with assertions | RadioButtonAssert |
Is() | Returns object for work with assertions | RadioButtonAssert |
Select(string/int) | Select radiobutton by value/index | void |
Selected() | Get selected radiobutton value | string |
Values() | Returns list of values | List |
1.2.2 Table
Table — A complex element that consists of a header, a body (at least one row and one column) and a footer. This element allows several read-only interactions.
Tables are represented by the following classes in Java and C#:
- Java: com.epam.jdi.light.elements.complex.table.Table
- C#: JDI.Light.Elements.Complex.Table
@UI("#users-table")
//@FindBy(id = "users-table")
@JTable(
root = "#users-table",
row = "//tr[%s]/td",
column = "//tr/td[%s]",
cell = "//tr[{1}]/td[{0}]",
allCells = "td",
headers = "th",
header = {"Name", "Phone", "Email", "City"},
rowHeader = "Name",
size = 4
)
public static Table usersSetup;
@Test
public void tableDataTest() {
assertEquals(users.row(ELEMENT.startIndex + 1).asData(UserInfo.class),
GRADY_BROCK);
}
@Test
public void tableEntityTest() {
UserRow user = users.row(ELEMENT.startIndex + 1).asLine(UserRow.class);
user.name.click();
Alerts.validateAndAcceptAlert(containsString("Brock"));
user.city.click();
Alerts.validateAndAcceptAlert(is("Alcobendas"));
}
[Test]
public void HugeTableSearchByColumnNamesContainValuesTest()
{
PerformancePage.UsersTable.AssertThat().HasRowWithValues(
ContainsValue("Meyer", InColumn("Name")),
ContainsValue("co.uk", InColumn("Email")));
var row = PerformancePage.UsersTable.Row(
ContainsValue("Meyer", InColumn("Name")),
ContainsValue("co.uk", InColumn("Email")));
Assert.AreEqual(
"Brian Meyer;(016977) 0358;
mollis.nec@seddictumeleifend.co.uk;Houston",
row.GetValue());
}
[Test]
public void HugeTableSearchByColumnNumbersContainValuesTest()
{
PerformancePage.UsersTable.AssertThat().HasRowWithValues(
ContainsValue("Burke", InColumn(1)),
ContainsValue("ut.edu", InColumn(3)));
var row = PerformancePage.UsersTable.Row(1);
PerformancePage.UsersTable.Is().HasRowWithValues(
HasValue("Brian Meyer", InColumn("Name")),
HasValue("(016977) 0358", InColumn("Phone")),
HasValue("mollis.nec@seddictumeleifend.co.uk",
InColumn("Email")),
HasValue("Houston", InColumn("City")));
}
[Test]
public void HugeTableSearchByColumnNamesHasValuesTest()
{
PerformancePage.UsersTable.AssertThat().HasRowWithValues(
HasValue("Brian Meyer", InColumn("Name")),
HasValue("mollis.nec@seddictumeleifend.co.uk",
InColumn("Email")));
var row = PerformancePage.UsersTable.Row(
HasValue("Brian Meyer", InColumn("Name")),
HasValue("mollis.nec@seddictumeleifend.co.uk",
InColumn("Email")));
Assert.AreEqual("Brian Meyer;(016977)
0358;mollis.nec@seddictumeleifend.co.uk;Houston",
row.GetValue());
}
[Test]
public void HugeTableSearchByColumnNumbersHasValuesTest()
{
PerformancePage.UsersTable.AssertThat().HasRowWithValues(
HasValue("Brian Meyer", InColumn(1)),
HasValue("mollis.nec@seddictumeleifend.co.uk",
InColumn(3)));
var row = PerformancePage.UsersTable.Row(
ContainsValue("Meyer", InColumn("Name")),
ContainsValue("co.uk", InColumn("Email")));
Assert.AreEqual("Brian Meyer;
(016977) 0358;mollis.nec@seddictumeleifend.co.uk;Houston",
row.GetValue());
}
[Test]
public void TableChainTest()
{
PerformancePage.UsersTable.AssertThat()
.Size(400)
.Size(Is.GreaterThan(399))
.HasRowWithValues(
HasValue("Brian Meyer", InColumn("Name")),
HasValue("mollis.nec@seddictumeleifend.co.uk",
InColumn("Email")))
.NotEmpty()
.RowsWithValues(3, ContainsValue("Baker", InColumn(1)))
.HasColumn("Email")
.HasColumns(new[] {"Name", "City"})
.Columns(Is.SubsequenceOf(new[] {"Name", "City", "Phone",
"Email", "Address"}));
}
[Test]
public void TableRowPerformanceTest()
{
PerformancePage.Open();
PerformancePage.CheckOpened();
AreEqual("Burke Tucker;076 1971 1687;et.euismod.et@ut.edu;GozŽe",
PerformancePage.UsersTable.Row(1).GetValue());
AreEqual("Burke Tucker;076 1971 1687;et.euismod.et@ut.edu;GozŽe",
PerformancePage.UsersTable.Row("Burke Tucker").GetValue());
AreEqual("Burke Tucker;076 1971 1687;et.euismod.et@ut.edu;GozŽe",
PerformancePage.UsersTable.Row(Users.Name).GetValue());
var value = PerformancePage.UsersTable.Preview();
AreEqual("Name Phone Email City" +
"Burke Tucker 076 1971 1687 et.euismod.et@ut.edu GozŽe"+
"Grady Brock (011307) 16843 cursus.et@commodo.org Alcobendas"+
"Harding Lloyd 0800 1111 neque.In.ornare@mauris.co.uk Beauvais",
value.Substring(0, 194));
}
[Test]
public void TableCellPerformanceTest()
{
PerformancePage.Open();
PerformancePage.CheckOpened();
AreEqual("ipsum.non.arcu@auctorullamcorper.ca",
PerformancePage.UsersTable.Cell(3, 4));
AreEqual("ipsum.non.arcu@auctorullamcorper.ca",
PerformancePage.UsersTable.Cell("Email", 4));
AreEqual("ipsum.non.arcu@auctorullamcorper.ca",
PerformancePage.UsersTable.Cell(3, "Zachary Hendrix"));
AreEqual("ipsum.non.arcu@auctorullamcorper.ca",
PerformancePage.UsersTable.Cell("Email", "Zachary Hendrix"));
}
[Test]
public void TableColumnPerformanceTest()
{
PerformancePage.Open();
PerformancePage.CheckOpened();
AreEqual("076 1971 1687;(011307) 16843;0",
PerformancePage.UsersTable.Column(2).
GetValue().Substring(0, 30));
AreEqual("076 1971 1687;(011307) 16843;0",
PerformancePage.UsersTable.Column("Phone").
GetValue().Substring(0, 30));
AreEqual("076 1971 1687;(011307) 16843;0",
PerformancePage.UsersTable.Column(Users.Phone).
GetValue().Substring(0, 30));
}
<table class="uui-table stripe tbl-without-header table-td-click"
ui="table" id="users-table">
<tbody>
<tr>
<th>Name</th>
<th>Phone</th>
<th>Email</th>
<th>City</th>
</tr>
<tr>
<td>Burke Tucker</td>
<td>076 1971 1687</td>
<td>et.euismod.et@ut.edu</td>
<td>GozŽe</td>
</tr>
<tr>
<td>Grady Brock</td>
<td>(011307) 16843</td>
<td>cursus.et@commodo.org</td>
<td>Alcobendas</td>
</tr>
<tr>
<td>Harding Lloyd</td>
<td>0800 1111</td>
<td>neque.In.ornare@mauris.co.uk</td>
<td>Beauvais</td>
</tr>
</tbody>
</table>
JDI JTable annotation
Along with providing a Table type element JDI Light also provides a @JDropdown annotation for a better element locating. In addition to what Table type does @JDropdown also allows some kind of customization in the way the element is being located on the page.
This annotation has the following fields that can be used for locating a table element:
- String root() - value of this field points to the root locator of table element
- String[] header() - list of the columns names
- String headers() - locator of a table header
- String row() - locator representing a single row of a table
- String column() - locator representing a column of a table
- String cell() - locator representing a table cell
- String allCells() - locator representing all table cells
- String rowHeader() - the value of a table header corresponding to a particular raw
- int size() - amount of columns
- int count() - amount of rows
- int firstColumnIndex() - index of the first column
- int[] columnsMapping() - a collection containing indexes of the columns that are going to be used for processing, e.g. if one decides to work with not all columns but only with particular ones or if a column contains e.g. an icon or a checkbox and should not be processed then its index shouldn't be listed in columnsMapping field
Here is a list of available methods in Java:
Method | Description | Return Type |
---|---|---|
getStartIndex() | Returns start index | int |
setStartIndex(int) | Sets start index | void |
core() | Returns a UIElement | UIElement |
setHeader(List |
Sets header value | void |
headerUI() | Returns a header name | WebList |
footerUI() | Returns a footer name | WebList |
rowHeader() | Returns a value of a table header corresponding to a particular raw | List |
cell(int, int) | Returns a cell object of a table according to column number and row number | String |
cell(int, String) | Returns a cell object of a table according to the row number and column name | String |
cell(String, int) | Returns a cell object of a table according to the column name and row number | String |
cell(String, String) | Returns a cell object of a table according column name and row name | String |
column(Enum<?>) | Returns a column object of a table according to column name | Line |
column(int) | Returns a column object of a table according to column number | Line |
column(String) | Returns a column object of a table according to column name | Line |
columns() | Returns a list of column objects of a table | List |
count() | Returns amount of rows | int |
filterRows(Matcher |
Sets and returns a list of filtered rows of a table according to matching column | List |
filterRows(Pair |
Sets and returns a list of filtered rows of a table according to matching column | List |
getValue() | Returns a string content of values for a particular row, where values are separated by ";" | String |
header() | Returns a list of table's headers | List |
isEmpty() | Asserts whether a table is empty | boolean |
isNotEmpty() | Asserts whether a table is not empty | boolean |
preview() | Returns table preview | String |
row(Matcher |
Check that the table has rows that meet expected condition | Line |
row(Enum<?>) | Returns a row object of a table according to row name | Line |
row(int) | Returns a row object of a table according to row number | Line |
row(Pair |
Returns a row object of a table according to matching column | Line |
row(String) | Returns a row object of a table according to row name | Line |
row(ColumnMatcher...) | Returns a row object of a table according to matcher | Line |
rows() | Returns a list of rows of a table | List |
rows(ColumnMatcher...) | Get all table rows that match criteria | List |
rowsImages() | Get all table rows | List |
setup(Field) | Initialize field | void |
getTableJs() | Returns table | T |
clear() | clears the text field | void |
refresh() | Clears all data and lines | void |
offCache() | Turns off cache usage | void |
size() | Returns amount of columns | int |
validateRowIndex(int) | Validates row index | void |
webRow(int) | Returns all UIElements in the row according to row number | WebList |
webRow(int,String) | Returns all UIElements in the row according to row number | WebList |
webRow(String) | Returns all UIElements in the row according to row name | WebList |
webRow(Enum<?>) | Returns all UIElements in the row according to row name | List |
webColumn(int) | Returns all UIElements in the column according to column number | WebList |
webColumn(String) | Returns all UIElements in the column according to column name | WebList |
webColumn(Enum<?>) | Returns all UIElements in the column according to column name | WebList |
webCell(int, int) | Returns all UIElements in the column according to cell position | UIElement |
getJSValues(String) | Returns list of locators | List |
jsCells() | Returns list of locators | List |
jsColumn(int) | Returns list of column locators | List |
jsColumn(String) | Returns list of column locators | List |
jsRow(int) | Returns list of row locators | List |
jsRow(String) | Returns list of row locators | List |
jsRowIndexByName(String) | Returns row index by its name | int |
getRowIndexByName(String) | Returns row index by its name | int |
getRow(int) | Returns row by its row number | WebList |
getColumn(int) | Returns column by its row number | WebList |
getCell(int,int) | Returns cell by its column number and row number | UIElement |
filter() | Filters a table | WebList |
filterBy(String) | Filters a table with by a filterName | UIElement |
searchBy(String) | Filter {name} by column {0} | UIElement |
And here are methods available in C#:
Method | Description | Return Type |
---|---|---|
AssertThat() | Applicable for performing assert actions for tables | TableAssert |
Cell(int colNum, int rowNum) | Sets and returns a cell object of a table according to the cell's indices | string |
Cell(string colName, int rowNum) | Sets and returns a cell object of a table according to the cell's column name and row index | string |
Cell(int colNum, string rowName) | Sets and returns a cell object of a table according to the cell's column index and row name | string |
Cell(string colName, string rowName) | Sets and returns a cell object of a table according to the cell's column name and row name | string |
Column(int colNum) | Sets and returns a column object of a table according to the column's index | Line |
Column(string colName) | Sets and returns a column object of a table according to the column's name | Line |
Column(Enum colName) | Sets and returns a column object of a table according to column name | Line |
Columns() | Sets and returns a list of column objects of a table | List |
Columns(Matcher |
Asserts whether headers satisfy some matcher condition | TableAssert |
ContainsValue(string value, Column column) | Looks for an object by some value occurrence in a particular column | TableMatcher |
Empty() | Asserts whether table is empty | TableAssert |
FilterRows(Matcher |
Sets and returns a list of filtered rows of a table according to matching column | List |
FilterRows(params KeyValuePair |
Sets and returns a list of filtered rows of a table according to matching column | List |
GetValue() | Returns a string content of values for a particular row, where values are separated by ";" | string |
HasColumn(string column) | Asserts whether table has a particular header | TableAssert |
HasColumns(IEnumerable |
Asserts whether table has particular headers | TableAssert |
HasRowWithValues(params TableMatcher[] matchers) | Asserts whether a row with particular matchers exists in a table | TableAssert |
HasValue(string value, Column column) | Looks for an object (exact match) in a particular column | TableMatcher |
Is() | Applicable for performing assert actions for tables | TableAssert |
InColumn(string value) | Sets an object of some column to a particular value | Column |
InColumn(int num) | Sets an object of some column to a particular column number | Column |
NotEmpty() | Asserts whether table is not empty | TableAssert |
Row(params TableMatcher[] matchers) | Sets and returns a row object from a table according to some matcher params (returns 'null' if there is no such row) | Line |
Row(int rowNum) | Sets and returns a row object of a table according to the row index | Line |
Row(string rowName) | Sets and returns a row object of a table according to the row name | Line |
Row(Enum rowName) | Sets and returns a row object of a table according to row name | Line |
Row(Matcher |
Sets and returns a row object of a table according to matching column | Line |
Row(params KeyValuePair |
Sets and returns a row object of a table according to matching column | Line |
RowsAsLines(params TableMatcher[] matchers) | Sets and returns a list of rows of a table according to matchers | List |
RowsAsLines() | Sets and returns a list of rows of a table | List |
RowsWithValues(int count, params TableMatcher[] matchers) | Asserts whether rows with particular matchers exist in a table multiple times | TableAssert |
string Preview() | Returns a string content of the whole table | string |
Size(Matcher |
Asserts whether table size satisfies some matcher condition | TableAssert |
Size(int expectedSize) | Asserts whether table has a particular size | TableAssert |
1.2.3 DataTable
DataTable — A complex element that consists of a header, a body (at least one row and one column) and a footer. You are able to perform a list of read-only interactions with this element in order to get all data based on specified criteria.
DataTables are represented by the following classes in Java:
@UI("#users-table")
//@FindBy(id = "users-table")
public static DataTable<UserRow, UserInfo> usersData;
@JTable(
root = "#users-table",
row = "//tr[%s]/td",
column = "//tr/td[%s]",
cell = "//tr[{1}]/td[{0}]",
allCells = "td",
headers = "th",
header = {"Name", "Phone", "Email", "City"},
rowHeader = "Name",
size = 4
)
public static DataTable<UserRow, UserInfo> usersDataSetup;
public static UserInfo GRADY_BROCK = new UserInfo().set(u-> {
u.name = "Grady Brock";
u.email = "cursus.et@commodo.org";
u.phone = "(011307) 16843";
u.city = "Alcobendas";
});
@Test
public void filterDataTest() {
assertEquals(usersData.dataRow(ELEMENT.startIndex + 1), GRADY_BROCK);
assertEquals(usersData.dataRow("Grady Brock"), GRADY_BROCK);
assertEquals(usersData.dataRow(d -> d.name.contains("Brock")), GRADY_BROCK);
usersData.assertThat().row(d -> d.equals(GRADY_BROCK));
usersData.has().row(GRADY_BROCK);
}
@Test
public void filterLinesTest() {
UserRow line = usersData.line(ELEMENT.startIndex + 1);
validateUserRow(line);
line = usersData.line("Grady Brock");
validateUserRow(line);
line = usersData.line(d -> d.name.contains("Brock"));
validateUserRow(line);
}
private void validateUserRow(UserRow line) {
line.city.click();
Alerts.validateAndAcceptAlert(is(GRADY_BROCK.city));
assertEquals(line.email.getText(), GRADY_BROCK.email);
}
- Java: com.epam.jdi.light.elements.complex.table.DataTable
<table class="uui-table stripe tbl-without-header table-td-click"
ui="table" id="users-table">
<tbody>
<tr>
<th>Name</th>
<th>Phone</th>
<th>Email</th>
<th>City</th>
</tr>
<tr>
<td>Burke Tucker</td>
<td>076 1971 1687</td>
<td>et.euismod.et@ut.edu</td>
<td>GozŽe</td>
</tr>
<tr>
<td>Grady Brock</td>
<td>(011307) 16843</td>
<td>cursus.et@commodo.org</td>
<td>Alcobendas</td>
</tr>
<tr>
<td>Harding Lloyd</td>
<td>0800 1111</td>
<td>neque.In.ornare@mauris.co.uk</td>
<td>Beauvais</td>
</tr>
</tbody>
</table>
Here is a list of available methods in Java (DataTable expand Table class - methods from previous table are available too_):
In return types, column "D" refers to the user data object and "L" refers to the table line object.
Method | Description | Return Type |
---|---|---|
dataRow(int) | Get table row by the row number | D |
allData() | Get all table rows | List |
allData(MapArray |
Get all table rows | List |
allLines() | Gets all object rows from the specified table | List |
allLines(MapArray |
Gets all object rows from the specified table | List |
columnValues(String, Class |
Returns column values | |
dataRow(String) | Get table row by the row name | D |
dataRow(Enum<?>) | Get table row by the row name | D |
dataRow(Matcher |
Get table row that match criteria in column | D |
dataRow(ColumnMatcher...) | Get first table row that match criteria | D |
dataRow(JFunc1 |
Get first table row that match criteria | D |
dataRow(Pair |
Get table row that match criteria in column | D |
dataRows(JFunc1 |
Get all table rows that match criteria | List |
dataRows(ColumnMatcher...) | Get all table rows that match criteria | List |
dataRows(JFunc1 |
Get at least a specified number of rows of the table that meet the criteria | List |
filterData(Matcher |
Get table rows that match criteria in column | List |
filterDatas(Pair |
Get table rows that match criteria in column | List |
filterLines(Matcher |
Get table rows that match criteria in column | List |
filterLines(Pair |
Get table rows that match criteria in column | List |
get(String) | Returns values of the specified row | D |
getValue() | Get table value | String |
elements(int) | Returns elements of table | List |
line(Enum<?>) | Returns an object of a table according to row name | L |
line(int) | Returns an object of a table according to row number | L |
line(JFunc1 |
Get first table row that match criteria | L |
line(Matcher |
Get table row that match criteria in column | L |
line(Pair |
Get table row that match criteria in column | L |
line(ColumnMatcher...) | Get first table row that match criteria | L |
line(String) | Get table row by the row name | L |
lines(JFunc1 |
et first table row that match criteria | List |
lines(ColumnMatcher...) | Get all table rows that match criteria | List |
offCache() | Turns off cache usage | void |
refresh() | Clears all data and lines | void |
setup(Field) | Sets up the table using specified fields | void |
is() | Returns object for work with assertions | DataTableAssert |
is(Matcher<? super List |
Returns object for work with assertions | DataTableAssert |
assertThat(Matcher<? super List |
Returns object for work with assertions | DataTableAssert |
verify(Matcher<? super List |
Returns object for work with assertions | DataTableAssert |
1.2.4 Dropdown
Dropdown — A graphical control element that allows user to choose a single value from a list.
JDI Light has support for dropdown elements with their own type. There are several ways of dropdown usage in JDI Light, each serving different needs.
Dropdown representation
JDI Light provides a Dropdown class which is using for dropdown representation as a type of web element.
This class can also be used when working with HTML5 elements in cases when dropdown is represented with HTML <select> tag.
Consider an example of HTML5 dropdown with the given HTML code:
@JDropdown(root = "div[ui=dropdown]",
value = ".filter-option",
list = "li",
expand = ".caret")
public static Dropdown colors2; //@FindBy(css = "div[ui=dropdown]")
@Test
public void selectStringTest() {
colors2.select("Red");
lastLogEntry.assertThat()
.text(containsString("Colors: value changed to Red"));
}
@Test
public void selectEnumTest() {
colors2.select(Green);
lastLogEntry.assertThat()
.text(containsString("Colors: value changed to Green"));
}
@Test
public void selectIndexTest() {
colors2.select(ELEMENT.startIndex + 3);
lastLogEntry.assertThat()
.text(containsString("Colors: value changed to Blue"));
}
[FindBy(Css = "#dress-code")]
public Dropdown DressCode;
[Test]
public void SelectEnumTest()
{
DressCode.Select(Fancy);
Assert.AreEquals(DressCode.GetSelected(), "Fancy");
}
[Test]
public void LabelTest()
{
AreEqual(TestSite.Html5Page.DressCode.Label().GetText(), "Dress code:");
TestSite.Html5Page.DressCode.Label().Is.Text(ContainsString("Dress"));
}
[Test]
public void IsValidationTest()
{
TestSite.Html5Page.DressCode.Is.Selected("Casual");
TestSite.Html5Page.DressCode.Is.Selected(DressCode.Casual);
TestSite.Html5Page.DressCode.Is.Values(HasItems(new[] { "Pirate" }));
TestSite.Html5Page.DressCode.Is.Disabled(HasItems(new[] { "Disabled" }));
TestSite.Html5Page.DressCode.Is.Enabled(HasItems(new[] { "Pirate", "Fancy" }));
}
[Test]
public void AssertValidationTest()
{
TestSite.Html5Page.DressCode.AssertThat.Values(
ContainsInAnyOrder(new[] {"Fancy", "Casual", "Disabled", "Pirate"}));
}
[Test]
public void BaseValidationTest()
{
BaseElementValidation(TestSite.Html5Page.DressCode);
}
<select id="dress-code">
<option value="fancy">Fancy</option>
<option value="casual" selected="">Casual</option>
<option value="disabled" disabled="">Disabled</option>
<option value="pirate">Pirate</option>
</select>
JDI Dropdown annotation
For convenience, JDI Light provides a @JDropdown annotation to locate dropdown elements. This annotation can be used in cases when working with a complex element that may have a more complicated HTML structure. JDropdown annotation allows to customize navigation of the web element inner structure by using annotation default methods.
[JDropDown(root: "#colors",
value: ".filter-option",
list:"li",
expand:".caret")]
public Droplist Colors;
[Test]
public void ComplexTest()
{
MetalAndColorsPage.ShouldBeOpened();
MetalAndColorsPage.Colors.Select(Green);
}
<div class="form-group colors" ui="dropdown" id="colors">
<select class="selectpicker uui-form-element" style="display: none;">
<option>Colors</option>
<option>Red</option>
<option>Green</option>
<option>Blue</option>
<option>Yellow</option>
</select>
<div class="btn-group bootstrap-select uui-form-element"><button type="button"
class="btn dropdown-toggle selectpicker btn-default" data-toggle="dropdown" title="Colors"><span
class="filter-option pull-left" value="">Colors</span> <span class="caret"></span></button>
<div class="dropdown-menu open" style="max-height: 933px; overflow: hidden; min-height: 90px;">
<ul class="dropdown-menu inner selectpicker" role="menu"
style="max-height: 921px; overflow-y: auto; min-height: 78px;">
<li rel="0" class="selected"><a tabindex="0" class="" style=""><span class="text">Colors</span>
<i class="glyphicon glyphicon-ok icon-ok check-mark"></i></a></li>
<li rel="1"><a tabindex="0" class="" style=""><span class="text">Red</span>
<i class="glyphicon glyphicon-ok icon-ok check-mark"></i></a></li>
<li rel="2"><a tabindex="0" class="" style=""><span class="text">Green</span>
<i class="glyphicon glyphicon-ok icon-ok check-mark"></i></a></li>
<li rel="3"><a tabindex="0" class="" style=""><span class="text">Blue</span>
<i class="glyphicon glyphicon-ok icon-ok check-mark"></i></a></li>
<li rel="4"><a tabindex="0" class="" style=""><span class="text">Yellow</span>
<i class="glyphicon glyphicon-ok icon-ok check-mark"></i></a></li>
</ul>
</div>
</div>
</div>
JDropdown annotation consists of the following elements using which element inner structure can be customised:
- root() - value of this element points to the root locator of dropdown element
- value() - locator of option selected by default in dropdown list
- list() - locator representing list options
- expand() - locator for expanding the dropdown list
- how() - type of locators with which elements will be identified. By default it is css
Here is a list of some available methods:
Method | Description | Return Type |
---|---|---|
iCore() | UIElement | |
list() | Returns a WebList item representing a list of available Dropdown options | WebList |
select(String/int) | Select the specified element by the value | void |
isDisplayed() | Show\wait that dropdown element displayed on the screen | boolean |
selected(String) | Is 'String' selected | boolean |
selected() | Check that '{name}' is displayed | String |
values() | Get '{name}' values | List |
getText() | Gets element text | String |
getValue() | Gets element value | String |
setValue(String) | Sets element value | void |
setup(Field field) | Setup the dropdown using specified fields | void |
size() | Return amount of elements in the list | int |
Available Assert methods in C#:
Method | Description | Return Type |
---|---|---|
AssertThat | Gets dropdown assertion | DropDownAssert |
Disabled(Matcher |
Checks that dropdown values are disabled by some condition | DropDownAssert |
Enabled(Matcher |
Checks that dropdown values are enabled by some condition | DropDownAssert |
Is | Gets dropdown assertion | DropDownAssert |
Selected(string option) | Checks whether some option is selected | DropDownAssert |
Selected(Enum option) | Checks whether some option is selected | DropDownAssert |
Values(Matcher |
Checks that dropdown values match some condition | DropDownAssert |
1.2.5 MultiDropdown
MultiDropdown – A graphical control element that allows user to choose several values from a list.
JDI Light provides a MultiSelector class which is using for MultiDropdown representation as a type of web element.
//@FindBy(id = "multi-dropdown")
@UI("#multi-dropdown")
public static MultiSelector multiDropdown;
@Test
public void selectTest() {
skipForFirefox();
multiDropdown.check("Electro", "Metalic");
assertEquals(multiDropdown.checked(), asList("Electro", "Metalic"));
}
@Test
public void disabledTest() {
skipForFirefox();
multiDropdown.select("Disabled");
assertEquals(multiDropdown.selected(), "Steam");
}
@Test
public void labelTest() {
assertEquals(multiDropdown.label().getText(), "Multi dropdown:");
multiDropdown.label().is().text(containsString("Multi"));
}
@Test
public void isValidationTest() {
multiDropdown.is().selected("Steam");
multiDropdown.is().selected(Steam);
multiDropdown.assertThat().values(hasItem("Wood"));
multiDropdown.assertThat().disabled(hasItem("Disabled"))
.enabled(not(hasItem("Disabled")))
.enabled(hasItems("Electro", "Metalic"));
}
[FindBy(Css = "#multi-dropdown")]
public MultiDropdown MultiDropdown { get; set; }
[Test]
public void SelectMultipleOptions()
{
var optionsList = new List<string> { "Steam", "Electro" };
TestSite.Html5Page.MultiDropdown.SelectOptions(optionsList);
Jdi.Assert.IsTrue(TestSite.Html5Page.MultiDropdown.OptionsAreSelected(optionsList));
}
[Test]
public void CheckOptionExists()
{
TestSite.Html5Page.MultiDropdown.Expand();
Jdi.Assert.IsTrue(TestSite.Html5Page.MultiDropdown.OptionExists("Steam"));
Jdi.Assert.IsFalse(TestSite.Html5Page.MultiDropdown.OptionExists("Steam2"));
}
[Test]
public void CheckOptionIsDisabled()
{
TestSite.Html5Page.MultiDropdown.Expand();
Jdi.Assert.IsFalse(TestSite.Html5Page.MultiDropdown.OptionIsEnabled("Disabled"));
Jdi.Assert.IsTrue(TestSite.Html5Page.MultiDropdown.OptionIsEnabled("Wood"));
}
[Test]
public void LabelTest()
{
Jdi.Assert.AreEquals(TestSite.Html5Page.MultiDropdown.Label().GetText(), "Multi dropdown:");
TestSite.Html5Page.MultiDropdown.Label().Is.Text(ContainsString("Multi"));
}
[Test]
public void IsValidationTest()
{
TestSite.Html5Page.MultiDropdown.SelectOptions(new List<string> { "Steam" });
TestSite.Html5Page.MultiDropdown.Is.Selected("Steam");
TestSite.Html5Page.MultiDropdown.Is.Selected(Ages.Steam);
TestSite.Html5Page.MultiDropdown.Is.Values(HasItems( new []{ "Wood" }));
TestSite.Html5Page.MultiDropdown.Is.Disabled(HasItems(new[] { "Disabled" }));
TestSite.Html5Page.MultiDropdown.Is.Enabled(HasItems( new []{ "Electro", "Metalic" }));
}
[Test]
public void AssertValidationTest()
{
TestSite.Html5Page.MultiDropdown.SelectOptions(new List<string> { "Steam" });
TestSite.Html5Page.MultiDropdown.AssertThat.Values(ContainsInAnyOrder( new []{ "Disabled", "Electro", "Metalic", "Wood", "Steam" }));
}
[Test]
public void BaseValidationTest()
{
BaseElementValidation(TestSite.Html5Page.MultiDropdown);
}
<span class="multiselect-native-select">
<select id="multi-dropdown" multiple="multiple">
<option value="electro">Electro</option>
<option value="steam" selected="">Steam</option>
<option value="metalic">Metalic</option>
<option value="dis" disabled="">Disabled</option>
<option value="wood">Wood</option>
</select>
<div class="btn-group">
<button type="button" class="multiselect dropdown-toggle btn btn-default" data-toggle="dropdown" title="Steam">
<span class="multiselect-selected-text">Steam</span>
<b class="caret"/>
</button>
<ul class="multiselect-container dropdown-menu">
<li>
<a tabindex="0">
<label class="checkbox" title="Electro">
<input type="checkbox" value="electro"> Electro</label>
</a>
</li>
<li class="active">
<a tabindex="0">
<label class="checkbox" title="Steam">
<input type="checkbox" value="steam"> Steam</label>
</a>
</li>
<li>
<a tabindex="0">
<label class="checkbox" title="Metalic">
<input type="checkbox" value="metalic"> Metalic</label>
</a>
</li>
<li class="disabled">
<a tabindex="-1">
<label class="checkbox" title="Disabled">
<input type="checkbox" value="dis" disabled=""> Disabled</label>
</a>
</li>
<li>
<a tabindex="0">
<label class="checkbox" title="Wood">
<input type="checkbox" value="wood"> Wood</label>
</a>
</li>
</ul>
</div>
</span>
MultiDropdown are represented by the following classes:
- Java: com.epam.jdi.light.ui.html.elements.complex.MultiSelector
- C#: JDI.Light.Elements.Composite.MultiDropdown
The list of methods available for Java in JDI Light:
Method | Description | Return Type |
---|---|---|
list() | locator representing list options | WebList |
select(String/int) | Selects the value based on its visible text/index | WebList |
check(String/String.../TEnum.../int...) | Check that only particular elements are selected | void |
checked() | Get checked elements | List |
is() | Applicable for performing assert actions for MultiDropdown | UIMSelectAssert |
selected() | Get selected value | String |
selected(String) | Get selected value | boolean |
values() | Get the elements values | List |
values(TextTypes) | Get the elements values | List |
listEnabled() | Get the list of enabled elements | List |
listDisabled() | Get the list of disabled elements | List |
setValue() | Sets element value | void |
getValue() | Gets element value | String |
getStartIndex() | Gets start index | int |
setStartIndex(int) | Sets start index | void |
unckeckAll(String) | Uncheck all selected elements | void |
uncheck(String.../TEnum.../int.../String) | Unchecks particular elements by index/name | void |
Here is the list of some methods available for C# in JDI Light:
Method | Description | Return Type |
---|---|---|
AssertThat | Gets multiDropDown assert | MultiDropdownAssert |
Close() | Close expanded list | void |
Disabled(Matcher |
Check whether some values are disabled in MultiDropDown by some matcher | MultiDropdownAssert |
Enabled(Matcher |
Check whether some values are enabled in MultiDropDown by some matcher | MultiDropdownAssert |
Expand() | Expand list | void |
GetSelectedOptions() | Get selected options | List |
Is | Gets multiDropDown assert | MultiDropdownAssert |
OptionIsEnabled(string) | Check whether option is enabled | bool |
OptionExists(string) | Check whether option exists in list | bool |
SelectOption(string) | Select specified option | void |
SelectOptions(List) | Select specified options | void |
Selected(string option) | Check whether option is selected | MultiDropdownAssert |
Selected(Enum option) | Check whether option is selected | MultiDropdownAssert |
Values(Matcher |
Check whether some values exist in MultiDropDown by some matcher | MultiDropdownAssert |
1.2.6 DataList
DataList – A graphical control element that allows user to choose one value from a list or enter it by himself. DataList element contains a set of options with values available as inputs.
DataList is provided by JDI Light in:
- Java: com.epam.jdi.light.ui.html.elements.complex.DataListOptions
- C#: JDI.Light.Elements.Common.DataList
C# JDI DataList annotation
For better use in C# JDI Light provides a [JDataList] annotation to locate DataList elements. This annotation consists of the following elements:
- root - value of this element points to the root locator of the dropdown element
- values - options locator in dropdown list
- how - type of locators with which elements will be identified. By default it is set as css
// @FindBy(id = "ice-cream-flavors")
@UI("#ice-cream-flavors")
public static DataListOptions iceCream;
@Test
public void getValueTest() {
assertEquals(iceCream.getValue(), "Coconut");
}
@Test
public void getTextTest() {
assertEquals(iceCream.getText(), "Coconut");
}
@Test
public void inputTest() {
iceCream.input("New text");
assertEquals(iceCream.getText(), "New text");
}
@Test
public void inputNullValueTest() {
String value = iceCream.getText();
iceCream.input(null);
iceCream.has().text(value);
}
@Test
public void clearTest() {
iceCream.clear();
assertEquals(iceCream.getText(), "");
}
@Test
public void selectTest() {
iceCream.select("Chocolate");
assertEquals(iceCream.getValue(), "Chocolate");
}
[JDataList("#ice-cream", "#ice-cream-flavors > option")]
public DataList IceCream { get; set; }
[JDataList("#disabled-dropdown","#disabled-dropdown > option")]
public DataList DisabledDropdownAsDataList { get; set; }
[Test]
public void GetValueTest()
{
AreEqual(TestSite.Html5Page.IceCream.Selected(), "Coconut");
}
[Test]
public void LabelTest()
{
AreEqual(TestSite.Html5Page.IceCream.Label().GetText(), "Choose your lovely icecream");
TestSite.Html5Page.IceCream.Label().Is.Text(ContainsString("lovely icecream"));
}
[Test]
public void IsValidationTest()
{
TestSite.Html5Page.IceCream.Is.Enabled();
TestSite.Html5Page.IceCream.Is.Attr("value" ,EqualTo(_text));
TestSite.Html5Page.IceCream.Select("Vanilla");
TestSite.Html5Page.IceCream.Is.Attr("value", ContainsString("Van"));
}
[Test]
public void AssertValidationTest()
{
TestSite.Html5Page.IceCream.AssertThat.Attr("value", ContainsString(_text));
}
[Test]
public void BaseValidationTest()
{
BaseElementValidation(TestSite.Html5Page.IceCream);
}
[Test]
public void NegativeSelectTest()
{
Throws<ElementNotSelectableException>(() => TestSite.Html5Page.DisabledDropdownAsDataList.Select("Fancy", false));
}
[Test]
public void NegativeSelectEnumTest()
{
Throws<ElementNotSelectableException>(() => TestSite.Html5Page.DisabledDropdownAsDataList.Select(DressCode.Fancy, false));
}
[Test]
public void NegativeSelectNumTest()
{
Throws<ElementNotFoundException>(() => TestSite.Html5Page.IceCream.Select(7, false));
}
[Test]
public void AssertOptionsValuesTest()
{
IsTrue(TestSite.Html5Page.IceCream.Values().SequenceEqual(_options));
}
Have a look at the following example with HTML code provided:
<datalist id="ice-cream-flavors">
<option value="Chocolate"></option>
<option value="Coconut"></option>
<option value="Mint"></option>
<option value="Strawberry"></option>
<option value="Vanilla"></option>
</datalist>
The list of methods available for Java in JDI Light:
Method | Description | Return Type |
---|---|---|
list() | Returns a WebList item representing a list of available Datalist options | WebList |
getText() | Gets button text | String |
listEnabled() | Return list of values of enabled options | List |
listDisabled() | Return list of values of disabled options | List |
isEnabled() | Check that '{name}' is enabled | boolean |
isDisplayed() | Check that '{name}' is displayed | boolean |
isExpanded() | Return if element expanded | boolean |
isCollapsed() | Checks whether element is collapsed | boolean |
is() | Returns DropdownAssert class | DropdownAssert |
getStartIndex() | Returns start index | int |
setStartIndex() | Sets start index | void |
select(String/int) | Select combobox option by value or index | void |
selected() | Get selected option value | String |
values() | Get all option values from combobox | List |
Here is the list of some methods available for C# in JDI Light:
Method | Description | Return Type |
---|---|---|
assertThat() | Returns object for work with assertions | ComboBoxAssert |
Expand() | Expands the list of possible values | void |
GetSelected() | Get selected combobox value | string |
Input(string) | Input user's value into combobox | void |
is() | Returns object for work with assertions | ComboBoxAssert |
Select(string/int) | Select combobox by value/index | void |
1.2.7 CheckList
CheckList – A graphical control element representing a set of checkboxes, each of which allows user to control a two-state parameter (enabled or disabled).
Checklist element type is available in the following packages:
- Java: com.epam.jdi.light.elements.complex.CheckList
- C#: JDI.Light.Elements.Complex.CheckList
See an example with HTML code describing checklist element.
//@FindBy(name = "checks-group")
@UI("[name=checks-group]")
public static Checklist weather;
@Test
public void getValueTest() {
assertEquals(weather.getValue(), "Hot option");
}
@Test
public void checkTest() {
weather.check("Cold");
assertEquals(weather.checked(), asList("Cold"));
}
@Test
public void uncheckTest() {
weather.check("Rainy day", "Sunny");
weather.uncheck("Rainy day");
weather.is().checked(hasSize(3));
weather.is().checked(hasItems("Hot option", "Cold", "Sunny"));
}
@Test
public void selectTest() {
weather.select("Cold");
assertEquals(weather.checked(), asList("Hot option", "Cold"));
}
[FindBy(Css = "div:nth-child(11) > div.html-left")]
public ICheckList weather;
[FindBy(Css = "div:nth-child(11) > div.html-left")]
public ICheckList<MyCheckBox> genericWeather;
[Test]
public void CheckCheckList()
{
weather.Check("Cold", "Hot option");
Jdi.Assert.CollectionEquals(new[] { "Cold", "Hot option" }, weather.Checked());
}
[Test]
public void UncheckTest()
{
_weather.Check(false, "Rainy day", "Sunny");
_weather.Uncheck(false, "Rainy day", "Sunny");
_weather.Is.Selected(HasSize(2));
_weather.Is.Selected(HasItems(new[] { "Hot option", "Cold" }));
}
[Test]
public void IsValidationTests()
{
weather.AssertThat
.Values(HasItems(new[] {"Cold", "Sunny"}))
.Disabled(HasItems(new[] {"Disabled"}))
.Size(Is.LessThan(6))
.AllDisplayed();
}
[Test]
public void UncheckAllTest()
{
_weather.Uncheck(false, "Rainy day", "Sunny");
_weather.UncheckAll();
_weather.Is.Selected(HasSize(0));
}
[Test]
public void CheckAllTest()
{
_weather.CheckAll();
_weather.Is.Selected(HasSize(4));
_weather.Is.Selected(HasItems(new[] { "Hot option", "Cold", "Rainy day", "Sunny" }));
}
[Test]
public void IsDisabledTest()
{
_weather.Select(false, "Disabled");
_weather.Is.Selected(HasItems(new [] { "Hot option" } ));
}
<input type="checkbox" id="hot" name="checks-group" checked="">
<label for="hot">Hot option</label> <br>
<input type="checkbox" id="cold" name="checks-group">
<label for="cold">Cold</label> <br>
<input type="checkbox" id="rainy" name="checks-group">
<label for="rainy">Rainy day</label> <br>
<input type="checkbox" id="sunny-day" name="checks-group">
<label for="sunny-day">Sunny</label> <br>
<input type="checkbox" id="disabled-ch" name="checks-group" disabled="">
<label for="disabled-ch">Disabled</label>
List of available methods in Java JDI Light:
Method | Description | Return Type |
---|---|---|
list() | Returns a WebList item representing a list of available Checklist options | WebList |
isDisplayed() | Check that Checklist is displayed | boolean |
check(String.../TEnum/TEnum.../int/int...) | Check specified checkboxes and uncheck others | void |
checkAll() | Check all checkboxes in checklist | void |
checked() | Get selected checkbox values | List |
is() | Get select assert | ChecklistAssert |
listEnabled() | Get enabled checkboxes | List |
listDisabled() | Get disabled checkboxes | List |
selected(UIElement/String) | Get selected checkbox values | boolean |
selected() | Get '{name}' selected option | String |
select(String.../TEnum/TEnum.../int/String/int...) | Select checkboxes | void |
uncheck(String.../TEnum/TEnum.../int.../int) | Uncheck specified checkboxes and check others | void |
uncheckAll() | Uncheck all checkboxes in checklist | void |
setValue(String) | Sets the value | void |
getStartIndex() | Returns start index | int |
setStartIndex(int) | Set start index | void |
Here is the list of some methods available for C# in JDI Light:
Method | Description | Return Type |
---|---|---|
AssertThat | Get select assert | SelectAssert |
Check(params string[]/params int[]) | Check checklist by values/indexes | void |
CheckAll() | Check all checkboxes | void |
Checked() | Get selected checkboxes from checklist value | List<String> |
Has | Get select assert | SelectAssert |
Is | Get select assert | SelectAssert |
ListEnabled() | Get enabled checkboxes | List<String> |
ListDisabled() | Get disabled checkboxes | List<String> |
Select(params string[]/params int[]) | Select checklist by values/indexes | void |
Selected(string option) | Checks whether a checkbox is selected | bool |
Size() | Get checklist size | int |
Uncheck(params string[]/params int[]) | Unselect checklist by values/indexes | void |
UncheckAll() | Uncheck all checkboxes | void |
Values() | Get checklist values | List<String> |
1.2.8 MultiSelector
MultiSelector – A graphical control element that allows user to make a multiple choice. MultiSelector is represented by the following class:
- Java: com.epam.jdi.light.ui.html.complex.MultiSelector
- C#: JDI.Light.Elements.Common.MultiSelector
@UI("#ages") // @FindBy(css = "#ages")
public static MultiSelector ages;
@Test
public void selectTest() {
ages.check("Electro", "Metalic");
assertEquals(ages.checked(), asList("Electro", "Metalic"));
}
@Test
public void selectEnumTest() {
ages.check(Wood, Steam);
assertEquals(ages.checked(), asList("Steam", "Wood"));
}
@Test
public void selectNumTest() {
ages.check(1, 5);
assertEquals(ages.checked(), asList("Electro", "Wood"));
}
[Test]
public void MultiSelectByValues()
{
MyMultiSelector.Select(string[]);
}
[Test]
public void MultiSelectByIndexes()
{
MyMultiSelector.Select(int[]);
}
<select id="ages" multiple="" size="4">
<option value="electro">Electro</option>
<option value="steam" selected="">Steam</option>
<option value="metalic">Metalic</option>
<option value="dis" disabled="">Disabled</option>
<option value="wood">Wood</option>
</select>
Here is a list of available methods and properties in C#:
Method / Property | Description | Return Type |
---|---|---|
AssertThat | Property that returns object for work with assertions | SelectAssert |
Check(string/string[]/int/int[]/Enum[]) | Select multiselector by values | void |
Checked() | Get selected values | List<string> |
has() | Returns object for work with assertions | SelectAssert |
Is | Property that returns object for work with assertions | SelectAssert |
Selected() | Get selected values | string |
shouldBe() | Returns object for work with assertions | SelectAssert |
Uncheck(string[]/Enum[]/int[]) | Select multiselector by values/indexes | void |
waitFor() | Returns object for work with assertions | SelectAssert |
Here is the list of available methods/asserts in Java:
Method | Description | Return Type |
---|---|---|
select(String) | Selects the value based on its visible text | void |
select(int) | Selects the value based on its index | void |
assertThat() | Returns object for work with assertions | SelectAssert |
check(String/String.../TEnum.../int...) | Select multiselector by values | void |
checked() | Get selected values | List |
is() | Returns object for work with assertions | UIMSelectAssert<?,?> |
values() | Get the elements values | List |
values(TextTypes) | Get the elements values | List |
selected() | Get selected element value by name | String |
selected(String) | Checks if element selected by name | boolean |
listEnabled() | Get the list of enabled elements | List |
listDisabled() | Get the list of disabled elements | List |
setValue(String) | Sets element value | void |
getValue() | Gets element value | String |
getStartIndex() | Returns start index | int |
SetStartIndex(int) | Sets start index | void |
uncheck(String.../TEnum.../int...) | Select multiselector by values/indices | void |
uncheckAll() | Unchecks all elements | void |
1.3 HTML5 Composite elements
1.3.1 Section
[FindBy(Id = "contact-form")]
public Contact ContactSection;
[FindBy(Css = ".footer-content")]
public static Footer Footer;
[FindBy(Css = ".uui-header")]
public static Header Header;
public JdiSearch Search;
[FindBy(Id = "summary-block")]
public Summary SummaryBlock;
[Test]
public void SectionTest()
{
var e = TestSite.HomePage.Get<Section>(By.CssSelector(".main-title"));
Assert.AreEqual("EPAM FRAMEWORK WISHES…", e.Text);
Assert.AreEqual("Section", e.Name);
Assert.AreEqual(true, e.Displayed);
Assert.AreEqual(true, e.Enabled);
Assert.AreEqual(false, e.Hidden);
Assert.AreEqual(By.CssSelector(".main-title"), e.Locator);
Assert.AreEqual(false, e.Selected);
Assert.AreEqual("h3", e.TagName);
}
[TestCaseSource(nameof(_contactSectionCases))]
public void CustomContactSectionTest(string htmlElementToCheckName, string expectedLocator, string expectedName, string expectedSmartLocator)
{
var targetElement =
ContactSection.GetType().GetMember(htmlElementToCheckName)[0].GetMemberValue(ContactSection) as UIElement;
ContactSection.CheckInitializedElement(targetElement, expectedLocator, expectedName, expectedSmartLocator);
}
[Test]
public void CustomFooterSectionTest()
{
FooterSection.CheckInitializedElement(FooterSection.AboutLink, "By.PartialLinkText: About", "AboutLink", null);
}
[TestCaseSource(nameof(_headerSectionCases))]
public void CustomHeaderSectionTest(string htmlElementToCheckName, string expectedLocator, string expectedName, string expectedSmartLocator)
{
var targetElement =
HeaderSection.GetType().GetMember(htmlElementToCheckName)[0].GetMemberValue(HeaderSection) as UIElement;
HeaderSection.CheckInitializedElement(targetElement, expectedLocator, expectedName, expectedSmartLocator);
}
[TestCaseSource(nameof(_jdiSearchSectionCases))]
public void CustomJdiSearchSectionTest(string htmlElementToCheckName, string expectedLocator, string expectedName, string expectedSmartLocator)
{
var targetElement =
JdiSearchSection.GetType().GetMember(htmlElementToCheckName)[0].GetMemberValue(JdiSearchSection) as UIElement;
JdiSearchSection.CheckInitializedElement(targetElement, expectedLocator, expectedName, expectedSmartLocator);
}
[Test]
public void CustomSummarySectionTest()
{
TestSite.MetalsColorsPage.Open();
SummarySection.CheckInitializedElement(SummarySection.Calculate, "By.Id: calculate-button", "Calculate", null);
}
private static object[] _contactSectionCases =
{
new object[] { nameof(ContactSection.DescriptionField), "By.CssSelector: textarea#description", "Description", null },
new object[] { nameof(ContactSection.FirstRoller), "By.XPath: .//a[@class='ui-slider-handle ui-state-default ui-corner-all' and position()=1]", "FirstRoller", null },
new object[] { nameof(ContactSection.LastNameField), "By.CssSelector: input#last-name", "Last Name", null },
new object[] { nameof(ContactSection.NameField), "By.CssSelector: input#name", "First Name", null },
new object[] { nameof(ContactSection.SecondRoller), "By.XPath: .//a[@class='ui-slider-handle ui-state-default ui-corner-all' and position()=2]", "SecondRoller", null },
new object[] { nameof(ContactSection.SubmitButton), "By.XPath: //button[@type='submit' and contains(., 'Submit')]", "SubmitButton", null },
};
private static object[] _headerSectionCases =
{
new object[] { nameof(HeaderSection.Image), "By.XPath: //img[@src=\"label/Logo_Epam_Color.svg\"]", "Image", null },
new object[] { nameof(HeaderSection.Menu), "By.CssSelector: ul.uui-navigation.nav", "Menu", null },
new object[] { nameof(HeaderSection.UserIcon), "By.CssSelector: #user-icon", "UserIcon", null },
new object[] { nameof(HeaderSection.Search), "By.CssSelector: input#last-name", "Search", "By.Id: search" }
};
private static object[] _jdiSearchSectionCases =
{
new object[] { nameof(JdiSearchSection.SearchButton), "By.CssSelector: .search>.icon-search", "SearchButton", null },
new object[] { nameof(JdiSearchSection.SearchButtonActive), "By.CssSelector: .icon-search.active", "SearchButtonActive", null },
new object[] { nameof(JdiSearchSection.SearchInput), "By.CssSelector: .search-field input", "SearchInput", null },
};
Section - Logical part of Web Page that contains other UI Elements
Section is located in the following classes:
- Java: com.epam.jdi.light.elements.composite.Section
- C#: JDI.Light.Elements.Composite.Section
@UI(".someSectionUI") // @FindBy(css = ".someSectionUI")
public static CustomSection customSectionUI;
@Test(dataProvider = "customSectionWebElementDataProvider", dataProviderClass = CustomSectionDataProvider.class)
public void customSectionWebElementTest(IBaseElement htmlElementToCheck, String expectedLocator, Object expectedParent, String expectedName) {
checkInitializedElement(htmlElementToCheck, expectedLocator, expectedParent, expectedName);
}
And here are methods available in Java:
Method | Description | Return Type |
---|---|---|
click() | Makes a click | void |
click(ElementArea) | Makes a click to area | void |
is() | Returns object for work with assertions | TextAssert |
1.3.2 Form
Form – Logical part of a web page that represents an HTML form. Form consists of elements based on SetValue interface and buttons with submit function.
Form provides the fill, submit and verify/check functionality.
<form class="form" id="contact-form">
<div class="row overflow">
<div class="col-sm-4">
<div class="form-group form-group10">
<label for="first-name">First Name</label>
<input id="first-name" type="text" class="uui-form-element">
</div>
</div>
<div class="col-sm-4">
<div class="form-group form-group10">
<label for="last-name">Last Name</label>
<input id="last-name" type="text" class="uui-form-element">
</div>
</div>
<div class="col-sm-4">
<div class="form-group form-group10">
<label for="position">Position</label>
<input id="position" type="text" class="uui-form-element">
</div>
</div>
<div class="col-sm-3">
<div class="form-group form-group10 lower">
<label for="passport">Passport</label>
<input id="passport" type="checkbox" name="passport" class="uui-form-element">
</div>
</div>
<div class="col-sm-4">
<div class="form-group form-group10">
<label for="passport-number">Number</label>
<input id="passport-number" type="text" class="uui-form-element">
</div>
</div>
<div class="col-sm-5">
<div class="form-group form-group10">
<label for="passport-seria">Seria</label>
<input id="passport-seria" type="text" class="uui-form-element">
</div>
</div>
</div>
<div class="row">
<div class="col-sm-4">
<label for="gender">Gender</label>
<select class="uui-form-element" ui="dropdown" id="gender">
<option>Male</option>
<option checked="">Female</option>
</select>
</div>
<div class="col-sm-4">
<label for="religion">Religion</label>
<div class="form-group form-group10">
<input list="religion-options" id="religion" placeholder="Religion" class="uui-form-element">
<datalist id="religion-options">
<option>Christian</option>
<option>Muslims</option>
<option>Induism</option>
<option>Other</option>
</datalist>
</div>
</div>
<div class="col-sm-4">
<label for="weather">Weather</label>
<div class="form-group salad" ui="droplist" id="weather">
<div class="dropdown salad">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="caret"/>
</button>
<ul class="dropdown-menu" style="display: none;">
<li>
<a href="#" class="checkbox">
<input type="checkbox" id="g5" class="uui-form-element blue">
<label for="g5">Sun</label>
</a>
</li>
<li>
<a href="#" class="checkbox">
<input type="checkbox" id="g6" class="uui-form-element blue">
<label for="g6">Rain</label>
</a>
</li>
<li>
<a href="#" class="checkbox">
<input type="checkbox" id="g7" class="uui-form-element blue">
<label for="g7">Weather</label>
</a>
</li>
<li>
<a href="#" class="checkbox">
<input type="checkbox" id="g8" class="uui-form-element blue">
<label for="g8">Snow</label>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="row overflow">
<div class="col-sm-12">
<div class="form-group">
<label for="description">Description</label>
<textarea class="uui-form-element" rows="4" cols="10" id="description"/>
</div>
<div>
<input id="accept-conditions" type="checkbox" name="accept-conditions">
<label for="accept-conditions">Accept conditions</label>
</div>
</div>
<div class="col-sm-12 text-right">
<button class="uui-button dark-blue" type="submit">Submit</button>
</div>
</div>
</form>
Form is located in the following classes:
- Java: com.epam.jdi.light.elements.composite.Form
- C#: JDI.Light.Elements.Composite.Form
public class FormContactsTests implements TestsInit {
@BeforeMethod
public void before() {
shouldBeLoggedIn();
contactFormPage.shouldBeOpened();
refresh();
}
private static Contacts defaultContact() {
return new Contacts().set(c -> {
c.firstName = "Roman";
c.lastName = "Iovlev";
c.position = "ChiefQA";
//c.passport = true;
c.passportNumber = "4321";
c.passportSeria = "123456";
c.description = "JDI - awesome UI automation tool";
c.acceptConditions = "true";
c.gender = "Female";
c.religion = "Other";
});
}
@Test
public void fillContactFormTest() {
main.contactForm.description.getText();
main.contactForm.fill(DEFAULT_CONTACT);
main.contactForm.check(DEFAULT_CONTACT);
}
@Test
public void submitTextToContactFormTest() {
main.contactForm.submit("Roman");
main.contactForm.check(ONLY_NAME_FILLED_DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void submitEntityToContactFormTest() {
main.contactForm.submit(DEFAULT_CONTACT);
main.contactForm.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void submitTextToContactFormUsingCustomButtonTest() {
main.contactForm.submit("Roman", "custom");
main.contactForm.check(ONLY_NAME_FILLED_DEFAULT_CONTACT);
}
@Test
public void submitTextToContactFormUsingNonExistentButtonTest() {
main.contactFormCustom.submit("Roman", "nonExistent");
}
@Test
public void submitEntityToContactFormUsingCustomButtonTest() {
main.contactForm.submit(DEFAULT_CONTACT, "custom");
main.contactForm.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void submitEntityToContactFormUsingNonExistentButtonTest() {
main.contactFormCustom.submit(DEFAULT_CONTACT, "nonExistent");
}
@Test
public void plainSubmitTest() {
main.contactForm.fill(DEFAULT_CONTACT);
main.contactForm.submit();
main.contactForm.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void pressButtonTest() {
main.contactFormCustom.fill(DEFAULT_CONTACT);
main.contactFormCustom.pressButton("custom");
main.contactFormCustom.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void verifyMethodPositiveTest() {
main.contactForm.fill(DEFAULT_CONTACT);
List<String> verified = main.contactForm.verify(DEFAULT_CONTACT);
assertEquals(verified.size(), 0);
}
@Test
public void verifyMethodNegativeTest() {
main.contactForm.fill(ALL_EXCEPT_NAME_FILLED_DEFAULT_CONTACT);
List<String> verified = main.contactForm.verify(DEFAULT_CONTACT);
assertEquals(verified.size(), 1);
assertTrue(verified.get(0).contains("Roman"));
}
@Test
public void checkMethodPositiveTest() {
main.contactForm.fill(DEFAULT_CONTACT);
main.contactForm.check(DEFAULT_CONTACT);
assertEquals(main.contactForm.verify(DEFAULT_CONTACT).size(), 0);
}
@Test(expectedExceptions = RuntimeException.class)
public void checkMethodNegativeTest() {
main.contactForm.fill(ALL_EXCEPT_NAME_FILLED_DEFAULT_CONTACT);
TIMEOUTS.element.set(1);
main.contactForm.check(DEFAULT_CONTACT);
}
@Test
public void sendMethodTest() {
main.contactFormCustom.fill(DEFAULT_CONTACT);
main.contactFormCustom.send();
main.contactFormCustom.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void sendEntityMethodTest() {
main.contactFormCustom.send(DEFAULT_CONTACT);
main.contactFormCustom.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void addEntityMethodTest() {
main.contactFormCustom.add(DEFAULT_CONTACT);
main.contactFormCustom.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void publishMethodTest() {
main.contactFormCustom.publish(DEFAULT_CONTACT);
main.contactFormCustom.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void saveMethodTest() {
main.contactFormCustom.save(DEFAULT_CONTACT);
main.contactFormCustom.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void updateMethodTest() {
main.contactFormCustom.update(DEFAULT_CONTACT);
main.contactFormCustom.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void cancelMethodTest() {
main.contactFormCustom.cancel(DEFAULT_CONTACT);
main.contactFormCustom.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void closeMethodTest() {
main.contactFormCustom.close(DEFAULT_CONTACT);
main.contactFormCustom.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void backMethodTest() {
main.contactFormCustom.back(DEFAULT_CONTACT);
main.contactFormCustom.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void selectMethodTest() {
main.contactFormCustom.select(DEFAULT_CONTACT);
main.contactFormCustom.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void nextMethodTest() {
main.contactFormCustom.next(DEFAULT_CONTACT);
main.contactFormCustom.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void searchMethodTest() {
main.contactFormCustom.search(DEFAULT_CONTACT);
main.contactFormCustom.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void onlyMandatoryOptionTest() {
main.contactFormCustom.onlyMandatory().fill(DEFAULT_CONTACT);
main.contactFormCustom.check(ONLY_NAME_FILLED_DEFAULT_CONTACT);
assertEquals(main.contactFormCustom.getFilter(), ALL);
}
@Test
public void onlyOptionalOptionTest() {
main.contactFormCustom.onlyOptional().fill(DEFAULT_CONTACT);
main.contactFormCustom.check(ALL_EXCEPT_NAME_FILLED_DEFAULT_CONTACT);
assertEquals(main.contactFormCustom.getFilter(), ALL);
}
@Test
public void overriddenFillActionTest() {
main.contactFormCustomFill.fill(DEFAULT_CONTACT);
main.contactFormCustomFill.check(UPPER_CASE_NAME_CONTACT);
}
@Test
public void uiFormTest() {
main.contactFormUI.submit(DEFAULT_CONTACT);
main.contactFormUI.check(DEFAULT_CONTACT);
checkContactFormSubmitted();
}
@Test
public void overriddenGetActionTest() {
main.contactFormCustomGet.fill(DEFAULT_CONTACT);
main.contactFormCustomGet.check(LOWER_CASE_NAME_CONTACT);
}
private void checkContactFormSubmitted() {
lastLogEntry.assertThat()
.text(containsString("submit:button clicked"));
}
}
Form is parameterized by an entity that corresponds to the form. For example, a login form can be parameterized by a user entity. The entity should extend DataClass class (parameterized by the entity itself). The names of the entity fields should be exactly the same as the names of the form fields. All fields of the entity managed by the form should be Strings.
JDI Light allows you to define a form in three ways:
By creating a normal JDI Light Form - a typical Form in JDI with typified elements, @UI annotations, extending from Form.
By using smart locators for a JDI Light Form - Such Form utilizes the
Smart locator functionality of JDI. In this case there is no need to explicitly define
locators for the form elements as such locators can be obtained implicitly from field names
using Smart locator functionality.
See more details and examples for Smart locators in documentation
If a Form consists of only TextFields and Buttons, there is no need to define a Form UI Object. Such form can be added directly to the related page or to the root Site class. In this case the form field will be taken from the entity that the form is being parameterized by.
Form Filters
In Java, Form has a filter property that defines which form elements will be filled/submited or verified/checked. Filter can be set to either ALL, MANDATORY or OPTIONAL.
Based on this property, fill/submit and verify/check functions are applied to either all form elements or only mandatory (only optional) form elements.
Mandatory form fields should be marked with @Mandatory annotation. Optional form fields are the ones without
@Mandatory annotation. ALL is the default Form option.
To set form filters
as MANDATORY or OPTIONAL, onlyMandatory() and onlyOptional() methods
should be used. They set the corresponding form filter option for a duration of a single
action (all form action methods set the form filter option back to ALL).
Form Actions
In Java, Form also has a FILL_ACTION and GET_ACTION lambdas. This defines how the Form should be filled and verified. The default behavior defined in the Form class simply utilizes setValue(String value) method of the SetValue interface and getValue() method of the HasValue interface.
However, these lambdas can be redefined in the HtmlSettings class in order to customise the behavior for "non-text" form elements such as Checkboxes (the behavior of custom elements is defined by @FillValue and @VerifyValue annotations).
FILL_ACTION and GET_ACTION lambdas can also be further modified in order to customize Form behavior, but it is important to take into account that behavior defined in the HtmlSettings might be lost.
It is customary to reassign these lambdas before all the tests are run, for example in TestNG's @BeforeSuite method.
In Java, if fill/submit and verify/check methods need to be redefined for a specific form, it is possible to override fillAction() and getAction() for such form.
Methods available for Java in JDI Light:
Method | Description | Return Type |
---|---|---|
add(T) | Fills all settable elements and clicks “add” Button or ”addButton” | void |
back(T) | Fills all settable elements and clicks “back” Button or ”backButton” | void |
cancel(T) | Fills all settable elements and clicks “cancel” Button or ”cancelButton” | void |
check(T) | Verifies that form has been filled correctly. If not, throws an exception | void |
close(T) | Fills all settable elements and clicks “close” Button or ”closeButton” | void |
fill(T) | Fills all settable elements of the form that can be matched with fields of the input entity | void |
fillAction(Field, Object, Object, String) | Defines the specifics of how form elements will be filled | void |
getAction(Field, Object, Object) | Defines the specifics of how form elements will be obtained for verification and checks | String |
isDisplayed() | Check that form is displayed | boolean |
isValid() | Return that form is valid | boolean |
login() | Clicks "login" Button or "loginButton" | void |
login(T) | Fills all settable elements and clicks “login” Button or ”loginButton” | void |
loginAs(T) | Fills all settable elements and clicks “login” Button or ”loginButton” | void |
next(T) | Fills all settable elements and clicks “next” Button or ”nextButton” | void |
onlyMandatory() | Sets form filter option to MANDATORY, meaning that only mandatory form elements are filled/submitted or verified/checked for the duration of a single form action | void |
onlyOptional() | Sets form filter option to OPTIONAL, meaning that only optional form elements are filled/submitted or verified/checked for the duration of a single form action | void |
pressButton(String) | Clicks “buttonName” Button or "buttonNamebutton". Allows different buttons to send one form, e.g. save/publish/cancel/search/update/... | void |
publish(T) | Fills all settable elements and clicks “publish” Button or ”publishButton” | void |
save(T) | Fills all settable elements and clicks “save” Button or ”saveButton” | void |
select(T) | Fills all settable elements and clicks “select” Button or ”selectButton” | void |
search(T) | Fills all settable elements and clicks “search” Button or ”searchButton” | void |
send() | Sends the form by clicking “send” Button or "sendButton" | void |
send(T) | Fills all settable elements and clicks “send” Button or ”sendButton” | void |
submit() | Sends the form by clicking "submit" Button or "submitButton" | void |
submit(String) | Fills first settable form field with value and clicks "submit" Button or "submitButton" | void |
submit(T) | Fills all settable elements and clicks "submit" Button or "submitButton" | void |
submit(String, String) | Fills first settable field with value and clicks “buttonName” Button or "buttonNamebutton" | void |
submit(T, String) | Fills all settable elements and clicks “buttonName” Button or "buttonNamebutton" | void |
verify(T) | Verifies that form has been filled correctly. If not, returns a list of keys where verification has failed | List |
update(T entity) | Fills all settable elements and clicks “update” Button or ”updateButton” | void |
1.3.3 WebPage
WebPage - A parent Java class for all JDI Page Object classes. WebPage class extends DriverBase class, implements PageObject interface and contains a number of commonly used methods:
WebPage is provided by JDI Light in:
- Java: com.epam.jdi.light.elements.composite.WebPage
Methods available for Java in JDI Light:
public class ActionsWebPageTests implements TestsInit {
@BeforeMethod(alwaysRun = true)
public void before() {
shouldBeLoggedIn();
contactFormPage.shouldBeOpened();
leftMenu.select("Contact form");
}
@Test
public void getUrlTest() {
Assert.assertEquals(WebPage.getUrl(), "https://jdi-testing.github.io/jdi-light/contacts.html");
}
@Test
public void getTitleTest() {
Assert.assertEquals(WebPage.getTitle(), "Contact Form");
}
@Test
public void checkOpenedTest() {
contactFormPage.checkOpened();
}
@Test
public void isOpenedTest() {
Assert.assertTrue(contactFormPage.isOpened());
}
@Test
public void scrollToBottomTest() {
WebPage.scrollToBottom();
}
@Test
public void scrollToTopTest() {
WebPage.scrollToTop();
}
@Test
public void scrollDownTest() {
WebPage.scrollDown(30);
}
@Test
public void scrollUpTest() {
WebPage.scrollUp(20);
}
@Test
public void scrollRightTest() {
WebPage.scrollRight(10);
}
@Test
public void scrollLeftTest() {
WebPage.scrollLeft(5);
}
@Test
public void toStringTest() {
Assert.assertEquals(contactFormPage.toString(), "StaticSite.contactFormPage (url=https://jdi-testing.github.io/jdi-light/contacts.html; title=Contact Form)");
}
}
Method | Description | Return Type |
---|---|---|
asForm() | Returns new Form parameterized with local Name | Form |
back() | Go back to previous page | void |
checkOpened() | Checks that page has opened | void |
forward() | Go forward to next page | void |
getCurrentPage() | Returns the name of current Page | String |
getHtml() | Gets HTML of current page | String |
getTitle() | Returns Page Title | String |
getUrl() | Returns URL of Page | String |
isOpened() | Checks that page has opened | boolean |
open(String) | Opens url specified for page | void |
open(Object...) | Opens url specified for page with parameters | void |
openedPage(String) | Checks that page has opened | void |
openSite() | Opens a Site | void |
openSite(Class<?>) | Parameterized Site opening | void |
openUrl(String) | Opening WebPage with URL | void |
openUrl(String,String) | Opening WebPage with URL and page name | void |
refresh() | Reloads current page | void |
reload() | Same as refresh() | void |
scroll(int,int) | Scrolls to designated position | void |
scrollToTop() | Scrolls to top | void |
scrollToBottom() | Scrolls to bottom | void |
scrollDown(int) | Scrolls down to designated position | void |
scrollUp(int) | Scrolls up to designated position | void |
scrollRight(int) | Scrolls right to designated position | void |
scrollLeft(int) | Scrolls left to designated position | void |
setCurrentPage(WebPage) | Instantiates the current Page with Name | void |
setUrl(String) | Setting Up URL of Page | void |
setUrl(String,String,CheckTypes) | Parameterized setting Up URL of Page | void |
shouldBeOpened() | Checks that page has opened | void |
shouldBeOpened(Object) | Checks that page has opened with parameters | void |
title() | Returns new StringCheckType object with checked Title | StringCheckType |
toString() | Overrides the Object class toString() method | String |
updatePageData(Url,Title) | Setting Page URL and Title | void |
url() | Returns new StringCheckType object with checked URL | StringCheckType |
visualWindowCheck() | empty | void |
WebPage() | Default constructor for WebPage class | WebPage |
WebPage(String) | Parameterized URL constructor for WebPage class | WebPage |
WebPage(String,String) | Parameterized with URL and Title constructor | WebPage |
windowScreenshot() | Getting window screenshot,returns path or exception | String |
xOffset() | Getting window x offset | long |
yOffset() | Getting window y offset | long |
zoom(double) | Zooms current page | void |
zoomLevel() | Getting zoom level | double |
More than that, it has a nested StringCheckType class with the following methods:
Method | Description | Return Type |
---|---|---|
check() | Checks that current page url/title equals to expected url/title | boolean |
contains() | Checks that current page url/title contains expected url/title-matcher | boolean |
match() | Checks that current page url/title matches to expected url/title-matcher | boolean |
StringCheckType(Supplier |
A parameterized constructor | StringCheckType |
2. Angular elements
2.1 Angular Common elements
2.1.1 Icons
Icon overview
Icon is located in the following class:
- Java: com.epam.jdi.light.ui.html.elements.common.Icon
There is two different icons in Angular: Basic icon and SVG icon:
//@FindBy(id="#basic_icon")
@UI("#basic_icon")
public static Icon basicIcon;
//@FindBy(id="#svg_icon")
@UI("#svg_icon")
public static Icon svgIcon;
@Test
public void checkBasicIconIsDisplayed() {
basicIcon.show();
basicIcon.is().displayed();
}
@Test
public void checkSVGIconIsDisplayed() {
svgIcon.show();
svgIcon.is().displayed();
}
<mat-icon _ngcontent-hkf-c334="" role="img" aria-hidden="false" aria-label="Example home icon" class="mat-icon notranslate material-icons mat-icon-no-color">home</mat-icon>
<mat-icon _ngcontent-hkf-c335="" role="img" svgicon="thumbs-up" aria-hidden="false" aria-label="Example thumbs up SVG icon" class="mat-icon notranslate mat-icon-no-color"><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fit="" preserveAspectRatio="xMidYMid meet" focusable="false">
<path d="M0 0h24v24H0z" fill="none"></path>
<path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-1.91l-.01-.01L23 10z"></path>
</svg></mat-icon>
Method | Description | Return Type |
---|---|---|
isDisplayed() | Verify state | boolean |
show() | Scroll to element | void |
Here you can find Icons tests
2.1.2 Progress spinner
Progress Spinner overview
Progress Spinner is located in the following class:
- Java: com.epam.jdi.light.angular.elements.common.Spinner
//@FindBy(id="#basic-progress-spinner")
@UI("#basic-progress-spinner")
public static Spinner basicProgressSpinner;
//@FindBy(id="#show-spinner")
@UI("#show-spinner")
public static Button showSpinner;
@Test
public void checkSpinnerAppearAndThenDisappear() {
showSpinner.click();
basicProgressSpinner.is().displayed();
basicProgressSpinner.waitFor().hidden();
}
<mat-spinner _ngcontent-krq-c336="" role="progressbar" mode="indeterminate" class="mat-spinner mat-progress-spinner mat-primary mat-progress-spinner-indeterminate-animation" style="width: 100px; height: 100px;">
<svg preserveAspectRatio="xMidYMid meet" focusable="false" viewBox="0 0 100 100" style="width: 100px; height: 100px;">
<circle cx="50%" cy="50%" r="45" class="ng-star-inserted" style="animation-name: mat-progress-spinner-stroke-rotate-100; stroke-dasharray: 282.743px; stroke-width: 10%;"/>
</svg>
</mat-spinner>
Method | Description | Return Type |
---|---|---|
isDisplayed() | Verify state | boolean |
show() | Scroll to element | void |
Here you can find Spinner tests
2.1.3 Slide toggle
Slide toggle overview
Slide toggle is located in the following class:
- Java: com.epam.jdi.light.angular.elements.common.SlideToggle
There is two different slide toggles in Angular: Basic and Configurable:
Basic toggle:
//@FindBy(id="slide-toggles-basic")
@UI("#slide-toggles-basic")
public static SlideToggle basicSlideToggle;
@Test
public void basicTest() {
basicSlideToggle.is().displayed();
resultSlideToggle.is().displayed();
checkedCheckbox.is().displayed();
disableCheckbox.is().displayed();
colorRadioButtons.is().displayed();
}
@Test
public void basicToggleCheckedTest() {
basicSlideToggle.check();
basicSlideToggle.is().selected();
basicSlideToggle.uncheck();
basicSlideToggle.is().deselected();
}
<mat-slide-toggle _ngcontent-bco-c235="" class="mat-slide-toggle mat-accent mat-checked" id="mat-slide-toggle-1" tabindex="-1">
<label class="mat-slide-toggle-label" for="mat-slide-toggle-1-input">
<div class="mat-slide-toggle-bar">
<input type="checkbox" role="switch" class="mat-slide-toggle-input cdk-visually-hidden" id="mat-slide-toggle-1-input" tabindex="0" aria-checked="true">
<div class="mat-slide-toggle-thumb-container">
<div class="mat-slide-toggle-thumb"/>
<div mat-ripple="" class="mat-ripple mat-slide-toggle-ripple mat-focus-indicator">
<div class="mat-ripple-element mat-slide-toggle-persistent-ripple"/>
</div>
</div>
</div>
<span class="mat-slide-toggle-content">
<span style="display: none;"> </span>Slide me!</span>
</label>
</mat-slide-toggle>
Configurable slide toggle:
//@FindBy(id="slide-toggles-configured")
@UI("#slide-toggles-configured")
public static SlideToggle resultSlideToggle;
@Test
public void resultToggleColorTest() {
disableCheckbox.uncheck();
resultSlideToggle.check();
primaryRadioButton.click();
resultSlideToggle.has().cssClass("mat-primary");
accentRadioButton.click();
resultSlideToggle.has().cssClass("mat-accent");
warningRadioButton.click();
resultSlideToggle.has().cssClass("mat-warn");
}
@Test
public void resultToggleCheckedTest() {
resultSlideToggle.uncheck();
checkedCheckbox.check();
resultSlideToggle.is().selected();
checkedCheckbox.uncheck();
resultSlideToggle.is().deselected();
}
@Test
public void resultToggleDisableTest() {
disableCheckbox.check();
resultSlideToggle.is().disabled();
disableCheckbox.uncheck();
resultSlideToggle.is().enabled();
}
<mat-card-content _ngcontent-noq-c236="" class="mat-card-content">
<h4 _ngcontent-noq-c236="">Slider configuration</h4>
<section _ngcontent-noq-c236="" class="example-section">
<label _ngcontent-noq-c236="" class="example-margin">Color:</label>
<mat-radio-group _ngcontent-noq-c236="" role="radiogroup" class="mat-radio-group ng-untouched ng-pristine ng-valid">
<mat-radio-button _ngcontent-noq-c236="" value="primary" class="mat-radio-button example-margin mat-accent" tabindex="-1" id="mat-radio-13">
<label class="mat-radio-label" for="mat-radio-13-input">
<div class="mat-radio-container">
<div class="mat-radio-outer-circle"/>
<div class="mat-radio-inner-circle"/>
<input type="radio" class="mat-radio-input cdk-visually-hidden" id="mat-radio-13-input" tabindex="0" name="mat-radio-group-11" value="primary">
<div mat-ripple="" class="mat-ripple mat-radio-ripple mat-focus-indicator">
<div class="mat-ripple-element mat-radio-persistent-ripple"/>
</div>
</div>
<div class="mat-radio-label-content">
<span style="display: none;"> </span> Primary </div>
</label>
</mat-radio-button>
<mat-radio-button _ngcontent-noq-c236="" value="accent" class="mat-radio-button example-margin mat-accent mat-radio-checked" tabindex="-1" id="mat-radio-14">
<label class="mat-radio-label" for="mat-radio-14-input">
<div class="mat-radio-container">
<div class="mat-radio-outer-circle"/>
<div class="mat-radio-inner-circle"/>
<input type="radio" class="mat-radio-input cdk-visually-hidden" id="mat-radio-14-input" tabindex="0" name="mat-radio-group-11" value="accent">
<div mat-ripple="" class="mat-ripple mat-radio-ripple mat-focus-indicator">
<div class="mat-ripple-element mat-radio-persistent-ripple"/>
</div>
</div>
<div class="mat-radio-label-content">
<span style="display: none;"> </span> Accent </div>
</label>
</mat-radio-button>
<mat-radio-button _ngcontent-noq-c236="" value="warn" class="mat-radio-button example-margin mat-accent" tabindex="-1" id="mat-radio-15">
<label class="mat-radio-label" for="mat-radio-15-input">
<div class="mat-radio-container">
<div class="mat-radio-outer-circle"/>
<div class="mat-radio-inner-circle"/>
<input type="radio" class="mat-radio-input cdk-visually-hidden" id="mat-radio-15-input" tabindex="0" name="mat-radio-group-11" value="warn">
<div mat-ripple="" class="mat-ripple mat-radio-ripple mat-focus-indicator">
<div class="mat-ripple-element mat-radio-persistent-ripple"/>
</div>
</div>
<div class="mat-radio-label-content">
<span style="display: none;"> </span> Warn </div>
</label>
</mat-radio-button>
</mat-radio-group>
</section>
<section _ngcontent-noq-c236="" class="example-section">
<mat-checkbox _ngcontent-noq-c236="" class="mat-checkbox example-margin mat-accent ng-untouched ng-pristine ng-valid" id="mat-checkbox-6">
<label class="mat-checkbox-layout" for="mat-checkbox-6-input">
<div class="mat-checkbox-inner-container">
<input type="checkbox" class="mat-checkbox-input cdk-visually-hidden" id="mat-checkbox-6-input" tabindex="0" aria-checked="false">
<div matripple="" class="mat-ripple mat-checkbox-ripple mat-focus-indicator">
<div class="mat-ripple-element mat-checkbox-persistent-ripple"/>
</div>
<div class="mat-checkbox-frame"/>
<div class="mat-checkbox-background">
<svg version="1.1" focusable="false" viewBox="0 0 24 24" xml:space="preserve" class="mat-checkbox-checkmark">
<path fill="none" stroke="white" d="M4.1,12.7 9,17.6 20.3,6.3" class="mat-checkbox-checkmark-path"/>
</svg>
<div class="mat-checkbox-mixedmark"/>
</div>
</div>
<span class="mat-checkbox-label">
<span style="display: none;"> </span>Checked</span>
</label>
</mat-checkbox>
</section>
<section _ngcontent-noq-c236="" class="example-section">
<mat-checkbox _ngcontent-noq-c236="" class="mat-checkbox example-margin mat-accent ng-untouched ng-pristine ng-valid" id="mat-checkbox-7">
<label class="mat-checkbox-layout" for="mat-checkbox-7-input">
<div class="mat-checkbox-inner-container">
<input type="checkbox" class="mat-checkbox-input cdk-visually-hidden" id="mat-checkbox-7-input" tabindex="0" aria-checked="false">
<div matripple="" class="mat-ripple mat-checkbox-ripple mat-focus-indicator">
<div class="mat-ripple-element mat-checkbox-persistent-ripple"/>
</div>
<div class="mat-checkbox-frame"/>
<div class="mat-checkbox-background">
<svg version="1.1" focusable="false" viewBox="0 0 24 24" xml:space="preserve" class="mat-checkbox-checkmark">
<path fill="none" stroke="white" d="M4.1,12.7 9,17.6 20.3,6.3" class="mat-checkbox-checkmark-path"/>
</svg>
<div class="mat-checkbox-mixedmark"/>
</div>
</div>
<span class="mat-checkbox-label">
<span style="display: none;"> </span>Disabled</span>
</label>
</mat-checkbox>
</section>
</mat-card-content>
List of some available Slide toggle methods:
Method | Description | Return Type |
---|---|---|
check() | Check element | void |
uncheck() | Uncheck element | void |
isEnabled() | Verify state | boolean |
isDisabled() | Verify state | boolean |
isDisplayed() | Verify state | boolean |
isSelected() | Verify state | boolean |
selected() | Verify state | boolean |
deselected() | Verify state | boolean |
click() | Click element | void |
hasClass() | Verify element class | boolean |
Here you can find Slide toggle tests
2.1.4 Checkbox
Checkbox overview
Checkbox is located in the following class:
- Java: com.epam.jdi.light.angular.elements.common.Checkbox
There is two different checkboxes in Angular: Basic and Configurable.
See examples with HTML code describing datepicker elements.
//@FindBy(id="basic-checkbox")
@UI("basic-checkbox")
public static Checkbox basicCheckbox;
@Test
public void checkLabelValue() {
basicCheckbox.label().has().value("Check me!");
resultCheckbox.label().has().value("I'm a checkbox");
}
@Test
public void basicCheckboxValidation() {
basicCheckbox.is().displayed().and().enabled().and().deselected();
}
@Test
public void checkBasicCheckbox() {
basicCheckbox.check();
basicCheckbox.is().selected();
}
<section class="example-section">
<mat-checkbox id="basic-checkbox">Check me!</mat-checkbox>
</section>
//@FindBy(id="checked-checkbox")
@UI("checked-checkbox")
public static Checkbox checkedCheckbox;
//@FindBy(id="indeterminate-checkbox")
@UI("indeterminate-checkbox")
public static Checkbox indeterminateCheckbox;
//@FindBy(id="disabled-checkbox")
@UI("disabled-checkbox")
public static Checkbox disabledCheckbox;
//@FindBy(id="result-checkbox")
@UI("result-checkbox")
public static Checkbox resultCheckbox;
//@FindBy(id="align-before-radio-button")
@UI("align-before-radio-button")
public static Button alignBeforeRadioButton;
//@FindBy(id="align-after-radio-button")
@UI("align-after-radio-button")
public static Button alignAfterRadioButton;
@Test
public void indeterminateTest() {
indeterminateCheckbox.click();
resultCheckbox.is().indeterminate();
}
@Test
public void disabledOption() {
disabledCheckbox.click();
resultCheckbox.is().disabled();
}
@Test
public void configurableCheckboxTest() {
indeterminateCheckbox.check();
alignBeforeRadioButton.click();
resultCheckbox.is().indeterminate().and().cssClass("mat-checkbox-label-before");
}
<mat-card>
<mat-card-content>
<h4>Checkbox configuration</h4>
<section class="example-section">
<mat-checkbox id="checked-checkbox" class="example-margin" [(ngModel)]="checked">
Checked
</mat-checkbox>
<mat-checkbox id="indeterminate-checkbox" class="example-margin" [(ngModel)]="indeterminate">
Indeterminate
</mat-checkbox>
</section>
<section class="example-section">
<label class="example-margin">Align:</label>
<mat-radio-group [(ngModel)]="labelPosition">
<mat-radio-button id="align-after-radio-button" class="example-margin" value="after">
After
</mat-radio-button>
<mat-radio-button id="align-before-radio-button" class="example-margin" value="before">
Before
</mat-radio-button>
</mat-radio-group>
</section>
<section class="example-section">
<mat-checkbox id="disabled-checkbox" class="example-margin" [(ngModel)]="disabled">
Disabled
</mat-checkbox>
</section>
</mat-card-content>
</mat-card>
<mat-card class="result">
<mat-card-content>
<h4>Result</h4>
<section class="example-section">
<mat-checkbox
id="result-checkbox"
class="example-margin"
[(ngModel)]="checked"
[(indeterminate)]="indeterminate"
[labelPosition]="labelPosition"
[disabled]="disabled">
I'm a checkbox
</mat-checkbox>
</section>
</mat-card-content>
</mat-card>
List of some available Checkbox methods:
Method | Description | Return Type |
---|---|---|
is() | Assert action | CheckboxAssert |
check() | Check element | void |
uncheck() | Uncheck element | void |
click() | Click on element | void |
isSelected() | Shows that Checkbox has selected | boolean |
isEnabled() | Shows that Checkbox has enabled | boolean |
isDisabled() | Shows that Checkbox has disabled | boolean |
isIndeterminate() | Shows that Checkbox has indeterminate | boolean |
label() | Get element label | Label |
Here you can find Checkbox tests
2.1.5 Inputs
Input overview
Input is located in the following class:
- Java: _com.epam.jdi.light.ui.html.elements.common.TextField _com.epam.jdi.light.ui.html.elements.common.TextArea
There are eight different inputs in Angular:
- Basic inputs
- Input with a custom ErrorStateMatcher
- Auto-resizing textarea
- Input with a clear button
- Input with error messages
- Input in a form
- Input with hints
- Input with prefixes and suffixes
Basic inputs:
//@FindBy(id="inputs_basic_food")
@UI("#inputs_basic_food")
public static TextField foodBasicInput;
//@FindBy(id="inputs_basic_comment")
@UI("#inputs_basic_comment")
public static TextField leaveACommentBasicInput;
@Test
public void basicInputTest() {
foodBasicInput.isDisplayed();
foodBasicInput.clear();
foodBasicInput.setText("Lasagna");
foodBasicInput.is().text("Lasagna");
foodBasicInput.clear();
foodBasicInput.sendKeys("Ice Cream");
foodBasicInput.is().text(containsString("Ice"));
leaveACommentBasicInput.isDisplayed();
leaveACommentBasicInput.sendKeys("Delicious");
leaveACommentBasicInput.is().text("Delicious");
}
<input _ngcontent-ohc-c255="" matinput="" id="inputs_basic_food" placeholder="Ex. Pizza" value="Sushi" class="mat-input-element mat-form-field-autofill-control ng-tns-c94-34 cdk-text-field-autofill-monitored" aria-invalid="false" aria-required="false">
Input with a custom ErrorStateMatcher:
//@FindBy(id="inputs_errorStateMatcher_email")
@UI("#inputs_errorStateMatcher_email")
public static TextField emailErrorStateMatcherInput;
//@FindBy(id="inputs_errorStateMatcher_message")
@UI("#inputs_errorStateMatcher_message")
public static Text errorStateMatcherMessageInput;
@Test
public void inputWithACustomErrorStateMatcherTest() {
emailErrorStateMatcherInput.isDisplayed();
emailErrorStateMatcherInput.sendKeys("test");
errorStateMatcherMessageInput.is().text("Please enter a valid email address");
}
<input _ngcontent-ohc-c256="" matinput="" id="inputs_errorStateMatcher_email" placeholder="Ex. pat@example.com" class="mat-input-element mat-form-field-autofill-control ng-tns-c94-39 cdk-text-field-autofill-monitored ng-untouched ng-pristine ng-invalid" aria-describedby="mat-hint-3" aria-invalid="false" aria-required="false">
Auto-resizing textarea:
//@FindBy(id="inputs_autosize_textarea")
@UI("#inputs_autosize_textarea")
public static TextArea autoSizeTextArea;
@Test
public void autoResizingTextAreaTest() {
autoSizeTextArea.isDisplayed();
autoSizeTextArea.setLines("line1", "line2");
autoSizeTextArea.addNewLine("line3");
autoSizeTextArea.is().text("line1\nline2\nline3");
autoSizeTextArea.clear();
autoSizeTextArea.is().text("");
autoSizeTextArea.setText("TextArea");
autoSizeTextArea.is().text(containsString("Text"));
}
<textarea _ngcontent-ohc-c257="" rows="1" matinput="" id="inputs_autosize_textarea" cdktextareaautosize="" cdkautosizeminrows="1" cdkautosizemaxrows="5" class="mat-input-element mat-form-field-autofill-control cdk-textarea-autosize ng-tns-c94-42 cdk-text-field-autofill-monitored" aria-invalid="false" aria-required="false" style="min-height: 18px; max-height: 90px; height: 18px;"></textarea>
Input with a clear button:
//@FindBy(id="inputs_clearable_textbox")
@UI("#inputs_clearable_textbox")
public static TextArea clearableInput;
//@FindBy(id="inputs_clearable_button")
@UI("#inputs_clearable_button")
public static Button clearableInputButton;
@Test
public void clearableInputTest() {
clearableInput.isDisplayed();
clearableInput.clear();
clearableInput.sendKeys("test");
clearableInputButton.isDisplayed();
clearableInputButton.click();
clearableInput.is().text("");
}
<input _ngcontent-ohc-c258="" matinput="" id="inputs_clearable_textbox" type="text" class="mat-input-element mat-form-field-autofill-control ng-tns-c94-43 cdk-text-field-autofill-monitored ng-untouched ng-pristine ng-valid" aria-invalid="false" aria-required="false">
<button _ngcontent-ohc-c258="" mat-button="" id="inputs_clearable_button" matsuffix="" mat-icon-button="" aria-label="Clear" class="mat-focus-indicator mat-button mat-icon-button mat-button-base ng-tns-c94-43 ng-star-inserted">
<span class="mat-button-wrapper">
<mat-icon _ngcontent-ohc-c258="" role="img" class="mat-icon notranslate material-icons mat-icon-no-color" aria-hidden="true">close</mat-icon>
</span>
<div matripple="" class="mat-ripple mat-button-ripple mat-button-ripple-round"/>
<div class="mat-button-focus-overlay"/>
</button>
Input with error messages:
//@FindBy(id="inputs_error_email")
@UI("#inputs_error_email")
public static TextField emailInput;
//@FindBy(id="inputs_error_message")
@UI("#inputs_error_message")
public static Text errorMessageInput;
@Test
public void inputWithErrorMessagesTest() {
emailInput.isDisplayed();
emailInput.sendKeys("test");
emailInput.sendKeys(Keys.ENTER);
errorMessageInput.isDisplayed();
errorMessageInput.is().text("Please enter a valid email address");
}
<input _ngcontent-ohc-c259="" matinput="" id="inputs_error_email" placeholder="Ex. pat@example.com" class="mat-input-element mat-form-field-autofill-control ng-tns-c94-44 cdk-text-field-autofill-monitored ng-untouched ng-pristine ng-invalid" aria-invalid="false" aria-required="false">
Inputs in a form:
//@FindBy(css="input-form-example form")
@UI("input-form-example form")
public static InputsForm inputsForm;
@Test
public void inputsInAFormTest() {
inputsForm.fill(DEFAULT_USER);
inputsForm.firstName.is().text("Long");
inputsForm.lastName.is().text("Dinh");
inputsForm.address.is().text("259 Tran Hung Dao Street");
inputsForm.address2.is().text("Ward Co Giang, District 1");
inputsForm.city.is().text("Ho Chi Minh");
inputsForm.state.is().text("Ho Chi Minh");
inputsForm.postalCode.is().text("70000");
}
<form _ngcontent-sod-c260="" novalidate="" class="example-form ng-untouched ng-pristine ng-valid"></form>
Input with hints:
//@FindBy(id="inputs_hints_message")
@UI("#inputs_hints_message")
public static TextField messageHintInput;
//@FindBy(id="inputs_hints_text")
@UI("#inputs_hints_text")
public static Text messageHint;
//@FindBy(id="inputs_hints_counter")
@UI("#inputs_hints_counter")
public static Text messageCounterHint;
@Test
public void inputWithHintsTest() {
messageHintInput.isDisplayed();
messageHintInput.sendKeys("test");
messageHint.isDisplayed();
messageHint.is().text("Don't disclose personal info");
messageCounterHint.isDisplayed();
messageCounterHint.is().text("4 / 256");
}
<input _ngcontent-ohc-c261="" matinput="" id="inputs_hints_message" maxlength="256" placeholder="Ex. I need help with..." class="mat-input-element mat-form-field-autofill-control ng-tns-c94-53 cdk-text-field-autofill-monitored" aria-describedby="inputs_hints_text inputs_hints_counter" aria-invalid="false" aria-required="false">
<mat-hint _ngcontent-ohc-c261="" id="inputs_hints_text" class="mat-hint ng-tns-c94-53"><strong _ngcontent-ohc-c261="">Don't disclose personal info</strong></mat-hint>
Input with prefixes and suffixes:
//@FindBy(id="inputs_prefixes")
@UI("#inputs_prefixes")
public static Text prefixInput;
//@FindBy(id="inputs_suffixes")
@UI("#inputs_suffixes")
public static Icon suffixInput;
//@FindBy(id="inputs_prefixes_suffixes_phone")
@UI("#inputs_prefixes_suffixes_phone")
public static TextField telephoneInput;
@Test
public void inputWithPrefixesAndSuffixesTest() {
prefixInput.isDisplayed();
suffixInput.isDisplayed();
telephoneInput.isDisplayed();
telephoneInput.sendKeys("0123456789");
telephoneInput.clear();
telephoneInput.is().text("");
}
<span _ngcontent-ohc-c262="" matprefix="" id="inputs_prefixes" class="ng-tns-c94-54">+1 </span>
<input _ngcontent-ohc-c262="" type="tel" matinput="" id="inputs_prefixes_suffixes_phone" placeholder="555-555-1234" class="mat-input-element mat-form-field-autofill-control ng-tns-c94-54 cdk-text-field-autofill-monitored" aria-invalid="false" aria-required="false">
<mat-icon _ngcontent-ohc-c262="" role="img" matsuffix="" id="inputs_suffixes" class="mat-icon notranslate material-icons mat-icon-no-color ng-tns-c94-54" aria-hidden="true">edit</mat-icon>
List of available methods:
TextField:
Method | Description | Return Type |
---|---|---|
getText() | returns text from the text field | String |
getValue() | returns text from the text field | String |
setValue(String) | returns text from the text field | void |
is() | property that returns object for work with assertions | TextAssert |
TextArea:
Method | Description | Return Type |
---|---|---|
setLines(String...) | Add lines as one string with '\n' delimiter | void |
getText() | Returns lines dividing text using '\n' | List |
addNewLine(String) | add line to the already existing | void |
cols() | returns value of cols attribute | int |
rows() | returns value of rows attribute | int |
getText() | returns text from the textarea | String |
getValue() | returns text from the textarea | String |
maxlength() | returns value of maxlength attribute | int |
minlengt() | returns value of minlength attribute | int |
setValue(String) | returns text from the text field | void |
is() | property that returns object for work with assertions | TextAssert |
Java tests examples
2.1.6 Toolbar
Toolbar overview
"mat-toolbar" is a container for headers, titles, or actions.
There is two different toolbars in Angular: Single row and Multiple row.
/**@FindBy(id = "toolbar-basic") public static ToolbarSection toolbarSection;*/
@UI("#toolbar-basic")
public static TextArea toolbarTextArea;
public static Text toolbarTextArea;
/**@FindBy(id = "toolbar-table") public static ToolbarSection toolbarSection;*/
@UI("#toolbar-table")
public static Table toolbarTable;
/**@FindBy(css = "#toolbar-table span:not(.example-spacer)") public static ToolbarSection toolbarSection;*/
@UI("#toolbar-table span:not(.example-spacer)")
public static JList<Text> toolbarRowsElementsWithText;
@Test
public void basicToolbarTest() {
String textForTest = "My App";
String classForTest = "mat-toolbar";
toolbarTextArea.is().displayed();
toolbarTable.has().cssClass(classForTest);
toolbarTextArea.is().text(containsString(textForTest));
}
@Test
public void multiRowToolbarTest() {
String classForTest = "mat-toolbar";
List<String> listForTest = Arrays.asList("Custom Toolbar", "Second Line", "Third Line");
toolbarTable.is().displayed();
toolbarTable.has().cssClass(classForTest);
toolbarRowsElementsWithText.is().values(listForTest);
}
@Test
public void multiRowToolbarColorTest() {
String colorForTest = "primary";
toolbarTable.has().attr("color", colorForTest);
}
<mat-toolbar _ngcontent-duh-c290="" id="toolbar-basic" class="mat-toolbar mat-toolbar-single-row">My App</mat-toolbar>
<mat-toolbar _ngcontent-duh-c291="" id="toolbar-table" color="primary" class="mat-toolbar mat-primary mat-toolbar-multiple-rows"><mat-toolbar-row _ngcontent-duh-c291="" class="mat-toolbar-row"><span _ngcontent-duh-c291="">Custom Toolbar</span></mat-toolbar-row><mat-toolbar-row _ngcontent-duh-c291="" class="mat-toolbar-row"><span _ngcontent-duh-c291="">Second Line</span><span _ngcontent-duh-c291="" class="example-spacer"></span><mat-icon _ngcontent-duh-c291="" role="img" aria-hidden="false" aria-label="Example user verified icon" class="mat-icon notranslate example-icon material-icons mat-icon-no-color">verified_user</mat-icon></mat-toolbar-row><mat-toolbar-row _ngcontent-duh-c291="" class="mat-toolbar-row"><span _ngcontent-duh-c291="">Third Line</span><span _ngcontent-duh-c291="" class="example-spacer"></span><mat-icon _ngcontent-duh-c291="" role="img" aria-hidden="false" aria-label="Example heart icon" class="mat-icon notranslate example-icon material-icons mat-icon-no-color">favorite</mat-icon><mat-icon _ngcontent-duh-c291="" role="img" aria-hidden="false" aria-label="Example delete icon" class="mat-icon notranslate example-icon material-icons mat-icon-no-color">delete</mat-icon></mat-toolbar-row></mat-toolbar>
Method | Description | Return Type |
---|---|---|
hasClass() | Match passed value with the element class | boolean |
values() | Assert that values are the same | List |
has() | assert that element has attribute | boolean |
attr() | Check whether an element has attribute of specified name and with given value | IsAssert |
is() | Assert action | TextAssert |
displayed() | Check that element is displayed | TextAssert |
Here you can find Toolbar tests
2.1.7 Basic Button
Button overview
Basic Button is located in the following class:
- Java: com.epam.jdi.light.ui.html.elements.common.Button
The angular Button:
//@FindBy(id="basic-buttons-label")
@UI("#basic-buttons-label")
public static Button basicBasicButton;
//@FindBy(id="basic-primary-button")
@UI("#basic-primary-button")
public static Button basicPrimaryButton;
@Test
public void clickTest() {
basicBasicButton.click();
basicBasicButton.has().cssClass(FOCUSED_CLASS);
basicButtonsSection.basicButtonsLabel.is().has().text(containsString(BASIC_TEXT));
}
@Test
public void clickWithMoveTest() {
basicWarnButton.click(ElementArea.TOP_LEFT);
basicWarnButton.has().cssClass(FOCUSED_CLASS);
basicButtonsSection.basicButtonsLabel.is().has().text(containsString(WARN_TEXT));
}
@Test
public void disableButtonTest() {
basicDisabledButton.is().disabled();
}
@Test
public void assertValidationTest() {
basicBasicButton.assertThat().text(is(BASIC_TEXT));
basicPrimaryButton.assertThat().text(is(PRIMARY_TEXT));
basicAccentButton.assertThat().text(is(ACCENT_TEXT));
basicWarnButton.assertThat().text(is(WARN_TEXT));
basicDisabledButton.assertThat().text(is(DISABLED_TEXT));
basicLinkButton.assertThat().text(is(LINK_TEXT));
}
@Test
public void isValidationTest() {
basicWarnButton.is().displayed();
basicWarnButton.is().enabled();
basicWarnButton.is().text(is(WARN_TEXT));
basicWarnButton.is().text(containsString(WARN_TEXT));
assertThat(basicWarnButton.core().css("font-size"), is("14px"));
basicWarnButton.assertThat().displayed()
.and().text(is(WARN_TEXT))
.core()
.css("font-size", is("14px"))
.and()
.cssClass("mat-button")
.and()
.attr("type")
.tag(is("button"));
basicDisabledButton.is().text(containsString(DISABLED_TEXT));
basicDisabledButton.is().disabled();
}
<button _ngcontent-jos-c358="" mat-raised-button="" color="primary" id="raised-primary-button" class="mat-focus-indicator mat-raised-button mat-button-base mat-primary" ng-reflect-color="primary">
<span class="mat-button-wrapper">Primary</span>
<div matripple="" class="mat-ripple mat-button-ripple" ng-reflect-disabled="false" ng-reflect-centered="false" ng-reflect-trigger="[object HTMLButtonElement]"></div>
<div class="mat-button-focus-overlay"></div>
</button>
Method | Description | Return Type |
---|---|---|
getValue() | Returns value | String |
is() | Assert action | TextAssert |
Basic Button java tests examples
2.1.8 Button toggle
Button toggle overview
Button toggle is based on Basic Button. Basic Button is located in the following class:
- Java: com.epam.jdi.light.ui.html.elements.common.Button
Button toggle located in the following class:
- Java: com.epam.jdi.light.angular.elements.complex.ButtonToggle
There are two different button toggles in Angular: Basic and Exclusive:
//@FindBy(id = "mat-button-toggle-group-font")
@UI("#mat-button-toggle-group-font")
public static ButtonToggle basicButtonToggle;
@Test
public void verifyButtonToggle() {
basicButtonToggle.is().displayed();
basicButtonToggle.is().enabled();
String ITALIC = "italic";
basicButtonToggle.clickButtonToggleByValue(ITALIC);
basicButtonToggle.is().assertButtonToggleIsSelected(ITALIC);
basicButtonToggle.is().assertButtonToggleButtonIsPressed(ITALIC);
basicButtonToggle.is().assertButtonToggleButtonHasText(ITALIC);
}
@Test
public void verifyButtonToggleCombineSelection() {
String BOLD = "bold";
basicButtonToggle.clickButtonToggleByValue(BOLD);
String UNDERLINE = "underline";
basicButtonToggle.clickButtonToggleByValue(UNDERLINE);
basicButtonToggle.is().assertButtonToggleIsSelected(BOLD);
basicButtonToggle.is().assertButtonToggleIsSelected(UNDERLINE);
basicButtonToggle.clickButtonToggleByValue(BOLD);
basicButtonToggle.is().assertButtonToggleIsNotSelected(BOLD);
}
<mat-button-toggle _ngcontent-eoo-c327="" value="underline" id="underline-button-toggle" class="mat-button-toggle mat-focus-indicator mat-button-toggle-appearance-standard" tabindex="-1">
<button type="button" class="mat-button-toggle-button mat-focus-indicator" tabindex="0" aria-pressed="false">
<div class="mat-button-toggle-label-content">Underline</div>
</button>
<div class="mat-button-toggle-focus-overlay"></div>
<div matripple="" class="mat-ripple mat-button-toggle-ripple"></div>
</mat-button-toggle>
Exclusive button toggle:
//@FindBy(id = "mat-button-toggle-group-align")
@UI("#mat-button-toggle-group-align")
public static ButtonToggle basicButtonToggleAlign;
//@FindBy(css = "div.example-selected-value")
@UI("div.example-selected-value")
public static Text selectedValue;
@Test
public void verifyExclusiveButtonToggle() {
String LEFT = "left";
basicButtonToggleAlign.is().displayed();
basicButtonToggleAlign.is().enabled();
basicButtonToggleAlign.clickButtonToggleByValue(LEFT);
basicButtonToggleAlign.is().assertButtonToggleIsSelected(LEFT);
selectedValue.has().text("Selected value: left");
}
@Test
public void verifyExclusiveButtonToggleSeparateSelection() {
String CENTER = "center";
String LEFT = "left";
String RIGHT = "right";
basicButtonToggleAlign.clickButtonToggleByValue(CENTER);
basicButtonToggleAlign.clickButtonToggleByValue(RIGHT);
basicButtonToggleAlign.clickButtonToggleByValue(LEFT);
basicButtonToggleAlign.is().assertButtonToggleIsSelected(LEFT);
basicButtonToggleAlign.is().assertButtonToggleIsNotSelected(RIGHT);
basicButtonToggleAlign.is().assertButtonToggleIsNotSelected(CENTER);
}
<mat-button-toggle _ngcontent-pwh-c328="" value="left" aria-label="Text align left" id="left-align-button-toggle" class="mat-button-toggle mat-focus-indicator mat-button-toggle-appearance-standard" tabindex="-1">
<button type="button" class="mat-button-toggle-button mat-focus-indicator" tabindex="0" aria-pressed="false" name="mat-button-toggle-group-7" aria-label="Text align left">
<div class="mat-button-toggle-label-content"><mat-icon _ngcontent-pwh-c328="" role="img" class="mat-icon notranslate material-icons mat-icon-no-color" aria-hidden="true">format_align_left</mat-icon></div>
</button>
<div class="mat-button-toggle-focus-overlay"></div>
<div matripple="" class="mat-ripple mat-button-toggle-ripple"></div>
</mat-button-toggle>
List of available methods:
Method | Description | Return Type |
---|---|---|
clickButtonToggleByValue(String) | Click required button | void |
clickButtonToggleByValue(String) | is button pressed | boolean |
buttonToggleHasText(String) | Does button has text | boolean |
isButtonToggleSelected(String) | Is button toggle selected | boolean |
is() | Assert action | ButtonToggleAssert |
Here you can find Button toggle tests
2.1.9 Badge
Badge overview
Badge is located in the following class:
- Java: com.epam.jdi.light.angular.elements.common.Badge
//@FindBy(css = "#text-with-badge span")
@UI("#text-with-badge span")
public static Badge textWithBadge;
//@FindBy(css = "#button-with-left-badge span:not(.mat-button-wrapper)")
@UI("#button-with-left-badge span:not(.mat-button-wrapper)")
public static Badge buttonWithBadge;
//@FindBy(css = "#icon-with-badge span")
@UI("#icon-with-badge span")
public static Badge iconWithBadge;
@Test
public void basicBadgeTest() {
textWithBadge.show();
textWithBadge.badge().is().displayed();
textWithBadge.badge().has().text("4");
textWithBadge.has().color("Violet");
}
@Test
public void buttonBadgeTest() {
buttonWithBadge.show();
buttonWithBadge.badge().is().displayed();
buttonWithBadge.badge().has().text("8");
buttonWithBadge.has().color("Yellow");
}
@Test
public void iconBadgeTest() {
iconWithBadge.show();
iconWithBadge.badge().is().displayed();
iconWithBadge.badge().has().text("15");
iconWithBadge.has().color("Red");
}
<span _ngcontent-iwc-c329="" matbadge="4" matbadgeoverlap="false" id="text-with-badge" class="mat-badge mat-badge-above mat-badge-after mat-badge-medium">
"Text with a badge"
<span _ngcontent-iwc-c329="" id="mat-badge-content-0" class="mat-badge-content mat-badge-active">4</span>
</span>
Method | Description | Return Type |
---|---|---|
is() | Assert action | BadgeAssert |
badge() | Get badge | UIElement |
color(String) | Check that color is correct | boolean |
Here you can find Badge tests
2.1.10 Progress bar
Progress bar overview
Progress bar is located in the following class:
- Java: com.epam.jdi.light.ui.angular.elements.common.ProgressBar
There is 5 different progress bars in Angular: Buffer, Determinate, Indeterminate, Query and Configurable:
Buffer progress bar:
//@FindBy(css = "#show-buffer-progress-bar-button")
@UI("#show-buffer-progress-bar-button")
public static Button showBufferProgressBarButton;
//@FindBy(css = "#mat-progress-bar-buffer")
@UI("#mat-progress-bar-buffer")
public static ProgressBar matProgressBarBuffer;
@Test
public void verifyBufferProgressBarTest() throws Exception {
showBufferProgressBarButton.click();
matProgressBarBuffer.shouldBe().displayed();
matProgressBarBuffer.show();
matProgressBarBuffer.shouldBe().visible();
matProgressBarBuffer.has().mode(BUFFER);
matProgressBarBuffer.has().value(0);
matProgressBarBuffer.has().bufferValue(0.0);
matProgressBarBuffer.has().max(100);
matProgressBarBuffer.has().min(0);
matProgressBarBuffer.has().color(BLUE);
matProgressBarBuffer.is().disappear(5);
}
<progress-bar-buffer-example _nghost-pnn-c338="" ng-version="9.1.0">
<h2 _ngcontent-pnn-c338="" class="example-h2">
<a _ngcontent-pnn-c338="" href="https://material.angular.io/components/progress-bar/overview#buffer"> Buffer progress-bar </a>
</h2>
<button _ngcontent-pnn-c338="" mat-raised-button="" id="show-buffer-progress-bar-button" class="mat-focus-indicator mat-raised-button mat-button-base">
<span class="mat-button-wrapper"> Show progress-bar for 5 seconds
</span>
<div matripple="" class="mat-ripple mat-button-ripple"/>
<div class="mat-button-focus-overlay"/>
</button>
<div _ngcontent-pnn-c338="" hidden="">
<mat-progress-bar _ngcontent-pnn-c338="" role="progressbar" aria-valuemin="0" aria-valuemax="100" id="mat-progress-bar-buffer" mode="buffer" class="mat-progress-bar mat-primary" aria-valuenow="0">
<svg width="100%" height="4" focusable="false" class="mat-progress-bar-background mat-progress-bar-element">
<defs>
<pattern x="4" y="0" width="8" height="4" patternUnits="userSpaceOnUse" id="mat-progress-bar-0">
<circle cx="2" cy="2" r="2"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url('/jdi-light/angular.html#mat-progress-bar-0')"/>
</svg>
<div class="mat-progress-bar-buffer mat-progress-bar-element" style="transform: scaleX(0);"/>
<div class="mat-progress-bar-primary mat-progress-bar-fill mat-progress-bar-element" style="transform: scaleX(0);"/>
<div class="mat-progress-bar-secondary mat-progress-bar-fill mat-progress-bar-element"/>
</mat-progress-bar>
</div>
</progress-bar-buffer-example>
Determinate progress bar:
//@FindBy(css = "#mat-progress-bar-determinate")
@UI("#mat-progress-bar-determinate")
public static ProgressBar matProgressBarDeterminate;
@Test
public void verifyDeterminateProgressBarTest() throws Exception {
matProgressBarDeterminate.shouldBe().displayed();
matProgressBarDeterminate.show();
matProgressBarDeterminate.shouldBe().visible();
matProgressBarDeterminate.has().mode(DETERMINATE);
matProgressBarDeterminate.has().value(40);
matProgressBarDeterminate.has().max(100);
matProgressBarDeterminate.has().min(0);
matProgressBarDeterminate.has().color(BLUE);
}
<progress-bar-determinate-example _nghost-pnn-c339="" ng-version="9.1.0">
<h2 _ngcontent-pnn-c339="" class="example-h2">
<a _ngcontent-pnn-c339="" href="https://material.angular.io/components/progress-bar/overview#determinate"> Determinate progress-bar </a>
</h2>
<mat-progress-bar _ngcontent-pnn-c339="" role="progressbar" aria-valuemin="0" aria-valuemax="100" id="mat-progress-bar-determinate" mode="determinate" value="40" class="mat-progress-bar mat-primary" aria-valuenow="40">
<svg width="100%" height="4" focusable="false" class="mat-progress-bar-background mat-progress-bar-element">
<defs>
<pattern x="4" y="0" width="8" height="4" patternUnits="userSpaceOnUse" id="mat-progress-bar-1">
<circle cx="2" cy="2" r="2"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url('/jdi-light/angular.html#mat-progress-bar-1')"/>
</svg>
<div class="mat-progress-bar-buffer mat-progress-bar-element"/>
<div class="mat-progress-bar-primary mat-progress-bar-fill mat-progress-bar-element" style="transform: scaleX(0.4);"/>
<div class="mat-progress-bar-secondary mat-progress-bar-fill mat-progress-bar-element"/>
</mat-progress-bar>
</progress-bar-determinate-example>
Indeterminate progress bar:
//@FindBy(css = "#show-indeterminate-progress-bar-button")
@UI("#show-indeterminate-progress-bar-button")
public static Button showIndeterminateProgressBarButton;
//@FindBy(css = "#mat-progress-bar-indeterminate")
@UI("#mat-progress-bar-indeterminate")
public static ProgressBar matProgressBarIndeterminate;
@Test
public void verifyIndeterminateProgressBarTest() {
showIndeterminateProgressBarButton.click();
matProgressBarIndeterminate.shouldBe().displayed();
matProgressBarIndeterminate.show();
matProgressBarIndeterminate.shouldBe().visible();
matProgressBarIndeterminate.has().mode(INDETERMINATE);
matProgressBarIndeterminate.has().max(100);
matProgressBarIndeterminate.has().min(0);
matProgressBarIndeterminate.has().color(BLUE);
matProgressBarIndeterminate.is().disappear(5);
}
<progress-bar-query-example class="ng-star-inserted">
<mat-progress-bar role="progressbar" aria-valuemin="0" aria-valuemax="100" tabindex="-1" mode="query" class="mat-progress-bar mat-primary">
<div aria-hidden="true">
<svg width="100%" height="4" focusable="false" class="mat-progress-bar-background mat-progress-bar-element">
<defs>
<pattern x="4" y="0" width="8" height="4" patternUnits="userSpaceOnUse" id="mat-progress-bar-3">
<circle cx="2" cy="2" r="2"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url('/components/progress-bar/overview#mat-progress-bar-3')"/>
</svg>
<div class="mat-progress-bar-buffer mat-progress-bar-element"/>
<div class="mat-progress-bar-primary mat-progress-bar-fill mat-progress-bar-element" style="transform: scale3d(0, 1, 1);"/>
<div class="mat-progress-bar-secondary mat-progress-bar-fill mat-progress-bar-element"/>
</div>
</mat-progress-bar>
</progress-bar-query-example>
Query progress bar:
//@FindBy(css = "#mat-progress-bar-query")
@UI("#mat-progress-bar-query")
public static ProgressBar matProgressBarQuery;
@Test
public void verifyQueryProgressBarTest() {
matProgressBarQuery.shouldBe().displayed();
matProgressBarQuery.show();
matProgressBarQuery.shouldBe().visible();
matProgressBarQuery.has().mode(QUERY);
matProgressBarQuery.has().max(100);
matProgressBarQuery.has().min(0);
matProgressBarQuery.has().color(BLUE);
}
<progress-bar-determinate-example _nghost-pnn-c339="" ng-version="9.1.0">
<h2 _ngcontent-pnn-c339="" class="example-h2">
<a _ngcontent-pnn-c339="" href="https://material.angular.io/components/progress-bar/overview#determinate"> Determinate progress-bar </a>
</h2>
<mat-progress-bar _ngcontent-pnn-c339="" role="progressbar" aria-valuemin="0" aria-valuemax="100" id="mat-progress-bar-determinate" mode="determinate" value="40" class="mat-progress-bar mat-primary" aria-valuenow="40">
<svg width="100%" height="4" focusable="false" class="mat-progress-bar-background mat-progress-bar-element">
<defs>
<pattern x="4" y="0" width="8" height="4" patternUnits="userSpaceOnUse" id="mat-progress-bar-1">
<circle cx="2" cy="2" r="2"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url('/jdi-light/angular.html#mat-progress-bar-1')"/>
</svg>
<div class="mat-progress-bar-buffer mat-progress-bar-element"/>
<div class="mat-progress-bar-primary mat-progress-bar-fill mat-progress-bar-element" style="transform: scaleX(0.4);"/>
<div class="mat-progress-bar-secondary mat-progress-bar-fill mat-progress-bar-element"/>
</mat-progress-bar>
</progress-bar-determinate-example>
Configurable progress bar:
//@FindBy(css = "#mat-progress-bar-configurable")
@UI("#mat-progress-bar-configurable")
public static ProgressBar matProgressBarConfigurable;
@Test
public void verifyBasicConfigurableProgressBarTest() throws Exception {
matProgressBarConfigurable.shouldBe().displayed();
matProgressBarConfigurable.show();
matProgressBarConfigurable.shouldBe().visible();
matProgressBarConfigurable.has().mode(DETERMINATE);
matProgressBarConfigurable.has().value(50);
matProgressBarConfigurable.has().max(100);
matProgressBarConfigurable.has().min(0);
matProgressBarConfigurable.has().color(BLUE);
}
<progress-bar-configurable-example _nghost-pnn-c342="" ng-version="9.1.0"><h2 _ngcontent-pnn-c342="" class="example-h2">Configurable progress bar</h2><mat-card _ngcontent-pnn-c342="" class="mat-card mat-focus-indicator"><mat-card-content _ngcontent-pnn-c342="" class="mat-card-content"><h4 _ngcontent-pnn-c342="">Progress bar configuration</h4><section _ngcontent-pnn-c342="" class="example-section"><label _ngcontent-pnn-c342="" class="example-margin">Color:</label><mat-radio-group _ngcontent-pnn-c342="" role="radiogroup" class="mat-radio-group ng-untouched ng-pristine ng-valid"><mat-radio-button _ngcontent-pnn-c342="" id="progress-bars-primary-color-radio" value="primary" class="mat-radio-button example-margin mat-accent mat-radio-checked" tabindex="-1"><label class="mat-radio-label" for="progress-bars-primary-color-radio-input"><div class="mat-radio-container"><div class="mat-radio-outer-circle"></div><div class="mat-radio-inner-circle"></div><input type="radio" class="mat-radio-input cdk-visually-hidden" id="progress-bars-primary-color-radio-input" tabindex="0" name="mat-radio-group-33" value="primary"><div mat-ripple="" class="mat-ripple mat-radio-ripple mat-focus-indicator"><div class="mat-ripple-element mat-radio-persistent-ripple"></div></div></div><div class="mat-radio-label-content"><span style="display: none;"> </span> Primary </div></label></mat-radio-button><mat-radio-button _ngcontent-pnn-c342="" id="progress-bars-accent-color-radio" value="accent" class="mat-radio-button example-margin mat-accent" tabindex="-1"><label class="mat-radio-label" for="progress-bars-accent-color-radio-input"><div class="mat-radio-container"><div class="mat-radio-outer-circle"></div><div class="mat-radio-inner-circle"></div><input type="radio" class="mat-radio-input cdk-visually-hidden" id="progress-bars-accent-color-radio-input" tabindex="0" name="mat-radio-group-33" value="accent"><div mat-ripple="" class="mat-ripple mat-radio-ripple mat-focus-indicator"><div class="mat-ripple-element mat-radio-persistent-ripple"></div></div></div><div class="mat-radio-label-content"><span style="display: none;"> </span> Accent </div></label></mat-radio-button><mat-radio-button _ngcontent-pnn-c342="" id="progress-bars-warn-color-radio" value="warn" class="mat-radio-button example-margin mat-accent" tabindex="-1"><label class="mat-radio-label" for="progress-bars-warn-color-radio-input"><div class="mat-radio-container"><div class="mat-radio-outer-circle"></div><div class="mat-radio-inner-circle"></div><input type="radio" class="mat-radio-input cdk-visually-hidden" id="progress-bars-warn-color-radio-input" tabindex="0" name="mat-radio-group-33" value="warn"><div mat-ripple="" class="mat-ripple mat-radio-ripple mat-focus-indicator"><div class="mat-ripple-element mat-radio-persistent-ripple"></div></div></div><div class="mat-radio-label-content"><span style="display: none;"> </span> Warn </div></label></mat-radio-button></mat-radio-group></section><section _ngcontent-pnn-c342="" class="example-section"><label _ngcontent-pnn-c342="" class="example-margin">Mode:</label><mat-radio-group _ngcontent-pnn-c342="" role="radiogroup" class="mat-radio-group ng-untouched ng-pristine ng-valid"><mat-radio-button _ngcontent-pnn-c342="" id="progress-bars-determinate-mode-radio" value="determinate" class="mat-radio-button example-margin mat-accent mat-radio-checked" tabindex="-1"><label class="mat-radio-label" for="progress-bars-determinate-mode-radio-input"><div class="mat-radio-container"><div class="mat-radio-outer-circle"></div><div class="mat-radio-inner-circle"></div><input type="radio" class="mat-radio-input cdk-visually-hidden" id="progress-bars-determinate-mode-radio-input" tabindex="0" name="mat-radio-group-37" value="determinate"><div mat-ripple="" class="mat-ripple mat-radio-ripple mat-focus-indicator"><div class="mat-ripple-element mat-radio-persistent-ripple"></div></div></div><div class="mat-radio-label-content"><span style="display: none;"> </span> Determinate </div></label></mat-radio-button><mat-radio-button _ngcontent-pnn-c342="" id="progress-bars-indeterminate-mode-radio" value="indeterminate" class="mat-radio-button example-margin mat-accent" tabindex="-1"><label class="mat-radio-label" for="progress-bars-indeterminate-mode-radio-input"><div class="mat-radio-container"><div class="mat-radio-outer-circle"></div><div class="mat-radio-inner-circle"></div><input type="radio" class="mat-radio-input cdk-visually-hidden" id="progress-bars-indeterminate-mode-radio-input" tabindex="0" name="mat-radio-group-37" value="indeterminate"><div mat-ripple="" class="mat-ripple mat-radio-ripple mat-focus-indicator"><div class="mat-ripple-element mat-radio-persistent-ripple"></div></div></div><div class="mat-radio-label-content"><span style="display: none;"> </span> Indeterminate </div></label></mat-radio-button><mat-radio-button _ngcontent-pnn-c342="" id="progress-bars-buffer-mode-radio" value="buffer" class="mat-radio-button example-margin mat-accent" tabindex="-1"><label class="mat-radio-label" for="progress-bars-buffer-mode-radio-input"><div class="mat-radio-container"><div class="mat-radio-outer-circle"></div><div class="mat-radio-inner-circle"></div><input type="radio" class="mat-radio-input cdk-visually-hidden" id="progress-bars-buffer-mode-radio-input" tabindex="0" name="mat-radio-group-37" value="buffer"><div mat-ripple="" class="mat-ripple mat-radio-ripple mat-focus-indicator"><div class="mat-ripple-element mat-radio-persistent-ripple"></div></div></div><div class="mat-radio-label-content"><span style="display: none;"> </span> Buffer </div></label></mat-radio-button><mat-radio-button _ngcontent-pnn-c342="" id="progress-bars-query-mode-radio" value="query" class="mat-radio-button example-margin mat-accent" tabindex="-1"><label class="mat-radio-label" for="progress-bars-query-mode-radio-input"><div class="mat-radio-container"><div class="mat-radio-outer-circle"></div><div class="mat-radio-inner-circle"></div><input type="radio" class="mat-radio-input cdk-visually-hidden" id="progress-bars-query-mode-radio-input" tabindex="0" name="mat-radio-group-37" value="query"><div mat-ripple="" class="mat-ripple mat-radio-ripple mat-focus-indicator"><div class="mat-ripple-element mat-radio-persistent-ripple"></div></div></div><div class="mat-radio-label-content"><span style="display: none;"> </span> Query </div></label></mat-radio-button></mat-radio-group></section><section _ngcontent-pnn-c342="" class="example-section ng-star-inserted"><label _ngcontent-pnn-c342="" class="example-margin">Progress:</label><mat-slider _ngcontent-pnn-c342="" role="slider" id="progress-bars-progress-slider" class="mat-slider mat-focus-indicator example-margin mat-accent mat-slider-horizontal ng-untouched ng-pristine ng-valid" tabindex="0" aria-disabled="false" aria-valuemax="100" aria-valuemin="0" aria-valuenow="50" aria-orientation="horizontal"><div class="mat-slider-wrapper"><div class="mat-slider-track-wrapper"><div class="mat-slider-track-background" style="transform: translateX(0px) scale3d(0.5, 1, 1);"></div><div class="mat-slider-track-fill" style="transform: translateX(0px) scale3d(0.5, 1, 1);"></div></div><div class="mat-slider-ticks-container" style="transform: translateX(0%);"><div class="mat-slider-ticks" style="background-size: 0% 2px; transform: translateZ(0px) translateX(0%);"></div></div><div class="mat-slider-thumb-container" style="transform: translateX(-50%);"><div class="mat-slider-focus-ring"></div><div class="mat-slider-thumb"></div><div class="mat-slider-thumb-label"><span class="mat-slider-thumb-label-text">50</span></div></div></div></mat-slider></section><!----><!----></mat-card-content></mat-card><mat-card _ngcontent-pnn-c342="" class="mat-card mat-focus-indicator"><mat-card-content _ngcontent-pnn-c342="" class="mat-card-content"><h4 _ngcontent-pnn-c342="">Result</h4><section _ngcontent-pnn-c342="" class="example-section"><mat-progress-bar _ngcontent-pnn-c342="" role="progressbar" aria-valuemin="0" aria-valuemax="100" id="mat-progress-bar-configurable" class="mat-progress-bar example-margin mat-primary" aria-valuenow="50" mode="determinate"><svg width="100%" height="4" focusable="false" class="mat-progress-bar-background mat-progress-bar-element"><defs><pattern x="4" y="0" width="8" height="4" patternUnits="userSpaceOnUse" id="mat-progress-bar-4"><circle cx="2" cy="2" r="2"></circle></pattern></defs><rect width="100%" height="100%" fill="url('/jdi-light/angular.html#mat-progress-bar-4')"></rect></svg><div class="mat-progress-bar-buffer mat-progress-bar-element"></div><div class="mat-progress-bar-primary mat-progress-bar-fill mat-progress-bar-element" style="transform: scaleX(0.5);"></div><div class="mat-progress-bar-secondary mat-progress-bar-fill mat-progress-bar-element"></div></mat-progress-bar></section></mat-card-content></mat-card></progress-bar-configurable-example>
List of the available Progress bar methods:
Method | Description | Return Type |
---|---|---|
is() | Assert action | ProgressBarAssert |
max() | Get max limit | int |
min() | Get min limit | int |
mode() | Get mode value | String |
value() | Get progress value | int |
getValue() | Get progress value | String |
bufferValue() | Assert action | double |
isVisible() | Check if progress bar is visible | boolean |
Progress bar java tests examples
2.1.11 Slider
Slider overview
Progress bar locates in the following class:
- Java: com.epam.jdi.light.angular.elements.common.Slider
There is 3 different sliders in Angular: Basic, Slider with custom thumb label formatting and Configurable:
Basic slider:
//@FindBy(css = "#mat-slider-basic")
@UI("#mat-slider-basic")
public static Slider matSliderBasic;
@Test
public void sliderBasicGetValueTest() {
matSliderBasic.show();
matSliderBasic.has().value(0.0);
matSliderBasic.setupValue(30);
matSliderBasic.has().value(30.0);
}
<slider-overview-example _nghost-ret-c263="" ng-version="9.1.0">
<h2 _ngcontent-ret-c263="" class="example-h2">
<a _ngcontent-ret-c263="" href="https://material.angular.io/components/slider/overview"> Basic slider </a>
</h2>
<mat-slider _ngcontent-ret-c263="" role="slider" id="mat-slider-basic" class="mat-slider mat-focus-indicator mat-accent mat-slider-horizontal mat-slider-min-value" tabindex="0" aria-disabled="false" aria-valuemax="100" aria-valuemin="0" aria-valuenow="0" aria-orientation="horizontal">
<div class="mat-slider-wrapper">
<div class="mat-slider-track-wrapper">
<div class="mat-slider-track-background" style="transform: translateX(7px) scale3d(1, 1, 1);"/>
<div class="mat-slider-track-fill" style="transform: translateX(-7px) scale3d(0, 1, 1); display: none;"/>
</div>
<div class="mat-slider-ticks-container" style="transform: translateX(0%);">
<div class="mat-slider-ticks" style="background-size: 0% 2px; transform: translateZ(0px) translateX(0%); padding-left: 7px;"/>
</div>
<div class="mat-slider-thumb-container" style="transform: translateX(-100%);">
<div class="mat-slider-focus-ring"/>
<div class="mat-slider-thumb"/>
<div class="mat-slider-thumb-label">
<span class="mat-slider-thumb-label-text">0</span>
</div>
</div>
</div>
</mat-slider>
</slider-overview-example>
Slider with custom thumb label formatting:
//@FindBy(css = "#mat-slider-formatting")
@UI("#mat-slider-formatting")
public static Slider matSliderFormatting;
@Test
public void sliderFormattingGetValueTest() {
matSliderFormatting.has().value(1.0);
matSliderFormatting.show();
matSliderFormatting.setupValue(2000);
matSliderFormatting.has().value(2000.0);
}
<slider-formatting-example _nghost-ret-c264="" ng-version="9.1.0">
<h2 _ngcontent-ret-c264="" class="example-h2">
<a _ngcontent-ret-c264="" href="https://material.angular.io/components/slider/overview#formatting-the-thumb-label"> Slider with custom thumb label formatting </a>
</h2>
<mat-slider _ngcontent-ret-c264="" role="slider" id="mat-slider-formatting" thumblabel="" tickinterval="1000" min="1" max="100000" class="mat-slider mat-focus-indicator mat-accent mat-slider-has-ticks mat-slider-horizontal mat-slider-thumb-label-showing mat-slider-min-value" tabindex="0" aria-disabled="false" aria-valuemax="100000" aria-valuemin="1" aria-valuenow="1" aria-orientation="horizontal">
<div class="mat-slider-wrapper">
<div class="mat-slider-track-wrapper">
<div class="mat-slider-track-background" style="transform: translateX(0px) scale3d(1, 1, 1);"/>
<div class="mat-slider-track-fill" style="transform: translateX(0px) scale3d(0, 1, 1); display: none;"/>
</div>
<div class="mat-slider-ticks-container" style="transform: translateX(-0.500005%);">
<div class="mat-slider-ticks" style="background-size: 1.00001% 2px; transform: translateZ(0px) translateX(0.500005%);"/>
</div>
<div class="mat-slider-thumb-container" style="transform: translateX(-100%);">
<div class="mat-slider-focus-ring"/>
<div class="mat-slider-thumb"/>
<div class="mat-slider-thumb-label">
<span class="mat-slider-thumb-label-text">1</span>
</div>
</div>
</div>
</mat-slider>
</slider-formatting-example>
Configurable slider:
//@FindBy(css = "#mat-slider-configurable")
@UI("#mat-slider-configurable")
public static Slider matSliderConfigurable;
@Test
public void sliderConfigurableGetValueTest() {
matSliderConfigurable.has().value(0.0);
matSliderConfigurable.show();
matSliderConfigurable.setupValue(60);
matSliderConfigurable.has().value(60.0);
}
@Test
public void sliderConfigurableSetupValueTest() {
matSliderConfigurable.show();
matSliderConfigurable.setupValue(35.5);
matSliderConfigurable.has().value(35.5);
}
<slider-configurable-example _nghost-ret-c265="" ng-version="9.1.0">
<h2 _ngcontent-ret-c265="" class="example-h2">Configurable slider</h2>
<mat-card _ngcontent-ret-c265="" class="mat-card mat-focus-indicator">
<mat-card-content _ngcontent-ret-c265="" class="mat-card-content">
<h4 _ngcontent-ret-c265="">Slider configuration</h4>
<section _ngcontent-ret-c265="" class="example-section">
<mat-form-field _ngcontent-ret-c265="" class="mat-form-field example-margin ng-tns-c94-55 mat-primary mat-form-field-type-mat-input mat-form-field-appearance-fill mat-form-field-can-float mat-form-field-has-label ng-untouched ng-pristine ng-valid mat-form-field-should-float">
<div class="mat-form-field-wrapper ng-tns-c94-55">
<div class="mat-form-field-flex ng-tns-c94-55">
<div class="mat-form-field-infix ng-tns-c94-55">
<input _ngcontent-ret-c265="" matinput="" type="number" id="slider-configurable-value" class="mat-input-element mat-form-field-autofill-control ng-tns-c94-55 cdk-text-field-autofill-monitored ng-untouched ng-pristine ng-valid" aria-invalid="false" aria-required="false">
<span class="mat-form-field-label-wrapper ng-tns-c94-55">
<label class="mat-form-field-label ng-tns-c94-55 ng-star-inserted" id="mat-form-field-label-85" for="slider-configurable-value" aria-owns="slider-configurable-value">
<mat-label _ngcontent-ret-c265="" class="ng-tns-c94-55 ng-star-inserted">Value</mat-label>
</label>
</span>
</div>
</div>
<div class="mat-form-field-underline ng-tns-c94-55 ng-star-inserted">
<span class="mat-form-field-ripple ng-tns-c94-55"/>
</div>
<div class="mat-form-field-subscript-wrapper ng-tns-c94-55">
<div class="mat-form-field-hint-wrapper ng-tns-c94-55 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<div class="mat-form-field-hint-spacer ng-tns-c94-55"/>
</div>
</div>
</div>
</mat-form-field>
<mat-form-field _ngcontent-ret-c265="" class="mat-form-field example-margin ng-tns-c94-56 mat-primary mat-form-field-type-mat-input mat-form-field-appearance-fill mat-form-field-can-float mat-form-field-has-label ng-untouched ng-pristine ng-valid mat-form-field-should-float">
<div class="mat-form-field-wrapper ng-tns-c94-56">
<div class="mat-form-field-flex ng-tns-c94-56">
<div class="mat-form-field-infix ng-tns-c94-56">
<input _ngcontent-ret-c265="" matinput="" type="number" id="slider-configurable-min" class="mat-input-element mat-form-field-autofill-control ng-tns-c94-56 cdk-text-field-autofill-monitored ng-untouched ng-pristine ng-valid" aria-invalid="false" aria-required="false">
<span class="mat-form-field-label-wrapper ng-tns-c94-56">
<label class="mat-form-field-label ng-tns-c94-56 ng-star-inserted" id="mat-form-field-label-87" for="slider-configurable-min" aria-owns="slider-configurable-min">
<mat-label _ngcontent-ret-c265="" class="ng-tns-c94-56 ng-star-inserted">Min value</mat-label>
</label>
</span>
</div>
</div>
<div class="mat-form-field-underline ng-tns-c94-56 ng-star-inserted">
<span class="mat-form-field-ripple ng-tns-c94-56"/>
</div>
<div class="mat-form-field-subscript-wrapper ng-tns-c94-56">
<div class="mat-form-field-hint-wrapper ng-tns-c94-56 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<div class="mat-form-field-hint-spacer ng-tns-c94-56"/>
</div>
</div>
</div>
</mat-form-field>
<mat-form-field _ngcontent-ret-c265="" class="mat-form-field example-margin ng-tns-c94-57 mat-primary mat-form-field-type-mat-input mat-form-field-appearance-fill mat-form-field-can-float mat-form-field-has-label ng-untouched ng-pristine ng-valid mat-form-field-should-float">
<div class="mat-form-field-wrapper ng-tns-c94-57">
<div class="mat-form-field-flex ng-tns-c94-57">
<div class="mat-form-field-infix ng-tns-c94-57">
<input _ngcontent-ret-c265="" matinput="" type="number" id="slider-configurable-max" class="mat-input-element mat-form-field-autofill-control ng-tns-c94-57 cdk-text-field-autofill-monitored ng-untouched ng-pristine ng-valid" aria-invalid="false" aria-required="false">
<span class="mat-form-field-label-wrapper ng-tns-c94-57">
<label class="mat-form-field-label ng-tns-c94-57 ng-star-inserted" id="mat-form-field-label-89" for="slider-configurable-max" aria-owns="slider-configurable-max">
<mat-label _ngcontent-ret-c265="" class="ng-tns-c94-57 ng-star-inserted">Max value</mat-label>
</label>
</span>
</div>
</div>
<div class="mat-form-field-underline ng-tns-c94-57 ng-star-inserted">
<span class="mat-form-field-ripple ng-tns-c94-57"/>
</div>
<div class="mat-form-field-subscript-wrapper ng-tns-c94-57">
<div class="mat-form-field-hint-wrapper ng-tns-c94-57 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<div class="mat-form-field-hint-spacer ng-tns-c94-57"/>
</div>
</div>
</div>
</mat-form-field>
<mat-form-field _ngcontent-ret-c265="" class="mat-form-field example-margin ng-tns-c94-58 mat-primary mat-form-field-type-mat-input mat-form-field-appearance-fill mat-form-field-can-float mat-form-field-has-label ng-untouched ng-pristine ng-valid mat-form-field-should-float">
<div class="mat-form-field-wrapper ng-tns-c94-58">
<div class="mat-form-field-flex ng-tns-c94-58">
<div class="mat-form-field-infix ng-tns-c94-58">
<input _ngcontent-ret-c265="" matinput="" type="number" id="slider-configurable-step" class="mat-input-element mat-form-field-autofill-control ng-tns-c94-58 cdk-text-field-autofill-monitored ng-untouched ng-pristine ng-valid" aria-invalid="false" aria-required="false">
<span class="mat-form-field-label-wrapper ng-tns-c94-58">
<label class="mat-form-field-label ng-tns-c94-58 ng-star-inserted" id="mat-form-field-label-91" for="slider-configurable-step" aria-owns="slider-configurable-step">
<mat-label _ngcontent-ret-c265="" class="ng-tns-c94-58 ng-star-inserted">Step size</mat-label>
</label>
</span>
</div>
</div>
<div class="mat-form-field-underline ng-tns-c94-58 ng-star-inserted">
<span class="mat-form-field-ripple ng-tns-c94-58"/>
</div>
<div class="mat-form-field-subscript-wrapper ng-tns-c94-58">
<div class="mat-form-field-hint-wrapper ng-tns-c94-58 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<div class="mat-form-field-hint-spacer ng-tns-c94-58"/>
</div>
</div>
</div>
</mat-form-field>
</section>
<section _ngcontent-ret-c265="" class="example-section">
<mat-checkbox _ngcontent-ret-c265="" id="slider-configurable-showTicks" class="mat-checkbox example-margin mat-accent ng-untouched ng-pristine ng-valid">
<label class="mat-checkbox-layout" for="slider-configurable-showTicks-input">
<div class="mat-checkbox-inner-container">
<input type="checkbox" class="mat-checkbox-input cdk-visually-hidden" id="slider-configurable-showTicks-input" tabindex="0" aria-checked="false">
<div matripple="" class="mat-ripple mat-checkbox-ripple mat-focus-indicator">
<div class="mat-ripple-element mat-checkbox-persistent-ripple"/>
</div>
<div class="mat-checkbox-frame"/>
<div class="mat-checkbox-background">
<svg version="1.1" focusable="false" viewBox="0 0 24 24" xml:space="preserve" class="mat-checkbox-checkmark">
<path fill="none" stroke="white" d="M4.1,12.7 9,17.6 20.3,6.3" class="mat-checkbox-checkmark-path"/>
</svg>
<div class="mat-checkbox-mixedmark"/>
</div>
</div>
<span class="mat-checkbox-label">
<span style="display: none;"> </span>Show ticks</span>
</label>
</mat-checkbox>
</section>
<section _ngcontent-ret-c265="" class="example-section">
<mat-checkbox _ngcontent-ret-c265="" id="slider-configurable-thumb-label" class="mat-checkbox example-margin mat-accent ng-untouched ng-pristine ng-valid">
<label class="mat-checkbox-layout" for="slider-configurable-thumb-label-input">
<div class="mat-checkbox-inner-container">
<input type="checkbox" class="mat-checkbox-input cdk-visually-hidden" id="slider-configurable-thumb-label-input" tabindex="0" aria-checked="false">
<div matripple="" class="mat-ripple mat-checkbox-ripple mat-focus-indicator">
<div class="mat-ripple-element mat-checkbox-persistent-ripple"/>
</div>
<div class="mat-checkbox-frame"/>
<div class="mat-checkbox-background">
<svg version="1.1" focusable="false" viewBox="0 0 24 24" xml:space="preserve" class="mat-checkbox-checkmark">
<path fill="none" stroke="white" d="M4.1,12.7 9,17.6 20.3,6.3" class="mat-checkbox-checkmark-path"/>
</svg>
<div class="mat-checkbox-mixedmark"/>
</div>
</div>
<span class="mat-checkbox-label">
<span style="display: none;"> </span>Show thumb label</span>
</label>
</mat-checkbox>
</section>
<section _ngcontent-ret-c265="" class="example-section">
<mat-checkbox _ngcontent-ret-c265="" id="slider-configurable-vertical" class="mat-checkbox example-margin mat-accent ng-untouched ng-pristine ng-valid">
<label class="mat-checkbox-layout" for="slider-configurable-vertical-input">
<div class="mat-checkbox-inner-container">
<input type="checkbox" class="mat-checkbox-input cdk-visually-hidden" id="slider-configurable-vertical-input" tabindex="0" aria-checked="false">
<div matripple="" class="mat-ripple mat-checkbox-ripple mat-focus-indicator">
<div class="mat-ripple-element mat-checkbox-persistent-ripple"/>
</div>
<div class="mat-checkbox-frame"/>
<div class="mat-checkbox-background">
<svg version="1.1" focusable="false" viewBox="0 0 24 24" xml:space="preserve" class="mat-checkbox-checkmark">
<path fill="none" stroke="white" d="M4.1,12.7 9,17.6 20.3,6.3" class="mat-checkbox-checkmark-path"/>
</svg>
<div class="mat-checkbox-mixedmark"/>
</div>
</div>
<span class="mat-checkbox-label">
<span style="display: none;"> </span>Vertical</span>
</label>
</mat-checkbox>
<mat-checkbox _ngcontent-ret-c265="" id="slider-configurable-invert" class="mat-checkbox example-margin mat-accent ng-untouched ng-pristine ng-valid">
<label class="mat-checkbox-layout" for="slider-configurable-invert-input">
<div class="mat-checkbox-inner-container">
<input type="checkbox" class="mat-checkbox-input cdk-visually-hidden" id="slider-configurable-invert-input" tabindex="0" aria-checked="false">
<div matripple="" class="mat-ripple mat-checkbox-ripple mat-focus-indicator">
<div class="mat-ripple-element mat-checkbox-persistent-ripple"/>
</div>
<div class="mat-checkbox-frame"/>
<div class="mat-checkbox-background">
<svg version="1.1" focusable="false" viewBox="0 0 24 24" xml:space="preserve" class="mat-checkbox-checkmark">
<path fill="none" stroke="white" d="M4.1,12.7 9,17.6 20.3,6.3" class="mat-checkbox-checkmark-path"/>
</svg>
<div class="mat-checkbox-mixedmark"/>
</div>
</div>
<span class="mat-checkbox-label">
<span style="display: none;"> </span>Inverted</span>
</label>
</mat-checkbox>
</section>
<section _ngcontent-ret-c265="" class="example-section">
<mat-checkbox _ngcontent-ret-c265="" id="slider-configurable-disabled" class="mat-checkbox example-margin mat-accent ng-untouched ng-pristine ng-valid">
<label class="mat-checkbox-layout" for="slider-configurable-disabled-input">
<div class="mat-checkbox-inner-container">
<input type="checkbox" class="mat-checkbox-input cdk-visually-hidden" id="slider-configurable-disabled-input" tabindex="0" aria-checked="false">
<div matripple="" class="mat-ripple mat-checkbox-ripple mat-focus-indicator">
<div class="mat-ripple-element mat-checkbox-persistent-ripple"/>
</div>
<div class="mat-checkbox-frame"/>
<div class="mat-checkbox-background">
<svg version="1.1" focusable="false" viewBox="0 0 24 24" xml:space="preserve" class="mat-checkbox-checkmark">
<path fill="none" stroke="white" d="M4.1,12.7 9,17.6 20.3,6.3" class="mat-checkbox-checkmark-path"/>
</svg>
<div class="mat-checkbox-mixedmark"/>
</div>
</div>
<span class="mat-checkbox-label">
<span style="display: none;"> </span>Disabled</span>
</label>
</mat-checkbox>
</section>
</mat-card-content>
</mat-card>
<mat-card _ngcontent-ret-c265="" class="mat-card mat-focus-indicator example-result-card">
<mat-card-content _ngcontent-ret-c265="" class="mat-card-content">
<h4 _ngcontent-ret-c265="">Result</h4>
<mat-slider _ngcontent-ret-c265="" role="slider" id="mat-slider-configurable" class="mat-slider mat-focus-indicator example-margin mat-accent mat-slider-horizontal mat-slider-min-value ng-untouched ng-pristine ng-valid" tabindex="0" aria-disabled="false" aria-valuemax="100" aria-valuemin="0" aria-valuenow="0" aria-orientation="horizontal">
<div class="mat-slider-wrapper">
<div class="mat-slider-track-wrapper">
<div class="mat-slider-track-background" style="transform: translateX(7px) scale3d(1, 1, 1);"/>
<div class="mat-slider-track-fill" style="transform: translateX(-7px) scale3d(0, 1, 1); display: none;"/>
</div>
<div class="mat-slider-ticks-container" style="transform: translateX(0%);">
<div class="mat-slider-ticks" style="background-size: 0% 2px; transform: translateZ(0px) translateX(0%); padding-left: 7px;"/>
</div>
<div class="mat-slider-thumb-container" style="transform: translateX(-100%);">
<div class="mat-slider-focus-ring"/>
<div class="mat-slider-thumb"/>
<div class="mat-slider-thumb-label">
<span class="mat-slider-thumb-label-text">0</span>
</div>
</div>
</div>
</mat-slider>
</mat-card-content>
</mat-card>
</slider-configurable-example>
List of the available Slider methods:
Method | Description | Return Type |
---|---|---|
min() | get min limit | double |
max() | get max limit | double |
value() | get value | double |
orientation() | Returns element orientation | String |
isInverted() | check if inverted | boolean |
isThumbLabelDisplayed() | is thumblabel displayed | boolean |
setValue(String) | Set value | void |
moveRight() | move carriage to right | void |
moveLeft() | move carriage to left | void |
isDisabled() | Is disabled | boolean |
isEnabled() | Is enabled | boolean |
getValue() | Returns value | String |
is() | Assert action | SliderAssert |
has() | Assert action | SliderAssert |
setupValue(double) | Set value | void |
slide(double) | Drag & drop based on percentage length | void |
Slider java tests examples
2.1.12 Tooltip
The Angular Material tooltip provides a text label that is displayed when the user hovers over or longpresses an element.
Tooltip overview
Tooltip is located in the following class:
- Java: com.epam.jdi.light.angular.elements.common.Tooltip
//FindBy(css = ".mat-tooltip")
@UI(".mat-tooltip")
public static Tooltip tooltip;
@Test
public void basicTooltipTest() {
basicTooltipButton.hover();
tooltip.has().assertTooltipText("Petit a petit, l’oiseau fait son nid");
}
@Test
public void customPositionTooltipTest() {
Map<String, Tooltip.Position> position = new HashMap<>();
position.put("after", Tooltip.Position.RIGHT);
position.put("before", Tooltip.Position.LEFT);
position.put("above", Tooltip.Position.ABOVE);
position.put("below", Tooltip.Position.BELOW);
position.put("left", Tooltip.Position.LEFT);
position.put("right", Tooltip.Position.RIGHT);
positionTooltipButton.show();
position.forEach(
(k, v) -> {
positionTooltipSelector.click();
(new MaterialSelectorContainer()).select(k);
positionTooltipButton.hover();
tooltip.has().assertTooltipPosition(v, positionTooltipButton);
}
);
}
<button mat-raised-button
matTooltip="Info about the action"
aria-label="Button that displays a tooltip when focused or hovered over">
Action
</button>
Method | Description | Return Type |
---|---|---|
text() | Get text | String |
color() | Get color | String |
position(UIBaseElement<?>) | Get position relative to element | Position |
is() | Assert action | TooltipAssert |
Here you can find Tooltip tests
2.1.13 Spinner
Tooltip overview
Spinner is located in the following class:
- Java: com.epam.jdi.light.angular.elements.common.Spinner
There is 2 different spinners in Angular: Basic and Configurable:
//FindBy(css = "#basic-progress-spinner")
@UI("#basic-progress-spinner")
public static Spinner basicProgressSpinner;
//FindBy(css = "#show-spinner")
@UI("#show-spinner")
public static Button showSpinner;
@Test
public void disappear() {
showSpinner.click();
basicProgressSpinner.waitFor().disappear();
}
@Test
public void baseValidationTest() {
showSpinner.show();
showSpinner.click();
baseValidation(basicProgressSpinner);
}
@Test
public void checkSpinnerHidden() {
showSpinner.click();
basicProgressSpinner.assertThat().hidden();
}
<progress-spinner-overview-example _nghost-prk-c338="" ng-version="9.1.0">
<h2 _ngcontent-prk-c338="" class="example-h2">
<a _ngcontent-prk-c338="" href="https://material.angular.io/components/progress-spinner/overview"> Basic progress-spinner </a>
</h2>
<button _ngcontent-prk-c338="" mat-raised-button="" id="show-spinner" class="mat-focus-indicator mat-raised-button mat-button-base">
<span class="mat-button-wrapper"> Show progress-spinner for 5 seconds
</span>
<div matripple="" class="mat-ripple mat-button-ripple"/>
<div class="mat-button-focus-overlay"/>
</button>
<div _ngcontent-prk-c338="" hidden="">
<mat-spinner _ngcontent-prk-c338="" role="progressbar" mode="indeterminate" id="basic-progress-spinner" class="mat-spinner mat-progress-spinner mat-primary mat-progress-spinner-indeterminate-animation" style="width: 100px; height: 100px;">
<svg preserveAspectRatio="xMidYMid meet" focusable="false" viewBox="0 0 100 100" style="width: 100px; height: 100px;">
<circle cx="50%" cy="50%" r="45" class="ng-star-inserted" style="animation-name: mat-progress-spinner-stroke-rotate-100; stroke-dasharray: 282.743px; stroke-width: 10%;"/>
<!---->
<!---->
</svg>
</mat-spinner>
</div>
</progress-spinner-overview-example>
Method | Description | Return Type |
---|---|---|
is() | Assert action | UIAssert |
click() | Click action | void |
isDisplayed() | Check that element is displayed | boolean |
isHidden() | Check that element is hidden | boolean |
Here you can find Spinner tests
2.2 Angular Complex elements
2.2.1 Radio Buttons
Radio button overview
Element that can be represented with one or more clickable buttons aiming to choose only one button of the group.
Radio buttons locates in the following classes:
- Java: com.epam.jdi.light.angular.elements.complex.RadioButtons.java
There are two different radio buttons types in Angular: Basic radios and Radios with NGmodel.
//FindBy(id = "basic-radio-group")
@UI("basic-radio-group")
public static RadioButtons basicRadioGroup;
//FindBy(id = "season-radio-group")
@UI("season-radio-group")
public static RadioButtons seasonRadioGroup;
//FindBy(id = "your-favorit-season-text")
@UI("your-favorit-season-text")
public static Text yourFavoriteSeasonText;
@Test
public void basicRadioButtonsTest() {
basicRadioGroup.is().displayed();
basicRadioGroup.click("2");
basicRadioGroup.click("1");
basicRadioGroup.click("2");
basicRadioGroup.is().checked("2");
basicRadioGroup.is().notChecked("1");
}
@Test
public void seasonsRadioButtonsTest() {
seasonRadioGroup.is().displayed();
seasonRadioGroup.click(SUMMER);
seasonRadioGroup.click(WINTER);
seasonRadioGroup.click(AUTUMN);
seasonRadioGroup.click(SPRING);
seasonRadioGroup.is().checked(SPRING);
yourFavoriteSeasonText.has().text(format("Your favorite season is: %s", SPRING));
seasonRadioGroup.is().notChecked(WINTER);
seasonRadioGroup.is().notChecked(SUMMER);
seasonRadioGroup.is().notChecked(AUTUMN);
}
<mat-radio-group id="basic-radio-group" aria-label="Select an option">
<mat-radio-button id="{{'radio-option-one'}}" value="1">Option 1</mat-radio-button>
<mat-radio-button id="{{'radio-option-two'}}" value="2">Option 2</mat-radio-button>
</mat-radio-group>
<mat-radio-group id="season-radio-group" aria-labelledby="example-radio-group-label" class="example-radio-group" [(ngModel)]="favoriteSeason">
<mat-radio-button id="{{'favorite-season-' + season.toLowerCase()}}" class="example-radio-button" *ngFor="let season of seasons" [value]="season">
{{season}}
</mat-radio-button>
</mat-radio-group>
Method | Description | Return Type |
---|---|---|
click(String) | Click the button by value | void |
isChecked(String) | Checks if radio button contain value | boolean |
is() | Assert action | RadioButtonsAssert |
Here you can find Radio Button tests
2.2.2 List
List overview
List is a container component that wraps and formats a series of line items.
List is located in the following classes:
- Java: com.epam.jdi.light.elements.complex.JList.java
There are two different lists in Angular: Basic list and List with sections.
See an example with HTML code describing basic list element.
//@FindBy(css = "#basic-list mat-list-item")
@UI("#basic-list mat-list-item")
public JList<Label> basicList;
//@FindBy(css = "#list-with-sections mat-list-item")
@UI("#list-with-sections mat-list-item")
public JList<Label> listWithSection;
@Test
public void basicListBasicTest() {
listSection.basicList.is().displayed();
}
@Test
public void basicListTextTest() {
listSection.basicList.get(1).is().text("Item 1");
listSection.basicList.get(2).is().text("Item 2");
listSection.basicList.get(3).is().text("Item 3");
}
@Test
public void listWithSectionsBasicTest() {
listSection.listWithSection.is().displayed();
}
@Test
public void listWithSectionsIconTest() {
listSection.listWithSection.get(1).children().get(3).is().text("folder");
listSection.listWithSection.get(2).children().get(3).is().text("folder");
listSection.listWithSection.get(3).children().get(3).is().text("folder");
listSection.listWithSection.get(4).children().get(3).is().text("note");
listSection.listWithSection.get(5).children().get(3).is().text("note");
}
<mat-list id="basic-list" role="list">
<mat-list-item id="basic-list-item-1" role="listitem">Item 1</mat-list-item>
<mat-list-item id="basic-list-item-2" role="listitem">Item 2</mat-list-item>
<mat-list-item id="basic-list-item-3" role="listitem">Item 3</mat-list-item>
</mat-list>
To add an icon to your list item, use the matListIcon attribute.
Subheader can be added to a list by annotating a heading tag with an matSubheader attribute. To add a divider, use
See an example with HTML code describing list with sections element.
<mat-list id="list-with-sections">
<div mat-subheader>Folders</div>
<mat-list-item id="{{ 'list-with-section-items-' + folder.name.toLowerCase() }}" *ngFor="let folder of folders">
<mat-icon mat-list-icon>folder</mat-icon>
<div mat-line>{{folder.name}}</div>
<div mat-line> {{folder.updated | date}} </div>
</mat-list-item>
<mat-divider></mat-divider>
<div mat-subheader>Notes</div>
<mat-list-item id="{{ 'list-with-section-items-' + note.name.toLowerCase().replace(' ','-') }}" *ngFor="let note of notes">
<mat-icon mat-list-icon>note</mat-icon>
<div mat-line>{{note.name}}</div>
<div mat-line> {{note.updated | date}} </div>
</mat-list-item>
</mat-list>
Method | Description | Return Type |
---|---|---|
is() | Assert action | UISelectAssert |
is(Matcher<? super List |
Assert action meets condition | UISelectAssert |
assertThat(Matcher<? super List |
Assert action | UISelectAssert |
wait(JFunc1 |
wait with condition | boolean |
List java tests examples
2.2.3 Grid list
Grid list overview
Grid list is a two-dimensional list view that arranges cells into grid-based layout.
Grid list is located in the following classes:
- Java: com.epam.jdi.light.elements.complex.JList.java
There are two different grid lists in Angular: Basic grid list and Dynamic grid list.
See an example with HTML code describing basic grid list element.
//@FindBy(css = "#basic-grid-list mat-grid-tile")
@UI("#basic-grid-list mat-grid-tile")
public JList<Label> basicGridList;
//@FindBy(css = "#dynamic-grid-list mat-grid-tile")
@UI("#dynamic-grid-list mat-grid-tile")
public JList<Label> dynamicGridList;
@Test
public void basicGridListBasicTest() {
gridListSection.basicGridList.is().displayed();
}
@Test
public void basicGridListTextTest() {
gridListSection.basicGridList.get(1).is().text("1");
}
@Test
public void basicGridListColorTest() {
gridListSection.basicGridList.get(1)
.has().css("background-color", "rgba(" + 173 + ", " + 216 + ", " + 230 + ", 1)");
}
@Test
public void dynamicGridListBasicTest() {
gridListSection.dynamicGridList.is().displayed();
}
@Test
public void dynamicGridListTextTest() {
gridListSection.dynamicGridList.get(1).is().text("One");
}
@Test
public void dynamicGridListColorTest() {
gridListSection.dynamicGridList.get(1)
.has().css("background-color", "rgba(" + 173 + ", " + 216 + ", " + 230 + ", 1)");
gridListSection.dynamicGridList.get(2)
.has().css("background-color", "rgba(" + 144 + ", " + 238 + ", " + 144 + ", 1)");
gridListSection.dynamicGridList.get(3)
.has().css("background-color", "rgba(" + 255 + ", " + 182 + ", " + 193 + ", 1)");
gridListSection.dynamicGridList.get(4)
.has().css("background-color", "rgba(" + 221 + ", " + 189 + ", " + 241 + ", 1)");
}
See an example with HTML code describing dynamic grid list element.
<mat-grid-list
id="basic-grid-list" cols="2" rowHeight="2:1">
<mat-grid-tile id="basic-grid-list-tile-1">1</mat-grid-tile>
<mat-grid-tile id="basic-grid-list-tile-2">2</mat-grid-tile>
<mat-grid-tile id="basic-grid-list-tile-3">3</mat-grid-tile>
<mat-grid-tile id="basic-grid-list-tile-4">4</mat-grid-tile>
</mat-grid-list>
See an example with HTML code describing dynamic grid list element.
<mat-grid-list id="dynamic-grid-list" cols="4" rowHeight="100px">
<mat-grid-tile
id="{{ 'dynamic-grid-list-' + tile.text.toLowerCase() }}"
*ngFor="let tile of tiles"
[colspan]="tile.cols"
[rowspan]="tile.rows"
[style.background]="tile.color">
{{tile.text}}
</mat-grid-tile>
</mat-grid-list>
Method | Description | Return Type |
---|---|---|
is() | Assert action | UISelectAssert |
is(Matcher<? super List |
Assert action meets condition | UISelectAssert |
assertThat(Matcher<? super List |
Assert action | UISelectAssert |
wait(JFunc1 |
wait with condition | boolean |
Grid list java tests examples
2.2.4 Card
Card overview
Card is a content container for text, photos, and actions in the context of a single subject
Card is located in the following classes:
- Java: com.epam.jdi.light.angular.elements.complex.Card
//FindBy(id = "simple-card")
@UI("#simple-card")
public static Card simpleCard;
//FindBy(id = "example-card")
@UI("#example-card")
public static Card card;
@Test
public void displayedBasicCardTest() {
simpleCard.is().displayed();
card.is().displayed();
}
@Test
public void attributeCardTest() {
simpleCard.is().assertCardText("Simple card");
card.is().assertAltImageAttribute("Photo of a Shiba Inu");
card.is().assertSrcImageAttribute("https://material.angular.io/assets/img/examples/shiba2.jpg");
}
@Test
public void displayedCardTest() {
card.getHeader().is().displayed();
card.getHeaderText().is().displayed();
card.getAvatar().is().displayed();
card.getTitle().is().displayed();
card.getTitle().is().text("Shiba Inu");
card.getSubtitle().is().displayed();
card.getSubtitle().is().text("Dog Breed");
card.getImage().is().displayed();
card.getContent().is().displayed();
card.getContent().is().displayed();
}
<mat-card id="simple-card" class="mat-card mat-focus-indicator">Simple card</mat-card>
Method | Description | Return Type |
---|---|---|
getHeader() | Get header | UIElement |
getAvatar() | Get avatar | UIElement |
getHeaderText() | Get header text | UIElement |
getTitle() | Get title | UIElement |
getSubtitle() | Get subtitle | UIElement |
getImage() | Get image | UIElement |
getContent() | Get content | UIElement |
getButtons() | Get buttons | UIElement |
getCardText() | Get card text | UIElement |
getButtonByText(String) | Get button by text | UIElement |
getButtonByNumber(int) | Get button by number | UIElement |
is() | Assert action | CardAssert |
Card java tests examples
2.2.5 Select
Select overview
Selectors are located in the following classes:
- Java: com.epam.jdi.light.angular.elements.complex.MaterialSelector
- Java: com.epam.jdi.light.angular.elements.complex.NativeSelector
There are two similar select elements in Angular: material and native element.
<mat-form-field>
is a component used to wrap several Angular Material components and apply common Text field
styles such as the underline, floating label, and hint messages.
Angular Material also supports use of the native <select>
element inside of <mat-form-field>
. The native
control has several performance, accessibility, and usability advantages.
//@FindBy(css = "#basic-mat-select")
@UI("#basic-mat-select")
public static MaterialSelector basicMatSelect;
@Test
public void checkLabelValue() {
basicMatSelect.label().has().value("Favorite food");
}
@Test
public void checkSelectorExpanded() {
basicMatSelect.expand();
basicMatSelect.is().expanded();
basicMatSelect.collapse();
basicMatSelect.is().collapsed();
}
@Test
public void checkSelectorCollapsed() {
basicMatSelect.collapse();
basicMatSelect.is().collapsed();
}
//@FindBy(css = "#basic-native-select")
@UI("#basic-native-select")
public static NativeSelector basicNativeSelect;
@Test
public void checkPreselectedValue() {
basicNativeSelect.verify().selected(matchesPattern("[a-zA-Z]+"));
}
@Test
public void checkOptionCanBeSelectedByName() {
basicNativeSelect.select(SAAB);
basicNativeSelect.is().selected(SAAB);
}
@Test
public void checkListDisabledOptions() {
basicNativeSelect.has().listDisabled(Collections.EMPTY_LIST);
}
See examples with HTML code describing select elements.
<mat-form-field _ngcontent-nsg-c244="" class="mat-form-field ng-tns-c95-6 mat-primary mat-form-field-type-mat-select mat-form-field-appearance-fill mat-form-field-can-float mat-form-field-has-label mat-form-field-hide-placeholder">
<div class="mat-form-field-wrapper ng-tns-c95-6">
<div class="mat-form-field-flex ng-tns-c95-6">
<div class="mat-form-field-infix ng-tns-c95-6">
<mat-select _ngcontent-nsg-c244="" role="listbox" id="basic-mat-select" class="mat-select ng-tns-c171-7 ng-tns-c95-6 ng-star-inserted mat-select-empty" tabindex="0" aria-labelledby="mat-form-field-label-13" aria-required="false" aria-disabled="false" aria-invalid="false" aria-multiselectable="false">
<div cdk-overlay-origin="" aria-hidden="true" class="mat-select-trigger ng-tns-c171-7">
<div class="mat-select-value ng-tns-c171-7">
<span class="mat-select-placeholder ng-tns-c171-7 ng-star-inserted"> </span>
</div>
<div class="mat-select-arrow-wrapper ng-tns-c171-7">
<div class="mat-select-arrow ng-tns-c171-7"/>
</div>
</div>
</mat-select>
<span class="mat-form-field-label-wrapper ng-tns-c95-6">
<label class="mat-form-field-label ng-tns-c95-6 mat-empty mat-form-field-empty ng-star-inserted" id="mat-form-field-label-13" for="basic-mat-select" aria-owns="basic-mat-select">
<mat-label _ngcontent-nsg-c244="" class="ng-tns-c95-6 ng-star-inserted">Favorite food</mat-label>
</label>
</span>
</div>
</div>
<div class="mat-form-field-underline ng-tns-c95-6 ng-star-inserted">
<span class="mat-form-field-ripple ng-tns-c95-6"/>
</div>
<div class="mat-form-field-subscript-wrapper ng-tns-c95-6">
<div class="mat-form-field-hint-wrapper ng-tns-c95-6 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<div class="mat-form-field-hint-spacer ng-tns-c95-6"/>
</div>
</div>
</div>
</mat-form-field>
<mat-form-field _ngcontent-nsg-c244="" class="mat-form-field ng-tns-c95-8 mat-primary mat-form-field-type-mat-native-select mat-form-field-appearance-fill mat-form-field-can-float mat-form-field-should-float mat-form-field-has-label">
<div class="mat-form-field-wrapper ng-tns-c95-8">
<div class="mat-form-field-flex ng-tns-c95-8">
<div class="mat-form-field-infix ng-tns-c95-8">
<select _ngcontent-nsg-c244="" matnativecontrol="" required="" id="basic-native-select" class="mat-input-element mat-form-field-autofill-control ng-tns-c95-8 cdk-text-field-autofill-monitored" aria-invalid="false" aria-required="true">
<option _ngcontent-nsg-c244="" value="volvo">Volvo</option>
<option _ngcontent-nsg-c244="" value="saab">Saab</option>
<option _ngcontent-nsg-c244="" value="mercedes">Mercedes</option>
<option _ngcontent-nsg-c244="" value="audi"