diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml
index 49f4c959e9..c6952f05ba 100644
--- a/msa/black-box-tests/pom.xml
+++ b/msa/black-box-tests/pom.xml
@@ -160,7 +160,31 @@
snmp
docker-info
+
+ org.seleniumhq.selenium
+ selenium-java
+ 4.5.3
+
+
+ io.github.bonigarcia
+ webdrivermanager
+ 5.3.0
+
+
+ io.qameta.allure
+ allure-testng
+ 2.19.0
+
+
+
+
+ com.google.guava
+ guava
+ 31.0.1-jre
+
+
+
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractBasePage.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractBasePage.java
new file mode 100644
index 0000000000..8e8a15c5af
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractBasePage.java
@@ -0,0 +1,129 @@
+package org.thingsboard.server.msa.ui.base;
+
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebDriverException;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+import org.thingsboard.rest.client.RestClient;
+import org.thingsboard.server.common.data.page.PageLink;
+import org.thingsboard.server.msa.ui.utils.Const;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+abstract public class BasePage extends Base {
+ protected WebDriver driver;
+ protected WebDriverWait wait;
+ protected Actions actions;
+ protected RestClient client;
+ protected PageLink pageLink;
+
+ public BasePage(WebDriver driver) {
+ this.driver = driver;
+ this.wait = new WebDriverWait(driver, Duration.ofMillis(5000));
+ this.actions = new Actions(driver);
+ try {
+ client = new RestClient(Const.URL);
+ client.login(Const.TENANT_EMAIL, Const.TENANT_PASSWORD);
+ pageLink = new PageLink(10);
+ } catch (Exception e) {
+ log.info("Can't login");
+ }
+ }
+
+ @SneakyThrows
+ protected static void sleep(double second) {
+ Thread.sleep((long) (second * 1000L));
+ }
+
+ protected WebElement waitUntilVisibilityOfElementLocated(String locator) {
+ try {
+ return wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(locator)));
+ } catch (WebDriverException e) {
+ log.error("No visibility element: " + locator);
+ return null;
+ }
+ }
+
+ protected WebElement waitUntilElementToBeClickable(String locator) {
+ try {
+ return wait.until(ExpectedConditions.elementToBeClickable(By.xpath(locator)));
+ } catch (WebDriverException e) {
+ log.error("No clickable element: " + locator);
+ return null;
+ }
+ }
+
+ protected List waitUntilVisibilityOfElementsLocated(String locator) {
+ try {
+ wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(locator)));
+ return driver.findElements(By.xpath(locator));
+ } catch (WebDriverException e) {
+ log.error("No visibility elements: " + locator);
+ return null;
+ }
+ }
+
+ protected List waitUntilElementsToBeClickable(String locator) {
+ try {
+ wait.until(ExpectedConditions.elementToBeClickable(By.xpath(locator)));
+ return driver.findElements(By.xpath(locator));
+ } catch (WebDriverException e) {
+ log.error("No clickable elements: " + locator);
+ return null;
+ }
+ }
+
+ public void waitUntilUrlContainsText(String urlPath) {
+ try {
+ wait.until(ExpectedConditions.urlContains(urlPath));
+ } catch (WebDriverException e) {
+ log.error("This URL path is missing");
+ }
+ }
+
+ protected void moveCursor(WebElement element) {
+ actions.moveToElement(element).perform();
+ }
+
+ protected void doubleClick(WebElement element) {
+ actions.doubleClick(element).build().perform();
+ }
+
+ public boolean elementIsNotPresent(String locator) {
+ try {
+ return wait.until(ExpectedConditions.not(ExpectedConditions.visibilityOfElementLocated(By.xpath(locator))));
+ } catch (WebDriverException e) {
+ throw new AssertionError("Element is present");
+ }
+ }
+
+ public boolean elementsIsNotPresent(String locator) {
+ try {
+ return wait.until(ExpectedConditions.not(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath(locator))));
+ } catch (WebDriverException e) {
+ throw new AssertionError("Elements is present");
+ }
+ }
+
+ public void waitUntilNumberOfTabToBe(int tabNumber) {
+ try {
+ wait.until(ExpectedConditions.numberOfWindowsToBe(tabNumber));
+ } catch (WebDriverException e) {
+ log.error("No tabs with this number");
+ }
+ }
+
+ public void goToNextTab(int tabNumber) {
+ waitUntilNumberOfTabToBe(tabNumber);
+ ArrayList tabs = new ArrayList<>(driver.getWindowHandles());
+ driver.switchTo().window(tabs.get(tabNumber - 1));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDiverBaseTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDiverBaseTest.java
new file mode 100644
index 0000000000..4e5d0d5ead
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDiverBaseTest.java
@@ -0,0 +1,74 @@
+package org.thingsboard.server.msa.ui.base;
+
+import io.github.bonigarcia.wdm.WebDriverManager;
+import lombok.extern.slf4j.Slf4j;
+import org.openqa.selenium.Dimension;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebDriverException;
+import org.openqa.selenium.chrome.ChromeDriver;
+import org.openqa.selenium.chrome.ChromeOptions;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Listeners;
+import org.thingsboard.server.msa.TestListener;
+import org.thingsboard.server.msa.ui.listeners.RetryTestListener;
+
+import java.time.Duration;
+
+@Slf4j
+@Listeners({TestListener.class, RetryTestListener.class})
+abstract public class DiverBaseTest extends Base {
+ protected WebDriver driver;
+
+ private final Dimension dimension = new Dimension(WIDTH, HEIGHT);
+ private static final int WIDTH = 1680;
+ private static final int HEIGHT = 1050;
+ private static final boolean HEADLESS = false;
+
+ @BeforeMethod
+ public void openBrowser() {
+ log.info("*----------------------* Setup driver *----------------------*");
+ if (HEADLESS == true) {
+ ChromeOptions options = new ChromeOptions();
+ options.addArguments("--no-sandbox");
+ options.addArguments("--disable-dev-shm-usage");
+ options.addArguments("--headless");
+ WebDriverManager.chromedriver().setup();
+ driver = new ChromeDriver(options);
+ } else {
+ WebDriverManager.chromedriver().setup();
+ driver = new ChromeDriver();
+ }
+ driver.manage().window().setSize(dimension);
+ }
+
+ @AfterMethod
+ public void closeBrowser() {
+ log.info("*----------------------* Teardown *----------------------*");
+ driver.quit();
+ }
+
+ public void openUrl(String url) {
+ driver.get(url);
+ }
+
+ public String getUrl() {
+ return driver.getCurrentUrl();
+ }
+
+ public WebDriver getDriver() {
+ return driver;
+ }
+
+ protected boolean urlContains(String urlPath) {
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofMillis(10000));
+ try {
+ wait.until(ExpectedConditions.urlContains(urlPath));
+ } catch (WebDriverException e) {
+ log.error("This URL path is missing");
+ }
+ return driver.getCurrentUrl().contains(urlPath);
+ }
+}
\ No newline at end of file
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/RetryAnalyzer.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/RetryAnalyzer.java
new file mode 100644
index 0000000000..30b157f13d
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/RetryAnalyzer.java
@@ -0,0 +1,20 @@
+package listeners;
+
+import org.testng.IRetryAnalyzer;
+import org.testng.ITestResult;
+
+public class RetryAnalyzer implements IRetryAnalyzer {
+
+ private int retryCount = 0;
+ private static final int MAX_RETRY_COUNT = 2;
+
+ @Override
+ public boolean retry(ITestResult result) {
+ if (retryCount < MAX_RETRY_COUNT) {
+ System.out.printf("Retrying test %s for the %d time(s).%n", result.getName(), retryCount + 1);
+ retryCount++;
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/RetryTestListener.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/RetryTestListener.java
new file mode 100644
index 0000000000..6083781820
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/RetryTestListener.java
@@ -0,0 +1,18 @@
+package listeners;
+
+import org.testng.IAnnotationTransformer;
+import org.testng.annotations.ITestAnnotation;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+public class RetryTestListener implements IAnnotationTransformer {
+
+ @Override
+ public void transform(ITestAnnotation annotation,
+ Class testClass,
+ Constructor testConstructor,
+ Method testMethod) {
+ annotation.setRetryAnalyzer(RetryAnalyzer.class);
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/TestListener.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/TestListener.java
new file mode 100644
index 0000000000..dec83f374b
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/TestListener.java
@@ -0,0 +1,62 @@
+package listeners;
+
+import base.Base;
+import base.TestInit;
+import io.qameta.allure.Allure;
+import lombok.extern.slf4j.Slf4j;
+import org.openqa.selenium.WebDriver;
+import org.testng.ITestContext;
+import org.testng.ITestListener;
+import org.testng.ITestResult;
+
+@Slf4j
+public class TestListener extends Base implements ITestListener {
+
+ WebDriver driver;
+
+ public void onTestSuccess(ITestResult tr) {
+ String str = "Test " + tr.getMethod().getMethodName() + " success";
+ log.info("*----------------------* " + str + " *----------------------*");
+ Allure.getLifecycle().updateTestCase((t) -> {
+ t.setStatusDetails(t.getStatusDetails().setMessage(str));
+ });
+ driver = ((TestInit) tr.getInstance()).getDriver();
+ captureScreen(driver, "success");
+ }
+
+ public void onTestFailure(ITestResult tr) {
+ String str = "Test " + tr.getMethod().getMethodName() + " failure";
+ String str1 = "Failed because of - " + tr.getThrowable();
+ log.info("*----------------------* " + str + " *----------------------*");
+ log.info("*----------------------* " + str1 + " *----------------------*");
+ Allure.getLifecycle().updateTestCase((t) -> {
+ t.setStatusDetails(t.getStatusDetails().setMessage(str));
+ t.setStatusDetails(t.getStatusDetails().setMessage(str1));
+ });
+ driver = ((TestInit) tr.getInstance()).getDriver();
+ captureScreen(driver, "failure");
+ }
+
+ public void onTestSkipped(ITestResult tr) {
+ String str = "Test " + tr.getMethod().getMethodName() + " skipped";
+ String str1 = "Skipped because of - " + tr.getThrowable();
+ log.info("*----------------------* " + str + " *----------------------*");
+ log.info("*----------------------* " + str1 + " *----------------------*");
+ Allure.getLifecycle().updateTestCase((t) -> {
+ t.setStatusDetails(t.getStatusDetails().setMessage(str));
+ t.setStatusDetails(t.getStatusDetails().setMessage(str1));
+ });
+ driver = ((TestInit) tr.getInstance()).getDriver();
+ captureScreen(driver, "skipped");
+ }
+
+ public void onStart(ITestContext testContext) {
+ String str = "Test " + testContext.getCurrentXmlTest().getName() + " start";
+ log.info("*----------------------* " + str + " *----------------------*");
+ }
+
+ public void onFinish(ITestContext testContext) {
+ String str = "Test " + testContext.getCurrentXmlTest().getName() + " finish";
+ log.info("*----------------------* " + str + " *----------------------*");
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CustomerPageElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CustomerPageElements.java
new file mode 100644
index 0000000000..dcb513ab71
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CustomerPageElements.java
@@ -0,0 +1,262 @@
+package org.thingsboard.server.msa.ui.pages;
+
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+import java.util.List;
+
+public class CustomerPageElementsAbstract extends OtherPageElementsHelperAbstract {
+ public CustomerPageElementsAbstract(WebDriver driver) {
+ super(driver);
+ }
+
+ private static final String CUSTOMER = "//mat-row//span[contains(text(),'%s')]";
+ private static final String EMAIL = ENTITY + "/../..//mat-cell[contains(@class,'email')]/span";
+ private static final String COUNTRY = ENTITY + "/../..//mat-cell[contains(@class,'country')]/span";
+ private static final String CITY = ENTITY + "/../..//mat-cell[contains(@class,'city')]/span";
+ private static final String TITLES = "//mat-cell[contains(@class,'cdk-column-title')]/span";
+ protected static final String EDIT_MENU_DASHBOARD_FIELD = "//input[@formcontrolname='dashboard']";
+ private static final String EDIT_MENU_DASHBOARD = "//div[@class='cdk-overlay-pane']//span/span";
+ private static final String MANAGE_CUSTOMERS_USERS_BTN = ENTITY + "/../..//mat-icon[contains(text(),' account_circle')]/../..";
+ private static final String MANAGE_CUSTOMERS_ASSETS_BTN = ENTITY + "/../..//mat-icon[contains(text(),' domain')]/../..";
+ private static final String MANAGE_CUSTOMERS_DEVICES_BTN = ENTITY + "/../..//mat-icon[contains(text(),' devices_other')]/../..";
+ private static final String MANAGE_CUSTOMERS_DASHBOARDS_BTN = ENTITY + "/../..//mat-icon[contains(text(),' dashboard')]/../..";
+ private static final String MANAGE_CUSTOMERS_EDGE_BTN = ENTITY + "/../..//mat-icon[contains(text(),' router')]/../..";
+ private static final String ADD_USER_EMAIL = "//tb-add-user-dialog//input[@formcontrolname='email']";
+ private static final String ACTIVATE_WINDOW_OK_BTN = "//span[contains(text(),'OK')]";
+ private static final String USER_LOGIN_BTN = "//mat-icon[@data-mat-icon-name='login']";
+ private static final String USERS_WIDGET = "//tb-widget";
+ private static final String SELECT_COUNTRY_MENU = "//mat-form-field//mat-select[@formcontrolname='country']";
+ private static final String COUNTRIES = "//span[@class='mat-option-text']";
+ protected static final String INPUT_FIELD = "//input[@formcontrolname='%s']";
+ protected static final String INPUT_FIELD_NAME_TITLE = "title";
+ private static final String INPUT_FIELD_NAME_CITY = "city";
+ private static final String INPUT_FIELD_NAME_STATE = "state";
+ private static final String INPUT_FIELD_NAME_ZIP = "zip";
+ private static final String INPUT_FIELD_NAME_ADDRESS = "address";
+ private static final String INPUT_FIELD_NAME_ADDRESS2 = "address2";
+ private static final String INPUT_FIELD_NAME_EMAIL = "email";
+ private static final String INPUT_FIELD_NAME_NUMBER = "phoneNumber";
+ private static final String INPUT_FIELD_NAME_ASSIGNED_LIST = "entity";
+ private static final String ASSIGNED_BTN = "//button[@type='submit']";
+ private static final String HIDE_HOME_DASHBOARD_TOOLBAR = "//mat-checkbox[@formcontrolname='homeDashboardHideToolbar']/label";
+ private static final String FILTER_BTN = "//tb-filters-edit";
+ private static final String TIME_BTN = "//tb-timewindow";
+ private static final String CUSTOMER_ICON_HEADER = "//tb-breadcrumb//span[contains(text(),'Customer %s')]";
+ private static final String CUSTOMER_USER_ICON_HEADER = "Users";
+ private static final String CUSTOMER_ASSETS_ICON_HEADER = "Assets";
+ private static final String CUSTOMER_DEVICES_ICON_HEADER = "Devices";
+ private static final String CUSTOMER_DASHBOARD_ICON_HEADER = "Dashboards";
+ private static final String CUSTOMER_EDGE_ICON_HEADER = "edge instances";
+ private static final String CUSTOMER_USER_ICON_HEAD = "(//mat-drawer-content//span[contains(@class,'tb-entity-table')])[1]";
+ private static final String MANAGE_BTN_VIEW = "//span[contains(text(),'%s')]";
+ private static final String MANAGE_CUSTOMERS_USERS_BTN_VIEW = "Manage users";
+ private static final String MANAGE_CUSTOMERS_ASSETS_BTN_VIEW = "Manage assets";
+ private static final String MANAGE_CUSTOMERS_DEVICE_BTN_VIEW = "Manage devices";
+ private static final String MANAGE_CUSTOMERS_DASHBOARD_BTN_VIEW = "Manage dashboards";
+ private static final String MANAGE_CUSTOMERS_EDGE_BTN_VIEW = "Manage edges ";
+
+ public WebElement titleFieldAddEntityView() {
+ return waitUntilElementToBeClickable(ADD_ENTITY_VIEW + String.format(INPUT_FIELD, INPUT_FIELD_NAME_TITLE));
+ }
+
+ public WebElement titleFieldEntityView() {
+ return waitUntilVisibilityOfElementLocated(String.format(INPUT_FIELD, INPUT_FIELD_NAME_TITLE));
+ }
+
+ public WebElement customer(String entityName) {
+ return waitUntilElementToBeClickable(String.format(CUSTOMER, entityName));
+ }
+
+ public WebElement email(String entityName) {
+ return waitUntilVisibilityOfElementLocated(String.format(EMAIL, entityName));
+ }
+
+ public WebElement country(String entityName) {
+ return waitUntilVisibilityOfElementLocated(String.format(COUNTRY, entityName));
+ }
+
+ public WebElement city(String entityName) {
+ return waitUntilVisibilityOfElementLocated(String.format(CITY, entityName));
+ }
+
+ public List entityTitles() {
+ return waitUntilVisibilityOfElementsLocated(TITLES);
+ }
+
+ public WebElement editMenuDashboardField() {
+ return waitUntilVisibilityOfElementLocated(EDIT_MENU_DASHBOARD_FIELD);
+ }
+
+ public WebElement editMenuDashboard() {
+ return waitUntilElementToBeClickable(EDIT_MENU_DASHBOARD);
+ }
+
+ public WebElement phoneNumberEntityView() {
+ return waitUntilVisibilityOfElementLocated(String.format(INPUT_FIELD, INPUT_FIELD_NAME_NUMBER));
+ }
+
+ public WebElement phoneNumberAddEntityView() {
+ return waitUntilVisibilityOfElementLocated(ADD_ENTITY_VIEW + String.format(INPUT_FIELD, INPUT_FIELD_NAME_NUMBER));
+ }
+
+ public WebElement manageCustomersUserBtn(String title) {
+ return waitUntilElementToBeClickable(String.format(MANAGE_CUSTOMERS_USERS_BTN, title));
+ }
+
+ public WebElement manageCustomersAssetsBtn(String title) {
+ return waitUntilElementToBeClickable(String.format(MANAGE_CUSTOMERS_ASSETS_BTN, title));
+ }
+
+ public WebElement manageCustomersDevicesBtn(String title) {
+ return waitUntilElementToBeClickable(String.format(MANAGE_CUSTOMERS_DEVICES_BTN, title));
+ }
+
+ public WebElement manageCustomersDashboardsBtn(String title) {
+ return waitUntilElementToBeClickable(String.format(MANAGE_CUSTOMERS_DASHBOARDS_BTN, title));
+ }
+
+ public WebElement manageCustomersEdgeBtn(String title) {
+ return waitUntilElementToBeClickable(String.format(MANAGE_CUSTOMERS_EDGE_BTN, title));
+ }
+
+ public WebElement addUserEmailField() {
+ return waitUntilElementToBeClickable(ADD_USER_EMAIL);
+ }
+
+ public WebElement activateWindowOkBtn() {
+ return waitUntilElementToBeClickable(ACTIVATE_WINDOW_OK_BTN);
+ }
+
+ public WebElement userLoginBtn() {
+ return waitUntilElementToBeClickable(USER_LOGIN_BTN);
+ }
+
+ public WebElement usersWidget() {
+ return waitUntilVisibilityOfElementLocated(USERS_WIDGET);
+ }
+
+ public WebElement countrySelectMenuEntityView() {
+ return waitUntilElementToBeClickable(SELECT_COUNTRY_MENU);
+ }
+
+ public WebElement countrySelectMenuAddEntityView() {
+ return waitUntilElementToBeClickable(ADD_ENTITY_VIEW + SELECT_COUNTRY_MENU);
+ }
+
+ public List countries() {
+ return waitUntilElementsToBeClickable(COUNTRIES);
+ }
+
+ public WebElement cityEntityView() {
+ return waitUntilVisibilityOfElementLocated(String.format(INPUT_FIELD, INPUT_FIELD_NAME_CITY));
+ }
+
+ public WebElement cityAddEntityView() {
+ return waitUntilVisibilityOfElementLocated(ADD_ENTITY_VIEW + String.format(INPUT_FIELD, INPUT_FIELD_NAME_CITY));
+ }
+
+ public WebElement stateEntityView() {
+ return waitUntilVisibilityOfElementLocated(String.format(INPUT_FIELD, INPUT_FIELD_NAME_STATE));
+ }
+
+ public WebElement stateAddEntityView() {
+ return waitUntilVisibilityOfElementLocated(ADD_ENTITY_VIEW + String.format(INPUT_FIELD, INPUT_FIELD_NAME_STATE));
+ }
+
+ public WebElement zipEntityView() {
+ return waitUntilVisibilityOfElementLocated(String.format(INPUT_FIELD, INPUT_FIELD_NAME_ZIP));
+ }
+
+ public WebElement zipAddEntityView() {
+ return waitUntilVisibilityOfElementLocated(ADD_ENTITY_VIEW + String.format(INPUT_FIELD, INPUT_FIELD_NAME_ZIP));
+ }
+
+ public WebElement addressEntityView() {
+ return waitUntilVisibilityOfElementLocated(String.format(INPUT_FIELD, INPUT_FIELD_NAME_ADDRESS));
+ }
+
+ public WebElement addressAddEntityView() {
+ return waitUntilVisibilityOfElementLocated(ADD_ENTITY_VIEW + String.format(INPUT_FIELD, INPUT_FIELD_NAME_ADDRESS));
+ }
+
+ public WebElement address2EntityView() {
+ return waitUntilVisibilityOfElementLocated(String.format(INPUT_FIELD, INPUT_FIELD_NAME_ADDRESS2));
+ }
+
+ public WebElement address2AddEntityView() {
+ return waitUntilVisibilityOfElementLocated(ADD_ENTITY_VIEW + String.format(INPUT_FIELD, INPUT_FIELD_NAME_ADDRESS2));
+ }
+
+ public WebElement emailEntityView() {
+ return waitUntilVisibilityOfElementLocated(String.format(INPUT_FIELD, INPUT_FIELD_NAME_EMAIL));
+ }
+
+ public WebElement emailAddEntityView() {
+ return waitUntilVisibilityOfElementLocated(ADD_ENTITY_VIEW + String.format(INPUT_FIELD, INPUT_FIELD_NAME_EMAIL));
+ }
+
+ public WebElement assignedField() {
+ return waitUntilVisibilityOfElementLocated(String.format(INPUT_FIELD, INPUT_FIELD_NAME_ASSIGNED_LIST));
+ }
+
+ public WebElement submitAssignedBtn() {
+ return waitUntilElementToBeClickable(ASSIGNED_BTN);
+ }
+
+ public WebElement hideHomeDashboardToolbarCheckbox() {
+ return waitUntilElementToBeClickable(HIDE_HOME_DASHBOARD_TOOLBAR);
+ }
+
+ public WebElement filterBtn() {
+ return waitUntilVisibilityOfElementLocated(FILTER_BTN);
+ }
+
+ public WebElement timeBtn() {
+ return waitUntilVisibilityOfElementLocated(TIME_BTN);
+ }
+
+ public WebElement customerUserIconHeader() {
+ return waitUntilVisibilityOfElementLocated(String.format(CUSTOMER_ICON_HEADER, CUSTOMER_USER_ICON_HEADER));
+ }
+
+ public WebElement customerAssetsIconHeader() {
+ return waitUntilVisibilityOfElementLocated(String.format(CUSTOMER_ICON_HEADER, CUSTOMER_ASSETS_ICON_HEADER));
+ }
+
+ public WebElement customerDevicesIconHeader() {
+ return waitUntilVisibilityOfElementLocated(String.format(CUSTOMER_ICON_HEADER, CUSTOMER_DEVICES_ICON_HEADER));
+ }
+
+ public WebElement customerDashboardIconHeader() {
+ return waitUntilVisibilityOfElementLocated(String.format(CUSTOMER_ICON_HEADER, CUSTOMER_DASHBOARD_ICON_HEADER));
+ }
+
+ public WebElement customerEdgeIconHeader() {
+ return waitUntilVisibilityOfElementLocated(String.format(CUSTOMER_ICON_HEADER, CUSTOMER_EDGE_ICON_HEADER));
+ }
+
+ public WebElement customerManageWindowIconHead() {
+ return waitUntilVisibilityOfElementLocated(CUSTOMER_USER_ICON_HEAD);
+ }
+
+ public WebElement manageCustomersUserBtnView() {
+ return waitUntilElementToBeClickable(String.format(MANAGE_BTN_VIEW, MANAGE_CUSTOMERS_USERS_BTN_VIEW));
+ }
+
+ public WebElement manageCustomersAssetsBtnView() {
+ return waitUntilElementToBeClickable(String.format(MANAGE_BTN_VIEW, MANAGE_CUSTOMERS_ASSETS_BTN_VIEW));
+ }
+
+ public WebElement manageCustomersDeviceBtnView() {
+ return waitUntilElementToBeClickable(String.format(MANAGE_BTN_VIEW, MANAGE_CUSTOMERS_DEVICE_BTN_VIEW));
+ }
+
+ public WebElement manageCustomersDashboardsBtnView() {
+ return waitUntilElementToBeClickable(String.format(MANAGE_BTN_VIEW, MANAGE_CUSTOMERS_DASHBOARD_BTN_VIEW));
+ }
+
+ public WebElement manageCustomersEdgeBtnView() {
+ return waitUntilElementToBeClickable(String.format(MANAGE_BTN_VIEW, MANAGE_CUSTOMERS_EDGE_BTN_VIEW));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CustomerPageHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CustomerPageHelper.java
new file mode 100644
index 0000000000..13d6a26077
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CustomerPageHelper.java
@@ -0,0 +1,161 @@
+package org.thingsboard.server.msa.ui.pages;
+
+import lombok.extern.slf4j.Slf4j;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.thingsboard.server.common.data.Customer;
+import org.thingsboard.server.common.data.page.PageData;
+
+import java.util.stream.Collectors;
+
+@Slf4j
+public class CustomerPageHelperAbstract extends CustomerPageElementsAbstract {
+ public CustomerPageHelperAbstract(WebDriver driver) {
+ super(driver);
+ }
+
+ private String customerName;
+ private String country;
+ private String dashboard;
+ private String dashboardFromView;
+
+ private String customerEmail;
+ private String customerCountry;
+ private String customerCity;
+
+ public void setCustomerName() {
+ this.customerName = entityTitles().get(0).getText();
+ }
+
+ public void setCustomerName(int number) {
+ this.customerName = entityTitles().get(number).getText();
+ }
+
+ public String getCustomerName() {
+ return customerName;
+ }
+
+ public void setCountry() {
+ this.country = countries().get(0).getText();
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setDashboard() {
+ this.dashboard = listOfEntity().get(0).getText();
+ }
+
+ public void setDashboardFromView() {
+ this.dashboardFromView = editMenuDashboardField().getAttribute("value");
+ }
+
+ public String getDashboard() {
+ return dashboard;
+ }
+
+ public String getDashboardFromView() {
+ return dashboardFromView;
+ }
+
+ public void setCustomerEmail(String title) {
+ this.customerEmail = email(title).getText();
+ }
+
+ public String getCustomerEmail() {
+ return customerEmail;
+ }
+
+ public void setCustomerCountry(String title) {
+ this.customerCountry = country(title).getText();
+ }
+
+ public String getCustomerCountry() {
+ return customerCountry;
+ }
+
+ public void setCustomerCity(String title) {
+ this.customerCity = city(title).getText();
+ }
+
+ public String getCustomerCity() {
+ return customerCity;
+ }
+
+ public void createCustomer(String entityName) {
+ try {
+ PageData tenantCustomer;
+ tenantCustomer = client.getCustomers(pageLink);
+ Customer customer = new Customer();
+ customer.setTitle(entityName);
+ client.saveCustomer(customer);
+ tenantCustomer.getData().add(customer);
+ } catch (Exception e) {
+ log.info("Can't create!");
+ }
+ }
+
+ public void deleteCustomer(String entityName) {
+ try {
+ PageData tenantRuleChains;
+ tenantRuleChains = client.getCustomers(pageLink);
+ try {
+ client.deleteCustomer(tenantRuleChains.getData().stream().filter(s -> s.getName().equals(entityName)).collect(Collectors.toList()).get(0).getId());
+ } catch (Exception e) {
+ client.deleteCustomer(tenantRuleChains.getData().stream().filter(s -> s.getName().equals(entityName)).collect(Collectors.toList()).get(1).getId());
+ }
+ } catch (Exception e) {
+ log.info("Can't delete!");
+ }
+ }
+
+ public void changeTitleEditMenu(String newTitle) {
+ titleFieldEntityView().clear();
+ wait.until(ExpectedConditions.textToBe(By.xpath(String.format(INPUT_FIELD, INPUT_FIELD_NAME_TITLE)), ""));
+ titleFieldEntityView().sendKeys(newTitle);
+ }
+
+ public void chooseDashboard() {
+ editMenuDashboardField().click();
+ sleep(0.5);
+ editMenuDashboard().click();
+ sleep(0.5);
+ }
+
+ public void createCustomersUser() {
+ plusBtn().click();
+ addUserEmailField().sendKeys(getRandomNumber() + "@gmail.com");
+ addBtnC().click();
+ activateWindowOkBtn().click();
+ }
+
+ public void selectCountryEntityView() {
+ countrySelectMenuEntityView().click();
+ setCountry();
+ countries().get(0).click();
+ }
+
+ public void selectCountryAddEntityView() {
+ countrySelectMenuAddEntityView().click();
+ setCountry();
+ countries().get(0).click();
+ }
+
+ public void assignedDashboard() {
+ plusBtn().click();
+ assignedField().click();
+ setDashboard();
+ listOfEntity().get(0).click();
+ submitAssignedBtn().click();
+ }
+
+ public boolean customerIsNotPresent(String title) {
+ return elementsIsNotPresent(getEntity(title));
+ }
+
+ public void sortByNameDown() {
+ doubleClick(sortByTitleBtn());
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageElements.java
new file mode 100644
index 0000000000..9e2595ed3c
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageElements.java
@@ -0,0 +1,38 @@
+package org.thingsboard.server.msa.ui.pages;
+
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+import java.util.List;
+
+public class DashboardPageElementsAbstract extends OtherPageElementsHelperAbstract {
+ public DashboardPageElementsAbstract(WebDriver driver) {
+ super(driver);
+ }
+
+ private static final String TITLES = "//mat-cell[contains(@class,'cdk-column-title')]/span";
+ private static final String ASSIGNED_BTN = ENTITY + "/../..//mat-icon[contains(text(),' assignment_ind')]/../..";
+ private static final String MANAGE_ASSIGNED_ENTITY_LIST_FIELD = "//input[@formcontrolname='entity']";
+ private static final String MANAGE_ASSIGNED_ENTITY = "//mat-option//span[contains(text(),'%s')]";
+ private static final String MANAGE_ASSIGNED_UPDATE_BTN = "//button[@type='submit']";
+
+ public List entityTitles() {
+ return waitUntilVisibilityOfElementsLocated(TITLES);
+ }
+
+ public WebElement assignedBtn(String title) {
+ return waitUntilElementToBeClickable(String.format(ASSIGNED_BTN, title));
+ }
+
+ public WebElement manageAssignedEntityListField() {
+ return waitUntilElementToBeClickable(MANAGE_ASSIGNED_ENTITY_LIST_FIELD);
+ }
+
+ public WebElement manageAssignedEntity(String title) {
+ return waitUntilElementToBeClickable(String.format(MANAGE_ASSIGNED_ENTITY, title));
+ }
+
+ public WebElement manageAssignedUpdateBtn() {
+ return waitUntilElementToBeClickable(MANAGE_ASSIGNED_UPDATE_BTN);
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageHelper.java
new file mode 100644
index 0000000000..7bf8956542
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageHelper.java
@@ -0,0 +1,25 @@
+package org.thingsboard.server.msa.ui.pages;
+
+import org.openqa.selenium.WebDriver;
+
+public class DashboardPageHelperAbstract extends DashboardPageElementsAbstract {
+ public DashboardPageHelperAbstract(WebDriver driver) {
+ super(driver);
+ }
+
+ private String dashboardTitle;
+
+ public void setDashboardTitle() {
+ this.dashboardTitle = entityTitles().get(0).getText();
+ }
+
+ public String getDashboardTitle() {
+ return dashboardTitle;
+ }
+
+ public void assignedCustomer(String title) {
+ manageAssignedEntityListField().click();
+ manageAssignedEntity(title).click();
+ manageAssignedUpdateBtn().click();
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/LoginPageElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/LoginPageElements.java
new file mode 100644
index 0000000000..54239e2971
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/LoginPageElements.java
@@ -0,0 +1,28 @@
+package org.thingsboard.server.msa.ui.pages;
+
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.thingsboard.server.msa.ui.base.AbstractBasePage;
+
+public class LoginPageElementsAbstract extends AbstractBasePage {
+ public LoginPageElementsAbstract(WebDriver driver) {
+ super(driver);
+ }
+
+ private static final String EMAIL_FIELD = "//input[@id='username-input']";
+ private static final String PASSWORD_FIELD = "//input[@id='password-input']";
+ private static final String SUBMIT_BTN = "//button[@type='submit']";
+
+ public WebElement emailField() {
+ return waitUntilElementToBeClickable(EMAIL_FIELD);
+ }
+
+ public WebElement passwordField() {
+ return waitUntilElementToBeClickable(PASSWORD_FIELD);
+ }
+
+ public WebElement submitBtn() {
+ return waitUntilElementToBeClickable(SUBMIT_BTN);
+ }
+
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/LoginPageHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/LoginPageHelper.java
new file mode 100644
index 0000000000..a39b507882
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/LoginPageHelper.java
@@ -0,0 +1,16 @@
+package org.thingsboard.server.msa.ui.pages;
+
+import org.openqa.selenium.WebDriver;
+import org.thingsboard.server.msa.ui.utils.Const;
+
+public class LoginPageHelperAbstract extends LoginPageElementsAbstract {
+ public LoginPageHelperAbstract(WebDriver driver) {
+ super(driver);
+ }
+
+ public void authorizationTenant() {
+ emailField().sendKeys(Const.TENANT_EMAIL);
+ passwordField().sendKeys(Const.TENANT_PASSWORD);
+ submitBtn().click();
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OpenRuleChainPageElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OpenRuleChainPageElements.java
new file mode 100644
index 0000000000..521758ea41
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OpenRuleChainPageElements.java
@@ -0,0 +1,33 @@
+package org.thingsboard.server.msa.ui.pages;
+
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.thingsboard.server.msa.ui.base.AbstractBasePage;
+
+public class OpenRuleChainPageElementsAbstract extends AbstractBasePage {
+ public OpenRuleChainPageElementsAbstract(WebDriver driver) {
+ super(driver);
+ }
+
+ private static final String DONE_BTN = "//mat-icon[contains(text(),'done')]/../..";
+ private static final String DONE_BTN_DISABLE = "//mat-icon[contains(text(),'done')]/../parent::button[@disabled='true']";
+ private static final String INPUT_NODE = "//div[@class='tb-rule-node tb-input-type']";
+ private static final String HEAD_RULE_CHAIN_NAME = "//div[@class='tb-breadcrumb']/span[2]";
+
+ public WebElement inputNode() {
+ return waitUntilVisibilityOfElementLocated(INPUT_NODE);
+ }
+
+ public WebElement headRuleChainName() {
+ return waitUntilVisibilityOfElementLocated(HEAD_RULE_CHAIN_NAME);
+ }
+
+ public String getDoneBtnDisable() {
+ return DONE_BTN_DISABLE;
+ }
+
+ public WebElement doneBtn() {
+ return waitUntilElementToBeClickable(DONE_BTN);
+ }
+
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OpenRuleChainPageHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OpenRuleChainPageHelper.java
new file mode 100644
index 0000000000..ccaaedab28
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OpenRuleChainPageHelper.java
@@ -0,0 +1,23 @@
+package org.thingsboard.server.msa.ui.pages;
+
+import org.openqa.selenium.WebDriver;
+
+public class OpenRuleChainPageHelperAbstract extends OpenRuleChainPageElementsAbstract {
+ public OpenRuleChainPageHelperAbstract(WebDriver driver) {
+ super(driver);
+ }
+
+ private String headName;
+
+ public void setHeadName() {
+ this.headName = headRuleChainName().getText().split(" ")[1];
+ }
+
+ public String getHeadName() {
+ return headName;
+ }
+
+ public void waitUntilDoneBtnDisable() {
+ waitUntilVisibilityOfElementLocated(getDoneBtnDisable());
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OtherPageElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OtherPageElements.java
new file mode 100644
index 0000000000..bf4be2dae2
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OtherPageElements.java
@@ -0,0 +1,228 @@
+package org.thingsboard.server.msa.ui.pages;
+
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.thingsboard.server.msa.ui.base.AbstractBasePage;
+
+import java.util.List;
+
+public class OtherPageElementsAbstract extends AbstractBasePage {
+ public OtherPageElementsAbstract(WebDriver driver) {
+ super(driver);
+ }
+
+ protected static final String ENTITY = "//mat-row//span[contains(text(),'%s')]";
+ protected static final String DELETE_BTN = ENTITY + "/../..//mat-icon[contains(text(),' delete')]/../..";
+ private static final String ENTITY_COUNT = "//div[@class='mat-paginator-range-label']";
+ private static final String WARNING_DELETE_POPUP_YES = "//tb-confirm-dialog//button[2]";
+ private static final String WARNING_DELETE_POPUP_TITLE = "//tb-confirm-dialog/h2";
+ private static final String REFRESH_BTN = "//mat-icon[contains(text(),'refresh')]/..";
+ private static final String HELP_BTN = "//mat-icon[contains(text(),'help')]/..";
+ private static final String CHECKBOX = "//mat-row//span[contains(text(),'%s')]/../..//mat-checkbox";
+ private static final String CHECKBOXES = "//tbody//mat-checkbox";
+ private static final String DELETE_SELECTED_BTN = "//span[contains(text(),'selected')]//..//mat-icon/../..";
+ private static final String DELETE_BTNS = "//mat-icon[contains(text(),' delete')]/../..";
+ private static final String MARKS_CHECKBOX = "//mat-row[contains (@class,'mat-selected')]//mat-checkbox[contains(@class, 'checked')]";
+ private static final String SELECT_ALL_CHECKBOX = "//thead//mat-checkbox";
+ private static final String ALL_ENTITY = "//mat-row[@class='mat-row cdk-row mat-row-select ng-star-inserted']";
+ private static final String EDIT_PENCIL_BTN = "//mat-icon[contains(text(),'edit')]/ancestor::button";
+ private static final String NAME_FIELD_EDIT_VIEW = "//input[@formcontrolname='name']";
+ private static final String HEADER_NAME_VIEW = "//header//div[@class='tb-details-title']/span";
+ private static final String DONE_BTN_EDIT_VIEW = "//mat-icon[contains(text(),'done')]/ancestor::button";
+ private static final String DESCRIPTION_ENTITY_VIEW = "//textarea";
+ private static final String DESCRIPTION_ADD_ENTITY_VIEW = "//tb-add-entity-dialog//textarea";
+ private static final String DEBUG_CHECKBOX_EDIT = "//mat-checkbox[@formcontrolname='debugMode']";
+ private static final String DEBUG_CHECKBOX_VIEW = "//mat-checkbox[@formcontrolname='debugMode']//input";
+ private static final String CLOSE_ENTITY_VIEW_BTN = "//header//mat-icon[contains(text(),'close')]/../..";
+ private static final String SEARCH_BTN = "//mat-toolbar//mat-icon[contains(text(),'search')]/.." +
+ "/parent::button[@class='mat-focus-indicator mat-tooltip-trigger mat-icon-button mat-button-base ng-star-inserted']";
+ private static final String SORT_BY_NAME_BTN = "//div[contains(text(),'Name')]";
+ private static final String SORT_BY_TITLE_BTN = "//div[contains(text(),'Title')]";
+ private static final String SORT_BY_TIME_BTN = "//div[contains(text(),'Created time')]/..";
+ private static final String CREATED_TIME = "//tbody[@role='rowgroup']//mat-cell[2]/span";
+ private static final String PLUS_BTN = "//mat-icon[contains(text(),'add')]/../parent::button";
+ private static final String CREATE_VIEW_ADD_BTN = "//span[contains(text(),'Add')]/..";
+ private static final String WARNING_MESSAGE = "//tb-snack-bar-component/div/div";
+ private static final String ERROR_MESSAGE = "//mat-error";
+ private static final String ENTITY_VIEW_TITLE = "//div[@class='tb-details-title']//span";
+ private static final String LIST_OF_ENTITY = "//div[@role='listbox']/mat-option";
+ protected static final String ADD_ENTITY_VIEW = "//tb-add-entity-dialog";
+ protected static final String STATE_CONTROLLER = "//tb-entity-state-controller";
+ private static final String SEARCH_FIELD = "//input[contains (@data-placeholder,'Search')]";
+
+ public String getEntity(String entityName) {
+ return String.format(ENTITY, entityName);
+ }
+
+ public String getWarningMessage() {
+ return WARNING_MESSAGE;
+ }
+
+ public String getDeleteBtns() {
+ return DELETE_BTNS;
+ }
+
+ public String getCheckbox(String entityName) {
+ return String.format(CHECKBOX, entityName);
+ }
+
+ public String getCheckboxes() {
+ return String.format(CHECKBOXES);
+ }
+
+ public WebElement warningPopUpYesBtn() {
+ return waitUntilElementToBeClickable(WARNING_DELETE_POPUP_YES);
+ }
+
+ public WebElement warningPopUpTitle() {
+ return waitUntilElementToBeClickable(WARNING_DELETE_POPUP_TITLE);
+ }
+
+ public WebElement entityCount() {
+ return waitUntilVisibilityOfElementLocated(ENTITY_COUNT);
+ }
+
+ public WebElement refreshBtn() {
+ return waitUntilElementToBeClickable(REFRESH_BTN);
+ }
+
+ public WebElement helpBtn() {
+ return waitUntilElementToBeClickable(HELP_BTN);
+ }
+
+ public WebElement checkBox(String entityName) {
+ return waitUntilElementToBeClickable(String.format(CHECKBOX, entityName));
+ }
+
+ public WebElement deleteSelectedBtn() {
+ return waitUntilElementToBeClickable(DELETE_SELECTED_BTN);
+ }
+
+ public WebElement selectAllCheckBox() {
+ return waitUntilElementToBeClickable(SELECT_ALL_CHECKBOX);
+ }
+
+ public WebElement editPencilBtn() {
+ return waitUntilElementToBeClickable(EDIT_PENCIL_BTN);
+ }
+
+ public WebElement nameFieldEditMenu() {
+ return waitUntilElementToBeClickable(NAME_FIELD_EDIT_VIEW);
+ }
+
+ public WebElement headerNameView() {
+ return waitUntilVisibilityOfElementLocated(HEADER_NAME_VIEW);
+ }
+
+ public WebElement doneBtnEditView() {
+ return waitUntilElementToBeClickable(DONE_BTN_EDIT_VIEW);
+ }
+
+ public WebElement descriptionEntityView() {
+ return waitUntilVisibilityOfElementLocated(DESCRIPTION_ENTITY_VIEW);
+ }
+
+ public WebElement descriptionAddEntityView() {
+ return waitUntilVisibilityOfElementLocated(DESCRIPTION_ADD_ENTITY_VIEW);
+ }
+
+ public WebElement debugCheckboxEdit() {
+ return waitUntilElementToBeClickable(DEBUG_CHECKBOX_EDIT);
+ }
+
+ public WebElement debugCheckboxView() {
+ return waitUntilVisibilityOfElementLocated(DEBUG_CHECKBOX_VIEW);
+ }
+
+ public WebElement closeEntityViewBtn() {
+ return waitUntilElementToBeClickable(CLOSE_ENTITY_VIEW_BTN);
+ }
+
+ public WebElement searchBtn() {
+ return waitUntilElementToBeClickable(SEARCH_BTN);
+ }
+
+ public List deleteBtns() {
+ return waitUntilVisibilityOfElementsLocated(DELETE_BTNS);
+ }
+
+ public List checkBoxes() {
+ return waitUntilElementsToBeClickable(CHECKBOXES);
+ }
+
+ public List markCheckbox() {
+ return waitUntilVisibilityOfElementsLocated(MARKS_CHECKBOX);
+ }
+
+ public List allEntity() {
+ return waitUntilVisibilityOfElementsLocated(ALL_ENTITY);
+ }
+
+ public WebElement doneBtnEditViewVisible() {
+ return waitUntilVisibilityOfElementLocated(DONE_BTN_EDIT_VIEW);
+ }
+
+ public WebElement sortByNameBtn() {
+ return waitUntilElementToBeClickable(SORT_BY_NAME_BTN);
+ }
+
+ public WebElement sortByTitleBtn() {
+ return waitUntilElementToBeClickable(SORT_BY_TITLE_BTN);
+ }
+
+ public WebElement sortByTimeBtn() {
+ return waitUntilElementToBeClickable(SORT_BY_TIME_BTN);
+ }
+
+ public List createdTime() {
+ return waitUntilVisibilityOfElementsLocated(CREATED_TIME);
+ }
+
+ public WebElement plusBtn() {
+ return waitUntilElementToBeClickable(PLUS_BTN);
+ }
+
+ public WebElement addBtnC() {
+ return waitUntilElementToBeClickable(CREATE_VIEW_ADD_BTN);
+ }
+
+ public WebElement addBtnV() {
+ return waitUntilVisibilityOfElementLocated(CREATE_VIEW_ADD_BTN);
+ }
+
+ public WebElement warningMessage() {
+ return waitUntilVisibilityOfElementLocated(WARNING_MESSAGE);
+ }
+
+ public WebElement deleteBtn(String entityName) {
+ return waitUntilVisibilityOfElementLocated(String.format(DELETE_BTN, entityName));
+ }
+
+ public WebElement entity(String entityName) {
+ return waitUntilElementToBeClickable(String.format(ENTITY, entityName));
+ }
+
+ public WebElement errorMessage() {
+ return waitUntilVisibilityOfElementLocated(ERROR_MESSAGE);
+ }
+
+ public WebElement entityViewTitle() {
+ return waitUntilVisibilityOfElementLocated(ENTITY_VIEW_TITLE);
+ }
+
+ public List listOfEntity() {
+ return waitUntilElementsToBeClickable(LIST_OF_ENTITY);
+ }
+
+ public WebElement addEntityView() {
+ return waitUntilVisibilityOfElementLocated(ADD_ENTITY_VIEW);
+ }
+
+ public WebElement stateController() {
+ return waitUntilVisibilityOfElementLocated(STATE_CONTROLLER);
+ }
+
+ public WebElement searchField() {
+ return waitUntilElementToBeClickable(SEARCH_FIELD);
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OtherPageElementsHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OtherPageElementsHelper.java
new file mode 100644
index 0000000000..dc4a41e9b9
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OtherPageElementsHelper.java
@@ -0,0 +1,98 @@
+package org.thingsboard.server.msa.ui.pages;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebDriver;
+
+public class OtherPageElementsHelperAbstract extends OtherPageElementsAbstract {
+ public OtherPageElementsHelperAbstract(WebDriver driver) {
+ super(driver);
+ }
+
+ private String headerName;
+
+ public void setHeaderName() {
+ this.headerName = headerNameView().getText();
+ }
+
+ public String getHeaderName() {
+ return headerName;
+ }
+
+ public boolean entityIsNotPresent(String entityName) {
+ return elementIsNotPresent(getEntity(entityName));
+ }
+
+ public void goToHelpPage() {
+ helpBtn().click();
+ goToNextTab(2);
+ }
+
+ public void clickOnCheckBoxes(int count) {
+ for (int i = 0; i < count; i++) {
+ checkBoxes().get(i).click();
+ }
+ }
+
+ public void changeNameEditMenu(String newName) {
+ nameFieldEditMenu().sendKeys(Keys.CONTROL + "a" + Keys.BACK_SPACE);
+ nameFieldEditMenu().sendKeys(newName);
+ }
+
+ public void changeDescription(String newDescription) {
+ descriptionEntityView().sendKeys(Keys.CONTROL + "a" + Keys.BACK_SPACE);
+ descriptionEntityView().sendKeys(newDescription);
+ }
+
+ public String deleteRuleChainTrash(String entityName) {
+ String s = "";
+ if (deleteBtn(entityName) != null) {
+ deleteBtn(entityName).click();
+ warningPopUpYesBtn().click();
+ return entityName;
+ } else {
+ for (int i = 0; i < deleteBtns().size(); i++) {
+ if (deleteBtns().get(i).isEnabled()) {
+ deleteBtns().get(i).click();
+ warningPopUpYesBtn().click();
+ if (elementIsNotPresent(getWarningMessage())) {
+ s = driver.findElements(By.xpath(getDeleteBtns()
+ + "/../../../mat-cell/following-sibling::mat-cell/following-sibling::mat-cell[contains(@class,'cdk-column-name')]/span")).get(i).getText();
+ break;
+ }
+ }
+ }
+ return s;
+ }
+ }
+
+ public String deleteSelected(String entityName) {
+ String s = "";
+ if (deleteBtn(entityName) != null) {
+ checkBox(entityName).click();
+ deleteSelectedBtn().click();
+ warningPopUpYesBtn().click();
+ return entityName;
+ } else {
+ for (int i = 0; i < checkBoxes().size(); i++) {
+ if (checkBoxes().get(i).isDisplayed()) {
+ s = driver.findElements(By.xpath(getCheckboxes() + "/../../mat-cell/following-sibling::mat-cell/following-sibling::mat-cell[contains(@class,'cdk-column-name')]/span")).get(i).getText();
+ checkBox(s).click();
+ deleteSelectedBtn().click();
+ warningPopUpYesBtn().click();
+ if (elementIsNotPresent(getWarningMessage())) {
+ break;
+ }
+ }
+ }
+ return s;
+ }
+ }
+
+ public void searchEntity(String namePath) {
+ searchBtn().click();
+ searchField().sendKeys(namePath);
+ sleep(0.5);
+ }
+}
+
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/RuleChainsPageElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/RuleChainsPageElements.java
new file mode 100644
index 0000000000..4a378bb1c3
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/RuleChainsPageElements.java
@@ -0,0 +1,113 @@
+package org.thingsboard.server.msa.ui.pages;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+import java.util.List;
+
+public class RuleChainsPageElementsAbstract extends OtherPageElementsHelperAbstract {
+ public RuleChainsPageElementsAbstract(WebDriver driver) {
+ super(driver);
+ }
+
+ private static final String MAKE_ROOT_BTN = ENTITY + "/../..//mat-icon[contains(text(),' flag')]/../..";
+ private static final String ROOT = ENTITY + "/../..//mat-icon[text() = 'check_box']";
+ private static final String ROOT_DISABLE = ENTITY + "/../..//mat-icon[text() = 'check_box_outline_blank']";
+ private static final String CREATED_TIME = ENTITY + "/../..//mat-cell/span[contains(text(),'%s')]";
+ private static final String CREATE_RULE_CHAIN_BTN = "//span[contains(text(),'Create new rule chain')]";
+ private static final String CREATE_RULE_CHAIN_NAME_FIELD = "//form[@class='ng-untouched ng-pristine ng-invalid']//input[@formcontrolname='name']";
+ private static final String RULE_CHAINS_NAMES_WITHOUT_ROOT = "//mat-icon[contains(text(),'check_box_outline_blank')]/../../../mat-cell[contains(@class,'name')]/span";
+ private static final String DELETE_RULE_CHAIN_FROM_VIEW_BTN = "//span[contains(text(),' Delete')]";
+ private static final String IMPORT_RULE_CHAIN_BTN = "//span[contains(text(),'Import rule chain')]";
+ private static final String BROWSE_FILE = "//input[@class='file-input']";
+ private static final String IMPORT_BROWSE_FILE = "//mat-dialog-container//span[contains(text(),'Import')]/..";
+ private static final String IMPORTING_FILE = "//div[contains(text(),'%s')]";
+ private static final String CLEAR_IMPORT_FILE_BTN = "//div[@class='tb-file-clear-container']//button";
+ private static final String OPEN_RULE_CHAIN = ENTITY + "/../..//mat-icon[contains(text(),' settings_ethernet')]";
+ private static final String OPEN_RULE_CHAIN_FROM_VIEW = "//span[contains(text(),'Open rule chain')]";
+ private static final String MAKE_ROOT_FROM_VIEW = "(//span[contains(text(),' Make rule chain root ')]/..)[1]";
+ private static final String ROOT_ACTIVE_CHECKBOXES = "//mat-icon[text() = 'check_box']";
+ private static final String ALL_NAMES = "//mat-icon[contains(text(),'check')]/../../../mat-cell[contains(@class,'name')]/span";
+
+ public String getDeleteRuleChainFromViewBtn() {
+ return DELETE_RULE_CHAIN_FROM_VIEW_BTN;
+ }
+
+ public WebElement makeRootBtn(String entityName) {
+ return waitUntilElementToBeClickable(String.format(MAKE_ROOT_BTN, entityName));
+ }
+
+ public List rootCheckBoxesEnable() {
+ return waitUntilVisibilityOfElementsLocated(ROOT_ACTIVE_CHECKBOXES);
+ }
+
+ public WebElement rootCheckBoxEnable(String entityName) {
+ return waitUntilVisibilityOfElementLocated(String.format(ROOT, entityName));
+ }
+
+ public WebElement rootCheckBoxDisable(String entityName) {
+ return waitUntilVisibilityOfElementLocated(String.format(ROOT_DISABLE, entityName));
+ }
+
+ public WebElement createRuleChainBtn() {
+ return waitUntilElementToBeClickable(CREATE_RULE_CHAIN_BTN);
+ }
+
+ public WebElement importRuleChainBtn() {
+ return waitUntilElementToBeClickable(IMPORT_RULE_CHAIN_BTN);
+ }
+
+ public WebElement nameField() {
+ return waitUntilElementToBeClickable(CREATE_RULE_CHAIN_NAME_FIELD);
+ }
+
+ public List notRootRuleChainsNames() {
+ return waitUntilVisibilityOfElementsLocated(RULE_CHAINS_NAMES_WITHOUT_ROOT);
+ }
+
+ public WebElement deleteBtnFromView() {
+ return waitUntilElementToBeClickable(DELETE_RULE_CHAIN_FROM_VIEW_BTN);
+ }
+
+ public WebElement browseFile() {
+ waitUntilElementToBeClickable(BROWSE_FILE + "/preceding-sibling::button");
+ return driver.findElement(By.xpath(BROWSE_FILE));
+ }
+
+ public WebElement importBrowseFileBtn() {
+ return waitUntilElementToBeClickable(IMPORT_BROWSE_FILE);
+ }
+
+ public WebElement importingFile(String fileName) {
+ return waitUntilVisibilityOfElementLocated(String.format(IMPORTING_FILE, fileName));
+ }
+
+ public WebElement clearImportFileBtn() {
+ return waitUntilElementToBeClickable(CLEAR_IMPORT_FILE_BTN);
+ }
+
+ public WebElement openRuleChainFromViewBtn() {
+ return waitUntilElementToBeClickable(OPEN_RULE_CHAIN_FROM_VIEW);
+ }
+
+ public WebElement openRuleChainBtn(String name) {
+ return waitUntilElementToBeClickable(String.format(OPEN_RULE_CHAIN, name));
+ }
+
+ public List entities(String name) {
+ return waitUntilVisibilityOfElementsLocated(String.format(ENTITY, name));
+ }
+
+ public WebElement makeRootFromViewBtn() {
+ return waitUntilElementToBeClickable(MAKE_ROOT_FROM_VIEW);
+ }
+
+ public List allNames() {
+ return waitUntilVisibilityOfElementsLocated(ALL_NAMES);
+ }
+
+ public WebElement createdTimeEntity(String name, String time) {
+ return waitUntilElementToBeClickable(String.format(CREATED_TIME, name, time));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/RuleChainsPageHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/RuleChainsPageHelper.java
new file mode 100644
index 0000000000..9d23660b11
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/RuleChainsPageHelper.java
@@ -0,0 +1,180 @@
+package org.thingsboard.server.msa.ui.pages;
+
+import lombok.extern.slf4j.Slf4j;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.testng.Assert;
+import org.thingsboard.server.common.data.page.PageData;
+import org.thingsboard.server.common.data.rule.RuleChain;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Random;
+import java.util.stream.Collectors;
+
+@Slf4j
+public class RuleChainsPageHelperAbstract extends RuleChainsPageElementsAbstract {
+ public RuleChainsPageHelperAbstract(WebDriver driver) {
+ super(driver);
+ }
+
+ public void openCreateRuleChainView() {
+ plusBtn().click();
+ createRuleChainBtn().click();
+ }
+
+ public void openImportRuleChainView() {
+ plusBtn().click();
+ importRuleChainBtn().click();
+ }
+
+ private int getRandomNumberFromRuleChainsCount() {
+ Random random = new Random();
+ return random.nextInt(notRootRuleChainsNames().size());
+ }
+
+ private String ruleChainName;
+
+ public void setRuleChainNameWithoutRoot() {
+ this.ruleChainName = notRootRuleChainsNames().get(getRandomNumberFromRuleChainsCount()).getText();
+ }
+
+ public void setRuleChainNameWithoutRoot(int number) {
+ this.ruleChainName = notRootRuleChainsNames().get(number).getText();
+ }
+
+ public void setRuleChainName(int number) {
+ this.ruleChainName = allNames().get(number).getText();
+ }
+
+ public String getRuleChainName() {
+ return this.ruleChainName;
+ }
+
+ public String getRuleChainId(String entityName) {
+ PageData tenantRuleChains;
+ tenantRuleChains = client.getRuleChains(pageLink);
+ return String.valueOf(tenantRuleChains.getData().stream().filter(s -> s.getName().equals(entityName)).collect(Collectors.toList()).get(0).getId());
+ }
+
+ public void deleteRuleChain(String entityName) {
+ try {
+ PageData tenantRuleChains;
+ tenantRuleChains = client.getRuleChains(pageLink);
+ try {
+ client.deleteRuleChain(tenantRuleChains.getData().stream().filter(s -> s.getName().equals(entityName)).collect(Collectors.toList()).get(0).getId());
+ } catch (Exception e) {
+ client.deleteRuleChain(tenantRuleChains.getData().stream().filter(s -> s.getName().equals(entityName)).collect(Collectors.toList()).get(1).getId());
+ }
+ } catch (Exception e) {
+ log.info("Can't delete!");
+ }
+ }
+
+ public void deleteAllRuleChain(String entityName) {
+ try {
+ PageData tenantRuleChains;
+ tenantRuleChains = client.getRuleChains(pageLink);
+ tenantRuleChains.getData().stream().filter(s -> s.getName().equals(entityName)).collect(Collectors.toList()).forEach(x -> client.deleteRuleChain(x.getId()));
+ } catch (Exception e) {
+ log.info("Can't delete!");
+ }
+ }
+
+ public void createRuleChain(String entityName) {
+ try {
+ PageData tenantRuleChains;
+ tenantRuleChains = client.getRuleChains(pageLink);
+ RuleChain ruleChain = new RuleChain();
+ ruleChain.setName(entityName);
+ client.saveRuleChain(ruleChain);
+ tenantRuleChains.getData().add(ruleChain);
+ } catch (Exception e) {
+ log.info("Can't create!");
+ }
+ }
+
+ public void makeRoot() {
+ try {
+ PageData tenantRuleChains;
+ tenantRuleChains = client.getRuleChains(pageLink);
+ tenantRuleChains.getData().stream().filter(s -> s.getName().equals("Root Rule Chain")).collect(Collectors.toList()).forEach(x -> client.setRootRuleChain(x.getId()));
+ } catch (Exception e) {
+ log.info("Can't make root!");
+ }
+ }
+
+ public void createRuleChains(String entityName, int count) {
+ try {
+ PageData tenantRuleChains;
+ tenantRuleChains = client.getRuleChains(pageLink);
+ RuleChain ruleChain = new RuleChain();
+ for (int i = 0; i < count; i++) {
+ ruleChain.setName(entityName);
+ client.saveRuleChain(ruleChain);
+ tenantRuleChains.getData().add(ruleChain);
+ }
+ } catch (Exception e) {
+ log.info("Can't create!");
+ }
+ }
+
+ public String deleteRuleChainFromView(String ruleChainName) {
+ String s = "";
+ if (deleteBtnFromView() != null) {
+ deleteBtnFromView().click();
+ warningPopUpYesBtn().click();
+ if (elementIsNotPresent(getWarningMessage())) {
+ return getEntity(ruleChainName);
+ }
+ } else {
+ for (int i = 0; i < notRootRuleChainsNames().size(); i++) {
+ notRootRuleChainsNames().get(i).click();
+ if (deleteBtnFromView() != null) {
+ deleteBtnFromView().click();
+ warningPopUpYesBtn().click();
+ if (elementIsNotPresent(getWarningMessage())) {
+ s = notRootRuleChainsNames().get(i).getText();
+ break;
+ }
+ }
+ }
+ }
+ return s;
+ }
+
+ public void assertCheckBoxIsNotDisplayed(String entityName) {
+ wait.until(ExpectedConditions.elementToBeClickable(By.xpath("(//mat-checkbox)[2]")));
+ Assert.assertFalse(driver.findElement(By.xpath(getCheckbox(entityName))).isDisplayed());
+ }
+
+ public void assertDeleteBtnInRootRuleChainIsNotDisplayed() {
+ Assert.assertFalse(driver.findElement(By.xpath(getDeleteRuleChainFromViewBtn())).isDisplayed());
+ }
+
+ public boolean ruleChainsIsNotPresent(String ruleChainName) {
+ return elementsIsNotPresent(getEntity(ruleChainName));
+ }
+
+ public void doubleClickOnRuleChain(String ruleChainName) {
+ doubleClick(entity(ruleChainName));
+ }
+
+ public void sortByNameDown() {
+ doubleClick(sortByNameBtn());
+ }
+
+ ArrayList sort;
+
+ public void setSort() {
+ ArrayList createdTime = new ArrayList<>();
+ createdTime().forEach(x -> createdTime.add(x.getText()));
+ Collections.sort(createdTime);
+ sort = createdTime;
+ }
+
+ public ArrayList getSort() {
+ return sort;
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/SideBarMenuViewElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/SideBarMenuViewElements.java
new file mode 100644
index 0000000000..1e1484be7b
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/SideBarMenuViewElements.java
@@ -0,0 +1,27 @@
+package pages;
+
+import base.BasePage;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+public class SideBarMenuViewElements extends BasePage {
+ public SideBarMenuViewElements(WebDriver driver) {
+ super(driver);
+ }
+
+ private static final String RULE_CHAINS_BTN = "//mat-toolbar//a[@href='/ruleChains']";
+ private static final String CUSTOMER_BTN = "//mat-toolbar//a[@href='/customers']";
+ private static final String DASHBOARD_BTN = "//mat-toolbar//a[@href='/dashboards']";
+
+ public WebElement ruleChainsBtn() {
+ return waitUntilElementToBeClickable(RULE_CHAINS_BTN);
+ }
+
+ public WebElement customerBtn() {
+ return waitUntilElementToBeClickable(CUSTOMER_BTN);
+ }
+
+ public WebElement dashboardBtn() {
+ return waitUntilElementToBeClickable(DASHBOARD_BTN);
+ }
+}
\ No newline at end of file
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/CreateCustomerTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/CreateCustomerTest.java
new file mode 100644
index 0000000000..c59b950862
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/CreateCustomerTest.java
@@ -0,0 +1,164 @@
+package org.thingsboard.server.msa.ui.tests.customerSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.CustomerPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.*;
+
+public class CreateCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private CustomerPageHelperAbstract customerPage;
+ private String customerName;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ customerPage = new CustomerPageHelperAbstract(driver);
+ }
+
+ @AfterMethod
+ public void delete() {
+ if (customerName != null) {
+ customerPage.deleteCustomer(customerName);
+ customerName = null;
+ }
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can click on Add after specifying the name (text/numbers /special characters)")
+ public void createCustomer() {
+ String customerName = ENTITY_NAME;
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.plusBtn().click();
+ customerPage.titleFieldAddEntityView().sendKeys(customerName);
+ customerPage.addBtnC().click();
+ customerPage.refreshBtn().click();
+ this.customerName = customerName;
+
+ Assert.assertNotNull(customerPage.customer(customerName));
+ Assert.assertTrue(customerPage.customer(customerName).isDisplayed());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ public void createCustomerWithFullInformation() {
+ String customerName = ENTITY_NAME;
+ String text = "Text";
+ String email = "email@mail.com";
+ String number = "2015550123";
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.plusBtn().click();
+ customerPage.titleFieldAddEntityView().sendKeys(customerName);
+ customerPage.selectCountryAddEntityView();
+ customerPage.descriptionAddEntityView().sendKeys(text);
+ customerPage.cityAddEntityView().sendKeys(text);
+ customerPage.stateAddEntityView().sendKeys(text);
+ customerPage.zipAddEntityView().sendKeys(text);
+ customerPage.addressAddEntityView().sendKeys(text);
+ customerPage.address2AddEntityView().sendKeys(text);
+ customerPage.phoneNumberAddEntityView().sendKeys(number);
+ customerPage.emailAddEntityView().sendKeys(email);
+ customerPage.addBtnC().click();
+ customerPage.setCustomerEmail(customerName);
+ customerPage.setCustomerCountry(customerName);
+ customerPage.setCustomerCity(customerName);
+ customerPage.entity(customerName).click();
+ this.customerName = customerName;
+
+ Assert.assertNotNull(customerPage.customer(customerName));
+ Assert.assertEquals(customerPage.entityViewTitle().getText(), customerName);
+ Assert.assertEquals(customerPage.titleFieldEntityView().getAttribute("value"), customerName);
+ Assert.assertEquals(customerPage.countrySelectMenuEntityView().getText(), customerPage.getCountry());
+ Assert.assertEquals(customerPage.descriptionEntityView().getAttribute("value"), text);
+ Assert.assertEquals(customerPage.cityEntityView().getAttribute("value"), text);
+ Assert.assertEquals(customerPage.stateEntityView().getAttribute("value"), text);
+ Assert.assertEquals(customerPage.zipEntityView().getAttribute("value"), text);
+ Assert.assertEquals(customerPage.addressEntityView().getAttribute("value"), text);
+ Assert.assertEquals(customerPage.address2EntityView().getAttribute("value"), text);
+ Assert.assertEquals(customerPage.phoneNumberEntityView().getAttribute("value"), "+1" + number);
+ Assert.assertEquals(customerPage.emailEntityView().getAttribute("value"), email);
+ Assert.assertEquals(customerPage.getCustomerEmail(), email);
+ Assert.assertEquals(customerPage.getCustomerCountry(), customerPage.getCountry());
+ Assert.assertEquals(customerPage.getCustomerCity(), text);
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can`t add customer without the name (empty field or just space)")
+ public void createCustomerWithoutName() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.plusBtn().click();
+
+ Assert.assertFalse(customerPage.addBtnV().isEnabled());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description()
+ public void createCustomerWithOnlySpace() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.plusBtn().click();
+ customerPage.titleFieldAddEntityView().sendKeys(" ");
+ customerPage.addBtnC().click();
+
+ Assert.assertNotNull(customerPage.warningMessage());
+ Assert.assertTrue(customerPage.warningMessage().isDisplayed());
+ Assert.assertEquals(customerPage.warningMessage().getText(), EMPTY_CUSTOMER_MESSAGE);
+ Assert.assertNotNull(customerPage.addEntityView());
+ Assert.assertTrue(customerPage.addEntityView().isDisplayed());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can't create a customer with the same name")
+ public void createCustomerSameName() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.setCustomerName();
+ String customerName = customerPage.getCustomerName();
+ customerPage.plusBtn().click();
+ customerPage.titleFieldAddEntityView().sendKeys(customerName);
+ customerPage.addBtnC().click();
+
+ Assert.assertNotNull(customerPage.warningMessage());
+ Assert.assertTrue(customerPage.warningMessage().isDisplayed());
+ Assert.assertEquals(customerPage.warningMessage().getText(), SAME_NAME_WARNING_CUSTOMER_MESSAGE);
+ Assert.assertNotNull(customerPage.addEntityView());
+ Assert.assertTrue(customerPage.addEntityView().isDisplayed());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can click on Add after specifying the name (text/numbers /special characters)")
+ public void createCustomerWithoutRefresh() {
+ String customerName = ENTITY_NAME;
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.plusBtn().click();
+ customerPage.titleFieldAddEntityView().sendKeys(customerName);
+ customerPage.addBtnC().click();
+ this.customerName = customerName;
+
+ Assert.assertNotNull(customerPage.customer(customerName));
+ Assert.assertTrue(customerPage.customer(customerName).isDisplayed());
+ }
+
+ @Test(priority = 40, groups = "smoke")
+ @Description("Question mark icon leads to rule chain documentation (PE)")
+ public void documentation() {
+ String urlPath = "docs/user-guide/ui/customers/";
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.setCustomerName();
+ customerPage.customer(customerPage.getCustomerName()).click();
+ customerPage.goToHelpPage();
+
+ Assert.assertTrue(urlContains(urlPath));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/CustomerEditMenuTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/CustomerEditMenuTest.java
new file mode 100644
index 0000000000..36297cbf3a
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/CustomerEditMenuTest.java
@@ -0,0 +1,270 @@
+package org.thingsboard.server.msa.ui.tests.customerSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.CustomerPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.DashboardPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+import org.thingsboard.server.msa.ui.utils.DataProviderCredential;
+
+import static org.thingsboard.server.msa.ui.base.AbstractBasePage.getRandomNumber;
+import static org.thingsboard.server.msa.ui.utils.Const.*;
+
+public class CustomerEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private CustomerPageHelperAbstract customerPage;
+ private DashboardPageHelperAbstract dashboardPage;
+ private String customerName;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ customerPage = new CustomerPageHelperAbstract(driver);
+ dashboardPage = new DashboardPageHelperAbstract(driver);
+ }
+
+ @AfterMethod
+ public void delete() {
+ if (customerName != null) {
+ customerPage.deleteCustomer(customerName);
+ customerName = null;
+ }
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can click by pencil icon and edit the title (change the title) and save the changes. All changes have been applied")
+ public void changeTitle() {
+ customerPage.createCustomer(ENTITY_NAME);
+ String title = "Changed" + getRandomNumber();
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.entityTitles().get(0).click();
+ customerPage.setHeaderName();
+ String titleBefore = customerPage.getHeaderName();
+ customerPage.editPencilBtn().click();
+ customerPage.changeTitleEditMenu(title);
+ customerPage.doneBtnEditView().click();
+ customerPage.setHeaderName();
+ String titleAfter = customerPage.getHeaderName();
+ customerName = title;
+
+ Assert.assertNotEquals(titleBefore, titleAfter);
+ Assert.assertEquals(titleAfter, title);
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can`t delete the title and save changes")
+ public void deleteTitle() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.entityTitles().get(0).click();
+ customerPage.editPencilBtn().click();
+ customerPage.titleFieldEntityView().clear();
+
+ Assert.assertFalse(customerPage.doneBtnEditViewVisible().isEnabled());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can`t save just a space in the title")
+ public void saveOnlyWithSpace() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.setCustomerName();
+ customerPage.entityTitles().get(0).click();
+ customerPage.editPencilBtn().click();
+ customerPage.changeTitleEditMenu(" ");
+ customerPage.doneBtnEditView().click();
+ customerPage.setHeaderName();
+
+ Assert.assertNotNull(customerPage.warningMessage());
+ Assert.assertTrue(customerPage.warningMessage().isDisplayed());
+ Assert.assertEquals(customerPage.warningMessage().getText(), EMPTY_CUSTOMER_MESSAGE);
+ Assert.assertEquals(customerPage.getCustomerName(), customerPage.getHeaderName());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can write/change/delete the descriptionEntityView and save the changes. All changes have been applied")
+ public void editDescription() {
+ String title = ENTITY_NAME;
+ customerPage.createCustomer(title);
+ String description = "Description";
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.entityTitles().get(0).click();
+ customerPage.editPencilBtn().click();
+ customerPage.descriptionEntityView().sendKeys(description);
+ customerPage.doneBtnEditView().click();
+ String description1 = customerPage.descriptionEntityView().getAttribute("value");
+ customerPage.editPencilBtn().click();
+ customerPage.descriptionEntityView().sendKeys(description);
+ customerPage.doneBtnEditView().click();
+ String description2 = customerPage.descriptionEntityView().getAttribute("value");
+ customerPage.editPencilBtn().click();
+ customerPage.changeDescription("");
+ customerPage.doneBtnEditView().click();
+ customerName = title;
+
+ Assert.assertEquals(description, description1);
+ Assert.assertEquals(description + description, description2);
+ Assert.assertTrue(customerPage.descriptionEntityView().getAttribute("value").isEmpty());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description
+ public void assignedDashboardFromDashboard() {
+ String title = ENTITY_NAME;
+ customerPage.createCustomer(title);
+
+ sideBarMenuView.dashboardBtn().click();
+ dashboardPage.setDashboardTitle();
+ dashboardPage.assignedBtn(dashboardPage.getDashboardTitle()).click();
+ dashboardPage.assignedCustomer(title);
+ sideBarMenuView.customerBtn().click();
+ customerPage.entity(title).click();
+ customerPage.editPencilBtn().click();
+ customerPage.chooseDashboard();
+ customerPage.doneBtnEditView().click();
+ customerPage.setDashboardFromView();
+ customerPage.closeEntityViewBtn().click();
+ customerPage.manageCustomersUserBtn(title).click();
+ customerPage.createCustomersUser();
+ customerPage.userLoginBtn().click();
+ customerName = title;
+
+ Assert.assertNotNull(customerPage.usersWidget());
+ Assert.assertTrue(customerPage.usersWidget().isDisplayed());
+ Assert.assertEquals(customerPage.getDashboardFromView(), dashboardPage.getDashboardTitle());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description
+ public void assignedDashboard() {
+ String title = ENTITY_NAME;
+ customerPage.createCustomer(title);
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.manageCustomersDashboardsBtn(title).click();
+ customerPage.assignedDashboard();
+ sideBarMenuView.customerBtn().click();
+ customerPage.entity(title).click();
+ customerPage.editPencilBtn().click();
+ customerPage.chooseDashboard();
+ customerPage.doneBtnEditView().click();
+ customerPage.setDashboardFromView();
+ customerPage.closeEntityViewBtn().click();
+ customerPage.manageCustomersUserBtn(title).click();
+ customerPage.createCustomersUser();
+ customerPage.userLoginBtn().click();
+ customerName = title;
+
+ Assert.assertNotNull(customerPage.usersWidget());
+ Assert.assertTrue(customerPage.usersWidget().isDisplayed());
+ Assert.assertEquals(customerPage.getDashboard(), customerPage.getDashboardFromView());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description
+ public void assignedDashboardWithoutHide() {
+ String title = ENTITY_NAME;
+ customerPage.createCustomer(title);
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.manageCustomersDashboardsBtn(title).click();
+ customerPage.assignedDashboard();
+ sideBarMenuView.customerBtn().click();
+ customerPage.entity(title).click();
+ customerPage.editPencilBtn().click();
+ customerPage.chooseDashboard();
+ customerPage.hideHomeDashboardToolbarCheckbox().click();
+ customerPage.doneBtnEditView().click();
+ customerPage.setDashboardFromView();
+ customerPage.closeEntityViewBtn().click();
+ customerPage.manageCustomersUserBtn(title).click();
+ customerPage.createCustomersUser();
+ customerPage.userLoginBtn().click();
+ customerName = title;
+
+ Assert.assertNotNull(customerPage.usersWidget());
+ Assert.assertTrue(customerPage.usersWidget().isDisplayed());
+ Assert.assertEquals(customerPage.getDashboard(), customerPage.getDashboardFromView());
+ Assert.assertNotNull(customerPage.stateController());
+ Assert.assertNotNull(customerPage.filterBtn());
+ Assert.assertNotNull(customerPage.timeBtn());
+ Assert.assertTrue(customerPage.stateController().isDisplayed());
+ Assert.assertTrue(customerPage.filterBtn().isDisplayed());
+ Assert.assertTrue(customerPage.timeBtn().isDisplayed());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description
+ public void addPhoneNumber() {
+ String title = ENTITY_NAME;
+ customerPage.createCustomer(title);
+ String number = "2015550123";
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.entityTitles().get(0).click();
+ customerPage.editPencilBtn().click();
+ customerPage.phoneNumberEntityView().sendKeys(number);
+ customerPage.doneBtnEditView().click();
+ customerName = title;
+
+ Assert.assertTrue(customerPage.phoneNumberEntityView().getAttribute("value").contains(number));
+ }
+
+ @Test(priority = 20, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "incorrectPhoneNumber")
+ @Description
+ public void addIncorrectPhoneNumber(String number) {
+ sideBarMenuView.customerBtn().click();
+ customerPage.entityTitles().get(0).click();
+ customerPage.editPencilBtn().click();
+ customerPage.phoneNumberEntityView().sendKeys(number);
+ boolean doneBtnIsEnable = customerPage.doneBtnEditViewVisible().isEnabled();
+ customerPage.doneBtnEditViewVisible().click();
+
+ Assert.assertFalse(doneBtnIsEnable);
+ Assert.assertNotNull(customerPage.errorMessage());
+ Assert.assertTrue(customerPage.errorMessage().isDisplayed());
+ Assert.assertEquals(customerPage.errorMessage().getText(), PHONE_NUMBER_ERROR_MESSAGE);
+ }
+
+ @Test(priority = 30, groups = "smoke")
+ public void addAllInformation() {
+ String title = ENTITY_NAME;
+ customerPage.createCustomer(title);
+ String text = "Text";
+ String email = "email@mail.com";
+ String number = "2015550123";
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.entityTitles().get(0).click();
+ customerPage.editPencilBtn().click();
+ customerPage.selectCountryEntityView();
+ customerPage.descriptionEntityView().sendKeys(text);
+ customerPage.cityEntityView().sendKeys(text);
+ customerPage.stateEntityView().sendKeys(text);
+ customerPage.zipEntityView().sendKeys(text);
+ customerPage.addressEntityView().sendKeys(text);
+ customerPage.address2EntityView().sendKeys(text);
+ customerPage.phoneNumberEntityView().sendKeys(number);
+ customerPage.emailEntityView().sendKeys(email);
+ customerPage.doneBtnEditView().click();
+ customerName = title;
+
+ Assert.assertEquals(customerPage.countrySelectMenuEntityView().getText(), customerPage.getCountry());
+ Assert.assertEquals(customerPage.descriptionEntityView().getAttribute("value"), text);
+ Assert.assertEquals(customerPage.cityEntityView().getAttribute("value"), text);
+ Assert.assertEquals(customerPage.stateEntityView().getAttribute("value"), text);
+ Assert.assertEquals(customerPage.zipEntityView().getAttribute("value"), text);
+ Assert.assertEquals(customerPage.addressEntityView().getAttribute("value"), text);
+ Assert.assertEquals(customerPage.address2EntityView().getAttribute("value"), text);
+ Assert.assertEquals(customerPage.phoneNumberEntityView().getAttribute("value"), "+1" + number);
+ Assert.assertEquals(customerPage.emailEntityView().getAttribute("value"), email);
+ }
+}
\ No newline at end of file
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/DeleteCustomerTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/DeleteCustomerTest.java
new file mode 100644
index 0000000000..7a22422777
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/DeleteCustomerTest.java
@@ -0,0 +1,83 @@
+package org.thingsboard.server.msa.ui.tests.customerSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.CustomerPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME;
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class DeleteCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private CustomerPageHelperAbstract customerPage;
+ private RuleChainsPageHelperAbstract ruleChainsPage;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ customerPage = new CustomerPageHelperAbstract(driver);
+ ruleChainsPage = new RuleChainsPageHelperAbstract(driver);
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can remove the customer by clicking on the trash can icon in the right corner")
+ public void removeCustomerByRightSideBtn() {
+ String customer = ENTITY_NAME;
+ customerPage.createCustomer(customer);
+
+ sideBarMenuView.customerBtn().click();
+ String deletedCustomer = customerPage.deleteRuleChainTrash(customer);
+ customerPage.refreshBtn().click();
+
+ Assert.assertTrue(customerPage.entityIsNotPresent(deletedCustomer));
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can mark the customer in the checkbox and then click on the trash can icon in the menu that appears at the top")
+ public void removeSelectedCustomer() {
+ String customerName = ENTITY_NAME;
+ customerPage.createCustomer(customerName);
+
+ sideBarMenuView.customerBtn().click();
+ String deletedCustomer = customerPage.deleteSelected(customerName);
+ ruleChainsPage.refreshBtn().click();
+
+ Assert.assertTrue(ruleChainsPage.entityIsNotPresent(deletedCustomer));
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can click on the name of the rule chain and click on the 'Delete customer' button")
+ public void removeFromCustomerView() {
+ String customerName = ENTITY_NAME;
+ customerPage.createCustomer(customerName);
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.entity(customerName).click();
+ String deletedCustomer = ruleChainsPage.deleteRuleChainFromView(customerName);
+ ruleChainsPage.refreshBtn().click();
+
+ Assert.assertTrue(ruleChainsPage.entityIsNotPresent(deletedCustomer));
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("The rule chain is deleted immediately after clicking remove (no need to refresh the page)")
+ public void removeCustomerByRightSideBtnWithoutRefresh() {
+ String customer = ENTITY_NAME;
+ customerPage.createCustomer(customer);
+
+ sideBarMenuView.customerBtn().click();
+ String deletedCustomer = customerPage.deleteRuleChainTrash(customer);
+ customerPage.refreshBtn().click();
+
+ Assert.assertTrue(customerPage.entityIsNotPresent(deletedCustomer));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/DeleteSeveralCustomerTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/DeleteSeveralCustomerTest.java
new file mode 100644
index 0000000000..9847f1b763
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/DeleteSeveralCustomerTest.java
@@ -0,0 +1,81 @@
+package org.thingsboard.server.msa.ui.tests.customerSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.CustomerPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME;
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class DeleteSeveralCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private CustomerPageHelperAbstract customerPage;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ customerPage = new CustomerPageHelperAbstract(driver);
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can mark several customers in the checkbox near the names and then click on the trash can icon in the menu that appears at the top")
+ public void canDeleteSeveralCustomersByTopBtn() {
+ String title1 = ENTITY_NAME + "1";
+ String title2 = ENTITY_NAME + "2";
+ int count = 2;
+ customerPage.createCustomer(title1);
+ customerPage.createCustomer(title2);
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.clickOnCheckBoxes(count);
+
+ Assert.assertEquals(customerPage.markCheckbox().size(), count);
+ customerPage.markCheckbox().forEach(x -> Assert.assertTrue(x.isDisplayed()));
+
+ customerPage.deleteSelectedBtn().click();
+ customerPage.warningPopUpYesBtn().click();
+ customerPage.refreshBtn().click();
+
+ Assert.assertTrue(customerPage.customerIsNotPresent(title1));
+ Assert.assertTrue(customerPage.customerIsNotPresent(title2));
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can mark several rule chains in the checkbox near the names and then click on the trash can icon in the menu that appears at the top")
+ public void selectAllCustomers() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.selectAllCheckBox().click();
+ customerPage.deleteSelectedBtn().click();
+
+ Assert.assertNotNull(customerPage.warningPopUpTitle());
+ Assert.assertTrue(customerPage.warningPopUpTitle().isDisplayed());
+ Assert.assertTrue(customerPage.warningPopUpTitle().getText().contains(String.valueOf(customerPage.markCheckbox().size())));
+ }
+
+ @Test(priority = 30, groups = "smoke")
+ @Description("The rule chains are deleted immediately after clicking remove (no need to refresh the page)")
+ public void deleteSeveralCustomersByTopBtnWithoutRefresh() {
+ String title1 = ENTITY_NAME + "1";
+ String title2 = ENTITY_NAME + "2";
+ int count = 2;
+ customerPage.createCustomer(title1);
+ customerPage.createCustomer(title2);
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.clickOnCheckBoxes(count);
+
+ customerPage.deleteSelectedBtn().click();
+ customerPage.warningPopUpYesBtn().click();
+
+ Assert.assertTrue(customerPage.customerIsNotPresent(title1));
+ Assert.assertTrue(customerPage.customerIsNotPresent(title2));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersAssetsTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersAssetsTest.java
new file mode 100644
index 0000000000..785ee8c813
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersAssetsTest.java
@@ -0,0 +1,54 @@
+package org.thingsboard.server.msa.ui.tests.customerSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.CustomerPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class ManageCustomersAssetsAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private CustomerPageHelperAbstract customerPage;
+ private final String manage = "Assets";
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ customerPage = new CustomerPageHelperAbstract(driver);
+ }
+
+ @Test(groups = "smoke")
+ @Description("Can go to the 'Customer assets' window by clicking on the 'Manage customer users' icon in the right corner")
+ public void openWindowByRightCornerBtn() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.setCustomerName();
+ customerPage.manageCustomersAssetsBtn(customerPage.getCustomerName()).click();
+
+ Assert.assertTrue(urlContains(manage.toLowerCase()));
+ Assert.assertNotNull(customerPage.customerAssetsIconHeader());
+ Assert.assertTrue(customerPage.customerAssetsIconHeader().isDisplayed());
+ Assert.assertTrue(customerPage.customerManageWindowIconHead().getText().contains(manage));
+ }
+
+ @Test(groups = "smoke")
+ @Description("Can go to the 'Customer Assets' window by clicking on the name/row of the customer and click on the 'Manage users' button")
+ public void openWindowByView() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.setCustomerName();
+ customerPage.entity(customerPage.getCustomerName()).click();
+ customerPage.manageCustomersAssetsBtnView().click();
+
+ Assert.assertTrue(urlContains(manage.toLowerCase()));
+ Assert.assertNotNull(customerPage.customerAssetsIconHeader());
+ Assert.assertTrue(customerPage.customerAssetsIconHeader().isDisplayed());
+ Assert.assertTrue(customerPage.customerManageWindowIconHead().getText().contains(manage));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersDashboardsTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersDashboardsTest.java
new file mode 100644
index 0000000000..68fe281d0b
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersDashboardsTest.java
@@ -0,0 +1,53 @@
+package org.thingsboard.server.msa.ui.tests.customerSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.CustomerPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class ManageCustomersDashboardsAbstractDiverBaseTest extends AbstractDiverBaseTest {
+ private SideBarMenuViewElements sideBarMenuView;
+ private CustomerPageHelperAbstract customerPage;
+ private final String manage = "Dashboards";
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ customerPage = new CustomerPageHelperAbstract(driver);
+ }
+
+ @Test(groups = "smoke")
+ @Description("Can go to the 'Customer Dashboards' window by clicking on the 'Manage customer users' icon in the right corner")
+ public void openWindowByRightCornerBtn() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.setCustomerName();
+ customerPage.manageCustomersDashboardsBtn(customerPage.getCustomerName()).click();
+
+ Assert.assertTrue(urlContains(manage.toLowerCase()));
+ Assert.assertNotNull(customerPage.customerDashboardIconHeader());
+ Assert.assertTrue(customerPage.customerDashboardIconHeader().isDisplayed());
+ Assert.assertTrue(customerPage.customerManageWindowIconHead().getText().contains(manage));
+ }
+
+ @Test(groups = "smoke")
+ @Description("Can go to the 'Customer Dashboards' window by clicking on the name/row of the customer and click on the 'Manage users' button")
+ public void openWindowByView() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.setCustomerName();
+ customerPage.entity(customerPage.getCustomerName()).click();
+ customerPage.manageCustomersDashboardsBtnView().click();
+
+ Assert.assertTrue(urlContains(manage.toLowerCase()));
+ Assert.assertNotNull(customerPage.customerDashboardIconHeader());
+ Assert.assertTrue(customerPage.customerDashboardIconHeader().isDisplayed());
+ Assert.assertTrue(customerPage.customerManageWindowIconHead().getText().contains(manage));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersDevicesTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersDevicesTest.java
new file mode 100644
index 0000000000..d62b5fe4cf
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersDevicesTest.java
@@ -0,0 +1,53 @@
+package org.thingsboard.server.msa.ui.tests.customerSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.CustomerPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class ManageCustomersDevicesAbstractDiverBaseTest extends AbstractDiverBaseTest {
+ private SideBarMenuViewElements sideBarMenuView;
+ private CustomerPageHelperAbstract customerPage;
+ private final String manage = "Devices";
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ customerPage = new CustomerPageHelperAbstract(driver);
+ }
+
+ @Test(groups = "smoke")
+ @Description("Can go to the 'Customer Devices' window by clicking on the 'Manage customer users' icon in the right corner")
+ public void openWindowByRightCornerBtn() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.setCustomerName();
+ customerPage.manageCustomersDevicesBtn(customerPage.getCustomerName()).click();
+
+ Assert.assertTrue(urlContains(manage.toLowerCase()));
+ Assert.assertNotNull(customerPage.customerDevicesIconHeader());
+ Assert.assertTrue(customerPage.customerDevicesIconHeader().isDisplayed());
+ Assert.assertTrue(customerPage.customerManageWindowIconHead().getText().contains(manage));
+ }
+
+ @Test(groups = "smoke")
+ @Description("Can go to the 'Customer Devices' window by clicking on the name/row of the customer and click on the 'Manage users' button")
+ public void openWindowByView() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.setCustomerName();
+ customerPage.entity(customerPage.getCustomerName()).click();
+ customerPage.manageCustomersDeviceBtnView().click();
+
+ Assert.assertTrue(urlContains(manage.toLowerCase()));
+ Assert.assertNotNull(customerPage.customerDevicesIconHeader());
+ Assert.assertTrue(customerPage.customerDevicesIconHeader().isDisplayed());
+ Assert.assertTrue(customerPage.customerManageWindowIconHead().getText().contains(manage));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersEdgesTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersEdgesTest.java
new file mode 100644
index 0000000000..ff0ac3e4f1
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersEdgesTest.java
@@ -0,0 +1,54 @@
+package org.thingsboard.server.msa.ui.tests.customerSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.CustomerPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class ManageCustomersEdgesAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private CustomerPageHelperAbstract customerPage;
+ private String iconText = "Edge instances";
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ customerPage = new CustomerPageHelperAbstract(driver);
+ }
+
+ @Test(groups = "smoke")
+ @Description("Can go to the 'Customer Edges' window by clicking on the 'Manage customer users' icon in the right corner")
+ public void openWindowByRightCornerBtn() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.setCustomerName();
+ customerPage.manageCustomersEdgeBtn(customerPage.getCustomerName()).click();
+
+ Assert.assertTrue(urlContains("edgeInstances"));
+ Assert.assertNotNull(customerPage.customerEdgeIconHeader());
+ Assert.assertTrue(customerPage.customerEdgeIconHeader().isDisplayed());
+ Assert.assertTrue(customerPage.customerManageWindowIconHead().getText().contains(iconText));
+ }
+
+ @Test(groups = "smoke")
+ @Description("Can go to the 'Customer Edges' window by clicking on the name/row of the customer and click on the 'Manage users' button")
+ public void openWindowByView() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.setCustomerName();
+ customerPage.entity(customerPage.getCustomerName()).click();
+ customerPage.manageCustomersEdgeBtnView().click();
+
+ Assert.assertTrue(urlContains("edgeInstances"));
+ Assert.assertNotNull(customerPage.customerEdgeIconHeader());
+ Assert.assertTrue(customerPage.customerEdgeIconHeader().isDisplayed());
+ Assert.assertTrue(customerPage.customerManageWindowIconHead().getText().contains(iconText));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersUsersTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersUsersTest.java
new file mode 100644
index 0000000000..855e227b5e
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersUsersTest.java
@@ -0,0 +1,54 @@
+package org.thingsboard.server.msa.ui.tests.customerSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.CustomerPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class ManageCustomersUsersAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private CustomerPageHelperAbstract customerPage;
+ private String iconText = "Customer Users";
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ customerPage = new CustomerPageHelperAbstract(driver);
+ }
+
+ @Test(groups = "smoke")
+ @Description("Can go to the 'Customer Users' window by clicking on the 'Manage customer users' icon in the right corner")
+ public void openWindowByRightCornerBtn() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.setCustomerName();
+ customerPage.manageCustomersUserBtn(customerPage.getCustomerName()).click();
+
+ Assert.assertTrue(urlContains("user"));
+ Assert.assertNotNull(customerPage.customerUserIconHeader());
+ Assert.assertTrue(customerPage.customerUserIconHeader().isDisplayed());
+ Assert.assertTrue(customerPage.customerManageWindowIconHead().getText().contains(iconText));
+ }
+
+ @Test(groups = "smoke")
+ @Description("Can go to the 'Customer Users' window by clicking on the name/row of the customer and click on the 'Manage users' button")
+ public void openWindowByView() {
+ sideBarMenuView.customerBtn().click();
+ customerPage.setCustomerName();
+ customerPage.entity(customerPage.getCustomerName()).click();
+ customerPage.manageCustomersUserBtnView().click();
+
+ Assert.assertTrue(urlContains("user"));
+ Assert.assertNotNull(customerPage.customerUserIconHeader());
+ Assert.assertTrue(customerPage.customerUserIconHeader().isDisplayed());
+ Assert.assertTrue(customerPage.customerManageWindowIconHead().getText().contains(iconText));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/SearchCustomerTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/SearchCustomerTest.java
new file mode 100644
index 0000000000..6db022da62
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/SearchCustomerTest.java
@@ -0,0 +1,56 @@
+package org.thingsboard.server.msa.ui.tests.customerSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.CustomerPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+import org.thingsboard.server.msa.ui.utils.DataProviderCredential;
+
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class SearchCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private CustomerPageHelperAbstract customerPage;
+ private String entityName;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ customerPage = new CustomerPageHelperAbstract(driver);
+ }
+
+ @AfterMethod
+ public void deleteCustomer() {
+ customerPage.deleteCustomer(entityName);
+ }
+
+ @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "customerNameForSearchByFirstAndSecondWord")
+ @Description("Can search by the first/second word of the name")
+ public void searchFirstWord(String namePath) {
+ sideBarMenuView.customerBtn().click();
+ customerPage.searchEntity(namePath);
+
+ customerPage.allEntity().forEach(x -> Assert.assertTrue(x.getText().contains(namePath)));
+ }
+
+ @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForSearchBySymbolAndNumber")
+ @Description("Can search by number/symbol")
+ public void searchNumber(String name, String namePath) {
+ customerPage.createCustomer(name);
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.searchEntity(namePath);
+ customerPage.setCustomerName();
+ entityName = name;
+
+ Assert.assertTrue(customerPage.getCustomerName().contains(namePath));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/SortByNameTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/SortByNameTest.java
new file mode 100644
index 0000000000..8ab49b6c68
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/SortByNameTest.java
@@ -0,0 +1,121 @@
+package org.thingsboard.server.msa.ui.tests.customerSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.CustomerPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+import org.thingsboard.server.msa.ui.utils.DataProviderCredential;
+
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest {
+ private SideBarMenuViewElements sideBarMenuView;
+ private CustomerPageHelperAbstract customerPage;
+ private String customerName;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ customerPage = new CustomerPageHelperAbstract(driver);
+ }
+
+ @AfterMethod
+ public void delete() {
+ if (customerName != null) {
+ customerPage.deleteCustomer(customerName);
+ customerName = null;
+ }
+ }
+
+ @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForSort")
+ @Description
+ public void specialCharacterUp(String title) {
+ customerPage.createCustomer(title);
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.sortByTitleBtn().click();
+ customerPage.setCustomerName();
+ customerName = title;
+
+ Assert.assertEquals(customerPage.getCustomerName(), title);
+ }
+
+ @Test(priority = 20, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForAllSort")
+ @Description
+ public void allSortUp(String customer, String customerSymbol, String customerNumber) {
+ customerPage.createCustomer(customerSymbol);
+ customerPage.createCustomer(customer);
+ customerPage.createCustomer(customerNumber);
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.sortByTitleBtn().click();
+ customerPage.setCustomerName(0);
+ String firstCustomer = customerPage.getCustomerName();
+ customerPage.setCustomerName(1);
+ String secondCustomer = customerPage.getCustomerName();
+ customerPage.setCustomerName(2);
+ String thirdCustomer = customerPage.getCustomerName();
+
+ boolean firstEquals = firstCustomer.equals(customerSymbol);
+ boolean secondEquals = secondCustomer.equals(customerNumber);
+ boolean thirdEquals = thirdCustomer.equals(customer);
+
+ customerPage.deleteCustomer(customer);
+ customerPage.deleteCustomer(customerNumber);
+ customerPage.deleteCustomer(customerSymbol);
+
+ Assert.assertTrue(firstEquals);
+ Assert.assertTrue(secondEquals);
+ Assert.assertTrue(thirdEquals);
+ }
+
+ @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForSort")
+ @Description
+ public void specialCharacterDown(String title) {
+ customerPage.createCustomer(title);
+
+ sideBarMenuView.customerBtn().click();
+ customerPage.sortByNameDown();
+ customerPage.setCustomerName(customerPage.allEntity().size() - 1);
+ customerName = title;
+
+ Assert.assertEquals(customerPage.getCustomerName(), title);
+ }
+
+ @Test(priority = 20, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForAllSort")
+ @Description
+ public void allSortDown(String customer, String customerSymbol, String customerNumber) {
+ customerPage.createCustomer(customerSymbol);
+ customerPage.createCustomer(customer);
+ customerPage.createCustomer(customerNumber);
+
+ sideBarMenuView.customerBtn().click();
+ int lastIndex = customerPage.allEntity().size() - 1;
+ customerPage.sortByNameDown();
+ customerPage.setCustomerName(lastIndex);
+ String firstCustomer = customerPage.getCustomerName();
+ customerPage.setCustomerName(lastIndex - 1);
+ String secondCustomer = customerPage.getCustomerName();
+ customerPage.setCustomerName(lastIndex - 2);
+ String thirdCustomer = customerPage.getCustomerName();
+
+ boolean firstEquals = firstCustomer.equals(customerSymbol);
+ boolean secondEquals = secondCustomer.equals(customerNumber);
+ boolean thirdEquals = thirdCustomer.equals(customer);
+
+ customerPage.deleteCustomer(customer);
+ customerPage.deleteCustomer(customerNumber);
+ customerPage.deleteCustomer(customerSymbol);
+
+ Assert.assertTrue(firstEquals);
+ Assert.assertTrue(secondEquals);
+ Assert.assertTrue(thirdEquals);
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/CreateRuleChainImportTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/CreateRuleChainImportTest.java
new file mode 100644
index 0000000000..2b05fb8867
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/CreateRuleChainImportTest.java
@@ -0,0 +1,110 @@
+package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.OpenRuleChainPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.*;
+
+public class CreateRuleChainImportAbstractDiverBaseTest extends AbstractDiverBaseTest {
+ private SideBarMenuViewElements sideBarMenuView;
+ private RuleChainsPageHelperAbstract ruleChainsPage;
+ private OpenRuleChainPageHelperAbstract openRuleChainPage;
+ private final String absolutePathToFileImportRuleChain = getClass().getClassLoader().getResource(IMPORT_RULE_CHAIN_FILE_NAME).getPath();
+ private final String absolutePathToFileImportTxt = getClass().getClassLoader().getResource(IMPORT_TXT_FILE_NAME).getPath();
+ private String ruleChainName;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ ruleChainsPage = new RuleChainsPageHelperAbstract(driver);
+ openRuleChainPage = new OpenRuleChainPageHelperAbstract(driver);
+ }
+
+ @AfterMethod
+ public void delete() {
+ if (ruleChainName != null) {
+ ruleChainsPage.deleteRuleChain(ruleChainName);
+ ruleChainName = null;
+ }
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can drop a JSON file and import it")
+ public void importRuleChain() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.openImportRuleChainView();
+ ruleChainsPage.browseFile().sendKeys(absolutePathToFileImportRuleChain);
+
+ Assert.assertNotNull(ruleChainsPage.importingFile(IMPORT_RULE_CHAIN_FILE_NAME));
+ Assert.assertTrue(ruleChainsPage.importingFile(IMPORT_RULE_CHAIN_FILE_NAME).isDisplayed());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can delete a file by clicking on the icon Remove")
+ public void importRuleChainAndDeleteFile() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.openImportRuleChainView();
+ ruleChainsPage.browseFile().sendKeys(absolutePathToFileImportRuleChain);
+ ruleChainsPage.clearImportFileBtn().click();
+
+ Assert.assertNotNull(ruleChainsPage.importingFile(EMPTY_IMPORT_MESSAGE));
+ Assert.assertTrue(ruleChainsPage.importingFile(EMPTY_IMPORT_MESSAGE).isDisplayed());
+ Assert.assertTrue(ruleChainsPage.entityIsNotPresent(IMPORT_TXT_FILE_NAME));
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can`t Select / drop a file of a different format than JSON")
+ public void importTxtFile() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.openImportRuleChainView();
+ ruleChainsPage.browseFile().sendKeys(absolutePathToFileImportTxt);
+
+ Assert.assertNotNull(ruleChainsPage.importingFile(EMPTY_IMPORT_MESSAGE));
+ Assert.assertTrue(ruleChainsPage.importingFile(EMPTY_IMPORT_MESSAGE).isDisplayed());
+ }
+
+ @Test(priority = 30, groups = "smoke")
+ @Description("After clicking on Import - imported rule chain opens (need to save by clicking on the Apply changes icon)")
+ public void importRuleChainAndSave() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.openImportRuleChainView();
+ ruleChainsPage.browseFile().sendKeys(absolutePathToFileImportRuleChain);
+ ruleChainsPage.importBrowseFileBtn().click();
+ openRuleChainPage.doneBtn().click();
+ openRuleChainPage.waitUntilDoneBtnDisable();
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainName = IMPORT_RULE_CHAIN_NAME;
+
+ Assert.assertNotNull(ruleChainsPage.entity(IMPORT_RULE_CHAIN_NAME));
+ Assert.assertTrue(ruleChainsPage.entity(IMPORT_RULE_CHAIN_NAME).isDisplayed());
+ }
+
+ @Test(priority = 40, groups = "smoke")
+ @Description("Can create a rule chain with the same name")
+ public void importRuleChainAndSaveWithSameName() {
+ ruleChainsPage.createRuleChain(IMPORT_RULE_CHAIN_NAME);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.openImportRuleChainView();
+ ruleChainsPage.browseFile().sendKeys(absolutePathToFileImportRuleChain);
+ ruleChainsPage.importBrowseFileBtn().click();
+ openRuleChainPage.doneBtn().click();
+ openRuleChainPage.waitUntilDoneBtnDisable();
+ sideBarMenuView.ruleChainsBtn().click();
+ boolean sizeBigger1 = ruleChainsPage.entities(IMPORT_RULE_CHAIN_NAME).size() > 1;
+
+ ruleChainsPage.deleteAllRuleChain(IMPORT_RULE_CHAIN_NAME);
+
+ Assert.assertTrue(sizeBigger1);
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/CreateRuleChainTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/CreateRuleChainTest.java
new file mode 100644
index 0000000000..32470c86f9
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/CreateRuleChainTest.java
@@ -0,0 +1,139 @@
+package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.*;
+
+public class CreateRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private RuleChainsPageHelperAbstract ruleChainsPage;
+ private String ruleChainName;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ ruleChainsPage = new RuleChainsPageHelperAbstract(driver);
+ }
+
+ @AfterMethod
+ public void delete() {
+ if (ruleChainName != null) {
+ ruleChainsPage.deleteRuleChain(ruleChainName);
+ ruleChainName = null;
+ }
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can click on Add after specifying the name (text/numbers /special characters)")
+ public void createRuleChain() {
+ String ruleChainName = ENTITY_NAME;
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.openCreateRuleChainView();
+ ruleChainsPage.nameField().sendKeys(ruleChainName);
+ ruleChainsPage.addBtnC().click();
+ ruleChainsPage.refreshBtn().click();
+ this.ruleChainName = ruleChainName;
+
+ Assert.assertNotNull(ruleChainsPage.entity(ruleChainName));
+ Assert.assertTrue(ruleChainsPage.entity(ruleChainName).isDisplayed());
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description()
+ public void createRuleChainWithDescription() {
+ String ruleChainName = ENTITY_NAME;
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.openCreateRuleChainView();
+ ruleChainsPage.nameField().sendKeys(ruleChainName);
+ ruleChainsPage.descriptionAddEntityView().sendKeys(ENTITY_NAME);
+ ruleChainsPage.addBtnC().click();
+ ruleChainsPage.refreshBtn().click();
+ ruleChainsPage.entity(ENTITY_NAME).click();
+ ruleChainsPage.setHeaderName();
+ this.ruleChainName = ruleChainName;
+
+ Assert.assertEquals(ruleChainsPage.getHeaderName(), ruleChainName);
+ Assert.assertEquals(ruleChainsPage.descriptionEntityView().getAttribute("value"), ruleChainName);
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can`t add rule chain without the name (empty field or just space)")
+ public void createRuleChainWithoutName() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.openCreateRuleChainView();
+
+ Assert.assertFalse(ruleChainsPage.addBtnV().isEnabled());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description()
+ public void createRuleChainWithOnlySpace() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.openCreateRuleChainView();
+ ruleChainsPage.nameField().sendKeys(" ");
+ ruleChainsPage.addBtnC().click();
+
+ Assert.assertNotNull(ruleChainsPage.warningMessage());
+ Assert.assertTrue(ruleChainsPage.warningMessage().isDisplayed());
+ Assert.assertEquals(ruleChainsPage.warningMessage().getText(), EMPTY_RULE_CHAIN_MESSAGE);
+ Assert.assertNotNull(ruleChainsPage.addEntityView());
+ Assert.assertTrue(ruleChainsPage.addEntityView().isDisplayed());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can create a rule chain with the same name")
+ public void createRuleChainWithSameName() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.setRuleChainNameWithoutRoot();
+ ruleChainsPage.openCreateRuleChainView();
+ String ruleChainName = ruleChainsPage.getRuleChainName();
+ ruleChainsPage.nameField().sendKeys(ruleChainName);
+ ruleChainsPage.addBtnC().click();
+ ruleChainsPage.refreshBtn().click();
+ this.ruleChainName = ruleChainName;
+
+ Assert.assertNotNull(ruleChainsPage.entity(ruleChainName));
+ Assert.assertTrue(ruleChainsPage.entities(ruleChainName).size() > 1);
+ }
+
+ @Test(priority = 30, groups = "smoke")
+ @Description("After clicking on Add - appears immediately in the list (no need to refresh the page)")
+ public void createRuleChainWithoutRefresh() {
+ String ruleChainName = ENTITY_NAME;
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.openCreateRuleChainView();
+ ruleChainsPage.nameField().sendKeys(ruleChainName);
+ ruleChainsPage.addBtnC().click();
+ this.ruleChainName = ruleChainName;
+
+ Assert.assertNotNull(ruleChainsPage.entity(ruleChainName));
+ Assert.assertTrue(ruleChainsPage.entity(ruleChainName).isDisplayed());
+ }
+
+ @Test(priority = 40, groups = "smoke")
+ @Description("Question mark icon leads to rule chain documentation (PE)")
+ public void documentation() {
+ String urlPath = "docs/user-guide/ui/rule-chains/";
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.setRuleChainNameWithoutRoot();
+ ruleChainsPage.entity(ruleChainsPage.getRuleChainName()).click();
+ ruleChainsPage.goToHelpPage();
+
+ Assert.assertTrue(urlContains(urlPath));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/DeleteRuleChainTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/DeleteRuleChainTest.java
new file mode 100644
index 0000000000..f2fe8c7c1c
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/DeleteRuleChainTest.java
@@ -0,0 +1,148 @@
+package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.*;
+
+public class DeleteRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest {
+ private SideBarMenuViewElements sideBarMenuView;
+ private RuleChainsPageHelperAbstract ruleChainsPage;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ ruleChainsPage = new RuleChainsPageHelperAbstract(driver);
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can remove the rule chain by clicking on the trash can icon in the right corner")
+ public void removeRuleChainByRightSideBtn() {
+ ruleChainsPage.createRuleChain(ENTITY_NAME);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ String deletedRuleChain = ruleChainsPage.deleteRuleChainTrash(ENTITY_NAME);
+ ruleChainsPage.refreshBtn().click();
+
+ Assert.assertTrue(ruleChainsPage.entityIsNotPresent(deletedRuleChain));
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can mark the rule chain in the checkbox and then click on the trash can icon in the menu that appears at the top")
+ public void removeSelectedRuleChain() {
+ String ruleChainName = ENTITY_NAME;
+ ruleChainsPage.createRuleChain(ruleChainName);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ String deletedRuleChain = ruleChainsPage.deleteSelected(ruleChainName);
+ ruleChainsPage.refreshBtn().click();
+
+ Assert.assertTrue(ruleChainsPage.entityIsNotPresent(deletedRuleChain));
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can click on the name of the rule chain and click on the 'Delete rule chain' button")
+ public void removeFromRuleChainView() {
+ ruleChainsPage.createRuleChain(ENTITY_NAME);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.entity(ENTITY_NAME).click();
+ String deletedRuleChain = ruleChainsPage.deleteRuleChainFromView(ENTITY_NAME);
+ ruleChainsPage.refreshBtn().click();
+
+ Assert.assertTrue(ruleChainsPage.entityIsNotPresent(deletedRuleChain));
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can`t remove Root Rule Chain (the trash can is disabled in the right corner)")
+ public void removeRootRuleChain() {
+ sideBarMenuView.ruleChainsBtn().click();
+
+ Assert.assertFalse(ruleChainsPage.deleteBtn(ROOT_RULE_CHAIN_NAME).isEnabled());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can`t remove Root Rule Chain (can`t mark the rule chain in the checkbox )")
+ public void removeSelectedRootRuleChain() {
+ sideBarMenuView.ruleChainsBtn().click();
+
+ ruleChainsPage.assertCheckBoxIsNotDisplayed(ROOT_RULE_CHAIN_NAME);
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can`t remove Root Rule Chain (missing delete button)")
+ public void removeFromRootRuleChainView() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.entity(ROOT_RULE_CHAIN_NAME).click();
+ ruleChainsPage.deleteBtnFromView();
+
+ ruleChainsPage.assertDeleteBtnInRootRuleChainIsNotDisplayed();
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can remove the rule chain by clicking on the trash can icon in the right corner")
+ public void removeProfileRuleChainByRightSideBtn() {
+ String deletedRuleChain = "Thermostat";
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.deleteBtn(deletedRuleChain).click();
+ ruleChainsPage.warningPopUpYesBtn().click();
+ ruleChainsPage.refreshBtn().click();
+
+ Assert.assertNotNull(ruleChainsPage.entity(deletedRuleChain));
+ Assert.assertTrue(ruleChainsPage.entity(deletedRuleChain).isDisplayed());
+ Assert.assertNotNull(ruleChainsPage.warningMessage());
+ Assert.assertTrue(ruleChainsPage.warningMessage().isDisplayed());
+ Assert.assertEquals(ruleChainsPage.warningMessage().getText(), DELETE_RULE_CHAIN_WITH_PROFILE_MESSAGE);
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can mark the rule chain in the checkbox and then click on the trash can icon in the menu that appears at the top")
+ public void removeSelectedProfileRuleChain() {
+ sideBarMenuView.ruleChainsBtn().click();
+ String deletedRuleChain = ruleChainsPage.deleteSelected("Thermostat");
+ ruleChainsPage.refreshBtn().click();
+
+ Assert.assertNotNull(ruleChainsPage.entity(deletedRuleChain));
+ Assert.assertTrue(ruleChainsPage.entity(deletedRuleChain).isDisplayed());
+ Assert.assertNotNull(ruleChainsPage.warningMessage());
+ Assert.assertTrue(ruleChainsPage.warningMessage().isDisplayed());
+ Assert.assertEquals(ruleChainsPage.warningMessage().getText(), DELETE_RULE_CHAIN_WITH_PROFILE_MESSAGE);
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can click on the name of the rule chain and click on the 'Delete rule chain' button")
+ public void removeFromProfileRuleChainView() {
+ String deletedRuleChain = "Thermostat";
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.entity(deletedRuleChain).click();
+ ruleChainsPage.deleteBtnFromView().click();
+ ruleChainsPage.warningPopUpYesBtn().click();
+
+ Assert.assertNotNull(ruleChainsPage.entity(deletedRuleChain));
+ Assert.assertNotNull(ruleChainsPage.warningMessage());
+ Assert.assertTrue(ruleChainsPage.warningMessage().isDisplayed());
+ Assert.assertEquals(ruleChainsPage.warningMessage().getText(), DELETE_RULE_CHAIN_WITH_PROFILE_MESSAGE);
+ }
+
+ @Test(priority = 30, groups = "smoke")
+ @Description("The rule chain is deleted immediately after clicking remove (no need to refresh the page)")
+ public void removeRuleChainByRightSideBtnWithoutRefresh() {
+ String ruleChainName = ENTITY_NAME;
+ ruleChainsPage.createRuleChain(ruleChainName);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ String deletedRuleChain = ruleChainsPage.deleteRuleChainTrash(ruleChainName);
+
+ Assert.assertTrue(ruleChainsPage.entityIsNotPresent(deletedRuleChain));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/DeleteSeveralRuleChainsTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/DeleteSeveralRuleChainsTest.java
new file mode 100644
index 0000000000..8481d9cde6
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/DeleteSeveralRuleChainsTest.java
@@ -0,0 +1,92 @@
+package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.*;
+
+public class DeleteSeveralRuleChainsAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private RuleChainsPageHelperAbstract ruleChainsPage;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ ruleChainsPage = new RuleChainsPageHelperAbstract(driver);
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can mark several rule chains in the checkbox near the names and then click on the trash can icon in the menu that appears at the top")
+ public void canDeleteSeveralRuleChainsByTopBtn() {
+ String ruleChainName = ENTITY_NAME;
+ int count = 2;
+ ruleChainsPage.createRuleChains(ruleChainName, count);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.clickOnCheckBoxes(count);
+
+ ruleChainsPage.deleteSelectedBtn().click();
+ ruleChainsPage.warningPopUpYesBtn().click();
+ ruleChainsPage.refreshBtn().click();
+
+ Assert.assertTrue(ruleChainsPage.ruleChainsIsNotPresent(ruleChainName));
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can mark several rule chains in the checkbox near the names and then click on the trash can icon in the menu that appears at the top")
+ public void selectAllRuleChain() {
+ String ruleChainName = ENTITY_NAME;
+ int count = 2;
+ ruleChainsPage.createRuleChains(ruleChainName, count);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.selectAllCheckBox().click();
+ ruleChainsPage.deleteSelectedBtn().click();
+ ruleChainsPage.warningPopUpYesBtn().click();
+ ruleChainsPage.refreshBtn().click();
+
+ Assert.assertTrue(ruleChainsPage.ruleChainsIsNotPresent(ruleChainName));
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can`t remove Root Rule Chain (the trash can is disabled in the right corner)")
+ public void removeRootRuleChain() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.selectAllCheckBox().click();
+
+ Assert.assertFalse(ruleChainsPage.deleteBtn(ROOT_RULE_CHAIN_NAME).isEnabled());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can`t remove Root Rule Chain (can`t mark the rule chain in the checkbox )")
+ public void removeSelectedRootRuleChain() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.selectAllCheckBox().click();
+
+ ruleChainsPage.assertCheckBoxIsNotDisplayed(ROOT_RULE_CHAIN_NAME);
+ }
+
+ @Test(priority = 30, groups = "smoke")
+ @Description("The rule chains are deleted immediately after clicking remove (no need to refresh the page)")
+ public void deleteSeveralRuleChainsByTopBtnWithoutRefresh() {
+ String ruleChainName = ENTITY_NAME;
+ int count = 2;
+ ruleChainsPage.createRuleChains(ruleChainName, count);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.clickOnCheckBoxes(count);
+ ruleChainsPage.deleteSelectedBtn().click();
+ ruleChainsPage.warningPopUpYesBtn().click();
+
+ Assert.assertTrue(ruleChainsPage.ruleChainsIsNotPresent(ruleChainName));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/MakeRuleChainRootTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/MakeRuleChainRootTest.java
new file mode 100644
index 0000000000..8a71a11232
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/MakeRuleChainRootTest.java
@@ -0,0 +1,75 @@
+package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class MakeRuleChainRootAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private RuleChainsPageHelperAbstract ruleChainsPage;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ ruleChainsPage = new RuleChainsPageHelperAbstract(driver);
+ }
+
+ @AfterMethod
+ public void makeRoot() {
+ ruleChainsPage.makeRoot();
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can make rule chain root by clicking on the 'Make rule chain root' icon in the right corner")
+ public void makeRuleChainRootByRightCornerBtn() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.setRuleChainNameWithoutRoot(0);
+ String ruleChain = ruleChainsPage.getRuleChainName();
+ ruleChainsPage.makeRootBtn(ruleChain).click();
+ ruleChainsPage.warningPopUpYesBtn().click();
+
+ Assert.assertTrue(ruleChainsPage.rootCheckBoxEnable(ruleChain).isDisplayed());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can make rule chain by clicking on the name/row of the rule chain and click on the 'make rule chain root' button")
+ public void makeRuleChainRootFromView() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.setRuleChainNameWithoutRoot(0);
+ String ruleChain = ruleChainsPage.getRuleChainName();
+ ruleChainsPage.entity(ruleChain).click();
+ ruleChainsPage.makeRootFromViewBtn().click();
+ ruleChainsPage.warningPopUpYesBtn().click();
+ ruleChainsPage.closeEntityViewBtn().click();
+
+ Assert.assertTrue(ruleChainsPage.rootCheckBoxEnable(ruleChain).isDisplayed());
+ }
+
+ @Test(priority = 30, groups = "smoke")
+ @Description("Can't make multiple root rule chains (only one rule chain can be root)")
+ public void multiplyRoot() {
+ SideBarMenuViewElements sideBarMenuView = new SideBarMenuViewElements(driver);
+ RuleChainsPageHelperAbstract ruleChainsPage = new RuleChainsPageHelperAbstract(driver);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.setRuleChainNameWithoutRoot(0);
+ String ruleChain = ruleChainsPage.getRuleChainName();
+ ruleChainsPage.entity(ruleChain).click();
+ ruleChainsPage.makeRootFromViewBtn().click();
+ ruleChainsPage.warningPopUpYesBtn().click();
+ ruleChainsPage.closeEntityViewBtn().click();
+
+ Assert.assertEquals(ruleChainsPage.rootCheckBoxesEnable().size(), 1);
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/OpenRuleChainTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/OpenRuleChainTest.java
new file mode 100644
index 0000000000..f38f20bdff
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/OpenRuleChainTest.java
@@ -0,0 +1,71 @@
+package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.OpenRuleChainPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class OpenRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private RuleChainsPageHelperAbstract ruleChainsPage;
+ private OpenRuleChainPageHelperAbstract openRuleChainPage;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ ruleChainsPage = new RuleChainsPageHelperAbstract(driver);
+ openRuleChainPage = new OpenRuleChainPageHelperAbstract(driver);
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can open the rule chain by clicking on the 'Open rule chain' icon in the right corner")
+ public void openRuleChainByRightCornerBtn() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.setRuleChainNameWithoutRoot(0);
+ String ruleChain = ruleChainsPage.getRuleChainName();
+ ruleChainsPage.openRuleChainBtn(ruleChain).click();
+ openRuleChainPage.setHeadName();
+
+ Assert.assertTrue(urlContains(ruleChainsPage.getRuleChainId(ruleChainsPage.getRuleChainName())));
+ Assert.assertTrue(openRuleChainPage.headRuleChainName().isDisplayed());
+ Assert.assertTrue(openRuleChainPage.inputNode().isDisplayed());
+ Assert.assertEquals(ruleChainsPage.getRuleChainName(), openRuleChainPage.getHeadName());
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can open the rule chain by clicking on the name/row of the rule chain and click on the 'Open rule chain' button")
+ public void openRuleChainByViewBtn() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.setRuleChainNameWithoutRoot(0);
+ String ruleChain = ruleChainsPage.getRuleChainName();
+ ruleChainsPage.entity(ruleChain).click();
+ ruleChainsPage.openRuleChainFromViewBtn().click();
+ openRuleChainPage.setHeadName();
+
+ Assert.assertTrue(urlContains(ruleChainsPage.getRuleChainId(ruleChain)));
+ Assert.assertTrue(openRuleChainPage.headRuleChainName().isDisplayed());
+ Assert.assertTrue(openRuleChainPage.inputNode().isDisplayed());
+ Assert.assertEquals(ruleChain, openRuleChainPage.getHeadName());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can`t open the rule chain by clicking twice on the row/name")
+ public void openRuleChainDoubleClick() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.setRuleChainNameWithoutRoot(0);
+ String ruleChain = ruleChainsPage.getRuleChainName();
+ ruleChainsPage.doubleClickOnRuleChain(ruleChain);
+
+ Assert.assertEquals(getUrl(), URL + "ruleChains");
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/RuleChainEditMenuTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/RuleChainEditMenuTest.java
new file mode 100644
index 0000000000..9a080d7435
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/RuleChainEditMenuTest.java
@@ -0,0 +1,130 @@
+package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.*;
+
+public class RuleChainEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private RuleChainsPageHelperAbstract ruleChainsPage;
+ private String ruleChainName;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ ruleChainsPage = new RuleChainsPageHelperAbstract(driver);
+ }
+
+ @AfterMethod
+ public void delete() {
+ if (ruleChainName != null) {
+ ruleChainsPage.deleteRuleChain(ruleChainName);
+ ruleChainName = null;
+ }
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description("Can click by pencil icon and edit the name (change the name) and save the changes. All changes have been applied")
+ public void changeName() {
+ ruleChainsPage.createRuleChain(ENTITY_NAME);
+ String name = "Changed";
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.notRootRuleChainsNames().get(0).click();
+ ruleChainsPage.setHeaderName();
+ String nameBefore = ruleChainsPage.getHeaderName();
+ ruleChainsPage.editPencilBtn().click();
+ ruleChainsPage.changeNameEditMenu(name);
+ ruleChainsPage.doneBtnEditView().click();
+ ruleChainsPage.setHeaderName();
+ String nameAfter = ruleChainsPage.getHeaderName();
+ ruleChainName = name;
+
+ Assert.assertNotEquals(nameBefore, nameAfter);
+ Assert.assertEquals(name, nameAfter);
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can`t delete the name and save changes")
+ public void deleteName() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.notRootRuleChainsNames().get(0).click();
+ ruleChainsPage.editPencilBtn().click();
+ ruleChainsPage.changeNameEditMenu("");
+
+ Assert.assertFalse(ruleChainsPage.doneBtnEditViewVisible().isEnabled());
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can`t save just a space in the name")
+ public void saveOnlyWithSpace() {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.notRootRuleChainsNames().get(0).click();
+ ruleChainsPage.editPencilBtn().click();
+ ruleChainsPage.changeNameEditMenu(" ");
+ ruleChainsPage.doneBtnEditView().click();
+
+ Assert.assertNotNull(ruleChainsPage.warningMessage());
+ Assert.assertTrue(ruleChainsPage.warningMessage().isDisplayed());
+ Assert.assertEquals(ruleChainsPage.warningMessage().getText(), EMPTY_RULE_CHAIN_MESSAGE);
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can write/change/delete the descriptionEntityView and save the changes. All changes have been applied")
+ public void editDescription() {
+ String name = ENTITY_NAME;
+ ruleChainsPage.createRuleChain(name);
+ String description = "Description";
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.notRootRuleChainsNames().get(0).click();
+ ruleChainsPage.editPencilBtn().click();
+ ruleChainsPage.descriptionEntityView().sendKeys(description);
+ ruleChainsPage.doneBtnEditView().click();
+ String description1 = ruleChainsPage.descriptionEntityView().getAttribute("value");
+ ruleChainsPage.editPencilBtn().click();
+ ruleChainsPage.descriptionEntityView().sendKeys(description);
+ ruleChainsPage.doneBtnEditView().click();
+ String description2 = ruleChainsPage.descriptionEntityView().getAttribute("value");
+ ruleChainsPage.editPencilBtn().click();
+ ruleChainsPage.changeDescription("");
+ ruleChainsPage.doneBtnEditView().click();
+ ruleChainName = name;
+
+ Assert.assertTrue(ruleChainsPage.descriptionEntityView().getAttribute("value").isEmpty());
+ Assert.assertEquals(description, description1);
+ Assert.assertEquals(description + description, description2);
+ }
+
+ @Test(priority = 20, groups = "smoke")
+ @Description("Can enable / disable debug and save changes. All changes have been applied")
+ public void debugMode() {
+ String name = ENTITY_NAME;
+ ruleChainsPage.createRuleChain(name);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.notRootRuleChainsNames().get(0).click();
+ ruleChainsPage.editPencilBtn().click();
+ ruleChainsPage.debugCheckboxEdit().click();
+ ruleChainsPage.doneBtnEditView().click();
+ boolean debugMode = Boolean.parseBoolean(ruleChainsPage.debugCheckboxView().getAttribute("aria-checked"));
+ ruleChainsPage.editPencilBtn().click();
+ ruleChainsPage.debugCheckboxEdit().click();
+ ruleChainsPage.doneBtnEditView().click();
+ ruleChainName = name;
+
+ Assert.assertFalse(Boolean.parseBoolean(ruleChainsPage.debugCheckboxView().getAttribute("aria-checked")));
+ Assert.assertTrue(debugMode);
+ }
+}
\ No newline at end of file
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/SearchRuleChainTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/SearchRuleChainTest.java
new file mode 100644
index 0000000000..0a8dc6d96b
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/SearchRuleChainTest.java
@@ -0,0 +1,52 @@
+package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+import org.thingsboard.server.msa.ui.utils.DataProviderCredential;
+
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class SearchRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private RuleChainsPageHelperAbstract ruleChainsPage;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ ruleChainsPage = new RuleChainsPageHelperAbstract(driver);
+ }
+
+ @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "ruleChainNameForSearchByFirstAndSecondWord")
+ @Description("Can search by the first/second word of the name")
+ public void searchFirstWord(String namePath) {
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.searchEntity(namePath);
+ ruleChainsPage.setRuleChainName(0);
+
+ Assert.assertTrue(ruleChainsPage.getRuleChainName().contains(namePath));
+ }
+
+ @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForSearchBySymbolAndNumber")
+ @Description("Can search by number/symbol")
+ public void searchNumber(String name, String namePath) {
+ ruleChainsPage.createRuleChain(name);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.searchEntity(namePath);
+ ruleChainsPage.setRuleChainName(0);
+ boolean ruleChainContainsNamePath = ruleChainsPage.getRuleChainName().contains(namePath);
+
+ ruleChainsPage.deleteRuleChain(name);
+
+ Assert.assertTrue(ruleChainContainsNamePath);
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/SortByNameTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/SortByNameTest.java
new file mode 100644
index 0000000000..a8f381c494
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/SortByNameTest.java
@@ -0,0 +1,122 @@
+package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+import org.thingsboard.server.msa.ui.utils.DataProviderCredential;
+
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private RuleChainsPageHelperAbstract ruleChainsPage;
+ private String ruleChainName;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ ruleChainsPage = new RuleChainsPageHelperAbstract(driver);
+ }
+
+ @AfterMethod
+ public void delete() {
+ if (ruleChainName != null) {
+ ruleChainsPage.deleteRuleChain(ruleChainName);
+ ruleChainName = null;
+ }
+ }
+
+ @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForSort")
+ @Description
+ public void specialCharacterUp(String ruleChainName) {
+ ruleChainsPage.createRuleChain(ruleChainName);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.sortByNameBtn().click();
+ ruleChainsPage.setRuleChainName(0);
+ this.ruleChainName = ruleChainName;
+
+ Assert.assertEquals(ruleChainsPage.getRuleChainName(), ruleChainName);
+ }
+
+ @Test(priority = 20, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForAllSort")
+ @Description
+ public void allSortUp(String ruleChain, String ruleChainSymbol, String ruleChainNumber) {
+ ruleChainsPage.createRuleChain(ruleChainSymbol);
+ ruleChainsPage.createRuleChain(ruleChain);
+ ruleChainsPage.createRuleChain(ruleChainNumber);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.sortByNameBtn().click();
+ ruleChainsPage.setRuleChainName(0);
+ String firstRuleChain = ruleChainsPage.getRuleChainName();
+ ruleChainsPage.setRuleChainName(1);
+ String secondRuleChain = ruleChainsPage.getRuleChainName();
+ ruleChainsPage.setRuleChainName(2);
+ String thirdRuleChain = ruleChainsPage.getRuleChainName();
+
+ boolean firstEquals = firstRuleChain.equals(ruleChainSymbol);
+ boolean secondEquals = secondRuleChain.equals(ruleChainNumber);
+ boolean thirdEquals = thirdRuleChain.equals(ruleChain);
+
+ ruleChainsPage.deleteRuleChain(ruleChain);
+ ruleChainsPage.deleteRuleChain(ruleChainNumber);
+ ruleChainsPage.deleteRuleChain(ruleChainSymbol);
+
+ Assert.assertTrue(firstEquals);
+ Assert.assertTrue(secondEquals);
+ Assert.assertTrue(thirdEquals);
+ }
+
+ @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForSort")
+ @Description
+ public void specialCharacterDown(String ruleChainName) {
+ ruleChainsPage.createRuleChain(ruleChainName);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.sortByNameDown();
+ ruleChainsPage.setRuleChainName(ruleChainsPage.allNames().size() - 1);
+ this.ruleChainName = ruleChainName;
+
+ Assert.assertEquals(ruleChainsPage.getRuleChainName(), ruleChainName);
+ }
+
+ @Test(priority = 20, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForAllSort")
+ @Description
+ public void allSortDown(String ruleChain, String ruleChainSymbol, String ruleChainNumber) {
+ ruleChainsPage.createRuleChain(ruleChainSymbol);
+ ruleChainsPage.createRuleChain(ruleChain);
+ ruleChainsPage.createRuleChain(ruleChainNumber);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ int lastIndex = ruleChainsPage.allNames().size() - 1;
+ ruleChainsPage.sortByNameDown();
+ ruleChainsPage.setRuleChainName(lastIndex);
+ String firstRuleChain = ruleChainsPage.getRuleChainName();
+ ruleChainsPage.setRuleChainName(lastIndex - 1);
+ String secondRuleChain = ruleChainsPage.getRuleChainName();
+ ruleChainsPage.setRuleChainName(lastIndex - 2);
+ String thirdRuleChain = ruleChainsPage.getRuleChainName();
+
+ boolean firstEquals = firstRuleChain.equals(ruleChainSymbol);
+ boolean secondEquals = secondRuleChain.equals(ruleChainNumber);
+ boolean thirdEquals = thirdRuleChain.equals(ruleChain);
+
+ ruleChainsPage.deleteRuleChain(ruleChain);
+ ruleChainsPage.deleteRuleChain(ruleChainNumber);
+ ruleChainsPage.deleteRuleChain(ruleChainSymbol);
+
+ Assert.assertTrue(firstEquals);
+ Assert.assertTrue(secondEquals);
+ Assert.assertTrue(thirdEquals);
+ }
+}
\ No newline at end of file
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/SortByTimeTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/SortByTimeTest.java
new file mode 100644
index 0000000000..3fc33e3ac0
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/SortByTimeTest.java
@@ -0,0 +1,70 @@
+package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke;
+
+import io.qameta.allure.Description;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest;
+import org.thingsboard.server.msa.ui.pages.LoginPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelperAbstract;
+import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements;
+
+import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME;
+import static org.thingsboard.server.msa.ui.utils.Const.URL;
+
+public class SortByTimeAbstractDiverBaseTest extends AbstractDiverBaseTest {
+
+ private SideBarMenuViewElements sideBarMenuView;
+ private RuleChainsPageHelperAbstract ruleChainsPage;
+ private String ruleChainName;
+
+ @BeforeMethod
+ public void login() {
+ openUrl(URL);
+ new LoginPageHelperAbstract(driver).authorizationTenant();
+ sideBarMenuView = new SideBarMenuViewElements(driver);
+ ruleChainsPage = new RuleChainsPageHelperAbstract(driver);
+ }
+
+ @AfterMethod
+ public void delete() {
+ if (ruleChainName != null) {
+ ruleChainsPage.deleteRuleChain(ruleChainName);
+ ruleChainName = null;
+ }
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description
+ public void sortByTimeDown() {
+ String ruleChain = ENTITY_NAME;
+ ruleChainsPage.createRuleChain(ruleChain);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.setSort();
+ String firstListElement = ruleChainsPage.getSort().get(ruleChainsPage.getSort().size() - 1);
+ String lastCreated = ruleChainsPage.createdTime().get(0).getText();
+ ruleChainName = ruleChain;
+
+ Assert.assertEquals(firstListElement, lastCreated);
+ Assert.assertNotNull(ruleChainsPage.createdTimeEntity(ruleChain, lastCreated));
+ }
+
+ @Test(priority = 10, groups = "smoke")
+ @Description
+ public void sortByTimeUp() {
+ String ruleChain = ENTITY_NAME;
+ ruleChainsPage.createRuleChain(ruleChain);
+
+ sideBarMenuView.ruleChainsBtn().click();
+ ruleChainsPage.sortByTimeBtn().click();
+ ruleChainsPage.setSort();
+ String firstListElement = ruleChainsPage.getSort().get(ruleChainsPage.getSort().size() - 1);
+ String lastCreated = ruleChainsPage.createdTime().get(ruleChainsPage.createdTime().size() - 1).getText();
+ ruleChainName = ruleChain;
+
+ Assert.assertEquals(firstListElement, lastCreated);
+ Assert.assertNotNull(ruleChainsPage.createdTimeEntity(ruleChain, lastCreated));
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/Const.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/Const.java
new file mode 100644
index 0000000000..db6bd40084
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/Const.java
@@ -0,0 +1,21 @@
+package utils;
+
+import base.Base;
+
+public class Const extends Base {
+
+ public static final String URL = "http://localhost:8080/";
+ public static final String TENANT_EMAIL = "tenant@thingsboard.org";
+ public static final String TENANT_PASSWORD = "tenant";
+ public static final String ENTITY_NAME = "Az!@#$%^&*()_-+=~`" + getRandomNumber();
+ public static final String ROOT_RULE_CHAIN_NAME = "Root Rule Chain";
+ public static final String IMPORT_RULE_CHAIN_NAME = "Rule Chain from Import";
+ public static final String IMPORT_RULE_CHAIN_FILE_NAME = "forImport.json";
+ public static final String IMPORT_TXT_FILE_NAME = "forImport.txt";
+ public static final String EMPTY_IMPORT_MESSAGE = "No file selected";
+ public static final String EMPTY_RULE_CHAIN_MESSAGE = "Rule chain name should be specified!";
+ public static final String EMPTY_CUSTOMER_MESSAGE = "Customer title should be specified!";
+ public static final String DELETE_RULE_CHAIN_WITH_PROFILE_MESSAGE = "The rule chain referenced by the device profiles cannot be deleted!";
+ public static final String SAME_NAME_WARNING_CUSTOMER_MESSAGE = "Customer with such title already exists!";
+ public static final String PHONE_NUMBER_ERROR_MESSAGE = "Phone number is invalid or not possible";
+}
\ No newline at end of file
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/DataProviderCredential.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/DataProviderCredential.java
new file mode 100644
index 0000000000..1509250abf
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/DataProviderCredential.java
@@ -0,0 +1,62 @@
+package utils;
+
+import org.testng.annotations.DataProvider;
+
+import static base.Base.getRandomSymbol;
+import static utils.Const.ENTITY_NAME;
+
+public class DataProviderCredential {
+
+ private static final String SYMBOL = String.valueOf(getRandomSymbol());
+ private static final String NAME = ENTITY_NAME;
+ private static final String NUMBER = "1";
+ private static final String LONG_PHONE_NUMBER = "20155501231";
+ private static final String SHORT_PHONE_NUMBER = "201555011";
+ private static final String RULE_CHAIN_SECOND_WORD_NAME_PATH = "Rule";
+ private static final String CUSTOMER_SECOND_WORD_NAME_PATH = "Customer";
+ private static final String RULE_CHAIN_FIRST_WORD_NAME_PATH = "Root";
+ private static final String CUSTOMER_FIRST_WORD_NAME_PATH = "A";
+
+ @DataProvider
+ public static Object[][] ruleChainNameForSearchByFirstAndSecondWord() {
+ return new Object[][]{
+ {RULE_CHAIN_SECOND_WORD_NAME_PATH},
+ {RULE_CHAIN_FIRST_WORD_NAME_PATH}};
+ }
+
+ @DataProvider
+ public static Object[][] nameForSearchBySymbolAndNumber() {
+ return new Object[][]{
+ {NAME, ENTITY_NAME.split("`")[1]},
+ {NAME, String.valueOf(getRandomSymbol())}};
+ }
+
+ @DataProvider
+ public static Object[][] nameForSort() {
+ return new Object[][]{
+ {NAME},
+ {SYMBOL},
+ {NUMBER}};
+ }
+
+ @DataProvider
+ public static Object[][] nameForAllSort() {
+ return new Object[][]{
+ {NAME, SYMBOL, NUMBER}};
+ }
+
+ @DataProvider
+ public static Object[][] incorrectPhoneNumber() {
+ return new Object[][]{
+ {LONG_PHONE_NUMBER},
+ {SHORT_PHONE_NUMBER},
+ {ENTITY_NAME}};
+ }
+
+ @DataProvider
+ public static Object[][] customerNameForSearchByFirstAndSecondWord() {
+ return new Object[][]{
+ {CUSTOMER_FIRST_WORD_NAME_PATH},
+ {CUSTOMER_SECOND_WORD_NAME_PATH}};
+ }
+}
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/EntityPrototypes.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/EntityPrototypes.java
new file mode 100644
index 0000000000..683dca511c
--- /dev/null
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/EntityPrototypes.java
@@ -0,0 +1,19 @@
+package org.thingsboard.server.msa.ui.utils;
+
+import org.thingsboard.server.common.data.Customer;
+import org.thingsboard.server.common.data.rule.RuleChain;
+
+public class CustomerPrototypes {
+
+ public static Customer defaultCustomerPrototype(String entityName){
+ Customer customer = new Customer();
+ customer.setTitle(entityName);
+ return customer;
+ }
+
+ public static RuleChain defaultRuleChainPrototype(String entityName){
+ RuleChain ruleChain = new RuleChain();
+ ruleChain.setName(entityName);
+ return ruleChain;
+ }
+}
diff --git a/msa/black-box-tests/src/test/resources/connectivity.xml b/msa/black-box-tests/src/test/resources/connectivity.xml
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/msa/black-box-tests/src/test/resources/forImport.json b/msa/black-box-tests/src/test/resources/forImport.json
new file mode 100644
index 0000000000..40367d7609
--- /dev/null
+++ b/msa/black-box-tests/src/test/resources/forImport.json
@@ -0,0 +1,20 @@
+{
+ "ruleChain": {
+ "additionalInfo": {
+ "description": ""
+ },
+ "name": "Rule Chain from Import",
+ "type": "CORE",
+ "firstRuleNodeId": null,
+ "root": false,
+ "debugMode": false,
+ "configuration": null,
+ "externalId": null
+ },
+ "metadata": {
+ "firstNodeIndex": null,
+ "nodes": [],
+ "connections": null,
+ "ruleChainConnections": null
+ }
+}
diff --git a/msa/black-box-tests/src/test/resources/forImport.txt b/msa/black-box-tests/src/test/resources/forImport.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/msa/black-box-tests/src/test/resources/smokeTests.xml b/msa/black-box-tests/src/test/resources/smokeTests.xml
new file mode 100644
index 0000000000..1194791760
--- /dev/null
+++ b/msa/black-box-tests/src/test/resources/smokeTests.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/msa/black-box-tests/src/test/resources/smokesCustomer.xml b/msa/black-box-tests/src/test/resources/smokesCustomer.xml
new file mode 100644
index 0000000000..0282d57cbd
--- /dev/null
+++ b/msa/black-box-tests/src/test/resources/smokesCustomer.xml
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/msa/black-box-tests/src/test/resources/smokesRuleChain.xml b/msa/black-box-tests/src/test/resources/smokesRuleChain.xml
new file mode 100644
index 0000000000..43598e5358
--- /dev/null
+++ b/msa/black-box-tests/src/test/resources/smokesRuleChain.xml
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file