From be1acd219b588e55ebef79f84fbe6577f8fa00f2 Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Tue, 22 Nov 2022 13:17:01 +0200 Subject: [PATCH 01/66] add ui tests --- msa/black-box-tests/pom.xml | 24 ++ .../server/msa/ui/base/AbstractBasePage.java | 129 +++++++++ .../msa/ui/base/AbstractDiverBaseTest.java | 74 +++++ .../msa/ui/listeners/RetryAnalyzer.java | 20 ++ .../msa/ui/listeners/RetryTestListener.java | 18 ++ .../server/msa/ui/listeners/TestListener.java | 62 ++++ .../msa/ui/pages/CustomerPageElements.java | 262 +++++++++++++++++ .../msa/ui/pages/CustomerPageHelper.java | 161 +++++++++++ .../msa/ui/pages/DashboardPageElements.java | 38 +++ .../msa/ui/pages/DashboardPageHelper.java | 25 ++ .../msa/ui/pages/LoginPageElements.java | 28 ++ .../server/msa/ui/pages/LoginPageHelper.java | 16 ++ .../ui/pages/OpenRuleChainPageElements.java | 33 +++ .../msa/ui/pages/OpenRuleChainPageHelper.java | 23 ++ .../msa/ui/pages/OtherPageElements.java | 228 +++++++++++++++ .../msa/ui/pages/OtherPageElementsHelper.java | 98 +++++++ .../msa/ui/pages/RuleChainsPageElements.java | 113 ++++++++ .../msa/ui/pages/RuleChainsPageHelper.java | 180 ++++++++++++ .../msa/ui/pages/SideBarMenuViewElements.java | 27 ++ .../customerSmoke/CreateCustomerTest.java | 164 +++++++++++ .../customerSmoke/CustomerEditMenuTest.java | 270 ++++++++++++++++++ .../customerSmoke/DeleteCustomerTest.java | 83 ++++++ .../DeleteSeveralCustomerTest.java | 81 ++++++ .../ManageCustomersAssetsTest.java | 54 ++++ .../ManageCustomersDashboardsTest.java | 53 ++++ .../ManageCustomersDevicesTest.java | 53 ++++ .../ManageCustomersEdgesTest.java | 54 ++++ .../ManageCustomersUsersTest.java | 54 ++++ .../customerSmoke/SearchCustomerTest.java | 56 ++++ .../tests/customerSmoke/SortByNameTest.java | 121 ++++++++ .../CreateRuleChainImportTest.java | 110 +++++++ .../ruleChainsSmoke/CreateRuleChainTest.java | 139 +++++++++ .../ruleChainsSmoke/DeleteRuleChainTest.java | 148 ++++++++++ .../DeleteSeveralRuleChainsTest.java | 92 ++++++ .../MakeRuleChainRootTest.java | 75 +++++ .../ruleChainsSmoke/OpenRuleChainTest.java | 71 +++++ .../RuleChainEditMenuTest.java | 130 +++++++++ .../ruleChainsSmoke/SearchRuleChainTest.java | 52 ++++ .../tests/ruleChainsSmoke/SortByNameTest.java | 122 ++++++++ .../tests/ruleChainsSmoke/SortByTimeTest.java | 70 +++++ .../server/msa/ui/utils/Const.java | 21 ++ .../msa/ui/utils/DataProviderCredential.java | 62 ++++ .../server/msa/ui/utils/EntityPrototypes.java | 19 ++ .../src/test/resources/connectivity.xml | 0 .../src/test/resources/forImport.json | 20 ++ .../src/test/resources/forImport.txt | 0 .../src/test/resources/smokeTests.xml | 26 ++ .../src/test/resources/smokesCustomer.xml | 137 +++++++++ .../src/test/resources/smokesRuleChain.xml | 138 +++++++++ 49 files changed, 4034 insertions(+) create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractBasePage.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDiverBaseTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/RetryAnalyzer.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/RetryTestListener.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/TestListener.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CustomerPageElements.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CustomerPageHelper.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageElements.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageHelper.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/LoginPageElements.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/LoginPageHelper.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OpenRuleChainPageElements.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OpenRuleChainPageHelper.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OtherPageElements.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/OtherPageElementsHelper.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/RuleChainsPageElements.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/RuleChainsPageHelper.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/SideBarMenuViewElements.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/CreateCustomerTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/CustomerEditMenuTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/DeleteCustomerTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/DeleteSeveralCustomerTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersAssetsTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersDashboardsTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersDevicesTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersEdgesTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/ManageCustomersUsersTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/SearchCustomerTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/customerSmoke/SortByNameTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/CreateRuleChainImportTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/CreateRuleChainTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/DeleteRuleChainTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/DeleteSeveralRuleChainsTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/MakeRuleChainRootTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/OpenRuleChainTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/RuleChainEditMenuTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/SearchRuleChainTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/SortByNameTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/ruleChainsSmoke/SortByTimeTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/Const.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/DataProviderCredential.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/EntityPrototypes.java create mode 100644 msa/black-box-tests/src/test/resources/connectivity.xml create mode 100644 msa/black-box-tests/src/test/resources/forImport.json create mode 100644 msa/black-box-tests/src/test/resources/forImport.txt create mode 100644 msa/black-box-tests/src/test/resources/smokeTests.xml create mode 100644 msa/black-box-tests/src/test/resources/smokesCustomer.xml create mode 100644 msa/black-box-tests/src/test/resources/smokesRuleChain.xml 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 From 843e6ee87c2455410bdf4fcd8839793ff1236b98 Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Tue, 22 Nov 2022 13:19:21 +0200 Subject: [PATCH 02/66] add ui tests --- .../server/msa/TestRestClient.java | 80 +++++++++---- .../msa/connectivity/MqttClientTest.java | 2 +- .../server/msa/ui/base/AbstractBasePage.java | 42 ++++--- .../msa/ui/base/AbstractDiverBaseTest.java | 60 ++++++++-- .../msa/ui/listeners/RetryAnalyzer.java | 17 ++- .../msa/ui/listeners/RetryTestListener.java | 17 ++- .../server/msa/ui/listeners/TestListener.java | 31 ++++-- .../msa/ui/pages/CustomerPageElements.java | 19 +++- .../msa/ui/pages/CustomerPageHelper.java | 50 +++------ .../msa/ui/pages/DashboardPageElements.java | 19 +++- .../msa/ui/pages/DashboardPageHelper.java | 19 +++- .../msa/ui/pages/LoginPageElements.java | 19 +++- .../server/msa/ui/pages/LoginPageHelper.java | 19 +++- .../ui/pages/OpenRuleChainPageElements.java | 19 +++- .../msa/ui/pages/OpenRuleChainPageHelper.java | 19 +++- .../msa/ui/pages/OtherPageElements.java | 20 +++- .../msa/ui/pages/OtherPageElementsHelper.java | 19 +++- .../msa/ui/pages/RuleChainsPageElements.java | 19 +++- .../msa/ui/pages/RuleChainsPageHelper.java | 94 ++++------------ .../msa/ui/pages/SideBarMenuViewElements.java | 21 +++- .../customerSmoke/CreateCustomerTest.java | 56 ++++++---- .../customerSmoke/CustomerEditMenuTest.java | 105 ++++++++++-------- .../customerSmoke/DeleteCustomerTest.java | 54 +++++---- .../DeleteSeveralCustomerTest.java | 57 ++++++---- .../ManageCustomersAssetsTest.java | 31 ++++-- .../ManageCustomersDashboardsTest.java | 31 ++++-- .../ManageCustomersDevicesTest.java | 31 ++++-- .../ManageCustomersEdgesTest.java | 33 ++++-- .../ManageCustomersUsersTest.java | 33 ++++-- .../customerSmoke/SearchCustomerTest.java | 50 +++++---- .../tests/customerSmoke/SortByNameTest.java | 65 +++++++---- .../CreateRuleChainImportTest.java | 65 +++++++---- .../ruleChainsSmoke/CreateRuleChainTest.java | 74 +++++++----- .../ruleChainsSmoke/DeleteRuleChainTest.java | 65 +++++++---- .../DeleteSeveralRuleChainsTest.java | 56 ++++++---- .../MakeRuleChainRootTest.java | 41 ++++--- .../ruleChainsSmoke/OpenRuleChainTest.java | 46 +++++--- .../RuleChainEditMenuTest.java | 54 +++++---- .../ruleChainsSmoke/SearchRuleChainTest.java | 39 +++++-- .../tests/ruleChainsSmoke/SortByNameTest.java | 62 +++++++---- .../tests/ruleChainsSmoke/SortByTimeTest.java | 38 +++++-- .../server/msa/ui/utils/Const.java | 21 +++- .../msa/ui/utils/DataProviderCredential.java | 21 +++- .../server/msa/ui/utils/EntityPrototypes.java | 17 ++- .../src/test/resources/connectivity.xml | 27 +++++ .../src/test/resources/forImport.txt | 16 +++ .../src/test/resources/smokeTests.xml | 6 +- .../src/test/resources/smokesCustomer.xml | 2 +- .../src/test/resources/smokesRuleChain.xml | 2 +- .../src/test/resources/testNG.xml | 10 +- msa/pom.xml | 2 + 51 files changed, 1237 insertions(+), 578 deletions(-) diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestRestClient.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestRestClient.java index 713205e228..be0068fd04 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestRestClient.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestRestClient.java @@ -26,7 +26,9 @@ import io.restassured.http.ContentType; import io.restassured.path.json.JsonPath; import io.restassured.response.ValidatableResponse; import io.restassured.specification.RequestSpecification; +import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.RuleChainId; @@ -76,7 +78,7 @@ public class TestRestClient { loginRequest.put("password", password); JsonPath jsonPath = given().spec(requestSpec).body(loginRequest) - .post( "/api/auth/login") + .post("/api/auth/login") .getBody().jsonPath(); token = jsonPath.get("token"); refreshToken = jsonPath.get("refreshToken"); @@ -84,7 +86,7 @@ public class TestRestClient { } public Device postDevice(String accessToken, Device device) { - return given().spec(requestSpec).body(device) + return given().spec(requestSpec).body(device) .pathParams("accessToken", accessToken) .post("/api/device?accessToken={accessToken}") .then() @@ -94,62 +96,65 @@ public class TestRestClient { } public ValidatableResponse getDeviceById(DeviceId deviceId, int statusCode) { - return given().spec(requestSpec) + return given().spec(requestSpec) .pathParams("deviceId", deviceId.getId()) .get("/api/device/{deviceId}") .then() .statusCode(statusCode); } + public Device getDeviceById(DeviceId deviceId) { - return getDeviceById(deviceId, HTTP_OK) + return getDeviceById(deviceId, HTTP_OK) .extract() .as(Device.class); } + public DeviceCredentials getDeviceCredentialsByDeviceId(DeviceId deviceId) { return given().spec(requestSpec).get("/api/device/{deviceId}/credentials", deviceId.getId()) - .then() - .assertThat() - .statusCode(HTTP_OK) - .extract() - .as(DeviceCredentials.class); + .then() + .assertThat() + .statusCode(HTTP_OK) + .extract() + .as(DeviceCredentials.class); } public ValidatableResponse postTelemetry(String credentialsId, JsonNode telemetry) { - return given().spec(requestSpec).body(telemetry) - .post("/api/v1/{credentialsId}/telemetry", credentialsId) - .then() - .statusCode(HTTP_OK); + return given().spec(requestSpec).body(telemetry) + .post("/api/v1/{credentialsId}/telemetry", credentialsId) + .then() + .statusCode(HTTP_OK); } public ValidatableResponse deleteDevice(DeviceId deviceId) { - return given().spec(requestSpec) + return given().spec(requestSpec) .delete("/api/device/{deviceId}", deviceId.getId()) .then() .statusCode(HTTP_OK); } + public ValidatableResponse deleteDeviceIfExists(DeviceId deviceId) { - return given().spec(requestSpec) + return given().spec(requestSpec) .delete("/api/device/{deviceId}", deviceId.getId()) .then() - .statusCode(anyOf(is(HTTP_OK),is(HTTP_NOT_FOUND))); + .statusCode(anyOf(is(HTTP_OK), is(HTTP_NOT_FOUND))); } public ValidatableResponse postTelemetryAttribute(String entityType, DeviceId deviceId, String scope, JsonNode attribute) { - return given().spec(requestSpec).body(attribute) + return given().spec(requestSpec).body(attribute) .post("/api/plugins/telemetry/{entityType}/{entityId}/attributes/{scope}", entityType, deviceId.getId(), scope) .then() .statusCode(HTTP_OK); } public ValidatableResponse postAttribute(String accessToken, JsonNode attribute) { - return given().spec(requestSpec).body(attribute) + return given().spec(requestSpec).body(attribute) .post("/api/v1/{accessToken}/attributes/", accessToken) .then() .statusCode(HTTP_OK); } public JsonNode getAttributes(String accessToken, String clientKeys, String sharedKeys) { - return given().spec(requestSpec) + return given().spec(requestSpec) .queryParam("clientKeys", clientKeys) .queryParam("sharedKeys", sharedKeys) .get("/api/v1/{accessToken}/attributes", accessToken) @@ -167,10 +172,11 @@ public class TestRestClient { .then() .statusCode(HTTP_OK) .extract() - .as(new TypeRef>() {}); + .as(new TypeRef>() { + }); } - public RuleChain postRootRuleChain(RuleChain ruleChain) { + public RuleChain postRuleChain(RuleChain ruleChain) { return given().spec(requestSpec) .body(ruleChain) .post("/api/ruleChain") @@ -239,7 +245,8 @@ public class TestRestClient { .then() .statusCode(HTTP_OK) .extract() - .as(new TypeRef>() {}); + .as(new TypeRef>() { + }); } public JsonNode postServerSideRpc(DeviceId deviceId, JsonNode serverRpcPayload) { @@ -252,6 +259,35 @@ public class TestRestClient { .as(JsonNode.class); } + public Customer postCustomer(Customer customer) { + return given().spec(requestSpec) + .body(customer) + .post("/api/customer") + .then() + .statusCode(HTTP_OK) + .extract() + .as(Customer.class); + } + + public void deleteCustomer(CustomerId customerId) { + given().spec(requestSpec) + .delete("/api/customer/{customerId}", customerId.getId()) + .then() + .statusCode(HTTP_OK); + } + + public PageData getCustomers(PageLink pageLink) { + Map params = new HashMap<>(); + addPageLinkToParam(params, pageLink); + return given().spec(requestSpec).queryParams(params) + .get("/api/customers") + .then() + .statusCode(HTTP_OK) + .extract() + .as(new TypeRef>() { + }); + } + public String getToken() { return token; } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java index 55dd432644..03271e629a 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java @@ -326,7 +326,7 @@ public class MqttClientTest extends AbstractContainerTest { RuleChain newRuleChain = new RuleChain(); newRuleChain.setName("testRuleChain"); - RuleChain ruleChain = testRestClient.postRootRuleChain(newRuleChain); + RuleChain ruleChain = testRestClient.postRuleChain(newRuleChain); JsonNode configuration = mapper.readTree(this.getClass().getClassLoader().getResourceAsStream("RpcResponseRuleChainMetadata.json")); RuleChainMetaData ruleChainMetaData = new RuleChainMetaData(); 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 index 8e8a15c5af..9e32d6e917 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.base; import lombok.SneakyThrows; @@ -9,33 +24,22 @@ 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; +import java.util.Random; @Slf4j -abstract public class BasePage extends Base { +abstract public class AbstractBasePage { protected WebDriver driver; protected WebDriverWait wait; protected Actions actions; - protected RestClient client; - protected PageLink pageLink; - public BasePage(WebDriver driver) { + public AbstractBasePage(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 @@ -126,4 +130,14 @@ abstract public class BasePage extends Base { ArrayList tabs = new ArrayList<>(driver.getWindowHandles()); driver.switchTo().window(tabs.get(tabNumber - 1)); } + + public static long getRandomNumber() { + return System.currentTimeMillis(); + } + + public static char getRandomSymbol() { + Random rand = new Random(); + String s = "~`!@#$^&*()_+=-"; + return s.charAt(rand.nextInt(s.length())); + } } 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 index 4e5d0d5ead..4079ec264c 100644 --- 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 @@ -1,10 +1,27 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.base; +import com.google.common.io.Files; import io.github.bonigarcia.wdm.WebDriverManager; +import io.qameta.allure.Attachment; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebDriverException; +import org.apache.commons.io.FileUtils; +import org.openqa.selenium.*; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.support.ui.ExpectedConditions; @@ -12,20 +29,27 @@ 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 org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.msa.AbstractContainerTest; +import org.thingsboard.server.msa.ui.listeners.TestListener; +import java.io.File; import java.time.Duration; +import java.util.stream.Collectors; @Slf4j -@Listeners({TestListener.class, RetryTestListener.class}) -abstract public class DiverBaseTest extends Base { - protected WebDriver driver; +@Listeners(TestListener.class) +abstract public class AbstractDiverBaseTest extends AbstractContainerTest { + 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; + protected static final PageLink pageLink = new PageLink(10); + @BeforeMethod public void openBrowser() { @@ -63,7 +87,7 @@ abstract public class DiverBaseTest extends Base { } protected boolean urlContains(String urlPath) { - WebDriverWait wait = new WebDriverWait(driver, Duration.ofMillis(10000)); + WebDriverWait wait = new WebDriverWait(driver, Duration.ofMillis(5000)); try { wait.until(ExpectedConditions.urlContains(urlPath)); } catch (WebDriverException e) { @@ -71,4 +95,22 @@ abstract public class DiverBaseTest extends Base { } return driver.getCurrentUrl().contains(urlPath); } + + public static RuleChain getRuleChainByName(String name) { + return testRestClient.getRuleChains(pageLink).getData().stream() + .filter(s -> s.getName().equals(name)).collect(Collectors.toList()).get(0); + } + + public static Customer getCustomerByName(String name) { + return testRestClient.getCustomers(pageLink).getData().stream() + .filter(x -> x.getName().equals(name)).collect(Collectors.toList()).get(0); + } + + @SneakyThrows + @Attachment(value = "Page screenshot", type = "image/png") + public static byte[] captureScreen(WebDriver driver, String dirPath) { + File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); + FileUtils.copyFile(screenshot, new File("./target/allure-results/screenshots/" + dirPath + "//" + screenshot.getName())); + return Files.toByteArray(screenshot); + } } \ 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 index 30b157f13d..bc3f88d99e 100644 --- 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 @@ -1,4 +1,19 @@ -package listeners; +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.ui.listeners; import org.testng.IRetryAnalyzer; import org.testng.ITestResult; 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 index 6083781820..0411083f87 100644 --- 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 @@ -1,4 +1,19 @@ -package listeners; +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.ui.listeners; import org.testng.IAnnotationTransformer; import org.testng.annotations.ITestAnnotation; 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 index dec83f374b..90ae18bec4 100644 --- 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 @@ -1,16 +1,33 @@ -package listeners; +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.ui.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; +import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest; + +import static org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest.captureScreen; @Slf4j -public class TestListener extends Base implements ITestListener { +public class TestListener implements ITestListener { WebDriver driver; @@ -20,7 +37,7 @@ public class TestListener extends Base implements ITestListener { Allure.getLifecycle().updateTestCase((t) -> { t.setStatusDetails(t.getStatusDetails().setMessage(str)); }); - driver = ((TestInit) tr.getInstance()).getDriver(); + driver = ((AbstractDiverBaseTest) tr.getInstance()).getDriver(); captureScreen(driver, "success"); } @@ -33,7 +50,7 @@ public class TestListener extends Base implements ITestListener { t.setStatusDetails(t.getStatusDetails().setMessage(str)); t.setStatusDetails(t.getStatusDetails().setMessage(str1)); }); - driver = ((TestInit) tr.getInstance()).getDriver(); + driver = ((AbstractDiverBaseTest) tr.getInstance()).getDriver(); captureScreen(driver, "failure"); } @@ -46,7 +63,7 @@ public class TestListener extends Base implements ITestListener { t.setStatusDetails(t.getStatusDetails().setMessage(str)); t.setStatusDetails(t.getStatusDetails().setMessage(str1)); }); - driver = ((TestInit) tr.getInstance()).getDriver(); + driver = ((AbstractDiverBaseTest) tr.getInstance()).getDriver(); captureScreen(driver, "skipped"); } 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 index dcb513ab71..e10fb7d1ed 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.pages; import org.openqa.selenium.WebDriver; @@ -5,8 +20,8 @@ import org.openqa.selenium.WebElement; import java.util.List; -public class CustomerPageElementsAbstract extends OtherPageElementsHelperAbstract { - public CustomerPageElementsAbstract(WebDriver driver) { +public class CustomerPageElements extends OtherPageElementsHelper { + public CustomerPageElements(WebDriver driver) { super(driver); } 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 index 13d6a26077..9956966a16 100644 --- 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 @@ -1,17 +1,28 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ 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) { +public class CustomerPageHelper extends CustomerPageElements { + public CustomerPageHelper(WebDriver driver) { super(driver); } @@ -84,33 +95,6 @@ public class CustomerPageHelperAbstract extends CustomerPageElementsAbstract { 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)), "")); 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 index 9e2595ed3c..80bd3780c7 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.pages; import org.openqa.selenium.WebDriver; @@ -5,8 +20,8 @@ import org.openqa.selenium.WebElement; import java.util.List; -public class DashboardPageElementsAbstract extends OtherPageElementsHelperAbstract { - public DashboardPageElementsAbstract(WebDriver driver) { +public class DashboardPageElements extends OtherPageElementsHelper { + public DashboardPageElements(WebDriver driver) { super(driver); } 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 index 7bf8956542..1b4ae6dfa9 100644 --- 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 @@ -1,9 +1,24 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.pages; import org.openqa.selenium.WebDriver; -public class DashboardPageHelperAbstract extends DashboardPageElementsAbstract { - public DashboardPageHelperAbstract(WebDriver driver) { +public class DashboardPageHelper extends DashboardPageElements { + public DashboardPageHelper(WebDriver driver) { super(driver); } 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 index 54239e2971..b6a2f09513 100644 --- 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 @@ -1,11 +1,26 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ 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) { +public class LoginPageElements extends AbstractBasePage { + public LoginPageElements(WebDriver driver) { super(driver); } 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 index a39b507882..e59d07e455 100644 --- 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 @@ -1,10 +1,25 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ 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) { +public class LoginPageHelper extends LoginPageElements { + public LoginPageHelper(WebDriver driver) { super(driver); } 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 index 521758ea41..7fa0bd7468 100644 --- 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 @@ -1,11 +1,26 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ 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) { +public class OpenRuleChainPageElements extends AbstractBasePage { + public OpenRuleChainPageElements(WebDriver driver) { super(driver); } 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 index ccaaedab28..0017396a8a 100644 --- 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 @@ -1,9 +1,24 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.pages; import org.openqa.selenium.WebDriver; -public class OpenRuleChainPageHelperAbstract extends OpenRuleChainPageElementsAbstract { - public OpenRuleChainPageHelperAbstract(WebDriver driver) { +public class OpenRuleChainPageHelper extends OpenRuleChainPageElements { + public OpenRuleChainPageHelper(WebDriver driver) { super(driver); } 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 index bf4be2dae2..1f3ecfa208 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.pages; import org.openqa.selenium.WebDriver; @@ -6,8 +21,8 @@ import org.thingsboard.server.msa.ui.base.AbstractBasePage; import java.util.List; -public class OtherPageElementsAbstract extends AbstractBasePage { - public OtherPageElementsAbstract(WebDriver driver) { +public class OtherPageElements extends AbstractBasePage { + public OtherPageElements(WebDriver driver) { super(driver); } @@ -103,6 +118,7 @@ public class OtherPageElementsAbstract extends AbstractBasePage { } public WebElement editPencilBtn() { + waitUntilVisibilityOfElementsLocated(EDIT_PENCIL_BTN); return waitUntilElementToBeClickable(EDIT_PENCIL_BTN); } 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 index dc4a41e9b9..dbef06e7fe 100644 --- 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 @@ -1,11 +1,26 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ 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) { +public class OtherPageElementsHelper extends OtherPageElements { + public OtherPageElementsHelper(WebDriver driver) { super(driver); } 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 index 4a378bb1c3..eee95edcae 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.pages; import org.openqa.selenium.By; @@ -6,8 +21,8 @@ import org.openqa.selenium.WebElement; import java.util.List; -public class RuleChainsPageElementsAbstract extends OtherPageElementsHelperAbstract { - public RuleChainsPageElementsAbstract(WebDriver driver) { +public class RuleChainsPageElements extends OtherPageElementsHelper { + public RuleChainsPageElements(WebDriver driver) { super(driver); } 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 index 9d23660b11..a6a7148bc4 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.pages; import lombok.extern.slf4j.Slf4j; @@ -5,17 +20,14 @@ 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) { +public class RuleChainsPageHelper extends RuleChainsPageElements { + public RuleChainsPageHelper(WebDriver driver) { super(driver); } @@ -52,74 +64,6 @@ public class RuleChainsPageHelperAbstract extends RuleChainsPageElementsAbstract 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) { @@ -149,8 +93,8 @@ public class RuleChainsPageHelperAbstract extends RuleChainsPageElementsAbstract Assert.assertFalse(driver.findElement(By.xpath(getCheckbox(entityName))).isDisplayed()); } - public void assertDeleteBtnInRootRuleChainIsNotDisplayed() { - Assert.assertFalse(driver.findElement(By.xpath(getDeleteRuleChainFromViewBtn())).isDisplayed()); + public boolean deleteBtnInRootRuleChainIsNotDisplayed() { + return wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath(getDeleteRuleChainFromViewBtn()))); } public boolean ruleChainsIsNotPresent(String ruleChainName) { 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 index 1e1484be7b..902966a1ac 100644 --- 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 @@ -1,10 +1,25 @@ -package pages; +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.ui.pages; -import base.BasePage; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import org.thingsboard.server.msa.ui.base.AbstractBasePage; -public class SideBarMenuViewElements extends BasePage { +public class SideBarMenuViewElements extends AbstractBasePage { public SideBarMenuViewElements(WebDriver driver) { super(driver); } 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 index c59b950862..9a604416d9 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.customerSmoke; import io.qameta.allure.Description; @@ -6,56 +21,57 @@ 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.CustomerPageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.*; -public class CreateCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class CreateCustomerTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private CustomerPageHelperAbstract customerPage; + private CustomerPageHelper customerPage; private String customerName; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - customerPage = new CustomerPageHelperAbstract(driver); + customerPage = new CustomerPageHelper(driver); } @AfterMethod public void delete() { if (customerName != null) { - customerPage.deleteCustomer(customerName); + testRestClient.deleteCustomer(getCustomerByName(customerName).getId()); customerName = null; } } @Test(priority = 10, groups = "smoke") - @Description("Can click on Add after specifying the name (text/numbers /special characters)") + @Description public void createCustomer() { - String customerName = ENTITY_NAME; + 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") + @Description public void createCustomerWithFullInformation() { - String customerName = ENTITY_NAME; + customerName = ENTITY_NAME; String text = "Text"; String email = "email@mail.com"; - String number = "2015550123"; + String number = "12015550123"; sideBarMenuView.customerBtn().click(); customerPage.plusBtn().click(); @@ -74,7 +90,6 @@ public class CreateCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { customerPage.setCustomerCountry(customerName); customerPage.setCustomerCity(customerName); customerPage.entity(customerName).click(); - this.customerName = customerName; Assert.assertNotNull(customerPage.customer(customerName)); Assert.assertEquals(customerPage.entityViewTitle().getText(), customerName); @@ -86,7 +101,7 @@ public class CreateCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { 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.phoneNumberEntityView().getAttribute("value"), "+" + number); Assert.assertEquals(customerPage.emailEntityView().getAttribute("value"), email); Assert.assertEquals(customerPage.getCustomerEmail(), email); Assert.assertEquals(customerPage.getCustomerCountry(), customerPage.getCountry()); @@ -94,7 +109,7 @@ public class CreateCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { } @Test(priority = 20, groups = "smoke") - @Description("Can`t add customer without the name (empty field or just space)") + @Description public void createCustomerWithoutName() { sideBarMenuView.customerBtn().click(); customerPage.plusBtn().click(); @@ -103,7 +118,7 @@ public class CreateCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { } @Test(priority = 20, groups = "smoke") - @Description() + @Description public void createCustomerWithOnlySpace() { sideBarMenuView.customerBtn().click(); customerPage.plusBtn().click(); @@ -118,7 +133,7 @@ public class CreateCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { } @Test(priority = 20, groups = "smoke") - @Description("Can't create a customer with the same name") + @Description public void createCustomerSameName() { sideBarMenuView.customerBtn().click(); customerPage.setCustomerName(); @@ -135,22 +150,21 @@ public class CreateCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { } @Test(priority = 20, groups = "smoke") - @Description("Can click on Add after specifying the name (text/numbers /special characters)") + @Description public void createCustomerWithoutRefresh() { - String customerName = ENTITY_NAME; + 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)") + @Description public void documentation() { String urlPath = "docs/user-guide/ui/customers/"; 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 index 36297cbf3a..2bfd157773 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.customerSmoke; import io.qameta.allure.Description; @@ -6,62 +21,64 @@ 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.CustomerPageHelper; +import org.thingsboard.server.msa.ui.pages.DashboardPageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; 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.*; +import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; -public class CustomerEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class CustomerEditMenuTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private CustomerPageHelperAbstract customerPage; - private DashboardPageHelperAbstract dashboardPage; + private CustomerPageHelper customerPage; + private DashboardPageHelper dashboardPage; private String customerName; + @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - customerPage = new CustomerPageHelperAbstract(driver); - dashboardPage = new DashboardPageHelperAbstract(driver); + customerPage = new CustomerPageHelper(driver); + dashboardPage = new DashboardPageHelper(driver); } @AfterMethod public void delete() { if (customerName != null) { - customerPage.deleteCustomer(customerName); + testRestClient.deleteCustomer(getCustomerByName(customerName).getId()); 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") + @Description public void changeTitle() { - customerPage.createCustomer(ENTITY_NAME); - String title = "Changed" + getRandomNumber(); + customerName = "Changed" + getRandomNumber(); + testRestClient.postCustomer(defaultCustomerPrototype(ENTITY_NAME)); sideBarMenuView.customerBtn().click(); customerPage.entityTitles().get(0).click(); customerPage.setHeaderName(); String titleBefore = customerPage.getHeaderName(); customerPage.editPencilBtn().click(); - customerPage.changeTitleEditMenu(title); + customerPage.changeTitleEditMenu(customerName); customerPage.doneBtnEditView().click(); customerPage.setHeaderName(); String titleAfter = customerPage.getHeaderName(); - customerName = title; Assert.assertNotEquals(titleBefore, titleAfter); - Assert.assertEquals(titleAfter, title); + Assert.assertEquals(titleAfter, customerName); } @Test(priority = 20, groups = "smoke") - @Description("Can`t delete the title and save changes") + @Description public void deleteTitle() { sideBarMenuView.customerBtn().click(); customerPage.entityTitles().get(0).click(); @@ -72,7 +89,7 @@ public class CustomerEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest } @Test(priority = 20, groups = "smoke") - @Description("Can`t save just a space in the title") + @Description public void saveOnlyWithSpace() { sideBarMenuView.customerBtn().click(); customerPage.setCustomerName(); @@ -89,10 +106,10 @@ public class CustomerEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest } @Test(priority = 20, groups = "smoke") - @Description("Can write/change/delete the descriptionEntityView and save the changes. All changes have been applied") + @Description public void editDescription() { - String title = ENTITY_NAME; - customerPage.createCustomer(title); + customerName = ENTITY_NAME; + testRestClient.postCustomer(defaultCustomerPrototype(customerName)); String description = "Description"; sideBarMenuView.customerBtn().click(); @@ -108,7 +125,6 @@ public class CustomerEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest customerPage.editPencilBtn().click(); customerPage.changeDescription(""); customerPage.doneBtnEditView().click(); - customerName = title; Assert.assertEquals(description, description1); Assert.assertEquals(description + description, description2); @@ -118,24 +134,23 @@ public class CustomerEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest @Test(priority = 20, groups = "smoke") @Description public void assignedDashboardFromDashboard() { - String title = ENTITY_NAME; - customerPage.createCustomer(title); + customerName = ENTITY_NAME; + testRestClient.postCustomer(defaultCustomerPrototype(customerName)); sideBarMenuView.dashboardBtn().click(); dashboardPage.setDashboardTitle(); dashboardPage.assignedBtn(dashboardPage.getDashboardTitle()).click(); - dashboardPage.assignedCustomer(title); + dashboardPage.assignedCustomer(customerName); sideBarMenuView.customerBtn().click(); - customerPage.entity(title).click(); + customerPage.entity(customerName).click(); customerPage.editPencilBtn().click(); customerPage.chooseDashboard(); customerPage.doneBtnEditView().click(); customerPage.setDashboardFromView(); customerPage.closeEntityViewBtn().click(); - customerPage.manageCustomersUserBtn(title).click(); + customerPage.manageCustomersUserBtn(customerName).click(); customerPage.createCustomersUser(); customerPage.userLoginBtn().click(); - customerName = title; Assert.assertNotNull(customerPage.usersWidget()); Assert.assertTrue(customerPage.usersWidget().isDisplayed()); @@ -145,23 +160,22 @@ public class CustomerEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest @Test(priority = 20, groups = "smoke") @Description public void assignedDashboard() { - String title = ENTITY_NAME; - customerPage.createCustomer(title); + customerName = ENTITY_NAME; + testRestClient.postCustomer(defaultCustomerPrototype(customerName)); sideBarMenuView.customerBtn().click(); - customerPage.manageCustomersDashboardsBtn(title).click(); + customerPage.manageCustomersDashboardsBtn(customerName).click(); customerPage.assignedDashboard(); sideBarMenuView.customerBtn().click(); - customerPage.entity(title).click(); + customerPage.entity(customerName).click(); customerPage.editPencilBtn().click(); customerPage.chooseDashboard(); customerPage.doneBtnEditView().click(); customerPage.setDashboardFromView(); customerPage.closeEntityViewBtn().click(); - customerPage.manageCustomersUserBtn(title).click(); + customerPage.manageCustomersUserBtn(customerName).click(); customerPage.createCustomersUser(); customerPage.userLoginBtn().click(); - customerName = title; Assert.assertNotNull(customerPage.usersWidget()); Assert.assertTrue(customerPage.usersWidget().isDisplayed()); @@ -171,24 +185,23 @@ public class CustomerEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest @Test(priority = 20, groups = "smoke") @Description public void assignedDashboardWithoutHide() { - String title = ENTITY_NAME; - customerPage.createCustomer(title); + customerName = ENTITY_NAME; + testRestClient.postCustomer(defaultCustomerPrototype(customerName)); sideBarMenuView.customerBtn().click(); - customerPage.manageCustomersDashboardsBtn(title).click(); + customerPage.manageCustomersDashboardsBtn(customerName).click(); customerPage.assignedDashboard(); sideBarMenuView.customerBtn().click(); - customerPage.entity(title).click(); + customerPage.entity(customerName).click(); customerPage.editPencilBtn().click(); customerPage.chooseDashboard(); customerPage.hideHomeDashboardToolbarCheckbox().click(); customerPage.doneBtnEditView().click(); customerPage.setDashboardFromView(); customerPage.closeEntityViewBtn().click(); - customerPage.manageCustomersUserBtn(title).click(); + customerPage.manageCustomersUserBtn(customerName).click(); customerPage.createCustomersUser(); customerPage.userLoginBtn().click(); - customerName = title; Assert.assertNotNull(customerPage.usersWidget()); Assert.assertTrue(customerPage.usersWidget().isDisplayed()); @@ -204,8 +217,8 @@ public class CustomerEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest @Test(priority = 20, groups = "smoke") @Description public void addPhoneNumber() { - String title = ENTITY_NAME; - customerPage.createCustomer(title); + customerName = ENTITY_NAME; + testRestClient.postCustomer(defaultCustomerPrototype(customerName)); String number = "2015550123"; sideBarMenuView.customerBtn().click(); @@ -213,7 +226,6 @@ public class CustomerEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest customerPage.editPencilBtn().click(); customerPage.phoneNumberEntityView().sendKeys(number); customerPage.doneBtnEditView().click(); - customerName = title; Assert.assertTrue(customerPage.phoneNumberEntityView().getAttribute("value").contains(number)); } @@ -235,9 +247,11 @@ public class CustomerEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest } @Test(priority = 30, groups = "smoke") + @Description public void addAllInformation() { - String title = ENTITY_NAME; - customerPage.createCustomer(title); + customerName = ENTITY_NAME; + testRestClient.postCustomer(defaultCustomerPrototype(customerName)); + ; String text = "Text"; String email = "email@mail.com"; String number = "2015550123"; @@ -255,7 +269,6 @@ public class CustomerEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest 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); 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 index 7a22422777..27e8605926 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.customerSmoke; import io.qameta.allure.Description; @@ -5,34 +20,35 @@ 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.CustomerPageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; 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; +import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; -public class DeleteCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class DeleteCustomerTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private CustomerPageHelperAbstract customerPage; - private RuleChainsPageHelperAbstract ruleChainsPage; + private CustomerPageHelper customerPage; + private RuleChainsPageHelper ruleChainsPage; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - customerPage = new CustomerPageHelperAbstract(driver); - ruleChainsPage = new RuleChainsPageHelperAbstract(driver); + customerPage = new CustomerPageHelper(driver); + ruleChainsPage = new RuleChainsPageHelper(driver); } @Test(priority = 10, groups = "smoke") - @Description("Can remove the customer by clicking on the trash can icon in the right corner") + @Description public void removeCustomerByRightSideBtn() { String customer = ENTITY_NAME; - customerPage.createCustomer(customer); + testRestClient.postCustomer(defaultCustomerPrototype(customer)); sideBarMenuView.customerBtn().click(); String deletedCustomer = customerPage.deleteRuleChainTrash(customer); @@ -42,10 +58,10 @@ public class DeleteCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { } @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") + @Description public void removeSelectedCustomer() { String customerName = ENTITY_NAME; - customerPage.createCustomer(customerName); + testRestClient.postCustomer(defaultCustomerPrototype(customerName)); sideBarMenuView.customerBtn().click(); String deletedCustomer = customerPage.deleteSelected(customerName); @@ -55,10 +71,10 @@ public class DeleteCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { } @Test(priority = 20, groups = "smoke") - @Description("Can click on the name of the rule chain and click on the 'Delete customer' button") + @Description public void removeFromCustomerView() { String customerName = ENTITY_NAME; - customerPage.createCustomer(customerName); + testRestClient.postCustomer(defaultCustomerPrototype(customerName)); sideBarMenuView.customerBtn().click(); customerPage.entity(customerName).click(); @@ -69,10 +85,10 @@ public class DeleteCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { } @Test(priority = 20, groups = "smoke") - @Description("The rule chain is deleted immediately after clicking remove (no need to refresh the page)") + @Description public void removeCustomerByRightSideBtnWithoutRefresh() { String customer = ENTITY_NAME; - customerPage.createCustomer(customer); + testRestClient.postCustomer(defaultCustomerPrototype(customer)); sideBarMenuView.customerBtn().click(); String deletedCustomer = customerPage.deleteRuleChainTrash(customer); 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 index 9847f1b763..138c563631 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.customerSmoke; import io.qameta.allure.Description; @@ -5,41 +20,37 @@ 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.CustomerPageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; 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; +import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; -public class DeleteSeveralCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class DeleteSeveralCustomerTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private CustomerPageHelperAbstract customerPage; + private CustomerPageHelper customerPage; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - customerPage = new CustomerPageHelperAbstract(driver); + customerPage = new CustomerPageHelper(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") + @Description public void canDeleteSeveralCustomersByTopBtn() { String title1 = ENTITY_NAME + "1"; String title2 = ENTITY_NAME + "2"; - int count = 2; - customerPage.createCustomer(title1); - customerPage.createCustomer(title2); + testRestClient.postCustomer(defaultCustomerPrototype(title1)); + testRestClient.postCustomer(defaultCustomerPrototype(title2)); sideBarMenuView.customerBtn().click(); - customerPage.clickOnCheckBoxes(count); - - Assert.assertEquals(customerPage.markCheckbox().size(), count); - customerPage.markCheckbox().forEach(x -> Assert.assertTrue(x.isDisplayed())); - + customerPage.clickOnCheckBoxes(2); customerPage.deleteSelectedBtn().click(); customerPage.warningPopUpYesBtn().click(); customerPage.refreshBtn().click(); @@ -49,7 +60,7 @@ public class DeleteSeveralCustomerAbstractDiverBaseTest extends AbstractDiverBas } @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") + @Description public void selectAllCustomers() { sideBarMenuView.customerBtn().click(); customerPage.selectAllCheckBox().click(); @@ -61,17 +72,15 @@ public class DeleteSeveralCustomerAbstractDiverBaseTest extends AbstractDiverBas } @Test(priority = 30, groups = "smoke") - @Description("The rule chains are deleted immediately after clicking remove (no need to refresh the page)") + @Description public void deleteSeveralCustomersByTopBtnWithoutRefresh() { String title1 = ENTITY_NAME + "1"; String title2 = ENTITY_NAME + "2"; - int count = 2; - customerPage.createCustomer(title1); - customerPage.createCustomer(title2); + testRestClient.postCustomer(defaultCustomerPrototype(title1)); + testRestClient.postCustomer(defaultCustomerPrototype(title2)); sideBarMenuView.customerBtn().click(); - customerPage.clickOnCheckBoxes(count); - + customerPage.clickOnCheckBoxes(2); customerPage.deleteSelectedBtn().click(); customerPage.warningPopUpYesBtn().click(); 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 index 785ee8c813..7b85771c23 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.customerSmoke; import io.qameta.allure.Description; @@ -5,28 +20,28 @@ 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.CustomerPageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class ManageCustomersAssetsAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class ManageCustomersAssetsTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private CustomerPageHelperAbstract customerPage; + private CustomerPageHelper customerPage; private final String manage = "Assets"; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); sideBarMenuView = new SideBarMenuViewElements(driver); - customerPage = new CustomerPageHelperAbstract(driver); + customerPage = new CustomerPageHelper(driver); } @Test(groups = "smoke") - @Description("Can go to the 'Customer assets' window by clicking on the 'Manage customer users' icon in the right corner") + @Description public void openWindowByRightCornerBtn() { sideBarMenuView.customerBtn().click(); customerPage.setCustomerName(); @@ -39,7 +54,7 @@ public class ManageCustomersAssetsAbstractDiverBaseTest extends AbstractDiverBas } @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") + @Description public void openWindowByView() { sideBarMenuView.customerBtn().click(); customerPage.setCustomerName(); 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 index 68fe281d0b..9ac2986fd0 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.customerSmoke; import io.qameta.allure.Description; @@ -5,27 +20,27 @@ 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.CustomerPageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class ManageCustomersDashboardsAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class ManageCustomersDashboardsTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private CustomerPageHelperAbstract customerPage; + private CustomerPageHelper customerPage; private final String manage = "Dashboards"; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); sideBarMenuView = new SideBarMenuViewElements(driver); - customerPage = new CustomerPageHelperAbstract(driver); + customerPage = new CustomerPageHelper(driver); } @Test(groups = "smoke") - @Description("Can go to the 'Customer Dashboards' window by clicking on the 'Manage customer users' icon in the right corner") + @Description public void openWindowByRightCornerBtn() { sideBarMenuView.customerBtn().click(); customerPage.setCustomerName(); @@ -38,7 +53,7 @@ public class ManageCustomersDashboardsAbstractDiverBaseTest extends AbstractDive } @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") + @Description public void openWindowByView() { sideBarMenuView.customerBtn().click(); customerPage.setCustomerName(); 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 index d62b5fe4cf..30b451899e 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.customerSmoke; import io.qameta.allure.Description; @@ -5,27 +20,27 @@ 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.CustomerPageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class ManageCustomersDevicesAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class ManageCustomersDevicesTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private CustomerPageHelperAbstract customerPage; + private CustomerPageHelper customerPage; private final String manage = "Devices"; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); sideBarMenuView = new SideBarMenuViewElements(driver); - customerPage = new CustomerPageHelperAbstract(driver); + customerPage = new CustomerPageHelper(driver); } @Test(groups = "smoke") - @Description("Can go to the 'Customer Devices' window by clicking on the 'Manage customer users' icon in the right corner") + @Description public void openWindowByRightCornerBtn() { sideBarMenuView.customerBtn().click(); customerPage.setCustomerName(); @@ -38,7 +53,7 @@ public class ManageCustomersDevicesAbstractDiverBaseTest extends AbstractDiverBa } @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") + @Description public void openWindowByView() { sideBarMenuView.customerBtn().click(); customerPage.setCustomerName(); 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 index ff0ac3e4f1..044f809f77 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.customerSmoke; import io.qameta.allure.Description; @@ -5,28 +20,28 @@ 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.CustomerPageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class ManageCustomersEdgesAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class ManageCustomersEdgesTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private CustomerPageHelperAbstract customerPage; - private String iconText = "Edge instances"; + private CustomerPageHelper customerPage; + private final String iconText = "Edge instances"; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); sideBarMenuView = new SideBarMenuViewElements(driver); - customerPage = new CustomerPageHelperAbstract(driver); + customerPage = new CustomerPageHelper(driver); } @Test(groups = "smoke") - @Description("Can go to the 'Customer Edges' window by clicking on the 'Manage customer users' icon in the right corner") + @Description public void openWindowByRightCornerBtn() { sideBarMenuView.customerBtn().click(); customerPage.setCustomerName(); @@ -39,7 +54,7 @@ public class ManageCustomersEdgesAbstractDiverBaseTest extends AbstractDiverBase } @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") + @Description public void openWindowByView() { sideBarMenuView.customerBtn().click(); customerPage.setCustomerName(); 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 index 855e227b5e..42d03bda1e 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.customerSmoke; import io.qameta.allure.Description; @@ -5,28 +20,28 @@ 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.CustomerPageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class ManageCustomersUsersAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class ManageCustomersUsersTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private CustomerPageHelperAbstract customerPage; - private String iconText = "Customer Users"; + private CustomerPageHelper customerPage; + private final String iconText = "Customer Users"; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); sideBarMenuView = new SideBarMenuViewElements(driver); - customerPage = new CustomerPageHelperAbstract(driver); + customerPage = new CustomerPageHelper(driver); } @Test(groups = "smoke") - @Description("Can go to the 'Customer Users' window by clicking on the 'Manage customer users' icon in the right corner") + @Description public void openWindowByRightCornerBtn() { sideBarMenuView.customerBtn().click(); customerPage.setCustomerName(); @@ -39,7 +54,7 @@ public class ManageCustomersUsersAbstractDiverBaseTest extends AbstractDiverBase } @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") + @Description public void openWindowByView() { sideBarMenuView.customerBtn().click(); customerPage.setCustomerName(); 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 index 6db022da62..97a4c6f85f 100644 --- 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 @@ -1,39 +1,49 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ 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.CustomerPageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; 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; +import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; -public class SearchCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class SearchCustomerTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private CustomerPageHelperAbstract customerPage; - private String entityName; + private CustomerPageHelper customerPage; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - customerPage = new CustomerPageHelperAbstract(driver); - } - - @AfterMethod - public void deleteCustomer() { - customerPage.deleteCustomer(entityName); + customerPage = new CustomerPageHelper(driver); } @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "customerNameForSearchByFirstAndSecondWord") - @Description("Can search by the first/second word of the name") + @Description public void searchFirstWord(String namePath) { sideBarMenuView.customerBtn().click(); customerPage.searchEntity(namePath); @@ -42,15 +52,17 @@ public class SearchCustomerAbstractDiverBaseTest extends AbstractDiverBaseTest { } @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForSearchBySymbolAndNumber") - @Description("Can search by number/symbol") + @Description public void searchNumber(String name, String namePath) { - customerPage.createCustomer(name); + testRestClient.postCustomer(defaultCustomerPrototype(name)); sideBarMenuView.customerBtn().click(); customerPage.searchEntity(namePath); customerPage.setCustomerName(); - entityName = name; + boolean customerNameContainsPath = customerPage.getCustomerName().contains(namePath); + + testRestClient.deleteCustomer(getCustomerByName(name).getId()); - Assert.assertTrue(customerPage.getCustomerName().contains(namePath)); + Assert.assertTrue(customerNameContainsPath); } } 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 index 8ab49b6c68..3a71ca5ddb 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.customerSmoke; import io.qameta.allure.Description; @@ -6,30 +21,32 @@ 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.CustomerPageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; 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; +import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; -public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class SortByNameTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private CustomerPageHelperAbstract customerPage; + private CustomerPageHelper customerPage; private String customerName; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - customerPage = new CustomerPageHelperAbstract(driver); + customerPage = new CustomerPageHelper(driver); } @AfterMethod public void delete() { if (customerName != null) { - customerPage.deleteCustomer(customerName); + testRestClient.deleteCustomer(getCustomerByName(customerName).getId()); customerName = null; } } @@ -37,12 +54,12 @@ public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForSort") @Description public void specialCharacterUp(String title) { - customerPage.createCustomer(title); + customerName = title; + testRestClient.postCustomer(defaultCustomerPrototype(title)); sideBarMenuView.customerBtn().click(); customerPage.sortByTitleBtn().click(); customerPage.setCustomerName(); - customerName = title; Assert.assertEquals(customerPage.getCustomerName(), title); } @@ -50,9 +67,9 @@ public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { @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); + testRestClient.postCustomer(defaultCustomerPrototype(customerSymbol)); + testRestClient.postCustomer(defaultCustomerPrototype(customer)); + testRestClient.postCustomer(defaultCustomerPrototype(customerNumber)); sideBarMenuView.customerBtn().click(); customerPage.sortByTitleBtn().click(); @@ -67,9 +84,9 @@ public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { boolean secondEquals = secondCustomer.equals(customerNumber); boolean thirdEquals = thirdCustomer.equals(customer); - customerPage.deleteCustomer(customer); - customerPage.deleteCustomer(customerNumber); - customerPage.deleteCustomer(customerSymbol); + testRestClient.deleteCustomer(getCustomerByName(customer).getId()); + testRestClient.deleteCustomer(getCustomerByName(customerNumber).getId()); + testRestClient.deleteCustomer(getCustomerByName(customerSymbol).getId()); Assert.assertTrue(firstEquals); Assert.assertTrue(secondEquals); @@ -79,12 +96,12 @@ public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForSort") @Description public void specialCharacterDown(String title) { - customerPage.createCustomer(title); + customerName = title; + testRestClient.postCustomer(defaultCustomerPrototype(title)); sideBarMenuView.customerBtn().click(); customerPage.sortByNameDown(); customerPage.setCustomerName(customerPage.allEntity().size() - 1); - customerName = title; Assert.assertEquals(customerPage.getCustomerName(), title); } @@ -92,9 +109,9 @@ public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { @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); + testRestClient.postCustomer(defaultCustomerPrototype(customerSymbol)); + testRestClient.postCustomer(defaultCustomerPrototype(customer)); + testRestClient.postCustomer(defaultCustomerPrototype(customerNumber)); sideBarMenuView.customerBtn().click(); int lastIndex = customerPage.allEntity().size() - 1; @@ -110,9 +127,9 @@ public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { boolean secondEquals = secondCustomer.equals(customerNumber); boolean thirdEquals = thirdCustomer.equals(customer); - customerPage.deleteCustomer(customer); - customerPage.deleteCustomer(customerNumber); - customerPage.deleteCustomer(customerSymbol); + testRestClient.deleteCustomer(getCustomerByName(customer).getId()); + testRestClient.deleteCustomer(getCustomerByName(customerNumber).getId()); + testRestClient.deleteCustomer(getCustomerByName(customerSymbol).getId()); Assert.assertTrue(firstEquals); Assert.assertTrue(secondEquals); 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 index 2b05fb8867..a027267469 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke; import io.qameta.allure.Description; @@ -6,17 +21,20 @@ 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.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.OpenRuleChainPageHelper; +import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; +import java.util.ArrayList; + import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class CreateRuleChainImportAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class CreateRuleChainImportTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private RuleChainsPageHelperAbstract ruleChainsPage; - private OpenRuleChainPageHelperAbstract openRuleChainPage; + private RuleChainsPageHelper ruleChainsPage; + private OpenRuleChainPageHelper 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; @@ -24,22 +42,23 @@ public class CreateRuleChainImportAbstractDiverBaseTest extends AbstractDiverBas @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - ruleChainsPage = new RuleChainsPageHelperAbstract(driver); - openRuleChainPage = new OpenRuleChainPageHelperAbstract(driver); + ruleChainsPage = new RuleChainsPageHelper(driver); + openRuleChainPage = new OpenRuleChainPageHelper(driver); } @AfterMethod public void delete() { if (ruleChainName != null) { - ruleChainsPage.deleteRuleChain(ruleChainName); + testRestClient.deleteRuleChain(getRuleChainByName(ruleChainName).getId()); ruleChainName = null; } } @Test(priority = 10, groups = "smoke") - @Description("Can drop a JSON file and import it") + @Description public void importRuleChain() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.openImportRuleChainView(); @@ -50,7 +69,7 @@ public class CreateRuleChainImportAbstractDiverBaseTest extends AbstractDiverBas } @Test(priority = 20, groups = "smoke") - @Description("Can delete a file by clicking on the icon Remove") + @Description public void importRuleChainAndDeleteFile() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.openImportRuleChainView(); @@ -63,7 +82,7 @@ public class CreateRuleChainImportAbstractDiverBaseTest extends AbstractDiverBas } @Test(priority = 20, groups = "smoke") - @Description("Can`t Select / drop a file of a different format than JSON") + @Description public void importTxtFile() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.openImportRuleChainView(); @@ -74,7 +93,7 @@ public class CreateRuleChainImportAbstractDiverBaseTest extends AbstractDiverBas } @Test(priority = 30, groups = "smoke") - @Description("After clicking on Import - imported rule chain opens (need to save by clicking on the Apply changes icon)") + @Description public void importRuleChainAndSave() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.openImportRuleChainView(); @@ -90,9 +109,11 @@ public class CreateRuleChainImportAbstractDiverBaseTest extends AbstractDiverBas } @Test(priority = 40, groups = "smoke") - @Description("Can create a rule chain with the same name") + @Description public void importRuleChainAndSaveWithSameName() { - ruleChainsPage.createRuleChain(IMPORT_RULE_CHAIN_NAME); + ruleChainName = IMPORT_RULE_CHAIN_NAME; + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); + ; sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.openImportRuleChainView(); @@ -101,10 +122,16 @@ public class CreateRuleChainImportAbstractDiverBaseTest extends AbstractDiverBas openRuleChainPage.doneBtn().click(); openRuleChainPage.waitUntilDoneBtnDisable(); sideBarMenuView.ruleChainsBtn().click(); - boolean sizeBigger1 = ruleChainsPage.entities(IMPORT_RULE_CHAIN_NAME).size() > 1; - ruleChainsPage.deleteAllRuleChain(IMPORT_RULE_CHAIN_NAME); + boolean entityNotNull = ruleChainsPage.entity(ruleChainName) != null; + boolean entitiesSizeMoreOne = ruleChainsPage.entities(ruleChainName).size() > 1; + ArrayList entityIsDisplayed = new ArrayList<>(); + ruleChainsPage.entities(ruleChainName).forEach(x -> entityIsDisplayed.add(x.isDisplayed())); + + testRestClient.deleteRuleChain(getRuleChainByName(ruleChainName).getId()); - Assert.assertTrue(sizeBigger1); + Assert.assertTrue(entityNotNull); + Assert.assertTrue(entitiesSizeMoreOne); + entityIsDisplayed.forEach(Assert::assertTrue); } } 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 index 32470c86f9..d3d71a45b0 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke; import io.qameta.allure.Description; @@ -6,54 +21,57 @@ 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.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; +import org.thingsboard.server.msa.ui.utils.EntityPrototypes; + +import java.util.ArrayList; import static org.thingsboard.server.msa.ui.utils.Const.*; -public class CreateRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class CreateRuleChainTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private RuleChainsPageHelperAbstract ruleChainsPage; + private RuleChainsPageHelper ruleChainsPage; private String ruleChainName; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - ruleChainsPage = new RuleChainsPageHelperAbstract(driver); + ruleChainsPage = new RuleChainsPageHelper(driver); } @AfterMethod public void delete() { if (ruleChainName != null) { - ruleChainsPage.deleteRuleChain(ruleChainName); + testRestClient.deleteRuleChain(getRuleChainByName(ruleChainName).getId()); ruleChainName = null; } } @Test(priority = 10, groups = "smoke") - @Description("Can click on Add after specifying the name (text/numbers /special characters)") + @Description public void createRuleChain() { - String ruleChainName = ENTITY_NAME; + 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() + @Description public void createRuleChainWithDescription() { - String ruleChainName = ENTITY_NAME; + ruleChainName = ENTITY_NAME; sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.openCreateRuleChainView(); @@ -63,14 +81,13 @@ public class CreateRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest 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)") + @Description public void createRuleChainWithoutName() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.openCreateRuleChainView(); @@ -79,7 +96,7 @@ public class CreateRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest } @Test(priority = 20, groups = "smoke") - @Description() + @Description public void createRuleChainWithOnlySpace() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.openCreateRuleChainView(); @@ -94,38 +111,45 @@ public class CreateRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest } @Test(priority = 20, groups = "smoke") - @Description("Can create a rule chain with the same name") + @Description public void createRuleChainWithSameName() { + ruleChainName = ENTITY_NAME; + testRestClient.postRuleChain(EntityPrototypes.defaultRuleChainPrototype(ruleChainName)); + 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); + boolean entityNotNull = ruleChainsPage.entity(ruleChainName) != null; + boolean entitiesSizeMoreOne = ruleChainsPage.entities(ruleChainName).size() > 1; + ArrayList entityIsDisplayed = new ArrayList<>(); + ruleChainsPage.entities(ruleChainName).forEach(x -> entityIsDisplayed.add(x.isDisplayed())); + + testRestClient.deleteRuleChain(getRuleChainByName(ruleChainName).getId()); + + Assert.assertTrue(entityNotNull); + Assert.assertTrue(entitiesSizeMoreOne); + entityIsDisplayed.forEach(Assert::assertTrue); } @Test(priority = 30, groups = "smoke") - @Description("After clicking on Add - appears immediately in the list (no need to refresh the page)") + @Description public void createRuleChainWithoutRefresh() { - String ruleChainName = ENTITY_NAME; + 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)") + @Description public void documentation() { String urlPath = "docs/user-guide/ui/rule-chains/"; 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 index f2fe8c7c1c..92da98af1b 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke; import io.qameta.allure.Description; @@ -5,41 +20,44 @@ 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.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class DeleteRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class DeleteRuleChainTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private RuleChainsPageHelperAbstract ruleChainsPage; + private RuleChainsPageHelper ruleChainsPage; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - ruleChainsPage = new RuleChainsPageHelperAbstract(driver); + ruleChainsPage = new RuleChainsPageHelper(driver); } @Test(priority = 10, groups = "smoke") - @Description("Can remove the rule chain by clicking on the trash can icon in the right corner") + @Description public void removeRuleChainByRightSideBtn() { - ruleChainsPage.createRuleChain(ENTITY_NAME); + String ruleChainName = ENTITY_NAME; + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); sideBarMenuView.ruleChainsBtn().click(); - String deletedRuleChain = ruleChainsPage.deleteRuleChainTrash(ENTITY_NAME); + String deletedRuleChain = ruleChainsPage.deleteRuleChainTrash(ruleChainName); 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") + @Description public void removeSelectedRuleChain() { String ruleChainName = ENTITY_NAME; - ruleChainsPage.createRuleChain(ruleChainName); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); sideBarMenuView.ruleChainsBtn().click(); String deletedRuleChain = ruleChainsPage.deleteSelected(ruleChainName); @@ -49,20 +67,21 @@ public class DeleteRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest } @Test(priority = 20, groups = "smoke") - @Description("Can click on the name of the rule chain and click on the 'Delete rule chain' button") + @Description public void removeFromRuleChainView() { - ruleChainsPage.createRuleChain(ENTITY_NAME); + String ruleChainName = ENTITY_NAME; + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.entity(ENTITY_NAME).click(); - String deletedRuleChain = ruleChainsPage.deleteRuleChainFromView(ENTITY_NAME); + String deletedRuleChain = ruleChainsPage.deleteRuleChainFromView(ruleChainName); 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)") + @Description public void removeRootRuleChain() { sideBarMenuView.ruleChainsBtn().click(); @@ -70,7 +89,7 @@ public class DeleteRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest } @Test(priority = 20, groups = "smoke") - @Description("Can`t remove Root Rule Chain (can`t mark the rule chain in the checkbox )") + @Description public void removeSelectedRootRuleChain() { sideBarMenuView.ruleChainsBtn().click(); @@ -78,17 +97,17 @@ public class DeleteRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest } @Test(priority = 20, groups = "smoke") - @Description("Can`t remove Root Rule Chain (missing delete button)") + @Description public void removeFromRootRuleChainView() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.entity(ROOT_RULE_CHAIN_NAME).click(); ruleChainsPage.deleteBtnFromView(); - ruleChainsPage.assertDeleteBtnInRootRuleChainIsNotDisplayed(); + Assert.assertTrue(ruleChainsPage.deleteBtnInRootRuleChainIsNotDisplayed()); } @Test(priority = 10, groups = "smoke") - @Description("Can remove the rule chain by clicking on the trash can icon in the right corner") + @Description public void removeProfileRuleChainByRightSideBtn() { String deletedRuleChain = "Thermostat"; @@ -105,7 +124,7 @@ public class DeleteRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest } @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") + @Description public void removeSelectedProfileRuleChain() { sideBarMenuView.ruleChainsBtn().click(); String deletedRuleChain = ruleChainsPage.deleteSelected("Thermostat"); @@ -119,7 +138,7 @@ public class DeleteRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest } @Test(priority = 20, groups = "smoke") - @Description("Can click on the name of the rule chain and click on the 'Delete rule chain' button") + @Description public void removeFromProfileRuleChainView() { String deletedRuleChain = "Thermostat"; @@ -135,10 +154,10 @@ public class DeleteRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest } @Test(priority = 30, groups = "smoke") - @Description("The rule chain is deleted immediately after clicking remove (no need to refresh the page)") + @Description public void removeRuleChainByRightSideBtnWithoutRefresh() { String ruleChainName = ENTITY_NAME; - ruleChainsPage.createRuleChain(ruleChainName); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); sideBarMenuView.ruleChainsBtn().click(); String deletedRuleChain = ruleChainsPage.deleteRuleChainTrash(ruleChainName); 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 index 8481d9cde6..5b8667580e 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke; import io.qameta.allure.Description; @@ -5,35 +20,36 @@ 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.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class DeleteSeveralRuleChainsAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class DeleteSeveralRuleChainsTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private RuleChainsPageHelperAbstract ruleChainsPage; + private RuleChainsPageHelper ruleChainsPage; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - ruleChainsPage = new RuleChainsPageHelperAbstract(driver); + ruleChainsPage = new RuleChainsPageHelper(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") + @Description public void canDeleteSeveralRuleChainsByTopBtn() { String ruleChainName = ENTITY_NAME; - int count = 2; - ruleChainsPage.createRuleChains(ruleChainName, count); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName + 1)); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); sideBarMenuView.ruleChainsBtn().click(); - ruleChainsPage.clickOnCheckBoxes(count); - + ruleChainsPage.clickOnCheckBoxes(2); ruleChainsPage.deleteSelectedBtn().click(); ruleChainsPage.warningPopUpYesBtn().click(); ruleChainsPage.refreshBtn().click(); @@ -42,11 +58,11 @@ public class DeleteSeveralRuleChainsAbstractDiverBaseTest extends AbstractDiverB } @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") + @Description public void selectAllRuleChain() { String ruleChainName = ENTITY_NAME; - int count = 2; - ruleChainsPage.createRuleChains(ruleChainName, count); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName + 1)); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.selectAllCheckBox().click(); @@ -58,7 +74,7 @@ public class DeleteSeveralRuleChainsAbstractDiverBaseTest extends AbstractDiverB } @Test(priority = 20, groups = "smoke") - @Description("Can`t remove Root Rule Chain (the trash can is disabled in the right corner)") + @Description public void removeRootRuleChain() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.selectAllCheckBox().click(); @@ -67,7 +83,7 @@ public class DeleteSeveralRuleChainsAbstractDiverBaseTest extends AbstractDiverB } @Test(priority = 20, groups = "smoke") - @Description("Can`t remove Root Rule Chain (can`t mark the rule chain in the checkbox )") + @Description public void removeSelectedRootRuleChain() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.selectAllCheckBox().click(); @@ -76,14 +92,14 @@ public class DeleteSeveralRuleChainsAbstractDiverBaseTest extends AbstractDiverB } @Test(priority = 30, groups = "smoke") - @Description("The rule chains are deleted immediately after clicking remove (no need to refresh the page)") + @Description public void deleteSeveralRuleChainsByTopBtnWithoutRefresh() { String ruleChainName = ENTITY_NAME; - int count = 2; - ruleChainsPage.createRuleChains(ruleChainName, count); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName + 1)); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); sideBarMenuView.ruleChainsBtn().click(); - ruleChainsPage.clickOnCheckBoxes(count); + ruleChainsPage.clickOnCheckBoxes(2); ruleChainsPage.deleteSelectedBtn().click(); ruleChainsPage.warningPopUpYesBtn().click(); 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 index 8a71a11232..7eb75de8f8 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke; import io.qameta.allure.Description; @@ -6,32 +21,33 @@ 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.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; -import static org.thingsboard.server.msa.ui.utils.Const.URL; +import static org.thingsboard.server.msa.ui.utils.Const.*; -public class MakeRuleChainRootAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class MakeRuleChainRootTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private RuleChainsPageHelperAbstract ruleChainsPage; + private RuleChainsPageHelper ruleChainsPage; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - ruleChainsPage = new RuleChainsPageHelperAbstract(driver); + ruleChainsPage = new RuleChainsPageHelper(driver); } @AfterMethod public void makeRoot() { - ruleChainsPage.makeRoot(); + testRestClient.setRootRuleChain(getRuleChainByName("Root Rule Chain").getId()); } @Test(priority = 10, groups = "smoke") - @Description("Can make rule chain root by clicking on the 'Make rule chain root' icon in the right corner") + @Description public void makeRuleChainRootByRightCornerBtn() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.setRuleChainNameWithoutRoot(0); @@ -43,7 +59,7 @@ public class MakeRuleChainRootAbstractDiverBaseTest extends AbstractDiverBaseTes } @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") + @Description public void makeRuleChainRootFromView() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.setRuleChainNameWithoutRoot(0); @@ -57,11 +73,8 @@ public class MakeRuleChainRootAbstractDiverBaseTest extends AbstractDiverBaseTes } @Test(priority = 30, groups = "smoke") - @Description("Can't make multiple root rule chains (only one rule chain can be root)") + @Description public void multiplyRoot() { - SideBarMenuViewElements sideBarMenuView = new SideBarMenuViewElements(driver); - RuleChainsPageHelperAbstract ruleChainsPage = new RuleChainsPageHelperAbstract(driver); - sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.setRuleChainNameWithoutRoot(0); String ruleChain = ruleChainsPage.getRuleChainName(); 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 index f38f20bdff..7810c7bf5a 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke; import io.qameta.allure.Description; @@ -5,30 +20,31 @@ 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.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.OpenRuleChainPageHelper; +import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; -import static org.thingsboard.server.msa.ui.utils.Const.URL; +import static org.thingsboard.server.msa.ui.utils.Const.*; -public class OpenRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class OpenRuleChainTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private RuleChainsPageHelperAbstract ruleChainsPage; - private OpenRuleChainPageHelperAbstract openRuleChainPage; + private RuleChainsPageHelper ruleChainsPage; + private OpenRuleChainPageHelper openRuleChainPage; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - ruleChainsPage = new RuleChainsPageHelperAbstract(driver); - openRuleChainPage = new OpenRuleChainPageHelperAbstract(driver); + ruleChainsPage = new RuleChainsPageHelper(driver); + openRuleChainPage = new OpenRuleChainPageHelper(driver); } @Test(priority = 10, groups = "smoke") - @Description("Can open the rule chain by clicking on the 'Open rule chain' icon in the right corner") + @Description public void openRuleChainByRightCornerBtn() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.setRuleChainNameWithoutRoot(0); @@ -36,14 +52,14 @@ public class OpenRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest { ruleChainsPage.openRuleChainBtn(ruleChain).click(); openRuleChainPage.setHeadName(); - Assert.assertTrue(urlContains(ruleChainsPage.getRuleChainId(ruleChainsPage.getRuleChainName()))); + Assert.assertTrue(urlContains(String.valueOf(getRuleChainByName(ruleChainsPage.getRuleChainName()).getId()))); 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") + @Description public void openRuleChainByViewBtn() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.setRuleChainNameWithoutRoot(0); @@ -52,14 +68,14 @@ public class OpenRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest { ruleChainsPage.openRuleChainFromViewBtn().click(); openRuleChainPage.setHeadName(); - Assert.assertTrue(urlContains(ruleChainsPage.getRuleChainId(ruleChain))); + Assert.assertTrue(urlContains(String.valueOf(getRuleChainByName(ruleChainsPage.getRuleChainName()).getId()))); 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") + @Description public void openRuleChainDoubleClick() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.setRuleChainNameWithoutRoot(0); 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 index 9a080d7435..12e442c3b0 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke; import io.qameta.allure.Description; @@ -6,38 +21,41 @@ 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.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class RuleChainEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class RuleChainEditMenuTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private RuleChainsPageHelperAbstract ruleChainsPage; + private RuleChainsPageHelper ruleChainsPage; private String ruleChainName; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - ruleChainsPage = new RuleChainsPageHelperAbstract(driver); + ruleChainsPage = new RuleChainsPageHelper(driver); } @AfterMethod public void delete() { if (ruleChainName != null) { - ruleChainsPage.deleteRuleChain(ruleChainName); + testRestClient.deleteRuleChain(getRuleChainByName(ruleChainName).getId()); 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") + @Description public void changeName() { - ruleChainsPage.createRuleChain(ENTITY_NAME); + testRestClient.postRuleChain(defaultRuleChainPrototype(ENTITY_NAME)); + ; String name = "Changed"; sideBarMenuView.ruleChainsBtn().click(); @@ -56,7 +74,7 @@ public class RuleChainEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTes } @Test(priority = 20, groups = "smoke") - @Description("Can`t delete the name and save changes") + @Description public void deleteName() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.notRootRuleChainsNames().get(0).click(); @@ -67,7 +85,7 @@ public class RuleChainEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTes } @Test(priority = 20, groups = "smoke") - @Description("Can`t save just a space in the name") + @Description public void saveOnlyWithSpace() { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.notRootRuleChainsNames().get(0).click(); @@ -81,10 +99,10 @@ public class RuleChainEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTes } @Test(priority = 20, groups = "smoke") - @Description("Can write/change/delete the descriptionEntityView and save the changes. All changes have been applied") + @Description public void editDescription() { - String name = ENTITY_NAME; - ruleChainsPage.createRuleChain(name); + ruleChainName = ENTITY_NAME; + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); String description = "Description"; sideBarMenuView.ruleChainsBtn().click(); @@ -100,7 +118,6 @@ public class RuleChainEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTes ruleChainsPage.editPencilBtn().click(); ruleChainsPage.changeDescription(""); ruleChainsPage.doneBtnEditView().click(); - ruleChainName = name; Assert.assertTrue(ruleChainsPage.descriptionEntityView().getAttribute("value").isEmpty()); Assert.assertEquals(description, description1); @@ -108,10 +125,10 @@ public class RuleChainEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTes } @Test(priority = 20, groups = "smoke") - @Description("Can enable / disable debug and save changes. All changes have been applied") + @Description public void debugMode() { - String name = ENTITY_NAME; - ruleChainsPage.createRuleChain(name); + ruleChainName = ENTITY_NAME; + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.notRootRuleChainsNames().get(0).click(); @@ -122,7 +139,6 @@ public class RuleChainEditMenuAbstractDiverBaseTest extends AbstractDiverBaseTes ruleChainsPage.editPencilBtn().click(); ruleChainsPage.debugCheckboxEdit().click(); ruleChainsPage.doneBtnEditView().click(); - ruleChainName = name; Assert.assertFalse(Boolean.parseBoolean(ruleChainsPage.debugCheckboxView().getAttribute("aria-checked"))); Assert.assertTrue(debugMode); 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 index 0a8dc6d96b..f39d54cd63 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke; import io.qameta.allure.Description; @@ -5,28 +20,30 @@ 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.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; 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; +import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class SearchRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class SearchRuleChainTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private RuleChainsPageHelperAbstract ruleChainsPage; + private RuleChainsPageHelper ruleChainsPage; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - ruleChainsPage = new RuleChainsPageHelperAbstract(driver); + ruleChainsPage = new RuleChainsPageHelper(driver); } @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "ruleChainNameForSearchByFirstAndSecondWord") - @Description("Can search by the first/second word of the name") + @Description public void searchFirstWord(String namePath) { sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.searchEntity(namePath); @@ -36,16 +53,16 @@ public class SearchRuleChainAbstractDiverBaseTest extends AbstractDiverBaseTest } @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForSearchBySymbolAndNumber") - @Description("Can search by number/symbol") + @Description public void searchNumber(String name, String namePath) { - ruleChainsPage.createRuleChain(name); + testRestClient.postRuleChain(defaultRuleChainPrototype(name)); sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.searchEntity(namePath); ruleChainsPage.setRuleChainName(0); boolean ruleChainContainsNamePath = ruleChainsPage.getRuleChainName().contains(namePath); - ruleChainsPage.deleteRuleChain(name); + testRestClient.deleteRuleChain(getRuleChainByName(name).getId()); 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 index a8f381c494..1a11ed9552 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke; import io.qameta.allure.Description; @@ -6,31 +21,33 @@ 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.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; 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; +import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class SortByNameTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private RuleChainsPageHelperAbstract ruleChainsPage; + private RuleChainsPageHelper ruleChainsPage; private String ruleChainName; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - ruleChainsPage = new RuleChainsPageHelperAbstract(driver); + ruleChainsPage = new RuleChainsPageHelper(driver); } @AfterMethod public void delete() { if (ruleChainName != null) { - ruleChainsPage.deleteRuleChain(ruleChainName); + testRestClient.deleteRuleChain(getRuleChainByName(ruleChainName).getId()); ruleChainName = null; } } @@ -38,7 +55,8 @@ public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForSort") @Description public void specialCharacterUp(String ruleChainName) { - ruleChainsPage.createRuleChain(ruleChainName); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); + ; sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.sortByNameBtn().click(); @@ -51,9 +69,9 @@ public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { @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); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainSymbol)); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChain)); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainNumber)); sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.sortByNameBtn().click(); @@ -68,9 +86,9 @@ public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { boolean secondEquals = secondRuleChain.equals(ruleChainNumber); boolean thirdEquals = thirdRuleChain.equals(ruleChain); - ruleChainsPage.deleteRuleChain(ruleChain); - ruleChainsPage.deleteRuleChain(ruleChainNumber); - ruleChainsPage.deleteRuleChain(ruleChainSymbol); + testRestClient.deleteRuleChain(getRuleChainByName(ruleChain).getId()); + testRestClient.deleteRuleChain(getRuleChainByName(ruleChainNumber).getId()); + testRestClient.deleteRuleChain(getRuleChainByName(ruleChainSymbol).getId()); Assert.assertTrue(firstEquals); Assert.assertTrue(secondEquals); @@ -80,7 +98,7 @@ public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { @Test(priority = 10, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "nameForSort") @Description public void specialCharacterDown(String ruleChainName) { - ruleChainsPage.createRuleChain(ruleChainName); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.sortByNameDown(); @@ -93,9 +111,9 @@ public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { @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); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainSymbol)); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChain)); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainNumber)); sideBarMenuView.ruleChainsBtn().click(); int lastIndex = ruleChainsPage.allNames().size() - 1; @@ -111,9 +129,9 @@ public class SortByNameAbstractDiverBaseTest extends AbstractDiverBaseTest { boolean secondEquals = secondRuleChain.equals(ruleChainNumber); boolean thirdEquals = thirdRuleChain.equals(ruleChain); - ruleChainsPage.deleteRuleChain(ruleChain); - ruleChainsPage.deleteRuleChain(ruleChainNumber); - ruleChainsPage.deleteRuleChain(ruleChainSymbol); + testRestClient.deleteRuleChain(getRuleChainByName(ruleChain).getId()); + testRestClient.deleteRuleChain(getRuleChainByName(ruleChainNumber).getId()); + testRestClient.deleteRuleChain(getRuleChainByName(ruleChainSymbol).getId()); Assert.assertTrue(firstEquals); Assert.assertTrue(secondEquals); 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 index 3fc33e3ac0..d05bd11b39 100644 --- 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 @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.thingsboard.server.msa.ui.tests.ruleChainsSmoke; import io.qameta.allure.Description; @@ -6,31 +21,32 @@ 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.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; 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; +import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class SortByTimeAbstractDiverBaseTest extends AbstractDiverBaseTest { +public class SortByTimeTest extends AbstractDiverBaseTest { private SideBarMenuViewElements sideBarMenuView; - private RuleChainsPageHelperAbstract ruleChainsPage; + private RuleChainsPageHelper ruleChainsPage; private String ruleChainName; @BeforeMethod public void login() { openUrl(URL); - new LoginPageHelperAbstract(driver).authorizationTenant(); + new LoginPageHelper(driver).authorizationTenant(); + testRestClient.login(TENANT_EMAIL, TENANT_PASSWORD); sideBarMenuView = new SideBarMenuViewElements(driver); - ruleChainsPage = new RuleChainsPageHelperAbstract(driver); + ruleChainsPage = new RuleChainsPageHelper(driver); } @AfterMethod public void delete() { if (ruleChainName != null) { - ruleChainsPage.deleteRuleChain(ruleChainName); + testRestClient.deleteRuleChain(getRuleChainByName(ruleChainName).getId()); ruleChainName = null; } } @@ -39,7 +55,7 @@ public class SortByTimeAbstractDiverBaseTest extends AbstractDiverBaseTest { @Description public void sortByTimeDown() { String ruleChain = ENTITY_NAME; - ruleChainsPage.createRuleChain(ruleChain); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChain)); sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.setSort(); @@ -55,7 +71,7 @@ public class SortByTimeAbstractDiverBaseTest extends AbstractDiverBaseTest { @Description public void sortByTimeUp() { String ruleChain = ENTITY_NAME; - ruleChainsPage.createRuleChain(ruleChain); + testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChain)); sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.sortByTimeBtn().click(); 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 index db6bd40084..351423d950 100644 --- 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 @@ -1,8 +1,23 @@ -package utils; +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.ui.utils; -import base.Base; +import static org.thingsboard.server.msa.ui.base.AbstractBasePage.getRandomNumber; -public class Const extends Base { +public class Const { public static final String URL = "http://localhost:8080/"; public static final String TENANT_EMAIL = "tenant@thingsboard.org"; 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 index 1509250abf..5536338fe5 100644 --- 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 @@ -1,9 +1,24 @@ -package utils; +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.ui.utils; import org.testng.annotations.DataProvider; -import static base.Base.getRandomSymbol; -import static utils.Const.ENTITY_NAME; +import static org.thingsboard.server.msa.ui.base.AbstractBasePage.getRandomSymbol; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; public class DataProviderCredential { 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 index 683dca511c..5fcfe8f4f9 100644 --- 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 @@ -1,9 +1,24 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ 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 class EntityPrototypes { public static Customer defaultCustomerPrototype(String entityName){ Customer customer = new Customer(); diff --git a/msa/black-box-tests/src/test/resources/connectivity.xml b/msa/black-box-tests/src/test/resources/connectivity.xml index e69de29bb2..c2c12c4efb 100644 --- a/msa/black-box-tests/src/test/resources/connectivity.xml +++ b/msa/black-box-tests/src/test/resources/connectivity.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/msa/black-box-tests/src/test/resources/forImport.txt b/msa/black-box-tests/src/test/resources/forImport.txt index e69de29bb2..908a557812 100644 --- a/msa/black-box-tests/src/test/resources/forImport.txt +++ b/msa/black-box-tests/src/test/resources/forImport.txt @@ -0,0 +1,16 @@ +==== + Copyright © 2016-2022 The Thingsboard Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==== + diff --git a/msa/black-box-tests/src/test/resources/smokeTests.xml b/msa/black-box-tests/src/test/resources/smokeTests.xml index 1194791760..85080e2bfd 100644 --- a/msa/black-box-tests/src/test/resources/smokeTests.xml +++ b/msa/black-box-tests/src/test/resources/smokeTests.xml @@ -1,7 +1,7 @@ - - - - - - + + + + \ No newline at end of file diff --git a/msa/pom.xml b/msa/pom.xml index e527566683..8bc033fcbc 100644 --- a/msa/pom.xml +++ b/msa/pom.xml @@ -46,6 +46,8 @@ web-ui tb-node transport + black-box-tests + From 17d6522571aab7d997f3a9b6554ad37b15324bbb Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Tue, 22 Nov 2022 13:24:23 +0200 Subject: [PATCH 03/66] add ui tests --- msa/pom.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/msa/pom.xml b/msa/pom.xml index 8bc033fcbc..e527566683 100644 --- a/msa/pom.xml +++ b/msa/pom.xml @@ -46,8 +46,6 @@ web-ui tb-node transport - black-box-tests - From f3e927e9c5abfe300b3f7bdf28ccebe37988fa13 Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Tue, 22 Nov 2022 18:12:19 +0200 Subject: [PATCH 04/66] updated README.md --- msa/black-box-tests/README.md | 7 ++++++- msa/black-box-tests/src/test/resources/testNG.xml | 10 ++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/msa/black-box-tests/README.md b/msa/black-box-tests/README.md index a60e7405a8..856bd08f4a 100644 --- a/msa/black-box-tests/README.md +++ b/msa/black-box-tests/README.md @@ -30,9 +30,14 @@ As result, in REPOSITORY column, next images should be present: mvn clean install -DblackBoxTests.skip=false -DblackBoxTests.hybridMode=true -To run the black box tests with using local env run tests in the [msa/black-box-tests](../black-box-tests) directory with runLocal property: +- To run the black box tests with using local env run tests in the [msa/black-box-tests](../black-box-tests) directory with runLocal property: mvn clean install -DblackBoxTests.skip=false -DrunLocal=true +- To run ui tests run tests in the [msa/black-box-tests](../black-box-tests) directory specifying suiteFile property: + + mvn clean install -DblackBoxTests.skip=false -DsuiteFile=src/test/resources/smokeTests.xml + + diff --git a/msa/black-box-tests/src/test/resources/testNG.xml b/msa/black-box-tests/src/test/resources/testNG.xml index f94bc7485c..45e93f76f1 100644 --- a/msa/black-box-tests/src/test/resources/testNG.xml +++ b/msa/black-box-tests/src/test/resources/testNG.xml @@ -17,9 +17,11 @@ --> + - - - - + + + + + \ No newline at end of file From ca4ae89367f006a1775487a599575a6410d7daac Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Thu, 24 Nov 2022 17:21:22 +0200 Subject: [PATCH 05/66] add chrome options for run in https --- msa/black-box-tests/README.md | 2 +- msa/black-box-tests/pom.xml | 18 +++++----------- .../msa/ui/base/AbstractDiverBaseTest.java | 5 ++++- .../server/msa/ui/utils/Const.java | 3 ++- pom.xml | 21 +++++++++++++++++++ 5 files changed, 33 insertions(+), 16 deletions(-) diff --git a/msa/black-box-tests/README.md b/msa/black-box-tests/README.md index 856bd08f4a..c91e1203fb 100644 --- a/msa/black-box-tests/README.md +++ b/msa/black-box-tests/README.md @@ -34,7 +34,7 @@ As result, in REPOSITORY column, next images should be present: mvn clean install -DblackBoxTests.skip=false -DrunLocal=true -- To run ui tests run tests in the [msa/black-box-tests](../black-box-tests) directory specifying suiteFile property: +- To run ui smoke tests in the [msa/black-box-tests](../black-box-tests) directory specifying suiteFile property: mvn clean install -DblackBoxTests.skip=false -DsuiteFile=src/test/resources/smokeTests.xml diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index c6952f05ba..f99fb21343 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -34,6 +34,7 @@ UTF-8 ${basedir}/../.. + src/test/resources/testNG.xml @@ -163,28 +164,19 @@ org.seleniumhq.selenium selenium-java - 4.5.3 + test io.github.bonigarcia webdrivermanager - 5.3.0 + test io.qameta.allure allure-testng - 2.19.0 + test - - - - com.google.guava - guava - 31.0.1-jre - - - @@ -192,7 +184,7 @@ maven-surefire-plugin - src/test/resources/testNG.xml + ${suiteFile} ${blackBoxTests.skip} 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 index 4079ec264c..438443cfde 100644 --- 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 @@ -56,14 +56,17 @@ abstract public class AbstractDiverBaseTest extends AbstractContainerTest { log.info("*----------------------* Setup driver *----------------------*"); if (HEADLESS == true) { ChromeOptions options = new ChromeOptions(); + options.addArguments("--ignore-certificate-errors"); options.addArguments("--no-sandbox"); options.addArguments("--disable-dev-shm-usage"); options.addArguments("--headless"); WebDriverManager.chromedriver().setup(); driver = new ChromeDriver(options); } else { + ChromeOptions options = new ChromeOptions(); + options.addArguments("--ignore-certificate-errors"); WebDriverManager.chromedriver().setup(); - driver = new ChromeDriver(); + driver = new ChromeDriver(options); } driver.manage().window().setSize(dimension); } 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 index 351423d950..8868d53768 100644 --- 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 @@ -15,11 +15,12 @@ */ package org.thingsboard.server.msa.ui.utils; +import static org.thingsboard.server.msa.TestProperties.getBaseUrl; import static org.thingsboard.server.msa.ui.base.AbstractBasePage.getRandomNumber; public class Const { - public static final String URL = "http://localhost:8080/"; + public static final String URL = getBaseUrl(); public static final String TENANT_EMAIL = "tenant@thingsboard.org"; public static final String TENANT_PASSWORD = "tenant"; public static final String ENTITY_NAME = "Az!@#$%^&*()_-+=~`" + getRandomNumber(); diff --git a/pom.xml b/pom.xml index 411e9be7cc..c23e4cf661 100755 --- a/pom.xml +++ b/pom.xml @@ -144,6 +144,9 @@ 6.1.0.202203080745-r 0.4.8 1.0.0 + 4.1.1 + 5.3.0 + 2.19.0 @@ -1656,6 +1659,24 @@ ${rest-assured.version} test + + org.seleniumhq.selenium + selenium-java + ${selenium.version} + test + + + io.github.bonigarcia + webdrivermanager + ${webdrivermanager.version} + test + + + io.qameta.allure + allure-testng + ${allure-testng.version} + test + org.hamcrest hamcrest-all From b02f6bc9b35ba481d90966d5d56ff8f9c7b15b99 Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Mon, 28 Nov 2022 12:52:12 +0200 Subject: [PATCH 06/66] remove imports with '*' --- .../msa/ui/tests/customerSmoke/CreateCustomerTest.java | 7 ++++++- .../msa/ui/tests/customerSmoke/CustomerEditMenuTest.java | 7 ++++++- .../msa/ui/tests/customerSmoke/DeleteCustomerTest.java | 5 ++++- .../ui/tests/customerSmoke/DeleteSeveralCustomerTest.java | 5 ++++- .../msa/ui/tests/customerSmoke/SearchCustomerTest.java | 4 +++- .../server/msa/ui/tests/customerSmoke/SortByNameTest.java | 4 +++- .../tests/ruleChainsSmoke/CreateRuleChainImportTest.java | 8 +++++++- .../msa/ui/tests/ruleChainsSmoke/CreateRuleChainTest.java | 6 +++++- .../msa/ui/tests/ruleChainsSmoke/DeleteRuleChainTest.java | 7 ++++++- .../ruleChainsSmoke/DeleteSeveralRuleChainsTest.java | 6 +++++- .../ui/tests/ruleChainsSmoke/MakeRuleChainRootTest.java | 4 +++- .../msa/ui/tests/ruleChainsSmoke/OpenRuleChainTest.java | 4 +++- .../ui/tests/ruleChainsSmoke/RuleChainEditMenuTest.java | 7 +++++-- .../msa/ui/tests/ruleChainsSmoke/SearchRuleChainTest.java | 4 +++- .../msa/ui/tests/ruleChainsSmoke/SortByNameTest.java | 4 +++- .../msa/ui/tests/ruleChainsSmoke/SortByTimeTest.java | 5 ++++- 16 files changed, 70 insertions(+), 17 deletions(-) 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 index 9a604416d9..a8f2a34659 100644 --- 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 @@ -25,7 +25,12 @@ import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; -import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.Const.EMPTY_CUSTOMER_MESSAGE; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.SAME_NAME_WARNING_CUSTOMER_MESSAGE; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; public class CreateCustomerTest extends AbstractDiverBaseTest { 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 index 2bfd157773..289a8d02df 100644 --- 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 @@ -28,7 +28,12 @@ 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.*; +import static org.thingsboard.server.msa.ui.utils.Const.EMPTY_CUSTOMER_MESSAGE; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.PHONE_NUMBER_ERROR_MESSAGE; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; public class CustomerEditMenuTest extends AbstractDiverBaseTest { 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 index 27e8605926..5fb851216d 100644 --- 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 @@ -25,7 +25,10 @@ import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; -import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; public class DeleteCustomerTest extends AbstractDiverBaseTest { 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 index 138c563631..7afdbf7daa 100644 --- 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 @@ -24,7 +24,10 @@ import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; -import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; public class DeleteSeveralCustomerTest extends AbstractDiverBaseTest { 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 index 97a4c6f85f..9d21d65a4f 100644 --- 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 @@ -25,7 +25,9 @@ import org.thingsboard.server.msa.ui.pages.LoginPageHelper; 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.*; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; public class SearchCustomerTest extends AbstractDiverBaseTest { 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 index 3a71ca5ddb..5a08561e5b 100644 --- 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 @@ -26,7 +26,9 @@ import org.thingsboard.server.msa.ui.pages.LoginPageHelper; 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.*; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; public class SortByNameTest extends AbstractDiverBaseTest { 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 index a027267469..71f3e01f88 100644 --- 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 @@ -28,7 +28,13 @@ import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import java.util.ArrayList; -import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.Const.EMPTY_IMPORT_MESSAGE; +import static org.thingsboard.server.msa.ui.utils.Const.IMPORT_RULE_CHAIN_FILE_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.IMPORT_RULE_CHAIN_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.IMPORT_TXT_FILE_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; public class CreateRuleChainImportTest extends AbstractDiverBaseTest { 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 index d3d71a45b0..716934a3a4 100644 --- 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 @@ -28,7 +28,11 @@ import org.thingsboard.server.msa.ui.utils.EntityPrototypes; import java.util.ArrayList; -import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.Const.EMPTY_RULE_CHAIN_MESSAGE; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; public class CreateRuleChainTest extends AbstractDiverBaseTest { 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 index 92da98af1b..8a8c40d64d 100644 --- 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 @@ -24,7 +24,12 @@ import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; -import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.Const.DELETE_RULE_CHAIN_WITH_PROFILE_MESSAGE; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.ROOT_RULE_CHAIN_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; public class DeleteRuleChainTest extends AbstractDiverBaseTest { 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 index 5b8667580e..9d4be40ec0 100644 --- 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 @@ -24,7 +24,11 @@ import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; -import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.ROOT_RULE_CHAIN_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; public class DeleteSeveralRuleChainsTest extends AbstractDiverBaseTest { 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 index 7eb75de8f8..a0d2a3ac9f 100644 --- 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 @@ -25,7 +25,9 @@ import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; -import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; public class MakeRuleChainRootTest extends AbstractDiverBaseTest { 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 index 7810c7bf5a..9e63bc95f0 100644 --- 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 @@ -25,7 +25,9 @@ import org.thingsboard.server.msa.ui.pages.OpenRuleChainPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; -import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; public class OpenRuleChainTest extends AbstractDiverBaseTest { 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 index 12e442c3b0..84812f31ea 100644 --- 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 @@ -25,7 +25,11 @@ import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; -import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.Const.EMPTY_RULE_CHAIN_MESSAGE; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; public class RuleChainEditMenuTest extends AbstractDiverBaseTest { @@ -55,7 +59,6 @@ public class RuleChainEditMenuTest extends AbstractDiverBaseTest { @Description public void changeName() { testRestClient.postRuleChain(defaultRuleChainPrototype(ENTITY_NAME)); - ; String name = "Changed"; sideBarMenuView.ruleChainsBtn().click(); 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 index f39d54cd63..a214ee2396 100644 --- 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 @@ -25,7 +25,9 @@ import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; 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.*; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; public class SearchRuleChainTest extends AbstractDiverBaseTest { 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 index 1a11ed9552..fa2bf82a32 100644 --- 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 @@ -26,7 +26,9 @@ import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; 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.*; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; public class SortByNameTest extends AbstractDiverBaseTest { 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 index d05bd11b39..3d3d0f572b 100644 --- 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 @@ -25,7 +25,10 @@ import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; -import static org.thingsboard.server.msa.ui.utils.Const.*; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; +import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; +import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; public class SortByTimeTest extends AbstractDiverBaseTest { From de4cc224a6f0ca11ec6eabc6b898376a44e22f54 Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Tue, 29 Nov 2022 16:12:12 +0200 Subject: [PATCH 07/66] add suite for all tests --- msa/black-box-tests/README.md | 8 ++++-- msa/black-box-tests/pom.xml | 4 +-- .../msa/ui/pages/CustomerPageElements.java | 5 ++++ .../customerSmoke/CustomerEditMenuTest.java | 1 - .../customerSmoke/DeleteCustomerTest.java | 7 ++--- .../CreateRuleChainImportTest.java | 3 +-- .../src/test/resources/all.xml | 26 +++++++++++++++++++ .../resources/{testNG.xml => blackBox.xml} | 0 .../resources/{smokeTests.xml => uiTests.xml} | 2 +- 9 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 msa/black-box-tests/src/test/resources/all.xml rename msa/black-box-tests/src/test/resources/{testNG.xml => blackBox.xml} (100%) rename msa/black-box-tests/src/test/resources/{smokeTests.xml => uiTests.xml} (95%) diff --git a/msa/black-box-tests/README.md b/msa/black-box-tests/README.md index c91e1203fb..a4bbe48961 100644 --- a/msa/black-box-tests/README.md +++ b/msa/black-box-tests/README.md @@ -34,9 +34,13 @@ As result, in REPOSITORY column, next images should be present: mvn clean install -DblackBoxTests.skip=false -DrunLocal=true -- To run ui smoke tests in the [msa/black-box-tests](../black-box-tests) directory specifying suiteFile property: +- To run ui smoke tests in the [msa/black-box-tests](../black-box-tests) directory specifying suite name: - mvn clean install -DblackBoxTests.skip=false -DsuiteFile=src/test/resources/smokeTests.xml + mvn clean install -DblackBoxTests.skip=false -Dsuite=uiTests + +- To run all tests in the [msa/black-box-tests](../black-box-tests) directory specifying suite name: + + mvn clean install -DblackBoxTests.skip=false -Dsuite=all diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index f99fb21343..380f9abbaa 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -34,7 +34,7 @@ UTF-8 ${basedir}/../.. - src/test/resources/testNG.xml + blackBox @@ -184,7 +184,7 @@ maven-surefire-plugin - ${suiteFile} + src/test/resources/${suite}.xml ${blackBoxTests.skip} 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 index e10fb7d1ed..05da22e4db 100644 --- 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 @@ -70,6 +70,7 @@ public class CustomerPageElements extends OtherPageElementsHelper { 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 "; + private static final String DELETE_FROM_VIEW_BTN = "//tb-customer//span[contains(text(),' Delete')]"; public WebElement titleFieldAddEntityView() { return waitUntilElementToBeClickable(ADD_ENTITY_VIEW + String.format(INPUT_FIELD, INPUT_FIELD_NAME_TITLE)); @@ -274,4 +275,8 @@ public class CustomerPageElements extends OtherPageElementsHelper { public WebElement manageCustomersEdgeBtnView() { return waitUntilElementToBeClickable(String.format(MANAGE_BTN_VIEW, MANAGE_CUSTOMERS_EDGE_BTN_VIEW)); } + + public WebElement customerViewDeleteBtn() { + return waitUntilElementToBeClickable(DELETE_FROM_VIEW_BTN); + } } 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 index 289a8d02df..582a2f797f 100644 --- 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 @@ -256,7 +256,6 @@ public class CustomerEditMenuTest extends AbstractDiverBaseTest { public void addAllInformation() { customerName = ENTITY_NAME; testRestClient.postCustomer(defaultCustomerPrototype(customerName)); - ; String text = "Text"; String email = "email@mail.com"; String number = "2015550123"; 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 index 5fb851216d..d801b58638 100644 --- 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 @@ -81,10 +81,11 @@ public class DeleteCustomerTest extends AbstractDiverBaseTest { sideBarMenuView.customerBtn().click(); customerPage.entity(customerName).click(); - String deletedCustomer = ruleChainsPage.deleteRuleChainFromView(customerName); - ruleChainsPage.refreshBtn().click(); + customerPage.customerViewDeleteBtn().click(); + customerPage.warningPopUpYesBtn().click(); + customerPage.refreshBtn().click(); - Assert.assertTrue(ruleChainsPage.entityIsNotPresent(deletedCustomer)); + Assert.assertTrue(customerPage.entityIsNotPresent(customerName)); } @Test(priority = 20, groups = "smoke") 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 index 71f3e01f88..cff351387e 100644 --- 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 @@ -101,6 +101,7 @@ public class CreateRuleChainImportTest extends AbstractDiverBaseTest { @Test(priority = 30, groups = "smoke") @Description public void importRuleChainAndSave() { + ruleChainName = IMPORT_RULE_CHAIN_NAME; sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.openImportRuleChainView(); ruleChainsPage.browseFile().sendKeys(absolutePathToFileImportRuleChain); @@ -108,7 +109,6 @@ public class CreateRuleChainImportTest extends AbstractDiverBaseTest { 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()); @@ -119,7 +119,6 @@ public class CreateRuleChainImportTest extends AbstractDiverBaseTest { public void importRuleChainAndSaveWithSameName() { ruleChainName = IMPORT_RULE_CHAIN_NAME; testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); - ; sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.openImportRuleChainView(); diff --git a/msa/black-box-tests/src/test/resources/all.xml b/msa/black-box-tests/src/test/resources/all.xml new file mode 100644 index 0000000000..3a35ec5c16 --- /dev/null +++ b/msa/black-box-tests/src/test/resources/all.xml @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file diff --git a/msa/black-box-tests/src/test/resources/testNG.xml b/msa/black-box-tests/src/test/resources/blackBox.xml similarity index 100% rename from msa/black-box-tests/src/test/resources/testNG.xml rename to msa/black-box-tests/src/test/resources/blackBox.xml diff --git a/msa/black-box-tests/src/test/resources/smokeTests.xml b/msa/black-box-tests/src/test/resources/uiTests.xml similarity index 95% rename from msa/black-box-tests/src/test/resources/smokeTests.xml rename to msa/black-box-tests/src/test/resources/uiTests.xml index 85080e2bfd..73754c8381 100644 --- a/msa/black-box-tests/src/test/resources/smokeTests.xml +++ b/msa/black-box-tests/src/test/resources/uiTests.xml @@ -18,7 +18,7 @@ --> - + From 473cfd7462cda9212510dcd547b35048abe656bd Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Tue, 29 Nov 2022 16:15:54 +0200 Subject: [PATCH 08/66] headless mode = true --- .../thingsboard/server/msa/ui/base/AbstractDiverBaseTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 438443cfde..204794b340 100644 --- 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 @@ -47,7 +47,7 @@ abstract public class AbstractDiverBaseTest extends AbstractContainerTest { 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; + private static final boolean HEADLESS = true; protected static final PageLink pageLink = new PageLink(10); From 373db7a0864db65acaab34005ecbd097b1a6b4e7 Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Tue, 29 Nov 2022 16:39:42 +0200 Subject: [PATCH 09/66] rename base ui test class --- ...tDiverBaseTest.java => AbstractDriverBaseTest.java} | 2 +- .../server/msa/ui/listeners/TestListener.java | 10 +++++----- .../msa/ui/tests/customerSmoke/CreateCustomerTest.java | 4 ++-- .../ui/tests/customerSmoke/CustomerEditMenuTest.java | 4 ++-- .../msa/ui/tests/customerSmoke/DeleteCustomerTest.java | 4 ++-- .../tests/customerSmoke/DeleteSeveralCustomerTest.java | 4 ++-- .../tests/customerSmoke/ManageCustomersAssetsTest.java | 4 ++-- .../customerSmoke/ManageCustomersDashboardsTest.java | 4 ++-- .../customerSmoke/ManageCustomersDevicesTest.java | 4 ++-- .../tests/customerSmoke/ManageCustomersEdgesTest.java | 4 ++-- .../tests/customerSmoke/ManageCustomersUsersTest.java | 4 ++-- .../msa/ui/tests/customerSmoke/SearchCustomerTest.java | 4 ++-- .../msa/ui/tests/customerSmoke/SortByNameTest.java | 4 ++-- .../ruleChainsSmoke/CreateRuleChainImportTest.java | 4 ++-- .../ui/tests/ruleChainsSmoke/CreateRuleChainTest.java | 4 ++-- .../ui/tests/ruleChainsSmoke/DeleteRuleChainTest.java | 4 ++-- .../ruleChainsSmoke/DeleteSeveralRuleChainsTest.java | 4 ++-- .../tests/ruleChainsSmoke/MakeRuleChainRootTest.java | 4 ++-- .../ui/tests/ruleChainsSmoke/OpenRuleChainTest.java | 4 ++-- .../tests/ruleChainsSmoke/RuleChainEditMenuTest.java | 4 ++-- .../ui/tests/ruleChainsSmoke/SearchRuleChainTest.java | 4 ++-- .../msa/ui/tests/ruleChainsSmoke/SortByNameTest.java | 4 ++-- .../msa/ui/tests/ruleChainsSmoke/SortByTimeTest.java | 4 ++-- 23 files changed, 48 insertions(+), 48 deletions(-) rename msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/{AbstractDiverBaseTest.java => AbstractDriverBaseTest.java} (98%) 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/AbstractDriverBaseTest.java similarity index 98% rename from msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDiverBaseTest.java rename to msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java index 204794b340..4cb557d394 100644 --- 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/AbstractDriverBaseTest.java @@ -41,7 +41,7 @@ import java.util.stream.Collectors; @Slf4j @Listeners(TestListener.class) -abstract public class AbstractDiverBaseTest extends AbstractContainerTest { +abstract public class AbstractDriverBaseTest extends AbstractContainerTest { protected WebDriver driver; private final Dimension dimension = new Dimension(WIDTH, HEIGHT); 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 index 90ae18bec4..56b15efd67 100644 --- 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 @@ -22,9 +22,9 @@ import org.openqa.selenium.WebDriver; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestResult; -import org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest; +import org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest; -import static org.thingsboard.server.msa.ui.base.AbstractDiverBaseTest.captureScreen; +import static org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest.captureScreen; @Slf4j public class TestListener implements ITestListener { @@ -37,7 +37,7 @@ public class TestListener implements ITestListener { Allure.getLifecycle().updateTestCase((t) -> { t.setStatusDetails(t.getStatusDetails().setMessage(str)); }); - driver = ((AbstractDiverBaseTest) tr.getInstance()).getDriver(); + driver = ((AbstractDriverBaseTest) tr.getInstance()).getDriver(); captureScreen(driver, "success"); } @@ -50,7 +50,7 @@ public class TestListener implements ITestListener { t.setStatusDetails(t.getStatusDetails().setMessage(str)); t.setStatusDetails(t.getStatusDetails().setMessage(str1)); }); - driver = ((AbstractDiverBaseTest) tr.getInstance()).getDriver(); + driver = ((AbstractDriverBaseTest) tr.getInstance()).getDriver(); captureScreen(driver, "failure"); } @@ -63,7 +63,7 @@ public class TestListener implements ITestListener { t.setStatusDetails(t.getStatusDetails().setMessage(str)); t.setStatusDetails(t.getStatusDetails().setMessage(str1)); }); - driver = ((AbstractDiverBaseTest) tr.getInstance()).getDriver(); + driver = ((AbstractDriverBaseTest) tr.getInstance()).getDriver(); captureScreen(driver, "skipped"); } 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 index a8f2a34659..bef792b8d0 100644 --- 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 @@ -20,7 +20,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; @@ -32,7 +32,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class CreateCustomerTest extends AbstractDiverBaseTest { +public class CreateCustomerTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private CustomerPageHelper customerPage; 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 index 582a2f797f..cd4c81b4bc 100644 --- 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 @@ -20,7 +20,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; import org.thingsboard.server.msa.ui.pages.DashboardPageHelper; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; @@ -36,7 +36,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; -public class CustomerEditMenuTest extends AbstractDiverBaseTest { +public class CustomerEditMenuTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private CustomerPageHelper customerPage; 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 index d801b58638..66cf328552 100644 --- 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 @@ -19,7 +19,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; @@ -31,7 +31,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; -public class DeleteCustomerTest extends AbstractDiverBaseTest { +public class DeleteCustomerTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private CustomerPageHelper customerPage; 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 index 7afdbf7daa..e1c839a347 100644 --- 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 @@ -19,7 +19,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; @@ -30,7 +30,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; -public class DeleteSeveralCustomerTest extends AbstractDiverBaseTest { +public class DeleteSeveralCustomerTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private CustomerPageHelper customerPage; 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 index 7b85771c23..5fcafc6514 100644 --- 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 @@ -19,14 +19,14 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class ManageCustomersAssetsTest extends AbstractDiverBaseTest { +public class ManageCustomersAssetsTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private CustomerPageHelper customerPage; 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 index 9ac2986fd0..2328298bc8 100644 --- 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 @@ -19,14 +19,14 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class ManageCustomersDashboardsTest extends AbstractDiverBaseTest { +public class ManageCustomersDashboardsTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private CustomerPageHelper customerPage; private final String manage = "Dashboards"; 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 index 30b451899e..df04e2ad8d 100644 --- 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 @@ -19,14 +19,14 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class ManageCustomersDevicesTest extends AbstractDiverBaseTest { +public class ManageCustomersDevicesTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private CustomerPageHelper customerPage; private final String manage = "Devices"; 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 index 044f809f77..a005760952 100644 --- 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 @@ -19,14 +19,14 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class ManageCustomersEdgesTest extends AbstractDiverBaseTest { +public class ManageCustomersEdgesTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private CustomerPageHelper customerPage; 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 index 42d03bda1e..b0a917135a 100644 --- 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 @@ -19,14 +19,14 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class ManageCustomersUsersTest extends AbstractDiverBaseTest { +public class ManageCustomersUsersTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private CustomerPageHelper customerPage; 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 index 9d21d65a4f..71fbae1477 100644 --- 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 @@ -19,7 +19,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; @@ -30,7 +30,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; -public class SearchCustomerTest extends AbstractDiverBaseTest { +public class SearchCustomerTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private CustomerPageHelper customerPage; 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 index 5a08561e5b..48c1a4dc5c 100644 --- 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 @@ -20,7 +20,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; @@ -31,7 +31,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultCustomerPrototype; -public class SortByNameTest extends AbstractDiverBaseTest { +public class SortByNameTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private CustomerPageHelper customerPage; private String customerName; 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 index cff351387e..dd986e0798 100644 --- 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 @@ -20,7 +20,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.OpenRuleChainPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; @@ -37,7 +37,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class CreateRuleChainImportTest extends AbstractDiverBaseTest { +public class CreateRuleChainImportTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private RuleChainsPageHelper ruleChainsPage; private OpenRuleChainPageHelper openRuleChainPage; 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 index 716934a3a4..b29a911e5a 100644 --- 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 @@ -20,7 +20,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; @@ -34,7 +34,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class CreateRuleChainTest extends AbstractDiverBaseTest { +public class CreateRuleChainTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private RuleChainsPageHelper ruleChainsPage; 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 index 8a8c40d64d..3f55a7a4cb 100644 --- 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 @@ -19,7 +19,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; @@ -32,7 +32,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class DeleteRuleChainTest extends AbstractDiverBaseTest { +public class DeleteRuleChainTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private RuleChainsPageHelper ruleChainsPage; 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 index 9d4be40ec0..bfcea53ccc 100644 --- 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 @@ -19,7 +19,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; @@ -31,7 +31,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class DeleteSeveralRuleChainsTest extends AbstractDiverBaseTest { +public class DeleteSeveralRuleChainsTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private RuleChainsPageHelper ruleChainsPage; 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 index a0d2a3ac9f..9cd9bbb846 100644 --- 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 @@ -20,7 +20,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; @@ -29,7 +29,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class MakeRuleChainRootTest extends AbstractDiverBaseTest { +public class MakeRuleChainRootTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private RuleChainsPageHelper ruleChainsPage; 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 index 9e63bc95f0..4f6a2f8a1c 100644 --- 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 @@ -19,7 +19,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.OpenRuleChainPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; @@ -29,7 +29,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; -public class OpenRuleChainTest extends AbstractDiverBaseTest { +public class OpenRuleChainTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private RuleChainsPageHelper ruleChainsPage; 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 index 84812f31ea..a0dd8f2b4b 100644 --- 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 @@ -20,7 +20,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; @@ -32,7 +32,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class RuleChainEditMenuTest extends AbstractDiverBaseTest { +public class RuleChainEditMenuTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private RuleChainsPageHelper ruleChainsPage; 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 index a214ee2396..d6cf13c21d 100644 --- 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 @@ -19,7 +19,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; @@ -30,7 +30,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class SearchRuleChainTest extends AbstractDiverBaseTest { +public class SearchRuleChainTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private RuleChainsPageHelper ruleChainsPage; 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 index fa2bf82a32..4de0244044 100644 --- 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 @@ -20,7 +20,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; @@ -31,7 +31,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class SortByNameTest extends AbstractDiverBaseTest { +public class SortByNameTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private RuleChainsPageHelper ruleChainsPage; 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 index 3d3d0f572b..ecba81f563 100644 --- 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 @@ -20,7 +20,7 @@ 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.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; @@ -31,7 +31,7 @@ import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; import static org.thingsboard.server.msa.ui.utils.EntityPrototypes.defaultRuleChainPrototype; -public class SortByTimeTest extends AbstractDiverBaseTest { +public class SortByTimeTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private RuleChainsPageHelper ruleChainsPage; From ea0d0418347c23db9d591da7a697592b548bec1a Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Tue, 29 Nov 2022 23:34:14 +0200 Subject: [PATCH 10/66] change webdrivermanager version --- .../server/msa/ui/tests/ruleChainsSmoke/OpenRuleChainTest.java | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 index 4f6a2f8a1c..2f0242c4fd 100644 --- 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 @@ -84,6 +84,6 @@ public class OpenRuleChainTest extends AbstractDriverBaseTest { String ruleChain = ruleChainsPage.getRuleChainName(); ruleChainsPage.doubleClickOnRuleChain(ruleChain); - Assert.assertEquals(getUrl(), URL + "ruleChains"); + Assert.assertEquals(getUrl(), URL + "/ruleChains"); } } diff --git a/pom.xml b/pom.xml index c23e4cf661..49f0742bc4 100755 --- a/pom.xml +++ b/pom.xml @@ -145,7 +145,7 @@ 0.4.8 1.0.0 4.1.1 - 5.3.0 + 5.2.0 2.19.0 From 9bcbfb3bd5a2b637f1345d741a0149fb5e156ffa Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Wed, 30 Nov 2022 12:05:44 +0200 Subject: [PATCH 11/66] add screenshot if headless false --- .../msa/ui/base/AbstractDriverBaseTest.java | 7 +++-- .../server/msa/ui/listeners/TestListener.java | 29 ++++++++----------- .../tests/ruleChainsSmoke/SortByNameTest.java | 1 - 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java index 4cb557d394..b17b1ad95b 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java @@ -54,18 +54,17 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { @BeforeMethod public void openBrowser() { log.info("*----------------------* Setup driver *----------------------*"); + WebDriverManager.chromedriver().driverVersion("100.0.04896.20").setup(); if (HEADLESS == true) { ChromeOptions options = new ChromeOptions(); options.addArguments("--ignore-certificate-errors"); options.addArguments("--no-sandbox"); options.addArguments("--disable-dev-shm-usage"); options.addArguments("--headless"); - WebDriverManager.chromedriver().setup(); driver = new ChromeDriver(options); } else { ChromeOptions options = new ChromeOptions(); options.addArguments("--ignore-certificate-errors"); - WebDriverManager.chromedriver().setup(); driver = new ChromeDriver(options); } driver.manage().window().setSize(dimension); @@ -89,6 +88,10 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { return driver; } + public boolean getHeadless() { + return HEADLESS; + } + protected boolean urlContains(String urlPath) { WebDriverWait wait = new WebDriverWait(driver, Duration.ofMillis(5000)); try { 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 index 56b15efd67..737022a096 100644 --- 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 @@ -34,11 +34,10 @@ public class TestListener implements ITestListener { 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 = ((AbstractDriverBaseTest) tr.getInstance()).getDriver(); - captureScreen(driver, "success"); + if (!((AbstractDriverBaseTest) tr.getInstance()).getHeadless()) { + driver = ((AbstractDriverBaseTest) tr.getInstance()).getDriver(); + captureScreen(driver, "success"); + } } public void onTestFailure(ITestResult tr) { @@ -46,12 +45,10 @@ public class TestListener implements ITestListener { 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 = ((AbstractDriverBaseTest) tr.getInstance()).getDriver(); - captureScreen(driver, "failure"); + if (!((AbstractDriverBaseTest) tr.getInstance()).getHeadless()) { + driver = ((AbstractDriverBaseTest) tr.getInstance()).getDriver(); + captureScreen(driver, "failure"); + } } public void onTestSkipped(ITestResult tr) { @@ -59,12 +56,10 @@ public class TestListener implements ITestListener { 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 = ((AbstractDriverBaseTest) tr.getInstance()).getDriver(); - captureScreen(driver, "skipped"); + if (!((AbstractDriverBaseTest) tr.getInstance()).getHeadless()) { + driver = ((AbstractDriverBaseTest) tr.getInstance()).getDriver(); + captureScreen(driver, "skipped"); + } } public void onStart(ITestContext testContext) { 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 index 4de0244044..df97ffb934 100644 --- 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 @@ -58,7 +58,6 @@ public class SortByNameTest extends AbstractDriverBaseTest { @Description public void specialCharacterUp(String ruleChainName) { testRestClient.postRuleChain(defaultRuleChainPrototype(ruleChainName)); - ; sideBarMenuView.ruleChainsBtn().click(); ruleChainsPage.sortByNameBtn().click(); From ddebab5059553a2c9580ec8a5038951acec19dcf Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Wed, 30 Nov 2022 14:13:42 +0200 Subject: [PATCH 12/66] fix open rule chain tests --- .../msa/ui/base/AbstractDriverBaseTest.java | 2 +- .../ruleChainsSmoke/OpenRuleChainTest.java | 34 +++++++++++++------ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java index b17b1ad95b..315f482751 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java @@ -54,7 +54,7 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { @BeforeMethod public void openBrowser() { log.info("*----------------------* Setup driver *----------------------*"); - WebDriverManager.chromedriver().driverVersion("100.0.04896.20").setup(); + WebDriverManager.chromedriver().setup(); if (HEADLESS == true) { ChromeOptions options = new ChromeOptions(); options.addArguments("--ignore-certificate-errors"); 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 index 2f0242c4fd..6cd70c2b82 100644 --- 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 @@ -17,6 +17,7 @@ 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.AbstractDriverBaseTest; @@ -24,7 +25,9 @@ import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.OpenRuleChainPageHelper; import org.thingsboard.server.msa.ui.pages.RuleChainsPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewElements; +import org.thingsboard.server.msa.ui.utils.EntityPrototypes; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; import static org.thingsboard.server.msa.ui.utils.Const.TENANT_EMAIL; import static org.thingsboard.server.msa.ui.utils.Const.TENANT_PASSWORD; import static org.thingsboard.server.msa.ui.utils.Const.URL; @@ -34,6 +37,7 @@ public class OpenRuleChainTest extends AbstractDriverBaseTest { private SideBarMenuViewElements sideBarMenuView; private RuleChainsPageHelper ruleChainsPage; private OpenRuleChainPageHelper openRuleChainPage; + private String ruleChainName; @BeforeMethod public void login() { @@ -45,35 +49,45 @@ public class OpenRuleChainTest extends AbstractDriverBaseTest { openRuleChainPage = new OpenRuleChainPageHelper(driver); } + @AfterMethod + public void delete(){ + if (ruleChainName != null) { + testRestClient.deleteRuleChain(getRuleChainByName(ruleChainName).getId()); + ruleChainName = null; + } + } + @Test(priority = 10, groups = "smoke") @Description public void openRuleChainByRightCornerBtn() { + ruleChainName = ENTITY_NAME; + testRestClient.postRuleChain(EntityPrototypes.defaultRuleChainPrototype(ENTITY_NAME)); + sideBarMenuView.ruleChainsBtn().click(); - ruleChainsPage.setRuleChainNameWithoutRoot(0); - String ruleChain = ruleChainsPage.getRuleChainName(); - ruleChainsPage.openRuleChainBtn(ruleChain).click(); + ruleChainsPage.openRuleChainBtn(ruleChainName).click(); openRuleChainPage.setHeadName(); - Assert.assertTrue(urlContains(String.valueOf(getRuleChainByName(ruleChainsPage.getRuleChainName()).getId()))); + Assert.assertTrue(urlContains(String.valueOf(getRuleChainByName(ruleChainName).getId()))); Assert.assertTrue(openRuleChainPage.headRuleChainName().isDisplayed()); Assert.assertTrue(openRuleChainPage.inputNode().isDisplayed()); - Assert.assertEquals(ruleChainsPage.getRuleChainName(), openRuleChainPage.getHeadName()); + Assert.assertEquals(ruleChainName, openRuleChainPage.getHeadName()); } @Test(priority = 10, groups = "smoke") @Description public void openRuleChainByViewBtn() { + ruleChainName = ENTITY_NAME; + testRestClient.postRuleChain(EntityPrototypes.defaultRuleChainPrototype(ENTITY_NAME)); + sideBarMenuView.ruleChainsBtn().click(); - ruleChainsPage.setRuleChainNameWithoutRoot(0); - String ruleChain = ruleChainsPage.getRuleChainName(); - ruleChainsPage.entity(ruleChain).click(); + ruleChainsPage.entity(ruleChainName).click(); ruleChainsPage.openRuleChainFromViewBtn().click(); openRuleChainPage.setHeadName(); - Assert.assertTrue(urlContains(String.valueOf(getRuleChainByName(ruleChainsPage.getRuleChainName()).getId()))); + Assert.assertTrue(urlContains(String.valueOf(getRuleChainByName(ruleChainName).getId()))); Assert.assertTrue(openRuleChainPage.headRuleChainName().isDisplayed()); Assert.assertTrue(openRuleChainPage.inputNode().isDisplayed()); - Assert.assertEquals(ruleChain, openRuleChainPage.getHeadName()); + Assert.assertEquals(ruleChainName, openRuleChainPage.getHeadName()); } @Test(priority = 20, groups = "smoke") From 8045e136685c78843da43c071687d26e47c3774f Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Wed, 30 Nov 2022 15:40:42 +0200 Subject: [PATCH 13/66] add before suite method --- .../server/msa/ui/base/AbstractDriverBaseTest.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java index 315f482751..6badd78e8e 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java @@ -21,13 +21,18 @@ import io.qameta.allure.Attachment; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; -import org.openqa.selenium.*; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.OutputType; +import org.openqa.selenium.TakesScreenshot; +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.BeforeSuite; import org.testng.annotations.Listeners; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.page.PageLink; @@ -50,11 +55,14 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { private static final boolean HEADLESS = true; protected static final PageLink pageLink = new PageLink(10); + @BeforeSuite + public void beforeUISuite() { + WebDriverManager.chromedriver().setup(); + } @BeforeMethod public void openBrowser() { log.info("*----------------------* Setup driver *----------------------*"); - WebDriverManager.chromedriver().setup(); if (HEADLESS == true) { ChromeOptions options = new ChromeOptions(); options.addArguments("--ignore-certificate-errors"); @@ -68,6 +76,7 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { driver = new ChromeDriver(options); } driver.manage().window().setSize(dimension); + } @AfterMethod From 5cf5af26b6ea45d5f0166123ede60366f9407583 Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Wed, 30 Nov 2022 17:28:30 +0200 Subject: [PATCH 14/66] change suite path --- msa/black-box-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index 380f9abbaa..1b710940b7 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -184,7 +184,7 @@ maven-surefire-plugin - src/test/resources/${suite}.xml + src/test/resources/all.xml ${blackBoxTests.skip} From 9274fff3ec14a1a74e49550758e3f6f2b7f34de1 Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Thu, 1 Dec 2022 11:31:07 +0200 Subject: [PATCH 15/66] add ManageCustomerEdgesTest in suite --- .../src/test/resources/smokesCustomer.xml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/msa/black-box-tests/src/test/resources/smokesCustomer.xml b/msa/black-box-tests/src/test/resources/smokesCustomer.xml index 8d26e1a796..106a552d8e 100644 --- a/msa/black-box-tests/src/test/resources/smokesCustomer.xml +++ b/msa/black-box-tests/src/test/resources/smokesCustomer.xml @@ -1,7 +1,7 @@ - - - - - - - - - \ No newline at end of file From ad895876f084b397dfbcc477da90d72a35c3c465 Mon Sep 17 00:00:00 2001 From: Serafym Tuhai Date: Mon, 12 Dec 2022 15:15:13 +0200 Subject: [PATCH 38/66] merge listeners, rm suites from all.xml --- .../server/msa/DisableUIListeners.java | 28 ++++++++ .../thingsboard/server/msa/TestListener.java | 45 ++++++++++--- .../msa/connectivity/CoapClientTest.java | 3 +- .../msa/connectivity/HttpClientTest.java | 2 + .../msa/connectivity/MqttClientTest.java | 2 + .../connectivity/MqttGatewayClientTest.java | 2 + .../msa/ui/base/AbstractDriverBaseTest.java | 8 +-- .../msa/ui/listeners/RetryAnalyzer.java | 7 ++ .../server/msa/ui/listeners/TestListener.java | 66 ------------------- .../src/test/resources/all.xml | 22 +++++-- 10 files changed, 100 insertions(+), 85 deletions(-) create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/DisableUIListeners.java delete mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/TestListener.java diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/DisableUIListeners.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/DisableUIListeners.java new file mode 100644 index 0000000000..86e9646516 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/DisableUIListeners.java @@ -0,0 +1,28 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface DisableUIListeners { + +} + diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestListener.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestListener.java index 51bc75c86a..ec23b69812 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestListener.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestListener.java @@ -16,18 +16,22 @@ package org.thingsboard.server.msa; import lombok.extern.slf4j.Slf4j; -import org.testng.ITestContext; +import org.openqa.selenium.WebDriver; +import org.testng.ITestListener; import org.testng.ITestResult; -import org.testng.TestListenerAdapter; +import org.testng.internal.ConstructorOrMethod; +import org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest; import static org.testng.internal.Utils.log; +import static org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest.captureScreen; @Slf4j -public class TestListener extends TestListenerAdapter { +public class TestListener implements ITestListener { + + WebDriver driver; @Override public void onTestStart(ITestResult result) { - super.onTestStart(result); log.info("===>>> Test started: " + result.getName()); } @@ -36,10 +40,14 @@ public class TestListener extends TestListenerAdapter { */ @Override public void onTestSuccess(ITestResult result) { - super.onTestSuccess(result); - if (result != null) { - log.info("<<<=== Test completed successfully: " + result.getName()); + log.info("<<<=== Test completed successfully: " + result.getName()); + ConstructorOrMethod consOrMethod = result.getMethod().getConstructorOrMethod(); + DisableUIListeners disable = consOrMethod.getMethod().getDeclaringClass().getAnnotation(DisableUIListeners.class); + if (disable != null) { + return; } + driver = ((AbstractDriverBaseTest) result.getInstance()).getDriver(); + captureScreen(driver, "success"); } /** @@ -47,7 +55,28 @@ public class TestListener extends TestListenerAdapter { */ @Override public void onTestFailure(ITestResult result) { - super.onTestFailure(result); log.info("<<<=== Test failed: " + result.getName()); + ConstructorOrMethod consOrMethod = result.getMethod().getConstructorOrMethod(); + DisableUIListeners disable = consOrMethod.getMethod().getDeclaringClass().getAnnotation(DisableUIListeners.class); + if (disable != null) { + return; + } + driver = ((AbstractDriverBaseTest) result.getInstance()).getDriver(); + captureScreen(driver, "failure"); + } + + /** + * Invoked when a test skipped + */ + @Override + public void onTestSkipped(ITestResult result) { + log.info("<<<=== Test skipped: " + result.getName()); + ConstructorOrMethod consOrMethod = result.getMethod().getConstructorOrMethod(); + DisableUIListeners disable = consOrMethod.getMethod().getDeclaringClass().getAnnotation(DisableUIListeners.class); + if (disable != null) { + return; + } + driver = ((AbstractDriverBaseTest) result.getInstance()).getDriver(); + captureScreen(driver, "skipped"); } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/CoapClientTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/CoapClientTest.java index fe3443dd0e..8ddc7e79c0 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/CoapClientTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/CoapClientTest.java @@ -18,7 +18,6 @@ package org.thingsboard.server.msa.connectivity; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.gson.JsonObject; -import io.restassured.path.json.JsonPath; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -29,11 +28,13 @@ import org.thingsboard.server.common.data.DeviceProfileProvisionType; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.msg.session.FeatureType; import org.thingsboard.server.msa.AbstractContainerTest; +import org.thingsboard.server.msa.DisableUIListeners; import org.thingsboard.server.msa.TestCoapClient; import static org.assertj.core.api.Assertions.assertThat; import static org.thingsboard.server.msa.prototypes.DevicePrototypes.defaultDevicePrototype; +@DisableUIListeners public class CoapClientTest extends AbstractContainerTest { private TestCoapClient client; diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java index adaefa887a..36da84e9d2 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java @@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileProvisionType; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.msa.AbstractContainerTest; +import org.thingsboard.server.msa.DisableUIListeners; import org.thingsboard.server.msa.WsClient; import org.thingsboard.server.msa.mapper.WsTelemetryResponse; @@ -37,6 +38,7 @@ import static org.thingsboard.server.common.data.DataConstants.DEVICE; import static org.thingsboard.server.common.data.DataConstants.SHARED_SCOPE; import static org.thingsboard.server.msa.prototypes.DevicePrototypes.defaultDevicePrototype; +@DisableUIListeners public class HttpClientTest extends AbstractContainerTest { private Device device; @BeforeMethod diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java index dff645ddf7..7899372566 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java @@ -46,6 +46,7 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.msa.AbstractContainerTest; +import org.thingsboard.server.msa.DisableUIListeners; import org.thingsboard.server.msa.WsClient; import org.thingsboard.server.msa.mapper.AttributesResponse; import org.thingsboard.server.msa.mapper.WsTelemetryResponse; @@ -68,6 +69,7 @@ import static org.thingsboard.server.common.data.DataConstants.DEVICE; import static org.thingsboard.server.common.data.DataConstants.SHARED_SCOPE; import static org.thingsboard.server.msa.prototypes.DevicePrototypes.defaultDevicePrototype; +@DisableUIListeners @Slf4j public class MqttClientTest extends AbstractContainerTest { diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttGatewayClientTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttGatewayClientTest.java index 84b2dd7253..6315cad5b0 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttGatewayClientTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttGatewayClientTest.java @@ -46,6 +46,7 @@ import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.msa.AbstractContainerTest; +import org.thingsboard.server.msa.DisableUIListeners; import org.thingsboard.server.msa.WsClient; import org.thingsboard.server.msa.mapper.WsTelemetryResponse; @@ -66,6 +67,7 @@ import static org.thingsboard.server.common.data.DataConstants.DEVICE; import static org.thingsboard.server.common.data.DataConstants.SHARED_SCOPE; import static org.thingsboard.server.msa.prototypes.DevicePrototypes.defaultGatewayPrototype; +@DisableUIListeners @Slf4j public class MqttGatewayClientTest extends AbstractContainerTest { private Device gatewayDevice; diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java index 4fa500625e..121acb4e92 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java @@ -34,14 +34,11 @@ 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.BeforeSuite; -import org.testng.annotations.Listeners; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.msa.AbstractContainerTest; import org.thingsboard.server.msa.ContainerTestSuite; -import org.thingsboard.server.msa.ui.listeners.TestListener; import java.io.File; import java.net.URL; @@ -51,7 +48,6 @@ import java.util.stream.Collectors; import static org.thingsboard.server.msa.TestProperties.getBaseUiUrl; @Slf4j -@Listeners(TestListener.class) abstract public class AbstractDriverBaseTest extends AbstractContainerTest { protected WebDriver driver; @@ -65,7 +61,7 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { @SneakyThrows @BeforeMethod public void openBrowser() { - log.info("*----------------------* Setup driver *----------------------*"); + log.info("===>>> Setup driver"); ChromeOptions options = new ChromeOptions(); options.setAcceptInsecureCerts(true); if (instance.isActive()) { @@ -81,7 +77,7 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { @AfterMethod public void closeBrowser() { - log.info("*----------------------* Teardown *----------------------*"); + log.info("<<<=== Teardown"); driver.quit(); } 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 index bc3f88d99e..56cd7c91cd 100644 --- 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 @@ -17,6 +17,8 @@ package org.thingsboard.server.msa.ui.listeners; import org.testng.IRetryAnalyzer; import org.testng.ITestResult; +import org.testng.internal.ConstructorOrMethod; +import org.thingsboard.server.msa.DisableUIListeners; public class RetryAnalyzer implements IRetryAnalyzer { @@ -25,6 +27,11 @@ public class RetryAnalyzer implements IRetryAnalyzer { @Override public boolean retry(ITestResult result) { + ConstructorOrMethod consOrMethod = result.getMethod().getConstructorOrMethod(); + DisableUIListeners disable = consOrMethod.getMethod().getDeclaringClass().getAnnotation(DisableUIListeners.class); + if (disable != null) { + return false; + } if (retryCount < MAX_RETRY_COUNT) { System.out.printf("Retrying test %s for the %d time(s).%n", result.getName(), retryCount + 1); retryCount++; 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 deleted file mode 100644 index 9a0e7aad77..0000000000 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/listeners/TestListener.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright © 2016-2022 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.msa.ui.listeners; - -import lombok.extern.slf4j.Slf4j; -import org.openqa.selenium.WebDriver; -import org.testng.ITestContext; -import org.testng.ITestListener; -import org.testng.ITestResult; -import org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest; - -import static org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest.captureScreen; - -@Slf4j -public class TestListener implements ITestListener { - - WebDriver driver; - - public void onTestSuccess(ITestResult tr) { - String str = "Test " + tr.getMethod().getMethodName() + " success"; - log.info("*----------------------* " + str + " *----------------------*"); - driver = ((AbstractDriverBaseTest) 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 + " *----------------------*"); - driver = ((AbstractDriverBaseTest) 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 + " *----------------------*"); - driver = ((AbstractDriverBaseTest) 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/resources/all.xml b/msa/black-box-tests/src/test/resources/all.xml index 41779d6a97..7eac146e4b 100644 --- a/msa/black-box-tests/src/test/resources/all.xml +++ b/msa/black-box-tests/src/test/resources/all.xml @@ -19,8 +19,22 @@ - - - - + + + + + + + + + + + + + + + + + + \ No newline at end of file From fa46e883f9d82473b59d27f50fd771e6c477a7d7 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Mon, 12 Dec 2022 18:08:08 +0200 Subject: [PATCH 39/66] UI: Fixed Catalan locale designator --- .../{locale.constant-es_CA.json => locale.constant-ca_ES.json} | 0 ui-ngx/src/assets/locale/locale.constant-en_US.json | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename ui-ngx/src/assets/locale/{locale.constant-es_CA.json => locale.constant-ca_ES.json} (100%) diff --git a/ui-ngx/src/assets/locale/locale.constant-es_CA.json b/ui-ngx/src/assets/locale/locale.constant-ca_ES.json similarity index 100% rename from ui-ngx/src/assets/locale/locale.constant-es_CA.json rename to ui-ngx/src/assets/locale/locale.constant-ca_ES.json diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 3df8a15e52..f3ebc6f69a 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -4792,7 +4792,7 @@ "ko_KR": "한국어", "ru_RU": "Русский", "es_ES": "Español", - "es_CA": "Catalan", + "ca_ES": "Catalan", "ja_JP": "日本語", "tr_TR": "Türkçe", "fa_IR": "فارسي", From d87634f5249f86c94d6ad2bbce29d5ab5d7881b9 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Tue, 13 Dec 2022 11:11:24 +0200 Subject: [PATCH 40/66] UI: Add new Danish language --- .../assets/locale/locale.constant-da_DK.json | 4002 +++++++++++++++++ .../assets/locale/locale.constant-en_US.json | 3 +- 2 files changed, 4004 insertions(+), 1 deletion(-) create mode 100644 ui-ngx/src/assets/locale/locale.constant-da_DK.json diff --git a/ui-ngx/src/assets/locale/locale.constant-da_DK.json b/ui-ngx/src/assets/locale/locale.constant-da_DK.json new file mode 100644 index 0000000000..6200b26ce7 --- /dev/null +++ b/ui-ngx/src/assets/locale/locale.constant-da_DK.json @@ -0,0 +1,4002 @@ +{ + "access": { + "unauthorized": "Uautoriseret", + "unauthorized-access": "Uautoriseret adgang", + "unauthorized-access-text": "Du skal logge ind for at få adgang til denne ressource!", + "access-forbidden": "Adgang forbudt", + "access-forbidden-text": "Du har ikke adgangsrettigheder til denne placering!
Prøv at logge ind med en anden bruger, hvis du stadig ønsker at få adgang til denne placering.", + "refresh-token-expired": "Sessionen er udløbet", + "refresh-token-failed": "Kunne ikke opdatere session", + "permission-denied": "Tilladelse nægtet", + "permission-denied-text": "Du har ikke tilladelse til at udføre denne handling!" + }, + "action": { + "activate": "Aktivér", + "suspend": "Udsæt", + "save": "Gem", + "saveAs": "Gem som", + "cancel": "Annuller", + "ok": "Okay", + "delete": "Slet", + "add": "Tilføj", + "yes": "Ja", + "no": "Nej", + "update": "Opdatering", + "remove": "Fjern", + "search": "Søg", + "clear-search": "Ryd søgning", + "assign": "Tildel", + "unassign": "Fjern tildeling", + "share": "Del", + "make-private": "Gør privat", + "make-public": "Gør offentlig", + "apply": "Anvend", + "apply-changes": "Anvend ændringer", + "edit-mode": "Redigeringstilstand", + "enter-edit-mode": "Gå til redigeringstilstand", + "decline-changes": "Afvis ændringer", + "open": "Åbn", + "close": "Tæt", + "back": "Tilbage", + "run": "Kør", + "sign-in": "Log på!", + "edit": "Rediger", + "view": "Vis", + "create": "Opret", + "drag": "Træk", + "refresh": "Genopfrisk", + "undo": "Fortryd", + "copy": "Kopiér", + "paste": "Sæt ind", + "copy-reference": "Kopiér reference", + "paste-reference": "Indsæt reference", + "import": "Importér", + "export": "Eksportér", + "share-via": "", + "move": "Flyt", + "select": "Vælg", + "continue": "Fortsæt", + "discard-changes": "Kassér ændringer", + "download": "Download", + "next-with-label": "", + "read-more": "Læs mere", + "hide": "Skjul" + }, + "aggregation": { + "aggregation": "Opsamling", + "function": "Dataopsamlingsfunktion", + "limit": "Maks.-værdier", + "group-interval": "Grupperingsinterval", + "min": "Min", + "max": "Maks", + "avg": "Gennemsnit", + "sum": "I alt", + "count": "Sammentælling", + "none": "Ingen" + }, + "admin": { + "general": "Generelt", + "general-settings": "Generelle indstillinger", + "home-settings": "Hjem-indstillinger", + "outgoing-mail": "Mailserver", + "outgoing-mail-settings": "Udgående mailserverindstillinger", + "system-settings": "Systemindstillinger", + "test-mail-sent": "Test-e-mail blev sendt!", + "base-url": "Basis-URL", + "base-url-required": "Basis-URL er påkrævet.", + "prohibit-different-url": "Det er ikke tilladt at bruge værtsnavn fra overskrifterne for klientanmodninger", + "prohibit-different-url-hint": "Denne indstilling skal aktiveres for produktionsmiljøer. Kan forårsage sikkerhedsproblemer ved deaktivering", + "mail-from": "Afsender", + "mail-from-required": "Afsender er påkrævet.", + "smtp-protocol": "SMTP-protokol", + "smtp-host": "SMTP-vært", + "smtp-host-required": "SMTP-vært er påkrævet.", + "smtp-port": "SMTP-port", + "smtp-port-required": "Du skal angive en smtp-port.", + "smtp-port-invalid": "Det ligner ikke en gyldig smtp-port.", + "timeout-msec": "Timeout (msek.)", + "timeout-required": "Timeout er påkrævet.", + "timeout-invalid": "Det ser ikke ud til at være en gyldig timeout.", + "enable-tls": "Aktivér TLS", + "tls-version": "TLS-version", + "enable-proxy": "Aktivér proxy", + "proxy-host": "Proxy-vært", + "proxy-host-required": "Proxy-vært er påkrævet.", + "proxy-port": "Proxy-port", + "proxy-port-required": "Proxy-port er påkrævet.", + "proxy-port-range": "Proxy-porten skal ligge i området fra 1 til 65535.", + "proxy-user": "Proxy-bruger", + "proxy-password": "Proxy-adgangskode", + "send-test-mail": "Send testmail", + "use-system-mail-settings": "Brug systemets mailserverindstillinger", + "mail-templates": "Mailskabeloner", + "mail-template-settings": "Indstillinger for mailskabeloner", + "use-system-mail-template-settings": "Brug systemmailskabeloner", + "mail-template": { + "mail-template": "Mailskabelon", + "test": "Test-e-mailmeddelelse", + "activation": "Meddelelse om aktivering af konto", + "account-activated": "Meddelelse om aktiveret konto", + "account-lockout": "Meddelelse om kontospærring", + "reset-password": "Meddelelse om nulstilling af adgangskode", + "password-was-reset": "Meddelelse om nulstillet adgangskode", + "user-activated": "Brugeraktiveret-meddelelse", + "user-registered": "Brugerregistreret-meddelelse", + "api-usage-state-enabled": "Api-brugstilstand aktiveret", + "api-usage-state-warning": "Advarsel om Api-brugstilstand", + "api-usage-state-disabled": "Api-brugstilstand deaktiveret" + }, + "mail-subject": "Mailens emne", + "mail-body": "Mailens brødtekst", + "sms-provider": "SMS-udbyder", + "sms-provider-settings": "Indstillinger for SMS-udbyder", + "use-system-sms-settings": "Anvend systemets indstillinger for SMS-udbyder", + "sms-provider-type": "SMS-udbydertype", + "sms-provider-type-required": "SMS-udbydertype er påkrævet.", + "sms-provider-type-aws-sns": "Amazon SNS", + "sms-provider-type-twilio": "Twilio", + "aws-access-key-id": "AWS-adgangsnøgle-id", + "aws-access-key-id-required": "AWS-adgangsnøgle-id er påkrævet", + "aws-secret-access-key": "AWS hemmelig adgangsnøgle", + "aws-secret-access-key-required": "AWS hemmelig adgangsnøgle er påkrævet", + "aws-region": "AWS-region", + "aws-region-required": "AWS-region er påkrævet", + "number-from": "Telefonnummer fra", + "number-from-required": "Telefonnummer fra er påkrævet.", + "number-to": "Telefonnummer til", + "number-to-required": "Telefonnummer til er påkrævet.", + "phone-number-hint": "Telefonnummer i E.164-format, f.eks. +19995550123", + "phone-number-hint-twilio": "Telefonnummer i E.164-format/Telefonnummers SID/Meddelelsesservice SID, f.eks. +19995550123/PNXXX/MGXXX", + "phone-number-pattern": "Ugyldigt telefonnummer. Skal være i E.164-format, f.eks. +19995550123.", + "phone-number-pattern-twilio": "Ugyldigt telefonnummer. Skal være i E.164-format/Telefonnummers SID/Meddelelsesservice SID, f.eks. +19995550123/PNXXX/MGXXX.", + "sms-message": "SMS-besked", + "sms-message-required": "SMS-besked er påkrævet.", + "sms-message-max-length": "SMS-beskeden må ikke være længere end 1600 tegn", + "twilio-account-sid": "Twilio-konto SID", + "twilio-account-sid-required": "Twilio-konto SID er påkrævet", + "twilio-account-token": "Twilio-konto-token", + "twilio-account-token-required": "Twilio-konto-token er påkrævet", + "send-test-sms": "Send test-SMS", + "test-sms-sent": "Test-SMS'en blev sendt!", + "security-settings": "Sikkerhedsindstillinger", + "password-policy": "Adgangskodepolitik", + "minimum-password-length": "Min. adgangskodelængde", + "minimum-password-length-required": "Min. adgangskodelængde er påkrævet", + "minimum-password-length-range": "Min. adgangskodelængde skal være mellem 5 og 50", + "minimum-uppercase-letters": "Min. antal store bogstaver", + "minimum-uppercase-letters-range": "Min. antal store bogstaver kan ikke være negativt", + "minimum-lowercase-letters": "Min. antal små bogstaver", + "minimum-lowercase-letters-range": "Min. antal små bogstaver kan ikke være negativt", + "minimum-digits": "Min. antal cifre", + "minimum-digits-range": "Minimum antal cifre kan ikke være negativt", + "minimum-special-characters": "Minimum antal specialtegn", + "minimum-special-characters-range": "Minimum antal specialtegn kan ikke være negativt", + "password-expiration-period-days": "Adgangskodens udløbsperiode i dage", + "password-expiration-period-days-range": "Adgangskodens udløbsperiode i dage kan ikke være negativ", + "password-reuse-frequency-days": "Hyppighed af genbrug af adgangskode i dage", + "password-reuse-frequency-days-range": "Hyppigheden af genbrug af adgangskode i dage kan ikke være negativ", + "general-policy": "Generelle retningslinjer", + "max-failed-login-attempts": "Maks. antal mislykkede loginforsøg, før kontoen spærres", + "minimum-max-failed-login-attempts-range": "Maks. antal mislykkede loginforsøg kan ikke være negativt", + "user-lockout-notification-email": "Hvis brugerkontoen spærres, sendes en meddelelse til e-mail", + "domain-name": "Domænenavn", + "domain-name-unique": "Domænenavn og protokol skal være entydige.", + "error-verification-url": "Et domænenavn må ikke indeholde symbolerne '/' og ':'. Eksempel: thingsboard.io", + "oauth2": { + "access-token-uri": "Adgangstoken URI", + "access-token-uri-required": "Adgangstoken URI er påkrævet.", + "activate-user": "Aktivér bruger", + "add-domain": "Tilføj domæne", + "delete-domain": "Slet domæne", + "add-provider": "Tilføj udbyder", + "delete-provider": "Slet udbyder", + "allow-user-creation": "Tillad brugeroprettelse", + "always-fullscreen": "Altid fuld skærm", + "authorization-uri": "Godkendelses-URI", + "authorization-uri-required": "Godkendelses-URI er påkrævet.", + "client-authentication-method": "Klientgodkendelsesmetode", + "client-id": "Klient-id", + "client-id-required": "Klient-id er påkrævet.", + "client-secret": "Kunde hemmelig", + "client-secret-required": "Kunde hemmelig er påkrævet.", + "custom-setting": "Brugerdefinerede indstillinger", + "customer-name-pattern": "Kundenavnsmønster", + "parent-customer-name-pattern": "Overordnet kundenavnsmønster", + "user-groups-name-pattern": "Mønster for brugergruppenavn", + "default-dashboard-name": "Standard dashboardnavn", + "delete-domain-text": "Vær forsigtig. Efter bekræftelsen vil et domæne og alle udbyderdata være utilgængelige.", + "delete-domain-title": "", + "delete-registration-text": "Vær forsigtig. Efter bekræftelsen vil udbyderdata være utilgængelige.", + "delete-registration-title": "", + "email-attribute-key": "E-mailattributnøgle", + "email-attribute-key-required": "E-mailattributnøgle er påkrævet.", + "first-name-attribute-key": "Fornavn attributnøgle", + "general": "Generelt", + "jwk-set-uri": "JSON webnøgle-URI", + "last-name-attribute-key": "Efternavn attributnøgle", + "login-button-icon": "Logon-knapikon", + "login-button-label": "Udbyder etiket", + "login-button-label-placeholder": "Log ind med $(Udbyder etiket)", + "login-button-label-required": "Etiket er påkrævet.", + "login-provider": "Log ind udbyder", + "mapper": "Kortlægger", + "new-domain": "Nyt domæne", + "oauth2": "OAuth2", + "redirect-uri-template": "Omdiriger URI-skabelon", + "copy-redirect-uri": "Kopiér omdirigering af URI", + "registration-id": "Registrerings-id", + "registration-id-required": "Registrerings-id er påkrævet.", + "registration-id-unique": "Registrerings-id skal være entydigt for systemet.", + "scope": "Omfang", + "scope-required": "Omfang er påkrævet.", + "tenant-name-pattern": "Mønster for lejernavn", + "tenant-name-pattern-required": "Mønster for lejernavn er påkrævet.", + "tenant-name-strategy": "Strategi for lejernavn", + "type": "Kortlæggertype", + "uri-pattern-error": "Ugyldigt URI-format.", + "url": "URL", + "url-pattern": "Ugyldigt URL-format.", + "url-required": "URL er påkrævet.", + "user-info-uri": "Brugerinfo URI", + "user-info-uri-required": "Brugerinfo URI er påkrævet.", + "user-name-attribute-name": "Attributnøgle for brugernavn", + "user-name-attribute-name-required": "Attributnøgle for brugernavn er påkrævet", + "protocol": "Protokol", + "domain-schema-http": "HTTP", + "domain-schema-https": "HTTPS", + "domain-schema-mixed": "HTTP+HTTPS", + "enable": "Aktivér OAuth2-indstillinger" + } + }, + "alarm": { + "alarm": "Alarm", + "alarms": "Alarmer", + "select-alarm": "Vælg alarm", + "no-alarms-matching": "", + "alarm-required": "Alarm er påkrævet", + "alarm-status": "Alarmstatus", + "alarm-status-list": "Alarmstatusliste", + "any-status": "Enhver status", + "search-status": { + "ANY": "Enhver", + "ACTIVE": "Aktiv", + "CLEARED": "Ryddet", + "ACK": "Kvitteret", + "UNACK": "Ikke kvitteret" + }, + "display-status": { + "ACTIVE_UNACK": "Aktiv Ikke-kvitteret", + "ACTIVE_ACK": "Aktiv Kvitteret", + "CLEARED_UNACK": "Ryddet Ikke-kvitteret", + "CLEARED_ACK": "Ryddet Kvitteret" + }, + "no-alarms-prompt": "Ingen alarmer fundet", + "created-time": "Oprettelsestidspunkt", + "type": "Type", + "severity": "Alvorsgrad", + "originator": "Ophavsmand", + "originator-type": "Ophavsmandtype", + "details": "Oplysninger", + "status": "Status", + "alarm-details": "Alarmoplysninger", + "start-time": "Starttid", + "end-time": "Sluttid", + "ack-time": "Tidspunkt for Kvitteret", + "clear-time": "Tidspunkt for Ryddet", + "alarm-severity-list": "Liste over alvorsgrad for alamer", + "any-severity": "Enhver alvorsgrad", + "severity-critical": "Kritisk", + "severity-major": "Stor", + "severity-minor": "Mindre", + "severity-warning": "Advarsel", + "severity-indeterminate": "Ubestemt", + "acknowledge": "Kvittér", + "clear": "Klar", + "search": "Søg efter alarmer", + "selected-alarms": "", + "no-data": "Ingen data at vise", + "polling-interval": "Alarmer undersøgelsesinterval (sek.)", + "polling-interval-required": "Alarmer undersøgelsesinterval er påkrævet.", + "min-polling-interval-message": "Mindst 1 sek. undersøgelsesinterval er tilladt.", + "aknowledge-alarms-title": "", + "aknowledge-alarms-text": "", + "aknowledge-alarm-title": "Kvittér for alarm", + "aknowledge-alarm-text": "Er du sikker på, du ønsker at kvittere for alarm?", + "clear-alarms-title": "", + "clear-alarms-text": "", + "clear-alarm-title": "Ryd alarm", + "clear-alarm-text": "Er du sikker på, at du vil slette Alarm?", + "alarm-status-filter": "Filter for alarmstatus", + "alarm-filter": "Alarmfilter", + "max-count-load": "Maks. antal alarmer, der skal indlæses (0 – ubegrænset)", + "max-count-load-required": "Maks. antal alarmer, der skal indlæses, er påkrævet.", + "max-count-load-error-min": "Minimumværdien er 0.", + "fetch-size": "Hent størrelse", + "fetch-size-required": "Hent størrelse er påkrævet.", + "fetch-size-error-min": "Minimumværdien er 10.", + "alarm-type-list": "Liste over alarmtyper", + "any-type": "Enhver type", + "search-propagated-alarms": "Søg efter overførte alarmer" + }, + "alias": { + "add": "Tilføj alias", + "edit": "Rediger alias", + "name": "Aliasnavn", + "name-required": "Aliasnavn er påkrævet", + "duplicate-alias": "Alias med samme navn findes allerede.", + "filter-type-single-entity": "Enkelt entitet", + "filter-type-entity-group": "Gruppeentiteter", + "filter-type-entity-list": "Entitetsliste", + "filter-type-entity-name": "Entitetsnavn", + "filter-type-entity-type": "Entitetstype", + "filter-type-entity-group-list": "Entitetsgruppeliste", + "filter-type-entity-group-name": "Entitetsgruppenavn", + "filter-type-entities-by-group-name": "Entiteter efter gruppenavn", + "filter-type-state-entity": "Entitet fra dashboardtilstand", + "filter-type-state-entity-description": "Entitet taget fra dashboardtilstandsparametre", + "filter-type-state-entity-owner": "Ejer af entitet fra dashboardtilstand", + "filter-type-state-entity-owner-description": "Ejer af entitet taget fra dashboardtilstandsparametre", + "filter-type-asset-type": "Aktivtype", + "filter-type-asset-type-description": "", + "filter-type-asset-type-and-name-description": "", + "filter-type-device-type": "Enhedstype", + "filter-type-device-type-description": "", + "filter-type-device-type-and-name-description": "", + "filter-type-entity-view-type": "Entitetsvisningstype", + "filter-type-entity-view-type-description": "", + "filter-type-entity-view-type-and-name-description": "", + "filter-type-relations-query": "Relationsforespørgsel", + "filter-type-relations-query-description": "", + "filter-type-asset-search-query": "Aktivsøgningsforespørgsel", + "filter-type-asset-search-query-description": "", + "filter-type-device-search-query": "Enhedssøgningsforespørgsel", + "filter-type-device-search-query-description": "", + "filter-type-entity-view-search-query": "Entitetsvisning for søgningsforespørgsel", + "filter-type-entity-view-search-query-description": "", + "filter-type-apiUsageState": "Api-brugstilstand", + "entity-filter": "Entitetsfilter", + "resolve-multiple": "Løs som flere entiteter", + "filter-type": "Filtertype", + "filter-type-required": "Filtertype er påkrævet.", + "entity-filter-no-entity-matched": "Der blev ikke fundet nogen entiteter, der matcher det angivne filter.", + "no-entity-filter-specified": "Intet entitetsfilter angivet", + "root-state-entity": "Brug dashboardtilstandsentitet som rod", + "group-state-entity": "Brug dashboardtilstandsentitet som entitetsgruppe", + "group-state-entity-owner": "Brug dashboardtilstandsentitet som entitetsgruppeejer", + "last-level-relation": "Hent kun sidste niveaurelation", + "root-entity": "Rodentitet", + "state-entity-parameter-name": "Parameternavn for tilstandsentitet", + "default-state-entity": "Standard tilstandsentitet", + "default-state-entity-group": "Standard tilstandsentitetsgruppe", + "default-entity-parameter-name": "Som standard", + "max-relation-level": "Maks. niveaurelation", + "unlimited-level": "Ubegrænset niveau", + "state-entity": "Dashboardtilstandsentitet", + "entities-of-group-state-entity": "Entiteter fra dashboardtilstandsentitetsgruppe", + "all-entities": "Alle entiteter", + "any-relation": "enhver" + }, + "asset": { + "asset": "Aktiv", + "assets": "Aktiver", + "management": "Styring af aktiver", + "view-assets": "Vis aktiver", + "add": "Tilføj aktiv", + "assign-to-customer": "Tildel til kunde", + "assign-asset-to-customer": "Tildel aktiv(er) til kunde", + "assign-asset-to-customer-text": "Vælg de aktiver, der skal tildeles til kunden", + "no-assets-text": "Ingen aktiver fundet", + "assign-to-customer-text": "Vælg den kunde, der skal tildeles aktivet/aktiverne", + "public": "Offentlig", + "assignedToCustomer": "Tildelt til kunde", + "make-public": "Gør aktiv offentligt", + "make-private": "Gør aktiv privat", + "unassign-from-customer": "Fjern tildeling fra kunde", + "delete": "Slet aktiv", + "asset-public": "Aktiv er offentligt", + "asset-type": "Aktivtype", + "asset-type-required": "Aktivtype er påkrævet.", + "select-asset-type": "Vælg aktivtype", + "enter-asset-type": "Indtast aktivtype", + "any-asset": "Ethvert aktiv", + "no-asset-types-matching": "", + "asset-type-list-empty": "Ingen aktivtyper valgt.", + "asset-types": "Aktivtyper", + "name": "Navn", + "name-required": "Navn er påkrævet.", + "description": "Beskrivelse", + "type": "Type", + "type-required": "Type er påkrævet.", + "details": "Oplysninger", + "events": "Begivenheder", + "add-asset-text": "Tilføj nyt aktiv", + "asset-details": "Oplysninger om aktiv", + "assign-assets": "Tildel aktiver", + "assign-assets-text": "", + "delete-assets": "Slet aktiver", + "unassign-assets": "Fjern tildeling af aktiver", + "unassign-assets-action-title": "", + "assign-new-asset": "Tildel nyt aktiv", + "delete-asset-title": "", + "delete-asset-text": "Vær forsigtig. Efter bekræftelsen vil aktivet og alle relaterede data være uoprettelige.", + "delete-assets-title": "", + "delete-assets-action-title": "", + "delete-assets-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte aktiver blive fjernet, og alle relaterede data vil være uoprettelige.", + "make-public-asset-title": "", + "make-public-asset-text": "Efter bekræftelsen vil aktivet og alle dets data blive gjort offentlige og tilgængelige for andre.", + "make-private-asset-title": "", + "make-private-asset-text": "Efter bekræftelsen vil aktivet og alle dets data blive gjort private og vil ikke være tilgængelige for andre.", + "unassign-asset-title": "", + "unassign-asset-text": "Efter bekræftelsen fjernes tildelingen af aktivet og vil ikke være tilgængeligt for kunden.", + "unassign-asset": "Fjern tildeling af aktiv", + "unassign-assets-title": "", + "unassign-assets-text": "Efter bekræftelsen vil alle valgte aktiver få fjernet tildelingen og ikke være tilgængelige for kunden.", + "copyId": "Kopiér aktiv-id", + "idCopiedMessage": "Aktiv-id er blevet kopieret til udklipsholder", + "select-asset": "Vælg aktiv", + "no-assets-matching": "", + "asset-required": "Aktiv er påkrævet", + "name-starts-with": "Aktivnavn starter med", + "selected-assets": "", + "search": "Søg efter aktiver", + "select-group-to-add": "Vælg målgruppe for at tilføje valgte aktiver", + "select-group-to-move": "Vælg målgruppe for at flytte valgte aktiver", + "remove-assets-from-group": "", + "group": "Aktivgruppe", + "list-of-groups": "", + "group-name-starts-with": "", + "import": "Importér aktiver", + "asset-file": "Aktivfil", + "label": "Mærkning" + }, + "attribute": { + "attributes": "Attributter", + "latest-telemetry": "Seneste telemetri", + "attributes-scope": "Omfang af entitetsattributter", + "scope-latest-telemetry": "Seneste telemetri", + "scope-client": "Klientattributter", + "scope-server": "Serverattributter", + "scope-shared": "Delte attributter", + "add": "Tilføj attribut", + "add-attribute-prompt": "Tilføj venligst attribut", + "key": "Nøgle", + "last-update-time": "Seneste opdateringstid", + "key-required": "Attributnøgle er påkrævet.", + "value": "Værdi", + "value-required": "Attributværdi er påkrævet.", + "delete-attributes-title": "", + "delete-attributes-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte attributter blive fjernet.", + "delete-attributes": "Slet attributter", + "enter-attribute-value": "Indtast attributværdi", + "show-on-widget": "Vis på widget", + "widget-mode": "Widget-tilstand", + "next-widget": "Næste widget", + "prev-widget": "Forrige widget", + "add-to-dashboard": "Føj til dashboard", + "add-widget-to-dashboard": "Føj widget til dashboard", + "selected-attributes": "", + "selected-telemetry": "", + "no-attributes-text": "Ingen attributter fundet", + "no-telemetry-text": "Ingen telemetri fundet" + }, + "api-usage": { + "api-usage": "Api-brug", + "data-points": "Datapunkter", + "data-points-storage-days": "Lagringsdage for datapunkter", + "email": "E-mail", + "email-messages": "E-mailbeskeder", + "email-messages-daily-activity": "Daglig aktivitet for e-mailbeskeder", + "email-messages-hourly-activity": "Timeaktivitet for e-mailbeskeder", + "email-messages-monthly-activity": "Månedlig aktivitet for e-mailbeskeder", + "exceptions": "Undtagelser", + "executions": "Udførelser", + "javascript": "JavaScript", + "javascript-executions": "JavaScript-udførelser", + "javascript-functions": "JavaScript-funktioner", + "javascript-functions-daily-activity": "JavaScript-funktioners daglige aktivitet", + "javascript-functions-hourly-activity": "JavaScript-funktioners timeaktivitet", + "javascript-functions-monthly-activity": "JavaScript-funktioners månedlige aktivitet", + "latest-error": "Seneste fejl", + "messages": "Beskeder", + "permanent-failures": "${entityName} Permanente fejl", + "permanent-timeouts": "${entityName} Permanente timeouts", + "processing-failures": "${entityName} Behandling af fejl", + "processing-failures-and-timeouts": "Behandling af fejl og timeouts", + "processing-timeouts": "${entityName} Behandling af timeouts", + "queue-stats": "Køstatistikker", + "rule-chain": "Regelkæde", + "rule-engine": "Regelprogram", + "rule-engine-daily-activity": "Regelmotors daglige aktivitet", + "rule-engine-executions": "Regelmotorudførelser", + "rule-engine-hourly-activity": "Regelmotors timeaktivitet", + "rule-engine-monthly-activity": "Regelmotors månedlige aktivitet", + "rule-engine-statistics": "Statistik for regelmotor", + "rule-node": "Regelknude", + "sms": "SMS", + "sms-messages": "SMS-beskeder", + "sms-messages-daily-activity": "Daglig aktivitet for SMS-beskeder", + "sms-messages-hourly-activity": "Timeaktivitet for SMS-beskeder", + "sms-messages-monthly-activity": "Månedlig aktivitet for SMS-beskeder", + "successful": "${entityName} Vellykket", + "telemetry": "Telemetri", + "telemetry-persistence": "Telemetri-vedholdenhed", + "telemetry-persistence-daily-activity": "Daglig aktivitet for telemetri-vedholdenhed", + "telemetry-persistence-hourly-activity": "Timeaktivitet for telemetri-vedholdenhed", + "telemetry-persistence-monthly-activity": "Månedlig aktivitet for telemetri-vedholdenhed", + "transport": "Transport", + "transport-daily-activity": "Daglig aktivitet for transport", + "transport-data-points": "Transportdatapunkter", + "transport-hourly-activity": "Timeaktivitet for transport", + "transport-messages": "Transportmeddelelser", + "transport-monthly-activity": "Månedlig aktivitet for transport", + "view-details": "Vis oplysninger", + "view-statistics": "Vis statistik" + }, + "audit-log": { + "audit": "Audit", + "audit-logs": "Auditlogs", + "timestamp": "Tidsstempel", + "entity-type": "Entitetstype", + "entity-name": "Entitetsnavn", + "user": "Bruger", + "type": "Type", + "status": "Status", + "details": "Oplysninger", + "type-added": "Tilføjet", + "type-deleted": "Slettet", + "type-updated": "Opdateret", + "type-attributes-updated": "Attributter opdateret", + "type-attributes-deleted": "Attributter slettet", + "type-rpc-call": "RPC-opkald", + "type-credentials-updated": "Brugeroplysninger opdateret", + "type-assigned-to-customer": "Tildelt til kunde", + "type-unassigned-from-customer": "Tildeling fjernet fra kunde", + "type-activated": "Aktiveret", + "type-suspended": "Indstillet", + "type-credentials-read": "Brugeroplysninger læst", + "type-attributes-read": "Attributter læst", + "type-added-to-entity-group": "Tilføjet til gruppe", + "type-removed-from-entity-group": "Fjernet fra gruppe", + "type-relation-add-or-update": "Relation opdateret", + "type-relation-delete": "Relation slettet", + "type-relations-delete": "Alle relationer slettet", + "type-alarm-ack": "Kvitteret", + "type-alarm-clear": "Ryddet", + "type-rest-api-rule-engine-call": "Regelmotor REST API-opkald", + "type-made-public": "Gjort offentligt", + "type-made-private": "Gjort privat", + "type-login": "Log på", + "type-logout": "Log af", + "type-lockout": "Spærring", + "status-success": "Succes", + "status-failure": "Fejl", + "audit-log-details": "Oplysninger om auditlog", + "no-audit-logs-prompt": "Ingen logs fundet", + "action-data": "Handlingsdata", + "failure-details": "Fejloplysninger", + "search": "Søg efter auditlogfiler", + "clear-search": "Ryd søgning", + "type-assigned-from-tenant": "Tildelt fra lejer", + "type-assigned-to-tenant": "Tildelt til lejer", + "type-provision-success": "Enhed klargjort", + "type-provision-failure": "Enhed klargjort mislykkedes", + "type-timeseries-updated": "Telemetri opdateret", + "type-timeseries-deleted": "Telemetri slettet", + "type-owner-changed": "Ejer ændret" + }, + "confirm-on-exit": { + "message": "Du har ikke-gemte ændringer. Er du sikker på, at du vil forlade denne side?", + "html-message": "Du har ikke-gemte ændringer.
Er du sikker på, at du vil forlade denne side?", + "title": "Ugemte ændringer" + }, + "contact": { + "country": "Land", + "city": "By", + "state": "Region", + "postal-code": "Postnummer", + "postal-code-invalid": "Ugyldigt postnummerformat.", + "address": "Adresse", + "address2": "Adresse 2", + "phone": "Telefon", + "email": "E-mail", + "no-address": "Ingen adresse" + }, + "common": { + "username": "Brugernavn", + "password": "Adgangskode", + "enter-username": "Indtast brugernavn", + "enter-password": "Indtast adgangskode", + "enter-search": "Indtast søgning", + "created-time": "Oprettelsestidspunkt", + "loading": "Indlæser..." + }, + "converter": { + "converter": "Dataomformer", + "converters": "Dataomformere", + "select-converter": "Vælg dataomformer", + "no-converters-matching": "", + "converter-required": "Dataomformer er påkrævet", + "delete": "Slet omformer", + "management": "Styring af dataomformere", + "add-converter-text": "Tilføj ny dataomformer", + "no-converters-text": "Ingen dataomformere fundet", + "selected-converters": "", + "delete-converter-title": "", + "delete-converter-text": "Vær forsigtig. Efter bekræftelsen vil dataomformeren og alle relaterede data være uoprettelige.", + "delete-converters-title": "", + "delete-converters-action-title": "", + "delete-converters-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte dataomformere blive fjernet, og alle relaterede data vil være uoprettelige.", + "events": "Begivenheder", + "add": "Tilføj dataomformer", + "search": "Søg efter dataomformere", + "converter-details": "Oplysninger om dataomformer", + "details": "Oplysninger", + "copyId": "Kopiér omformer-id", + "idCopiedMessage": "Omformer-id er blevet kopieret til udklipsholder", + "debug-mode": "Debug-tilstand", + "created-time": "Oprettelsestidspunkt", + "name": "Navn", + "name-required": "Navn er påkrævet.", + "description": "Beskrivelse", + "decoder": "Dekoder", + "encoder": "Indkoder", + "test-decoder-fuction": "Test af dekoderfunktion", + "test-encoder-fuction": "Test af indkoderfunktion", + "decoder-input-params": "Parametre for dekoderindgang", + "encoder-input-params": "Parametre for indkoderindgang", + "payload": "Data", + "payload-content-type": "Dataindholdstype", + "payload-content": "Dataindhold", + "message": "Meddelelse", + "message-type": "Meddelelsestype", + "message-type-required": "Meddelelsestype er påkrævet", + "test": "Test", + "metadata": "Metadata", + "metadata-required": "Metadataposter må ikke være tomme.", + "integration-metadata": "Integrationsmetadata", + "integration-metadata-required": "Integrationsmetadataposter må ikke være tomme.", + "output": "Output", + "import": "Importér omformer", + "export": "Eksportér omformer", + "export-failed-error": "", + "create-new-converter": "Opret ny omformer", + "converter-file": "Omformerfil", + "invalid-converter-file-error": "Omformeren kunne ikke importeres: Ugyldig omformerdatastruktur.", + "type": "Type", + "type-required": "Type er påkrævet.", + "type-uplink": "Uplink", + "type-downlink": "Downlink" + }, + "content-type": { + "json": "Json", + "text": "Tekst", + "binary": "Binær (Base64)" + }, + "customer": { + "customer": "Kunde", + "customers": "Kunder", + "management": "Kundeadministration", + "dashboard": "Kundens dashboard", + "dashboards": "Kundens dashboards", + "devices": "Kundeenheder", + "entity-views": "Kundeentitetsvisninger", + "assets": "Kundeaktiver", + "public-dashboards": "Offentlige dashboards", + "public-devices": "Offentlige enheder", + "public-assets": "Offentlige aktiver", + "public-entity-views": "Visninger af offentlig entitet", + "add": "Tilføj kunde", + "delete": "Slet kunde", + "manage-customer-user-groups": "Administrer kundebrugergrupper", + "manage-customer-groups": "Administrer kundegrupper", + "manage-customer-device-groups": "Administrer kundeenhedsgrupper", + "manage-customer-asset-groups": "Administrer kundeaktivgrupper", + "manage-customer-entity-view-groups": "Administrer visningsgrupper for kundeentitet", + "manage-customer-dashboard-groups": "Administrer kundedashboardgrupper", + "manage-customer-users": "Administrer kundebrugere", + "manage-customers": "Administrer kunder", + "manage-customer-devices": "Administrer kundeenheder", + "manage-customer-entity-views": "Administrer visninger af kundeentitet", + "manage-customer-dashboards": "Administrer kundedashboards", + "manage-public-devices": "Administrer offentlige enheder", + "manage-public-dashboards": "Administrer offentlige dashboards", + "manage-customer-assets": "Administrer kundeaktiver", + "manage-public-assets": "Administrer offentlige aktiver", + "add-customer-text": "Tilføj ny kunde", + "no-customers-text": "Ingen kunder fundet", + "customer-details": "Kundeinformation", + "delete-customer-title": "", + "delete-customer-text": "Vær forsigtig. Efter bekræftelsen vil kunden og alle relaterede data være uoprettelige.", + "delete-customers-title": "", + "delete-customers-action-title": "", + "delete-customers-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte kunder blive fjernet, og alle relaterede data vil være uoprettelige.", + "manage-user-groups": "Administrer brugergrupper", + "manage-asset-groups": "Administrer aktivgrupper", + "manage-device-groups": "Administrer enhedsgrupper", + "manage-dashboard-groups": "Administrer dashboardgrupper", + "manage-entity-view-groups": "Administrer entitetsvisningsgrupper", + "manage-users": "Administrer brugere", + "manage-assets": "Administrer aktiver", + "manage-devices": "Administrer enheder", + "manage-dashboards": "Administrer dashboards", + "title": "Titel", + "title-required": "Titel er påkrævet.", + "description": "Beskrivelse", + "details": "Oplysninger", + "events": "Begivenheder", + "copyId": "Kopiér kunde-id", + "idCopiedMessage": "Kunde-id er blevet kopieret til udklipsholder", + "select-customer": "Vælg kunde", + "no-customers-matching": "", + "customer-required": "Kunde er påkrævet", + "selected-customers": "", + "search": "Søg efter kunder", + "select-group-to-add": "Vælg målgruppe for at tilføje udvalgte kunder", + "select-group-to-move": "Vælg målgruppe for at flytte udvalgte kunder", + "remove-customers-from-group": "", + "group": "Kundegruppe", + "list-of-groups": "", + "group-name-starts-with": "", + "select-default-customer": "Vælg standardkunde", + "default-customer": "Standardkunde", + "default-customer-required": "Standardkunde er påkrævet for at debugge dashboard på lejerniveau", + "allow-white-labeling": "Tillad hvid mærkning" + }, + "customers-hierarchy": { + "customers-hierarchy": "Kundehierarki", + "open-nav-tree": "Åbn navigationstræ", + "return-to-top-level": "Tilbage til øverste niveau" + }, + "custom-menu": { + "custom-menu": "Brugerdefineret menu", + "custom-menu-hint": "Definer brugerdefineret menu JSON nedenfor. Denne JSON indeholder en liste over brugerdefinerede menupunkter." + }, + "custom-translation": { + "custom-translation": "Brugerdefineret oversættelse", + "translation-map": "Oversættelsestilknytning", + "key": "Oversættelsesnøgle", + "import": "Importér oversættelse", + "export": "Eksportér oversættelse", + "export-data": "Eksportér oversættelsesdata", + "import-data": "Importér oversættelsesdata", + "translation-file": "Oversættelsesfil", + "invalid-translation-file-error": "Kunne ikke importere oversættelsesfil: Ugyldig oversættelsesdatastruktur.", + "custom-translation-hint": "Definer brugerdefineret oversættelse JSON nedenfor. Denne JSON overskriver standardoversættelsen. Klik på 'Download lokalfil' for at hente eksisterende oversættelse. Du kan også bruge den downloadede fil som reference til tilgængelige nøgleværdipar for oversættelse.", + "download-locale-file": "Download lokalfil" + }, + "datetime": { + "date-from": "Dato fra", + "time-from": "Tidspunkt fra", + "date-to": "Dato til", + "time-to": "Tidspunkt til" + }, + "dashboard": { + "dashboard": "Dashboard", + "dashboards": "Dashboards", + "management": "Dashboardadministration", + "view-dashboards": "Vis dashboards", + "add": "Tilføj dashboard", + "assign-dashboard-to-customer": "Tildel dashboard(s) til kunde", + "assign-dashboard-to-customer-text": "Vælg de dashboards, der skal tildeles til kunden", + "assign-to-customer-text": "Vælg den kunde, der skal tildeles dashboard(s)", + "assign-to-customer": "Tildel til kunde", + "unassign-from-customer": "Fjern tildeling fra kunde", + "make-public": "Gør dashboard offentligt", + "make-private": "Gør dashboard privat", + "manage-assigned-customers": "Administrer tildelte kunder", + "assigned-customers": "Tildelte kunder", + "assign-to-customers": "Tildel dashboard(s) til kunder", + "assign-to-customers-text": "Vælg de kunder, der skal tildeles dashboard(s)", + "unassign-from-customers": "Fjern tildeling af dashboard(s) fra kunder", + "unassign-from-customers-text": "Vælg de kunder, hvor tildeling skal fjernes fra dashboard(s)", + "no-dashboards-text": "Ingen dashboards fundet", + "no-widgets": "Ingen widgets konfigureret", + "add-widget": "Tilføj ny widget", + "title": "Titel", + "select-widget-title": "Vælg widget", + "select-widget-value": "", + "select-widget-subtitle": "Liste over tilgængelige widget-typer", + "delete": "Slet dashboard", + "title-required": "Titel er påkrævet.", + "description": "Beskrivelse", + "details": "Oplysninger", + "dashboard-details": "Oplysninger om dashboard", + "add-dashboard-text": "Tilføj nyt dashboard", + "assign-dashboards": "Tildel dashboards", + "assign-new-dashboard": "Tildel nyt dashboard", + "assign-dashboards-text": "", + "unassign-dashboards-action-text": "", + "delete-dashboards": "Slet dashboards", + "unassign-dashboards": "Fjern tildeling af dashboards", + "unassign-dashboards-action-title": "", + "delete-dashboard-title": "", + "delete-dashboard-text": "Vær forsigtig. Efter bekræftelsen vil dashboardet og alle relaterede data være uoprettelige.", + "delete-dashboards-title": "", + "delete-dashboards-action-title": "", + "delete-dashboards-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte dashboards blive fjernet, og alle relaterede data vil være uoprettelige.", + "unassign-dashboard-title": "", + "unassign-dashboard-text": "Efter bekræftelsen vil dashboardets tildeling blive fjernet og vil ikke være tilgængelig for kunden.", + "unassign-dashboard": "Fjern tildeling af dashboard", + "unassign-dashboards-title": "", + "unassign-dashboards-text": "Efter bekræftelsen vil tildelingen af alle valgte dashboards blive fjernet og vil ikke være tilgængelige for kunden.", + "public-dashboard-title": "Dashboard er nu offentligt", + "public-dashboard-text": "", + "public-dashboard-notice": "Bemærk: Glem ikke at gøre relaterede enheder offentlige for at få adgang til deres data.", + "public-dashboard-link": "Link til offentligt dashboard", + "public-dashboard-link-text": "", + "public-dashboard-link-notice": "Bemærk: Glem ikke at gøre relaterede enheder, aktiver og entitetsvisninger offentlige for at få adgang til deres data.", + "make-private-dashboard-title": "", + "make-private-dashboard-text": "Efter bekræftelsen vil dashboardet blive gjort privat og vil ikke være tilgængeligt for andre.", + "make-private-dashboard": "Gør dashboard privat", + "socialshare-text": "", + "socialshare-title": "", + "select-dashboard": "Vælg dashboard", + "no-dashboards-matching": "", + "dashboard-required": "Dashboard er påkrævet.", + "select-existing": "Vælg eksisterende dashboard", + "create-new": "Opret nyt dashboard", + "new-dashboard-title": "Ny dashboardtitel", + "open-dashboard": "Åbn dashboard", + "set-background": "Angiv baggrund", + "background-color": "Baggrundsfarve", + "background-image": "Baggrundsbillede", + "background-size-mode": "Baggrundsstørrelsestilstand", + "no-image": "Intet billede valgt", + "drop-image": "Træk og slip et billede, eller klik for at vælge en fil, der skal uploades.", + "maximum-upload-file-size": "", + "cannot-upload-file": "Filen kan ikke uploades", + "settings": "Indstillinger", + "columns-count": "Kolonneantal", + "columns-count-required": "Kolonneantal er påkrævet.", + "min-columns-count-message": "Kun 10 minimum kolonneantal er tilladt.", + "max-columns-count-message": "Kun 1000 maksimum kolonneantal er tilladt.", + "widgets-margins": "Margin mellem widgets", + "margin-required": "Marginværdi er påkrævet.", + "min-margin-message": "Kun 0 er tilladt som minimummarginværdi.", + "max-margin-message": "Kun 50 er tilladt som maksimummarginværdi.", + "horizontal-margin": "Horisontal margin", + "horizontal-margin-required": "Horisontal marginværdi er påkrævet.", + "min-horizontal-margin-message": "Kun 0 er tilladt som horisontal minimummarginværdi.", + "max-horizontal-margin-message": "Kun 50 er tilladt som horisontal maksimummarginværdi.", + "vertical-margin": "Vertikal margin", + "vertical-margin-required": "Vertikal marginværdi er påkrævet.", + "min-vertical-margin-message": "Kun 0 er tilladt som vertikal minimummarginværdi.", + "max-vertical-margin-message": "Kun 50 er tilladt som vertikal maksimummarginværdi.", + "autofill-height": "Autoudfyld layouthøjde", + "mobile-layout": "Mobile layoutindstillinger", + "mobile-row-height": "Mobil rækkehøjde, px", + "mobile-row-height-required": "Mobil rækkehøjdeværdi er påkrævet.", + "min-mobile-row-height-message": "Kun 5 pixel er tilladt som minimumværdi for mobilrækkehøjde.", + "max-mobile-row-height-message": "Kun 200 pixel er tilladt som maksimumværdi for mobilrækkehøjde.", + "display-title": "Vis dashboardtitel", + "toolbar-always-open": "Hold værktøjslinjen åben", + "title-color": "Titelfarve", + "display-dashboards-selection": "Vis valg af dashboards", + "display-entities-selection": "Vis valg af entiteter", + "display-filters": "Vis filtre", + "display-dashboard-timewindow": "Vis tidsvindue", + "display-dashboard-export": "Vis eksport", + "import": "Importér dashboard", + "export": "Eksportér dashboard", + "export-failed-error": "", + "export-pdf": "Eksportér som PDF", + "export-png": "Eksportér som PNG", + "export-jpg": "Eksportér som JPEG", + "export-json-config": "Eksportér JSON-konfiguration", + "download-dashboard-progress": "", + "create-new-dashboard": "Opret nyt dashboard", + "dashboard-file": "Dashboardfil", + "invalid-dashboard-file-error": "Kunne ikke importere dashboard: Ugyldig dashboarddatastruktur.", + "dashboard-import-missing-aliases-title": "Konfigurer aliasser anvendt af importeret dashboard", + "create-new-widget": "Opret ny widget", + "import-widget": "Importér widget", + "widget-file": "Widget-fil", + "invalid-widget-file-error": "Kan ikke importere widget: Ugyldig widget-datastruktur.", + "widget-import-missing-aliases-title": "Konfigurer aliasser, der bruges af importeret widget", + "open-toolbar": "Skjul dashboardets værktøjslinje", + "close-toolbar": "Luk værktøjslinje", + "configuration-error": "Konfigurationsfejl", + "alias-resolution-error-title": "Konfigurationsfejl i dashboardaliasser", + "invalid-aliases-config": "Kunne ikke finde nogen enheder, der matcher nogle af aliasfiltrene.
Kontakt din administrator for at løse dette problem.", + "select-devices": "Vælg enheder", + "assignedToCustomer": "Tildelt til kunde", + "assignedToCustomers": "Tildelt til kunder", + "public": "Offentlig", + "public-link": "Offentligt link", + "copy-public-link": "Kopiér offentligt link", + "public-link-copied-message": "Dashboardets offentilige link er blevet kopieret til udklipsholderen", + "manage-states": "Administrer dashboardtilstande", + "states": "Dashboardtilstande", + "search-states": "Søg efter dashboardtilstande", + "selected-states": "", + "edit-state": "Rediger dashboardtilstand", + "delete-state": "Slet dashboardtilstand", + "add-state": "Tilføj dashboardtilstand", + "no-states-text": "Ingen tilstande fundet", + "state": "Dashboardtilstand", + "state-name": "Navn", + "state-name-required": "Dashboardtilstandsnavn er påkrævet.", + "state-id": "Tilstands-id", + "state-id-required": "Dashboardtilstands-id er påkrævet.", + "state-id-exists": "Dashboardtilstand med samme id findes allerede.", + "is-root-state": "Rodtilstand", + "delete-state-title": "Slet dashboardtilstand", + "delete-state-text": "", + "show-details": "Vis oplysninger", + "hide-details": "Skjul oplysninger", + "select-state": "Vælg måltilstand", + "state-controller": "Tilstandscontroller", + "selected-dashboards": "", + "search": "Søg efter dashboards", + "home-dashboard": "Startside", + "home-dashboard-hide-toolbar": "Skjul startsidens værktøjslinje", + "select-group-to-add": "Vælg målgruppe for at tilføje valgte dashboards", + "select-group-to-move": "Vælg målgruppe for at flytte valgte dashboards", + "remove-dashboards-from-group": "", + "group": "Gruppe af dashboards", + "list-of-groups": "", + "group-name-starts-with": "" + }, + "datakey": { + "settings": "Indstillinger", + "advanced": "Fremskreden", + "label": "Mærkning", + "color": "Farve", + "units": "Specielt symbol, der vises ved siden af værdi", + "decimals": "Antal cifre efter flydende punkt", + "data-generation-func": "Datagenereringsfunktion", + "use-data-post-processing-func": "Brug dataefterbehandlingsfunktion", + "configuration": "Konfiguration af datanøgle", + "timeseries": "Tidsserier", + "attributes": "Attributter", + "entity-field": "Entitetsfelt", + "alarm": "Alarmfelter", + "timeseries-required": "Entitets tidsserier er påkrævet.", + "timeseries-or-attributes-required": "Entitets tidsserier/attributter er påkrævet.", + "alarm-fields-timeseries-or-attributes-required": "Alarmfelter eller entitets tidsserier/attributter er påkrævet.", + "maximum-timeseries-or-attributes": "", + "alarm-fields-required": "Alarmfelter er påkrævet.", + "function-types": "Funktionstyper", + "function-types-required": "Funktionstyper er påkrævet.", + "maximum-function-types": "", + "time-description": "tidsstempel for den aktuelle værdi", + "value-description": "den aktuelle værdi", + "prev-value-description": "resultat af forrige funktionskald", + "time-prev-description": "tidsstempel for den forrige værdi", + "prev-orig-value-description": "oprindelig tidligere værdi" + }, + "datasource": { + "type": "Datakildetype", + "name": "Navn", + "label": "Mærkning", + "add-datasource-prompt": "Tilføj datakilde" + }, + "details": { + "details": "Oplysninger", + "edit-mode": "Redigeringstilstand", + "edit-json": "Rediger JSON", + "toggle-edit-mode": "Skift redigeringstilstand" + }, + "device": { + "device": "Enhed", + "device-required": "Enhed er påkrævet.", + "devices": "Enheder", + "management": "Enhedsadministration", + "view-devices": "Vis enheder", + "device-alias": "Enhedsalias", + "aliases": "Enhedsaliasser", + "no-alias-matching": "", + "no-aliases-found": "Ingen aliasser fundet.", + "no-key-matching": "", + "no-keys-found": "Ingen nøgler fundet.", + "create-new-alias": "Opret en ny!", + "create-new-key": "Opret en ny!", + "duplicate-alias-error": "", + "configure-alias": "", + "no-devices-matching": "", + "alias": "Alias", + "alias-required": "Enhedsalias er påkrævet.", + "remove-alias": "Fjern enhedsalias", + "add-alias": "Tilføj enhedsalias", + "name-starts-with": "Enhedens navn starter med", + "device-list": "Enhedsliste", + "use-device-name-filter": "Anvend filter", + "device-list-empty": "Ingen enheder valgt.", + "device-name-filter-required": "Enhedsnavnfilter er påkrævet.", + "device-name-filter-no-device-matched": "", + "add": "Tilføj enhed", + "assign-to-customer": "Tildel til kunde", + "assign-device-to-customer": "Tildel enhed(er) til kunde", + "assign-device-to-customer-text": "Vælg de enheder, der skal tildeles kunden", + "make-public": "Gør enheden offentlig", + "make-private": "Gør enheden privat", + "no-devices-text": "Ingen enheder fundet", + "assign-to-customer-text": "Vælg den kunde, der skal tilknyttes enheden/enhederne", + "device-details": "Enhedsoplysninger", + "add-device-text": "Tilføj ny enhed", + "credentials": "Brugeroplysninger", + "manage-credentials": "Administrer brugeroplysninger", + "delete": "Slet enhed", + "assign-devices": "Tildel enheder", + "assign-devices-text": "", + "delete-devices": "Slet enheder", + "unassign-from-customer": "Fjern tildeling fra kunde", + "unassign-devices": "Fjern tildeling af enheder", + "unassign-devices-action-title": "", + "assign-new-device": "Tildel ny enhed", + "make-public-device-title": "", + "make-public-device-text": "Efter bekræftelsen vil enheden og alle dens data blive gjort offentlige og tilgængelige for andre.", + "make-private-device-title": "", + "make-private-device-text": "Efter bekræftelsen vil enheden og alle dens data blive gjort private og vil ikke være tilgængelige for andre.", + "view-credentials": "Vis brugeroplysninger", + "delete-device-title": "", + "delete-device-text": "Vær forsigtig. Efter bekræftelsen vil enheden og alle relaterede data være uoprettelige.", + "delete-devices-title": "", + "delete-devices-action-title": "", + "delete-devices-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte enheder blive fjernet, og alle relaterede data vil være uoprettelige.", + "unassign-device-title": "", + "unassign-device-text": "Efter bekræftelsen vil enhedens tildeling blive fjernet og vil ikke være tilgængelig for kunden.", + "unassign-device": "Fjern tildeling af enhed", + "unassign-devices-title": "", + "unassign-devices-text": "Efter bekræftelsen vil tildelingen af alle valgte enheder blive fjernet og vil ikke være tilgængelige for kunden.", + "device-credentials": "Enhedsbrugeroplysninger", + "credentials-type": "Type af brugeroplysninger", + "access-token": "Adgangstoken", + "access-token-required": "Adgangstoken er påkrævet.", + "access-token-invalid": "Adgangstokenlængden skal være fra 1 til 20 tegn.", + "rsa-key": "RSA offentlig nøgle", + "rsa-key-required": "RSA offentlig nøgle er påkrævet.", + "client-id": "Klient-id", + "client-id-pattern": "Indeholder ugyldigt tegn.", + "user-name": "Brugernavn", + "user-name-required": "Brugernavn er påkrævet.", + "client-id-or-user-name-necessary": "Klient-id og/eller brugernavn er nødvendige", + "password": "Adgangskode", + "secret": "Hemmelig", + "secret-required": "Hemmelig er påkrævet.", + "device-type": "Enhedstype", + "device-type-required": "Enhedstype er påkrævet.", + "select-device-type": "Vælg enhedstype", + "enter-device-type": "Indtast enhedstype", + "any-device": "Enhver enhed", + "no-device-types-matching": "", + "device-type-list-empty": "Ingen enhedstyper valgt.", + "device-types": "Enhedstyper", + "name": "Navn", + "name-required": "Navn er påkrævet.", + "description": "Beskrivelse", + "label": "Mærkning", + "events": "Begivenheder", + "details": "Oplysninger", + "copyId": "Kopiér enheds-id", + "copyAccessToken": "Kopiér adgangstoken", + "copy-mqtt-authentication": "Kopiér MQTT-brugeroplysninger", + "idCopiedMessage": "Enheds-id er blevet kopieret til udklipsholder", + "accessTokenCopiedMessage": "Enhedsadgangstoken er blevet kopieret til udklipsholder", + "mqtt-authentication-copied-message": "Enhedens MQTT-godkendelse er blevet kopieret til udklipsholder", + "assignedToCustomer": "Tildelt til kunde", + "unable-delete-device-alias-title": "Kan ikke slette enhedsalias", + "unable-delete-device-alias-text": "", + "is-gateway": "Er gateway", + "overwrite-activity-time": "Overskriv aktivitetstid for tilsluttet enhed", + "public": "Offentlig", + "device-public": "Enheden er offentlig", + "select-device": "Vælg enhed", + "selected-devices": "", + "search": "Søg efter enheder", + "select-group-to-add": "Vælg målgruppe for at tilføje valgte enheder", + "select-group-to-move": "Vælg målgruppe for at flytte valgte enheder", + "remove-devices-from-group": "", + "group": "Gruppe af enheder", + "list-of-groups": "", + "group-name-starts-with": "", + "import": "Importér enhed", + "device-file": "Enhedsfil", + "device-configuration": "Enhedskonfiguration", + "transport-configuration": "Transportkonfiguration", + "wizard": { + "device-wizard": "Enhedsguide", + "device-details": "Enhedsoplysninger", + "new-device-profile": "Opret ny enhedsprofil", + "existing-device-profile": "Vælg eksisterende enhedsprofil", + "specific-configuration": "Specifik konfiguration", + "customer-to-assign-device": "Kunden skal tildele enheden", + "add-credential": "Tilføj brugeroplysninger" + } + }, + "device-profile": { + "device-profile": "Enhedsprofil", + "device-profiles": "Enhedsprofiler", + "all-device-profiles": "Alle", + "add": "Tilføj enhedsprofil", + "edit": "Rediger enhedsprofil", + "device-profile-details": "Oplysninger om enhedsprofil", + "no-device-profiles-text": "Ingen enhedsprofiler fundet", + "search": "Søg efter enhedsprofiler", + "selected-device-profiles": "", + "no-device-profiles-matching": "", + "device-profile-required": "Enhedsprofil er påkrævet", + "idCopiedMessage": "Enhedsprofil-id er blevet kopieret til udklipsholder", + "set-default": "Gør enhedsprofil standard", + "delete": "Slet enhedsprofil", + "copyId": "Kopiér enhedsprofil-id", + "new-device-profile-name": "Enhedsprofilnavn", + "new-device-profile-name-required": "Enhedsprofilnavn er påkrævet.", + "name": "Navn", + "name-required": "Navn er påkrævet.", + "type": "Profiltype", + "type-required": "Profiltype er påkrævet.", + "type-default": "Standard", + "transport-type": "Transporttype", + "transport-type-required": "Transporttype er påkrævet.", + "transport-type-default": "Standard", + "transport-type-default-hint": "Understøtter grundlæggende MQTT-, HTTP- og CoAP-transport", + "transport-type-mqtt": "MQTT", + "transport-type-mqtt-hint": "Aktiverer avancerede MQTT-transportindstillinger", + "transport-type-lwm2m": "LWM2M", + "transport-type-lwm2m-hint": "LWM2M-transporttype", + "transport-type-coap": "CoAP", + "transport-type-coap-hint": "Aktiverer avancerede CoAP-transportindstillinger", + "description": "Beskrivelse", + "default": "Standard", + "profile-configuration": "Profilkonfiguration", + "transport-configuration": "Transportkonfiguration", + "default-rule-chain": "Standardregelkæde", + "select-queue-hint": "Vælg fra en rulleliste, eller tilføj et brugerdefineret navn.", + "delete-device-profile-title": "", + "delete-device-profile-text": "Vær forsigtig. Efter bekræftelsen vil enhedsprofilen og alle relaterede data være uoprettelige.", + "delete-device-profiles-title": "", + "delete-device-profiles-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte enhedsprofiler blive fjernet, og alle relaterede data vil være uoprettelige.", + "set-default-device-profile-title": "", + "set-default-device-profile-text": "Efter bekræftelsen vil enhedsprofilen blive markeret som standard og vil blive brugt til nye enheder, hvor der ikke er angivet nogen profil.", + "no-device-profiles-found": "Ingen enhedsprofiler fundet.", + "create-new-device-profile": "Opret en ny!", + "mqtt-device-topic-filters": "MQTT-enhedsemnefiltre", + "mqtt-device-topic-filters-unique": "MQTT-enhedsemnefiltre skal være unikke.", + "mqtt-device-payload-type": "MQTT-enhedsdata", + "transport-device-payload-type-json": "JSON", + "transport-device-payload-type-proto": "Protobuf", + "mqtt-payload-type-required": "Datatype er påkrævet.", + "coap-device-type": "CoAP-enhedstype", + "coap-device-payload-type": "CoAP-enhedsdata", + "coap-device-type-required": "CoAP-enhedstype er påkrævet.", + "coap-device-type-default": "Standard", + "coap-device-type-efento": "Efento NB-IoT", + "support-level-wildcards": "Enkelt [+] jokertegn og [#] jokertegn på flere niveauer understøttes.", + "telemetry-topic-filter": "Telemetriemnefilter", + "telemetry-topic-filter-required": "Telemetriemnefilter er påkrævet.", + "attributes-topic-filter": "Attributemnefilter", + "attributes-topic-filter-required": "Attributemnefilter er påkrævet.", + "telemetry-proto-schema": "Telemetri-protoskema", + "telemetry-proto-schema-required": "Telemetri-protoskema er påkrævet.", + "attributes-proto-schema": "Protoskema for attributter", + "attributes-proto-schema-required": "Protoskema for attributter er påkrævet.", + "rpc-response-topic-filter": "RPC-svaremnefilter", + "rpc-response-topic-filter-required": "RPC-svaremnefilter er påkrævet.", + "not-valid-pattern-topic-filter": "Ikke gyldigt mønsteremnefilter", + "not-valid-single-character": "Ugyldig brug af jokertegn i et enkelt niveau", + "not-valid-multi-character": "Ugyldig brug af jokertegn i flere niveauer", + "single-level-wildcards-hint": "[+] er velegnet til ethvert emnefilterniveau. Eks.: v1/enheder/+/telemetri eller +/enheder/+/attributter.", + "multi-level-wildcards-hint": "[#] kan selv erstatte emnefilteret og skal være det sidste symbol i emnet. Eks.: # eller v1/enheder/me/#.", + "alarm-rules": "Alarmregler", + "alarm-rules-with-count": "", + "no-alarm-rules": "Ingen alarmregler konfigureret", + "add-alarm-rule": "Tilføj alarmregel", + "edit-alarm-rule": "Rediger alarmregel", + "alarm-type": "Alarmtype", + "alarm-type-required": "Alarmtype er påkrævet.", + "alarm-type-unique": "Alarmtypen skal være unik inden for alarmreglerne for enhedsprofilen.", + "create-alarm-pattern": "", + "create-alarm-rules": "Opret alarmregler", + "no-create-alarm-rules": "Ingen opret betingelser konfigureret", + "add-create-alarm-rule-prompt": "Tilføj opret alarmregel", + "clear-alarm-rule": "Ryd alarmregel", + "no-clear-alarm-rule": "Ingen klar betingelse konfigureret", + "add-create-alarm-rule": "Tilføj opret betingelse", + "add-clear-alarm-rule": "Tilføj ryd tilstand", + "select-alarm-severity": "Vælg alarmens alvorsgrad", + "alarm-severity-required": "Alarmens alvorsgrad er påkrævet.", + "condition-duration": "Varighed af betingelse", + "condition-duration-value": "Varighedsværdi", + "condition-duration-time-unit": "Tidsenhed", + "condition-duration-value-range": "Varighedsværdien skal ligge i området fra 1 til 2147483647.", + "condition-duration-value-pattern": "Varighedsværdien skal være heltal.", + "condition-duration-value-required": "Varighedsværdi er påkrævet.", + "condition-duration-time-unit-required": "Tidsenhed er påkrævet.", + "advanced-settings": "Avancerede indstillinger", + "alarm-rule-details": "Oplysninger", + "add-alarm-rule-details": "Tilføj oplysninger", + "propagate-alarm": "Overfør alarm", + "alarm-rule-relation-types-list": "Relationstyper, der skal overføres", + "alarm-rule-relation-types-list-hint": "Hvis der ikke vælges Overfør relationstyper vil alarmer blive overført uden filtrering på relationstype.", + "alarm-details": "Alarmoplysninger", + "alarm-rule-condition": "Alarmregelbetingelse", + "enter-alarm-rule-condition-prompt": "Tilføj alarmregelbetingelse", + "edit-alarm-rule-condition": "Rediger alarmregelbetingelse", + "device-provisioning": "Klargøring af enheden", + "provision-strategy": "Strategi for klargøring", + "provision-strategy-required": "Strategi for klargøring er påkrævet.", + "provision-strategy-disabled": "Deaktiveret", + "provision-strategy-created-new": "Tillad oprettelse af nye enheder", + "provision-strategy-check-pre-provisioned": "Kontrollér, om der er forhåndsklargjorte enheder", + "provision-device-key": "Klargøringsenhedsnøgle", + "provision-device-key-required": "Klargøringsenhedsnøgle er påkrævet.", + "copy-provision-key": "Kopiér klargøringsnøgle", + "provision-key-copied-message": "Klargøringsnøgle er blevet kopieret til udklipsholder", + "provision-device-secret": "Klargøringsenhed hemmelig", + "provision-device-secret-required": "Klargøringsenhed hemmelig er påkrævet.", + "copy-provision-secret": "Kopiér klargøring hemmelig", + "provision-secret-copied-message": "Klargøring hemmelig er blevet kopieret til udklipsholder", + "condition": "Betingelse", + "condition-type": "Betingelsestype", + "condition-type-simple": "Enkel", + "condition-type-duration": "Varighed", + "condition-during": "", + "condition-type-repeating": "Gentager", + "condition-type-required": "Betingelsesnavn er påkrævet.", + "condition-repeating-value": "Antal begivenheder", + "condition-repeating-value-range": "Antallet af begivenheder skal ligge i intervallet fra 1 til 2147483647.", + "condition-repeating-value-pattern": "Antal begivenheder skal være heltal.", + "condition-repeating-value-required": "Antal begivenheder er påkrævet.", + "condition-repeat-times": "", + "schedule-type": "Planlægningstype", + "schedule-type-required": "Planlægningstype er påkrævet.", + "schedule": "Tidsplan", + "edit-schedule": "Rediger alarmtidsplan", + "schedule-any-time": "Aktiv hele tiden", + "schedule-specific-time": "Aktiv på et bestemt tidspunkt", + "schedule-custom": "Brugerdefineret", + "schedule-day": { + "monday": "Mandag", + "tuesday": "Tirsdag", + "wednesday": "Onsdag", + "thursday": "Torsdag", + "friday": "Fredag", + "saturday": "Lørdag", + "sunday": "Søndag" + }, + "schedule-days": "Dage", + "schedule-time": "Tid", + "schedule-time-from": "Fra", + "schedule-time-to": "Til", + "schedule-days-of-week-required": "Der skal vælges mindst én ugedag.", + "create-device-profile": "Opret ny enhedsprofil", + "import": "Importér enhedsprofil", + "export": "Eksportér enhedsprofil", + "export-failed-error": "", + "device-profile-file": "Fil for enhedsprofil", + "invalid-device-profile-file-error": "Kan ikke importere enhedsprofil: Ugyldig datastruktur for enhedsprofil." + }, + "dialog": { + "close": "Tæt" + }, + "direction": { + "column": "Kolonne", + "row": "Række" + }, + "error": { + "unable-to-connect": "Kan ikke oprette forbindelse til serveren! Kontrollér din internetforbindelse.", + "unhandled-error-code": "", + "unknown-error": "Ukendt fejl" + }, + "entity": { + "entity": "Entitet", + "entities": "Entiteter", + "entities-count": "Antal entiteter", + "aliases": "Entitetsaliasser", + "entity-alias": "Entitetsalias", + "unable-delete-entity-alias-title": "Entitetsalias kunne ikke slettes", + "unable-delete-entity-alias-text": "", + "duplicate-alias-error": "", + "missing-entity-filter-error": "", + "configure-alias": "", + "alias": "Alias", + "alias-required": "Entitetsalias er påkrævet.", + "remove-alias": "Fjern entitetsalias", + "add-alias": "Tilføj entitetsalias", + "entity-list": "Entitetsliste", + "entity-type": "Entitetstype", + "entity-types": "Entitetstyper", + "entity-type-list": "Liste over entitetstype", + "any-entity": "Enhver entitet", + "enter-entity-type": "Indtast entitetstype", + "no-entities-matching": "", + "no-entity-types-matching": "", + "name-starts-with": "Navnet begynder med", + "use-entity-name-filter": "Anvend filter", + "entity-list-empty": "Ingen entiteter valgt.", + "entity-type-list-empty": "Ingen entitetstyper valgt.", + "entity-name-filter-required": "Entitetsnavnfilter er påkrævet.", + "entity-name-filter-no-entity-matched": "", + "all-subtypes": "Alle", + "select-entities": "Vælg entiteter", + "no-aliases-found": "Ingen aliasser fundet.", + "no-alias-matching": "", + "create-new-alias": "Opret en ny!", + "key": "Nøgle", + "key-name": "Nøglenavn", + "no-keys-found": "Ingen nøgler fundet.", + "no-key-matching": "", + "create-new-key": "Opret en ny!", + "type": "Type", + "type-required": "Entitetstype er påkrævet.", + "type-device": "Enhed", + "type-devices": "Enheder", + "list-of-devices": "", + "device-name-starts-with": "", + "type-device-profile": "Enhedsprofil", + "type-device-profiles": "Enhedsprofiler", + "list-of-device-profiles": "", + "device-profile-name-starts-with": "", + "type-asset": "Aktiv", + "type-assets": "Aktiver", + "list-of-assets": "", + "asset-name-starts-with": "", + "type-entity-view": "Entitetsvisning", + "type-entity-views": "Entitetsvisninger", + "list-of-entity-views": "", + "entity-view-name-starts-with": "", + "type-rule": "Regel", + "type-rules": "Regler", + "list-of-rules": "", + "rule-name-starts-with": "", + "type-plugin": "Plugin", + "type-plugins": "Plugins", + "list-of-plugins": "", + "plugin-name-starts-with": "", + "type-tenant": "Lejer", + "type-tenants": "Lejere", + "list-of-tenants": "", + "tenant-name-starts-with": "", + "type-tenant-profile": "Lejerprofil", + "type-tenant-profiles": "Lejerprofiler", + "list-of-tenant-profiles": "", + "tenant-profile-name-starts-with": "", + "type-customer": "Kunde", + "type-customers": "Kunder", + "list-of-customers": "", + "customer-name-starts-with": "", + "type-user": "Bruger", + "type-users": "Brugere", + "list-of-users": "", + "user-name-starts-with": "", + "type-dashboard": "Dashboard", + "type-dashboards": "Dashboards", + "list-of-dashboards": "", + "dashboard-name-starts-with": "", + "type-alarm": "Alarm", + "type-alarms": "Alarmer", + "list-of-alarms": "", + "alarm-name-starts-with": "", + "type-rulechain": "Regelkæde", + "type-rulechains": "Regelkæder", + "list-of-rulechains": "", + "rulechain-name-starts-with": "", + "type-scheduler-event": "Planlægningsbegivenhed", + "type-scheduler-events": "Planlægningsbegivenheder", + "list-of-scheduler-events": "", + "scheduler-event-name-starts-with": "", + "type-blob-entity": "Blob-entitet", + "type-blob-entities": "Blob-entiteter", + "list-of-blob-entities": "", + "blob-entity-name-starts-with": "", + "type-rulenode": "Regelknude", + "type-rulenodes": "Regelknuder", + "list-of-rulenodes": "", + "rulenode-name-starts-with": "", + "type-current-customer": "Nuværende kunde", + "type-current-tenant": "Nuværende lejer", + "type-current-user": "Nuværende bruger", + "type-current-user-owner": "Nuværende brugerejer", + "search": "Søg efter entiteter", + "selected-entities": "", + "entity-name": "Entitetsnavn", + "entity-label": "Entitetsetiket", + "details": "Entitetsoplysninger", + "no-entities-prompt": "Ingen entiteter fundet", + "no-data": "Ingen data at vise", + "columns-to-display": "Kolonner, der skal vises", + "type-api-usage-state": "Api-brugstilstand", + "type-entity-group": "Entitetsgruppe", + "type-converter": "Dataomformer", + "type-converters": "Dataomformere", + "list-of-converters": "", + "converter-name-starts-with": "", + "type-integration": "Integration", + "type-integrations": "Integrationer", + "list-of-integrations": "", + "integration-name-starts-with": "", + "type-role": "Rolle", + "type-roles": "Roller", + "list-of-roles": "", + "role-name-starts-with": "", + "type-group-permission": "Gruppetilladelse" + }, + "entity-group": { + "entity-group": "Entitetsgruppe", + "details": "Oplysninger", + "columns": "Kolonner", + "add-column": "Tilføj kolonne", + "column-value": "Værdi", + "column-value-required": "Kolonneværdi er påkrævet.", + "column-title": "Titel", + "default-sort-order": "Standardsorteringsrækkefølge", + "default-sort-order-required": "Standardsorteringsrækkefølge er påkrævet.", + "hide-in-mobile-view": "Mobil skjult", + "use-cell-style-function": "Brug celletypefunktion", + "use-cell-content-function": "Brug celleindholdsfunktion", + "edit-column": "Rediger kolonne", + "column-details": "Kolonneoplysninger", + "actions": "Handlinger", + "settings": "Indstillinger", + "search": "Søg entitetsgrupper", + "delete": "Slet entitetsgruppe", + "name": "Navn", + "name-required": "Navn er påkrævet.", + "description": "Beskrivelse", + "add": "Tilføj entitetsgruppe", + "open-entity-group": "Åbn entitetsgruppe", + "add-entity-group-text": "Tilføj ny entitetsgruppe", + "no-entity-groups-text": "Ingen entitetsgrupper fundet", + "entity-group-details": "Oplysninger om entitetsgruppe", + "selected-entity-groups": "", + "delete-entity-groups": "Slet entitetsgrupper", + "delete-entity-group-title": "", + "delete-entity-group-text": "Vær forsigtig. Efter bekræftelsen vil entitetsgruppen og alle relaterede data være uoprettelige.", + "delete-entity-groups-title": "", + "delete-entity-groups-action-title": "", + "delete-entity-groups-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte entitetsgrupper blive fjernet, og alle relaterede data vil være uoprettelige.", + "device-groups": "Enhedsgrupper", + "asset-groups": "Aktivgrupper", + "customer-groups": "Kundegrupper", + "device-group": "Enhedsgruppe", + "asset-group": "Aktivgruppe", + "user-group": "Brugergruppe", + "user-groups": "Brugergrupper", + "customer-group": "Kundegruppe", + "entity-view-groups": "Entitetsvisningsgrupper", + "entity-view-group": "Entitetsvisningsgruppe", + "dashboard-groups": "Dashboardgrupper", + "dashboard-group": "Dashboardgruppe", + "fetch-more": "Hent mere", + "column-type": { + "column-type": "Kolonnetype", + "client-attribute": "Klientattribut", + "shared-attribute": "Delt attribut", + "server-attribute": "Serverattribut", + "timeseries": "Tidsserier", + "entity-field": "Entitetsfelt" + }, + "column-type-required": "Kolonnetype er påkrævet.", + "entity-field": { + "created-time": "Oprettelsestidspunkt", + "name": "Navn", + "type": "Type", + "device_profile": "Enhedsprofil", + "assigned_customer": "Tildelt kunde", + "authority": "Autoritet", + "first_name": "Fornavn", + "last_name": "Efternavn", + "email": "E-mail", + "title": "Titel", + "country": "Land", + "state": "Region", + "city": "By", + "address": "Adresse", + "address2": "Adresse 2", + "zip": "Postnummer", + "phone": "Telefon", + "label": "Mærkning" + }, + "sort-order": { + "asc": "Stigende", + "desc": "Faldende", + "none": "Ingen" + }, + "details-mode": { + "on-row-click": "Ved klik på række", + "on-action-button-click": "Ved klik på knappen Oplysninger", + "disabled": "Deaktiveret" + }, + "change-owner": "Skift ejer", + "select-target-owner": "Vælg målejer", + "no-owners-matching": "", + "target-owner-required": "Målejer er påkrævet.", + "confirm-change-owner-title": "", + "confirm-change-owner-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte enheder blive fjernet fra den aktuelle ejer og blive placeret i gruppen 'Alle' for målejeren.", + "add-to-group": "Tilføj til gruppe", + "move-to-group": "Flyt til gruppe", + "select-entity-group": "Vælg entitetsgruppe", + "no-entity-groups-matching": "", + "target-entity-group-required": "Målentitetsgruppe er påkrævet.", + "select-user-group": "Vælg brugergruppe", + "no-user-groups-matching": "", + "target-user-group-required": "Målbrugergruppe er påkrævet.", + "remove-from-group": "Fjern fra gruppe", + "group-table-title": "Gruppetabeltitel", + "enable-search": "Aktivér entitetssøgning", + "enable-add": "Aktivér tilføjelse af entiteter", + "enable-delete": "Aktivér sletning af entiteter", + "enable-selection": "Aktivér entitetsvalg", + "enable-group-transfer": "Aktivér gruppeoverførselshandlinger", + "display-pagination": "Vis sidenummerering", + "default-page-size": "Standard sidestørrelse", + "enable-assignment-actions": "Aktivér tildelingshandlinger", + "enable-credentials-management": "Aktivér administration af brugeroplysninger", + "enable-login-as-user": "Aktivér login som brugerhandling", + "enable-users-management": "Aktivér administration af brugere", + "enable-customers-management": "Aktivér administration af kunder", + "enable-assets-management": "Aktivér administration af aktiver", + "enable-devices-management": "Aktivér administration af enheder", + "enable-entity-views-management": "Aktivér administration af entitetsvisninger", + "enable-dashboards-management": "Aktivér administration af dashboards", + "open-details-on": "Åbn entitetsoplysninger på", + "select-existing": "Vælg eksisterende entitetsgruppe", + "create-new": "Opret ny entitetsgruppe", + "new-entity-group-name": "Nyt entitetsgruppenavn", + "entity-group-list": "Entitetsgruppeliste", + "entity-group-list-empty": "Ingen entitetsgrupper valgt.", + "name-starts-with": "Entitetsgruppenavn starter med", + "entity-group-name-filter-required": "Entitetsgruppenavnfilter er påkrævet.", + "roles": "Roller", + "permissions": "Tilladelser", + "public": "Offentlig", + "entity-group-public": "Entitetsgruppe er offentlig", + "make-public": "Gør entitetsgruppen offentlig", + "make-private": "Gør entitetsgruppen privat", + "make-public-entity-group-title": "", + "make-public-entity-group-text": "Efter bekræftelsen vil entitetsgruppen og alle dens entiteter blive gjort offentlige og tilgængelige for andre.", + "make-private-entity-group-title": "", + "make-private-entity-group-text": "Efter bekræftelsen vil entitetsgruppen og alle dens entiteter blive gjort private og vil ikke være tilgængelige for andre.", + "share": "Del entitetsgruppe", + "copyId": "Kopiér entitetsgruppe-id", + "idCopiedMessage": "Entitetsgruppe-id er blevet kopieret til udklipsholder", + "entity-group-name": "Entitetsgruppenavn", + "all-users": "Alle brugere" + }, + "entity-field": { + "created-time": "Oprettelsestidspunkt", + "name": "Navn", + "type": "Type", + "first-name": "Fornavn", + "last-name": "Efternavn", + "email": "E-mail", + "title": "Titel", + "country": "Land", + "state": "Region", + "city": "By", + "address": "Adresse", + "address2": "Adresse 2", + "zip": "Postnummer", + "phone": "Telefon", + "label": "Mærkning" + }, + "entity-view": { + "entity-view": "Entitetsvisning", + "entity-view-required": "Entitetsvisning er påkrævet.", + "entity-views": "Entitetsvisninger", + "management": "Administration af entitetsvisning", + "view-entity-views": "Vis entitetsvisninger", + "entity-view-alias": "Alias for entitetsvisning", + "aliases": "Aliasser for entitetsvisning", + "no-alias-matching": "", + "no-aliases-found": "Ingen aliasser fundet.", + "no-key-matching": "", + "no-keys-found": "Ingen nøgler fundet.", + "create-new-alias": "Opret en ny!", + "create-new-key": "Opret en ny!", + "duplicate-alias-error": "", + "configure-alias": "", + "no-entity-views-matching": "", + "public": "Offentlig", + "alias": "Alias", + "alias-required": "Alias for entitetsvisning er påkrævet.", + "remove-alias": "Fjern alias for entitetsvisning", + "add-alias": "Tilføj alias for entitetsvisning", + "name-starts-with": "Entitetsvisningsnavn starter med", + "entity-view-list": "Liste over entitetsvisning", + "use-entity-view-name-filter": "Anvend filter", + "entity-view-list-empty": "Ingen entitetsvisninger valgt.", + "entity-view-name-filter-required": "Entitetsvisningsnavnfilter er påkrævet.", + "entity-view-name-filter-no-entity-view-matched": "", + "add": "Tilføj entitetsvisning", + "entity-view-public": "Entitetsvisning er offentlig", + "assign-to-customer": "Tildel til kunde", + "assign-entity-view-to-customer": "Tildel entitetsvisning(er) til kunde", + "assign-entity-view-to-customer-text": "Vælg de entitetsvisninger, der skal tildeles til kunden", + "no-entity-views-text": "Ingen entitetsvisninger fundet", + "assign-to-customer-text": "Vælg den kunde, der skal tildeles entitetsvisning(er)", + "entity-view-details": "Oplysninger for entitetsvisning", + "add-entity-view-text": "Tilføj ny entitetsvisning", + "delete": "Slet entitetsvisning", + "assign-entity-views": "Tildel entitetsvisninger", + "assign-entity-views-text": "", + "delete-entity-views": "Slet entitetsvisninger", + "make-public": "Gør entitetsvisning offentlig", + "make-private": "Gør entitetsvisning privat", + "unassign-from-customer": "Fjern tildeling fra kunde", + "unassign-entity-views": "Fjern tildeling af entitetsvisninger", + "unassign-entity-views-action-title": "", + "assign-new-entity-view": "Tildel ny entitetsvisning", + "delete-entity-view-title": "", + "delete-entity-view-text": "Vær forsigtig. Efter bekræftelsen vil entitetsvisningen og alle relaterede data være uoprettelige.", + "delete-entity-views-title": "", + "delete-entity-views-action-title": "", + "delete-entity-views-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte entitetsvisninger blive fjernet, og alle relaterede data vil være uoprettelige.", + "make-public-entity-view-title": "", + "make-public-entity-view-text": "Efter bekræftelsen vil entitetsvisningen og alle dens data blive gjort offentlige og tilgængelige for andre.", + "make-private-entity-view-title": "", + "make-private-entity-view-text": "Efter bekræftelsen vil entitetsvisningen og alle dens data blive gjort private og vil ikke være tilgængelige for andre.", + "unassign-entity-view-title": "", + "unassign-entity-view-text": "Efter bekræftelsen vil entitetsvisningens tildeling blive fjernet og vil ikke være tilgængelig for kunden.", + "unassign-entity-view": "Fjern tildeling af entitetsvisning", + "unassign-entity-views-title": "", + "unassign-entity-views-text": "Efter bekræftelsen vil tildelingen af alle valgte entitetsvisninger blive fjernet og vil ikke være tilgængelige for kunden.", + "entity-view-type": "Entitetsvisningstype", + "entity-view-type-required": "Entitetsvisningstype er påkrævet.", + "select-entity-view-type": "Vælg entitetsvisningstype", + "enter-entity-view-type": "Indtast entitetsvisningstype", + "any-entity-view": "Enhver entitetsvisning", + "no-entity-view-types-matching": "", + "entity-view-type-list-empty": "Der er ikke valgt nogen entitetsvisningstyper.", + "entity-view-types": "Entitetsvisningstyper", + "created-time": "Oprettelsestidspunkt", + "name": "Navn", + "name-required": "Navn er påkrævet.", + "description": "Beskrivelse", + "events": "Begivenheder", + "details": "Oplysninger", + "copyId": "Kopiér entitetsvisnings-id", + "idCopiedMessage": "Entitetsvisnings-id er blevet kopieret til udklipsholder", + "assignedToCustomer": "Tildelt til kunde", + "unable-entity-view-device-alias-title": "Kan ikke slette entitetsvisningsalias", + "unable-entity-view-device-alias-text": "", + "select-entity-view": "Vælg entitetsvisning", + "start-date": "Startdato", + "start-ts": "Starttid", + "end-date": "Slutdato", + "end-ts": "Sluttid", + "date-limits": "Datofrister", + "client-attributes": "Klientattributter", + "shared-attributes": "Delte attributter", + "server-attributes": "Serverattributter", + "timeseries": "Tidsserier", + "client-attributes-placeholder": "Klientattributter", + "shared-attributes-placeholder": "Delte attributter", + "server-attributes-placeholder": "Serverattributter", + "timeseries-placeholder": "Tidsserier", + "target-entity": "Målentitet", + "attributes-propagation": "Overførsel af attributter", + "attributes-propagation-hint": "Entitetsvisning vil automatisk kopiere specificerede attributter fra målentitet, hver gang du gemmer eller opdaterer denne entitetsvisning. Af ydelsesmæssige årsager overføres målenhedsattributter ikke til entitetsvisning ved hver attributændring. Du kan aktivere automatisk overførsel ved at konfigurere regelknuden \"Kopiér til visning\" i din regelkæde og knytte meddelelserne \"Postattributter\" og \"Attributter opdateret\" til den nye regelknude.", + "timeseries-data": "Tidsseriedata", + "timeseries-data-hint": "Konfigurer tidsseriedatanøgler for målentiteten, der vil være tilgængelige for entitetsvisningen. Disse tidsseriedata er skrivebeskyttede.", + "selected-entity-views": "", + "search": "Søg efter entitetsvisninger", + "select-group-to-add": "Vælg målgruppe for at tilføje valgte entitetsvisninger", + "select-group-to-move": "Vælg målgruppe for at flytte valgte entitetsvisninger", + "remove-entity-views-from-group": "", + "group": "Gruppe af entitetsvisninger", + "list-of-groups": "", + "group-name-starts-with": "" + }, + "event": { + "events": "Begivenheder", + "event-type": "Begivenhedstype", + "type-error": "Fejl", + "type-lc-event": "Livscyklusbegivenhed", + "type-rw-event": "Rådata", + "type-stats": "Statistikker", + "type-debug-converter": "Debug", + "type-debug-integration": "Debug", + "type-debug-rule-node": "Debug", + "type-debug-rule-chain": "Debug", + "no-events-prompt": "Ingen begivenheder fundet", + "error": "Fejl", + "alarm": "Alarm", + "event-time": "Begivenhedstidspunkt", + "server": "Server", + "body": "Tekst", + "method": "Metode", + "type": "Type", + "in": "Ind", + "out": "Ud", + "metadata": "Metadata", + "message": "Meddelelse", + "entity": "Entitet", + "message-id": "Meddelelses-id", + "message-type": "Meddelelsestype", + "data-type": "Datatype", + "relation-type": "Relationstype", + "data": "Data", + "event": "Begivenhed", + "status": "Status", + "success": "Succes", + "failed": "Mislykket", + "messages-processed": "Behandlede meddelelser", + "errors-occurred": "Der opstod fejl", + "uuid": "UUID" + }, + "extension": { + "extensions": "Udvidelser", + "selected-extensions": "", + "type": "Type", + "key": "Nøgle", + "value": "Værdi", + "id": "Id", + "extension-id": "Udvidelses-id", + "extension-type": "Udvidelsestype", + "transformer-json": "JSON *", + "unique-id-required": "Aktuelt udvidelses-id findes allerede.", + "delete": "Slet udvidelse", + "add": "Tilføj udvidelse", + "edit": "Rediger udvidelse", + "view": "Vis udvidelse", + "delete-extension-title": "", + "delete-extension-text": "Vær forsigtig. Efter bekræftelsen vil udvidelsen og alle relaterede data være uoprettelige.", + "delete-extensions-title": "", + "delete-extensions-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte udvidelser blive fjernet.", + "converters": "Omformere", + "converter-id": "Omformer-id", + "configuration": "Konfiguration", + "converter-configurations": "Omformerkonfigurationer", + "token": "Sikkerhedstoken", + "add-converter": "Tilføj omformer", + "add-config": "Tilføj omformerkonfiguration", + "device-name-expression": "Enhedsnavnudtryk", + "device-type-expression": "Enhedstypeudtryk", + "custom": "Brugerdefineret", + "to-double": "Til dobbelt", + "transformer": "Transformer", + "json-required": "Transformer-json er påkrævet.", + "json-parse": "Kan ikke parse transformer-json.", + "attributes": "Attributter", + "add-attribute": "Tilføj attribut", + "add-map": "Tilføj tilknytningselement", + "timeseries": "Tidsserier", + "add-timeseries": "Tilføj tidsserier", + "field-required": "Felt er påkrævet", + "brokers": "Mæglere", + "add-broker": "Tilføj mægler", + "host": "Vært", + "port": "Port", + "port-range": "Porten skal ligge i området fra 1 til 65535.", + "ssl": "Ssl", + "credentials": "Brugeroplysninger", + "username": "Brugernavn", + "password": "Adgangskode", + "retry-interval": "Forsøg interval igen i millisekunder", + "sas": "Signatur for delt adgang", + "anonymous": "Anonym", + "basic": "Basis", + "pem": "PEM", + "ca-cert": "CA-certifikatfil *", + "private-key": "Privat nøglefil *", + "cert": "Certifikatfil *", + "no-file": "Ingen fil valgt.", + "drop-file": "Træk og slip en fil, eller klik for at vælge en fil, der skal uploades.", + "mapping": "Tilknytning", + "topic-filter": "Emnefilter", + "converter-type": "Omformertype", + "converter-json": "Json", + "json-name-expression": "Udtryk for enhedsnavn json", + "topic-name-expression": "Udtryk for enhedsnavnemne", + "json-type-expression": "Udtryk for enhedstype json", + "topic-type-expression": "Udtryk for enhedstypeemne", + "attribute-key-expression": "Udtryk for attributnøgle", + "attr-json-key-expression": "Udtryk for attributnøgle json", + "attr-topic-key-expression": "Udtryk for attributnøgleemne", + "request-id-expression": "Udtryk for anmodnings-id", + "request-id-json-expression": "Udtryk for anmodnings-id json", + "request-id-topic-expression": "Udtryk for anmodnings-id emne", + "response-topic-expression": "Udtryk for svaremne", + "value-expression": "Udtryk for værdi", + "topic": "Emne", + "timeout": "Timeout i millisekunder", + "converter-json-required": "Omformer-json er påkrævet.", + "converter-json-parse": "Omformeren json kunne ikke parses.", + "filter-expression": "Udtryk for filter", + "connect-requests": "Tilslutningsanmodninger", + "add-connect-request": "Tilføj tilslutningsanmodning", + "disconnect-requests": "Afbryd anmodninger", + "add-disconnect-request": "Tilføj afbrydelsesanmodning", + "attribute-requests": "Attributanmodninger", + "add-attribute-request": "Tilføj attributanmodning", + "attribute-updates": "Attributopdateringer", + "add-attribute-update": "Tilføj attributopdatering", + "server-side-rpc": "Serverside RPC", + "add-server-side-rpc-request": "Tilføj serverside RPC-anmodning", + "device-name-filter": "Enhedsnavnfilter", + "attribute-filter": "Attributfilter", + "method-filter": "Metodefilter", + "request-topic-expression": "Anmod om udtryk for emne", + "response-timeout": "Svartimeout i millisekunder", + "topic-expression": "Udtryk for emne", + "client-scope": "Klientomfang", + "add-device": "Tilføj enhed", + "opc-server": "Servere", + "opc-add-server": "Tilføj server", + "opc-add-server-prompt": "Tilføj venligst server", + "opc-application-name": "Applikationsnavn", + "opc-application-uri": "Applikation uri", + "opc-scan-period-in-seconds": "Scanningsperiode i sekunder", + "opc-security": "Sikkerhed", + "opc-identity": "Identitet", + "opc-keystore": "Keystore", + "opc-type": "Type", + "opc-keystore-type": "Type", + "opc-keystore-location": "Placering *", + "opc-keystore-password": "Adgangskode", + "opc-keystore-alias": "Alias", + "opc-keystore-key-password": "Nøgleadgangskode", + "opc-device-node-pattern": "Mønster for enhedsknude", + "opc-device-name-pattern": "Mønster for enhedsnavn", + "modbus-server": "Servere/slaver", + "modbus-add-server": "Tilføj server/slave", + "modbus-add-server-prompt": "Tilføj venligst server/slave", + "modbus-transport": "Transport", + "modbus-tcp-reconnect": "Automatisk gentilslutning", + "modbus-rtu-over-tcp": "RTU over TCP", + "modbus-port-name": "Serielt portnavn", + "modbus-encoding": "Kodning", + "modbus-parity": "Paritet", + "modbus-baudrate": "Baudrate", + "modbus-databits": "Databits", + "modbus-stopbits": "Stopbits", + "modbus-databits-range": "Databits skal ligge i området fra 7 til 8.", + "modbus-stopbits-range": "Stopbits skal ligge i området fra 1 til 2.", + "modbus-unit-id": "Enheds-id", + "modbus-unit-id-range": "Enheds-id skal ligge i området fra 1 til 247.", + "modbus-device-name": "Enhedsnavn", + "modbus-poll-period": "Undersøgelsesperiode (ms)", + "modbus-attributes-poll-period": "Attributundersøgelsesperiode (ms)", + "modbus-timeseries-poll-period": "Tidsserieundersøgelsesperiode (ms)", + "modbus-poll-period-range": "Undersøgelsesperioden skal have positiv værdi.", + "modbus-tag": "Tag", + "modbus-function": "Funktion", + "modbus-register-address": "Registeradresse", + "modbus-register-address-range": "Registeradresse skal ligge i området fra 0 til 65535.", + "modbus-register-bit-index": "Bitindeks", + "modbus-register-bit-index-range": "Bitindeks skal ligge i området fra 0 til 15.", + "modbus-register-count": "Registeroptælling", + "modbus-register-count-range": "Registeroptælling skal være en positiv værdi.", + "modbus-byte-order": "Byterækkefølge", + "sync": { + "status": "Status", + "sync": "Synkroniseret", + "not-sync": "Ikke synkroniseret", + "last-sync-time": "Sidste synkroniseringstidspunkt", + "not-available": "Ikke til rådighed" + }, + "export-extensions-configuration": "Konfiguration af eksportér udvidelser", + "import-extensions-configuration": "Konfiguration af importér udvidelser", + "import-extensions": "Importér udvidelser", + "import-extension": "Importér udvidelse", + "export-extension": "Eksportér udvidelse", + "file": "Fil for udvidelser", + "invalid-file-error": "Ugyldig udvidelsesfil", + "text": "TEKST", + "json": "JSON", + "binary": "BINÆR", + "hex": "HEX" + }, + "filter": { + "add": "Tilføj filter", + "edit": "Rediger filter", + "name": "Filternavn", + "name-required": "Filternavn er påkrævet.", + "duplicate-filter": "Filter med samme navn findes allerede.", + "filters": "Filtre", + "unable-delete-filter-title": "Filteret kunne ikke slettes", + "unable-delete-filter-text": "", + "duplicate-filter-error": "", + "missing-key-filters-error": "", + "filter": "Filter", + "editable": "Redigerbar", + "no-filters-found": "Ingen filtre fundet.", + "no-filter-text": "Intet filter angivet", + "add-filter-prompt": "Tilføj venligst filter", + "no-filter-matching": "", + "create-new-filter": "Opret en ny!", + "filter-required": "Filter er påkrævet.", + "operation": { + "operation": "Driftsopgave", + "equal": "lig med", + "not-equal": "ikke lig med", + "starts-with": "starter med", + "ends-with": "slutter med", + "contains": "indeholder", + "not-contains": "indeholder ikke", + "greater": "større end", + "less": "mindre end", + "greater-or-equal": "større end eller lig med", + "less-or-equal": "mindre end eller lig med", + "and": "og", + "or": "eller" + }, + "ignore-case": "ignorer versalfølsomhed", + "value": "Værdi", + "remove-filter": "Fjern filter", + "preview": "Visning af filter", + "no-filters": "Ingen filtre konfigureret", + "add-filter": "Tilføj filter", + "add-complex-filter": "Tilføj komplekst filter", + "add-complex": "Tilføj kompleks", + "complex-filter": "Komplekst filter", + "edit-complex-filter": "Rediger komplekst filter", + "edit-filter-user-params": "Rediger filterprædikat for brugerparametre", + "filter-user-params": "Filtrerprædikat for brugerparametre", + "user-parameters": "Brugerparametre", + "display-label": "Etiket, der skal vises", + "autogenerated-label": "Generer automatisk etiket", + "order-priority": "Prioritet af feltrækkefølge", + "key-filter": "Nøglefilter", + "key-filters": "Nøglefiltre", + "key-name": "Nøglenavn", + "key-name-required": "Nøglenavn er påkrævet.", + "key-type": { + "key-type": "Nøgletype", + "attribute": "Attribut", + "timeseries": "Tidsserier", + "entity-field": "Entitetsfelt", + "constant": "Konstant" + }, + "value-type": { + "value-type": "Værditype", + "string": "Streng", + "numeric": "Numerisk", + "boolean": "Boolesk", + "date-time": "Datotid" + }, + "value-type-required": "Nøgleværditype er påkrævet.", + "key-value-type-change-title": "Er du sikker på, at du vil ændre nøgleværditypen?", + "key-value-type-change-message": "Hvis du bekræfter ny værditype, fjernes alle indtastede nøglefiltre.", + "no-key-filters": "Ingen nøglefiltre konfigureret", + "add-key-filter": "Tilføj nøglefilter", + "remove-key-filter": "Fjern nøglefilter", + "edit-key-filter": "Rediger nøglefilter", + "date": "Dato", + "time": "Tid", + "current-tenant": "Nuværende lejer", + "current-customer": "Nuværende kunde", + "current-user": "Nuværende bruger", + "current-device": "Nuværende enhed", + "default-value": "Standardværdi", + "dynamic-source-type": "Dynamisk kildetype", + "no-dynamic-value": "Ingen dynamisk værdi", + "source-attribute": "Kildeattribut", + "switch-to-dynamic-value": "Skift til dynamisk værdi", + "switch-to-default-value": "Skift til standardværdi", + "inherit-owner": "Nedarv fra ejer", + "source-attribute-not-set": "Hvis kildeattributten ikke er angivet" + }, + "fullscreen": { + "expand": "Udvid til fuld skærm", + "exit": "Afslut fuldskærm", + "toggle": "Skift mellem fuldskærmstilstand", + "fullscreen": "Fuld skærm" + }, + "function": { + "function": "Funktion" + }, + "gateway": { + "add-entry": "Tilføj konfiguration", + "connector-add": "Tilføj ny stikforbindelse", + "connector-enabled": "Aktivér stikforbindelse", + "connector-name": "Navn på stikforbindelse", + "connector-name-required": "Navn på stikforbindelse er påkrævet.", + "connector-type": "Stikforbindelsestype", + "connector-type-required": "Stikforbindelsestype er påkrævet.", + "connectors": "Konfiguration af stikforbindelser", + "create-new-gateway": "Opret en ny gateway", + "create-new-gateway-text": "", + "delete": "Slet konfiguration", + "download-tip": "Download konfigurationsfil", + "gateway": "Gateway", + "gateway-exists": "Enhed med samme navn findes allerede.", + "gateway-name": "Gateway-navn", + "gateway-name-required": "Gateway-navn er påkrævet.", + "gateway-saved": "Gateway-konfigurationen blev gemt.", + "json-parse": "Ikke gyldig JSON.", + "json-required": "Feltet må ikke være tomt.", + "no-connectors": "Ingen stikforbindelser", + "no-data": "Ingen konfigurationer", + "no-gateway-found": "Ingen gateway fundet.", + "no-gateway-matching": "", + "path-logs": "Sti til logfiler", + "path-logs-required": "Sti er påkrævet.", + "remote": "Fjernkonfiguration", + "remote-logging-level": "Logføringsniveau", + "remove-entry": "Fjern konfiguration", + "save-tip": "Gem konfigurationsfil", + "security-type": "Sikkerhedstype", + "security-types": { + "access-token": "Adgangstoken", + "tls": "TLS" + }, + "storage": "Lagring", + "storage-max-file-records": "Maks. antal poster i fil", + "storage-max-files": "Maks. antal filer", + "storage-max-files-min": "Min. antal er 1.", + "storage-max-files-pattern": "Antal er ikke gyldigt.", + "storage-max-files-required": "Antal er påkrævet.", + "storage-max-records": "Maks. antal poster i lagring", + "storage-max-records-min": "Min. antal poster er 1.", + "storage-max-records-pattern": "Antal er ikke gyldigt.", + "storage-max-records-required": "Maks. antal poster er påkrævet.", + "storage-pack-size": "Maks. antal pakkestørrelse for begivenhed", + "storage-pack-size-min": "Min. antal er 1.", + "storage-pack-size-pattern": "Antal er ikke gyldigt.", + "storage-pack-size-required": "Maks. antal pakkestørrelse for begivenhed er påkrævet.", + "storage-path": "Lagringssti", + "storage-path-required": "Lagringssti er påkrævet.", + "storage-type": "Lagringstype", + "storage-types": { + "file-storage": "Lagring af filter", + "memory-storage": "Lagring af hukommelse" + }, + "thingsboard": "ThingsBoard", + "thingsboard-host": "ThingsBoard-vært", + "thingsboard-host-required": "Vært er påkrævet.", + "thingsboard-port": "ThingsBoard-port", + "thingsboard-port-max": "Maks. portnummer er 65535.", + "thingsboard-port-min": "Min. portnummer er 1.", + "thingsboard-port-pattern": "Port er ikke gyldig.", + "thingsboard-port-required": "Port er påkrævet.", + "tidy": "Tidy", + "tidy-tip": "Tidy konfig. JSON", + "title-connectors-json": "", + "tls-path-ca-certificate": "Sti til CA-certifikat på gateway", + "tls-path-client-certificate": "Sti til klientcertifikat på gateway", + "tls-path-private-key": "Sti til privat nøgle på gateway", + "toggle-fullscreen": "Skift til fuld skærm", + "transformer-json-config": "Konfiguration JSON*", + "update-config": "Tilføj/opdater konfiguration JSON" + }, + "grid": { + "delete-item-title": "Er du sikker på, du ønsker at slette dette element?", + "delete-item-text": "Vær forsigtig. Efter bekræftelsen vil dette element og alle relaterede data være uoprettelige.", + "delete-items-title": "", + "delete-items-action-title": "", + "delete-items-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte elementer blive fjernet, og alle relaterede data vil være uoprettelige.", + "add-item-text": "Tilføj nyt element", + "no-items-text": "Ingen elementer fundet", + "item-details": "Oplysninger om element", + "delete-item": "Slet element", + "delete-items": "Slet elementer", + "scroll-to-top": "Gå til toppen" + }, + "help": { + "goto-help-page": "Gå til hjælpesiden" + }, + "home": { + "home": "Hjem", + "profile": "Profil", + "logout": "Log ud", + "menu": "Menu", + "avatar": "Avatar", + "open-user-menu": "Åbn brugermenu" + }, + "import": { + "no-file": "Ingen fil valgt", + "drop-file": "Træk og slip en JSON-fil, eller klik for at vælge en fil, der skal uploades.", + "drop-csv-file": "Træk og slip en CSV-fil, eller klik for at vælge en fil, der skal uploades.", + "drop-file-csv": "Træk og slip en CSV-fil, eller klik for at vælge en fil, der skal uploades.", + "column-value": "Værdi", + "column-title": "Titel", + "column-example": "Eksempel på værdidata", + "column-key": "Attribut-/telemetrinøgle", + "csv-delimiter": "CSV-skilletegn", + "csv-first-line-header": "Første linje indeholder kolonnenavne", + "csv-update-data": "Opdater attributter/telemetri", + "import-csv-number-columns-error": "En fil skal indeholde mindst to kolonner", + "import-csv-invalid-format-error": "", + "column-type": { + "name": "Navn", + "type": "Type", + "label": "Mærkning", + "column-type": "Kolonnetype", + "client-attribute": "Klientattribut", + "shared-attribute": "Delt attribut", + "server-attribute": "Serverattribut", + "timeseries": "Tidsserier", + "entity-field": "Entitetsfelt", + "access-token": "Adgangstoken", + "isgateway": "Er gateway", + "activity-time-from-gateway-device": "Aktivitetstid fra gateway-enhed", + "description": "Beskrivelse" + }, + "stepper-text": { + "select-file": "Vælg en fil", + "configuration": "Importér konfiguration", + "column-type": "Vælg kolonnetype", + "creat-entities": "Oprettelse af nye entiteter", + "done": "Udført" + }, + "message": { + "create-entities": "", + "update-entities": "", + "error-entities": "" + } + }, + "integration": { + "integration": "Integration", + "integrations": "Integrationer", + "select-integration": "Vælg integration", + "no-integrations-matching": "", + "integration-required": "Integration er påkrævet", + "delete": "Slet integration", + "management": "Integrationsstyring", + "add-integration-text": "Tilføj ny integration", + "no-integrations-text": "Ingen integrationer fundet", + "selected-integrations": "", + "delete-integration-title": "", + "delete-integration-text": "Vær forsigtig. Efter bekræftelsen vil integrationen og alle relaterede data være uoprettelige.", + "delete-integrations-title": "", + "delete-integrations-action-title": "", + "delete-integrations-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte integrationer blive fjernet, og alle relaterede data vil være uoprettelige.", + "events": "Begivenheder", + "enabled": "Aktiveret", + "allow-create-devices-or-assets": "Tillad oprettelse af enheder eller aktiver", + "add": "Tilføj integration", + "search": "Søg efter integrationer", + "integration-details": "Integrationsoplysninger", + "details": "Oplysninger", + "copyId": "Kopiér integrations-id", + "idCopiedMessage": "Integrations-id er blevet kopieret til udklipsholder", + "debug-mode": "Debug-tilstand", + "enable-security": "Aktivér sikkerhed", + "enable-security-new": "Aktivér sikkerhed for automatiske tokenopdateringer", + "headers-filter": "Filter for overskrifter", + "header": "Overskrift", + "no-headers-filter": "Intet filter for overskrifter", + "downlink-url": "Downlink URL", + "downlink-url-required": "Downlink URL er påkrævet", + "create-loriot-output": "Opret Loriot-applikationsoutput", + "send-downlink": "Send downlink", + "server": "Server", + "server-required": "Server er påkrævet", + "app-id": "Applikations-id", + "app-id-required": "Applikations-id er påkrævet", + "app-token": "Applikationsadgangstoken", + "app-token-required": "Applikationsadgangstoken er påkrævet", + "email": "E-mail", + "email-required": "E-mail er påkrævet", + "application-uri": "Applikation URI", + "as-id": "AS-id", + "as-id-required": "AS-id er påkrævet.", + "as-key": "AS-nøgle", + "as-key-required": "AS-nøgle er påkrævet.", + "client-id-new": "Klient-id", + "client-id-new-required": "Klient-id (login) er påkrævet (login).", + "client-secret": "Klient hemmelig", + "client-secret-required": "Klient hemmelig (adgangskode) er påkrævet (adgangskode).", + "max-time-diff-in-seconds": "Maksimal tidsforskel (sekunder)", + "max-time-diff-in-seconds-required": "Maksimal tidsforskel er påkrævet.", + "created-time": "Oprettelsestidspunkt", + "name": "Navn", + "name-required": "Navn er påkrævet.", + "description": "Beskrivelse", + "base-url": "Basis-URL", + "base-url-required": "Basis-URL er påkrævet", + "security-key": "Sikkerhedsnøgle", + "http-endpoint": "HTTP-slutpunkts-URL", + "replace-no-content-to-ok": "Erstat svarstatus fra 'Intet indhold' til 'OK'", + "copy-http-endpoint-url": "Kopiér HTTP-slutpunkts-URL", + "http-endpoint-url-copied-message": "HTTP-slutpunkts-URL er blevet kopieret til udklipsholder", + "host": "Vært", + "host-required": "Vært er påkrævet.", + "host-type": "Værtstype", + "host-type-required": "Værtstype er påkrævet.", + "custom-host": "Brugerdefineret vært", + "custom-host-required": "Brugerdefineret vært er påkrævet.", + "port": "Port", + "port-required": "Port er påkrævet.", + "port-range": "Porten skal ligge i området fra 1 til 65535.", + "connect-timeout": "Forbindelsestimeout (sek.)", + "connect-timeout-required": "Forbindelsestimeout er påkrævet.", + "connect-timeout-range": "Forbindelsestimeout skal ligge i området fra 1 til 200.", + "client-id": "Klient-id", + "client-id-required": "Klient-id er påkrævet.", + "client-id-range": "Klient-id skal ligge i et interval fra 1 til 23 tegn. [MQTT-3.1.3-5]", + "client-id-pattern": "Klient-id skal bestå af tal og store og små bogstaver. [MQTT-3.1.3-5]", + "max-bytes-in-message": "Maksimum bytes i meddelelse", + "max-bytes-in-message-range": "Maksimum bytes i meddelelsen skal ligge i området fra 1 til 256000000.", + "device-id": "Enheds-id", + "device-id-required": "Enheds-id er påkrævet.", + "device-id-range": "Enheds-id'et skal ligge i området fra 1 til 65535 tegn.", + "device-id-pattern": "Enheds-id'et skal bestå af tal og store og små bogstaver. [MQTT-3.1.3-5]", + "group-id": "Gruppe-id", + "group-id-required": "Gruppe-id er påkrævet.", + "topics": "Emner", + "topics-required": "Emne er påkrævet.", + "routing-keys": "Routing-nøgler", + "routing-keys-required": "Routing-nøgle er påkrævet.", + "queues": "Køer", + "queues-required": "Kønavn er påkrævet.", + "exchange-name": "Udskiftningsnavn", + "exchange-name-required": "Udskiftningsnavn er påkrævet.", + "downlink-topic": "Downlink-emne", + "connection-timeout": "Forbindelsestimeout, ms", + "connection-timeout-min": "Ugyldig forbindelsestimeoutværdi.", + "handshake-timeout": "Handshake-timeout, ms", + "handshake-timeout-min": "Ugyldig handshake-timeoutværdi.", + "virtual-host": "Virtuel vært", + "rabbit-mq-poll-interval": "Undersøgelsesinterval, ms", + "rabbit-mq-poll-interval-min": "Ugyldig undersøgelsesintervalværdi.", + "application-server-url": "Applikationsserver URL", + "application-server-api-token": "Applikationsserver API-token", + "application-server-api-token-required": "Applikationsserver API-token er påkrævet.", + "bootstrap-servers": "Bootstrap-servere", + "bootstrap-servers-required": "Bootstrap-servere er påkrævet.", + "poll-interval": "Undersøgelsesinterval", + "poll-interval-required": "Undersøgelsesinterval er påkrævet.", + "auto-create-topics": "Opret emner automatisk", + "clean-session": "Ryd session", + "enable-ssl": "Aktivér SSL", + "credentials": "Brugeroplysninger", + "credentials-type": "Type af brugeroplysninger", + "credentials-type-required": "Type af brugeroplysninger er påkrævet.", + "username": "Brugernavn", + "username-required": "Brugernavn er påkrævet.", + "password": "Adgangskode", + "password-required": "Brugernavn er påkrævet.", + "azure-ca-cert": "CA-certifikatfil", + "ca-cert": "CA-certifikatfil *", + "private-key": "Privat nøglefil *", + "private-key-password": "Adgangskode til privat nøgle", + "cert": "Certifikatfil *", + "no-file": "Ingen fil valgt.", + "drop-file": "Træk og slip en fil, eller klik for at vælge en fil, der skal uploades.", + "check-connection": "Kontrollér forbindelsen", + "check-success": "Forbindelse oprettet.", + "topic-filters": "Emnefiltre", + "remove-topic-filter": "Fjern emnefilter", + "add-topic-filter": "Tilføj emnefilter", + "add-topic-filter-prompt": "Tilføj venligst emnefilter", + "topic": "Emne", + "mqtt-qos": "QoS", + "mqtt-qos-at-most-once": "Højst én gang", + "mqtt-qos-at-least-once": "Mindst én gang", + "mqtt-qos-exactly-once": "Præcis én gang", + "downlink-topic-pattern": "Mønster for downlink-emne", + "downlink-topic-pattern-required": "Mønster for downlink-emne er påkrævet.", + "aws-access-key-id": "AWS-adgangsnøgle-id", + "aws-secret-access-key": "AWS hemmelig adgangsnøgle", + "aws-region": "Region", + "aws-iot-endpoint": "AWS IoT-slutpunkt", + "aws-iot-endpoint-required": "AWS IoT-slutpunkt er påkrævet.", + "aws-iot-credentials": "AWS IoT-brugeroplysninger", + "aws-sqs-polling-period-in-seconds": "Undersøgelsesperiode i sekunder", + "aws-sqs-queue-url": "SQS Kø URL", + "aws-sqs-queue-url-required": "SQS Kø URL er påkrævet", + "aws-sqs-access-key-id-required": "Adgangsnøgle-id er påkrævet", + "aws-sqs-secret-access-key-required": "Hemmelig adgangsnøgle er påkrævet", + "application-credentials": "Applikationsbrugeroplysninger", + "api-key": "API-nøgle", + "api-key-required": "API-nøgle er påkrævet.", + "api-key-format": "Ugyldigt API-nøgleformat.", + "auth-token": "Godkendelsestoken", + "auth-token-required": "Godkendelsestoken er påkrævet.", + "region": "Region", + "region-required": "Region er påkrævet.", + "application-id": "Applikations-id", + "application-id-required": "Applikations-id er påkrævet.", + "access-key": "Adgangsnøgle", + "access-key-required": "Adgangsnøgle er påkrævet.", + "connection-parameters": "Tilslutningsparametre", + "service-bus-namespace-name": "Namespace-navn for servicebus", + "service-bus-namespace-name-required": "Namespace-navn for servicebus er påkrævet.", + "connection-string": "Tilslutningsstreng", + "connection-string-required": "Tilslutningsstreng påkrævet!", + "event-hub-name": "Navn på begivenhedshub", + "event-hub-name-required": "Navn på begivenhedshub er påkrævet.", + "event-iot-hub-name-required": "Iot-hubnavn er påkrævet for downlink", + "sas-key-name": "SAS-nøglenavn", + "sas-key-name-required": "SAS-nøglenavn er påkrævet.", + "sas-key": "SAS-nøgle", + "sas-key-required": "SAS-nøgle er påkrævet.", + "iot-hub-name": "IoT-hubnavn (påkrævet for downlink)", + "hostname": "Værtsnavn", + "hostname-required": "Værtsnavn er påkrævet", + "integration-clazz": "Integrationsklasse", + "integration-clazz-required": "Integrationsklasse er påkrævet", + "integration-configuration": "Konfiguration af integration JSON", + "metadata": "Metadata", + "type": "Type", + "type-required": "Type er påkrævet.", + "uplink-converter": "Uplink-dataomformer", + "uplink-converter-required": "Uplink-dataomformer er påkrævet.", + "downlink-converter": "Downlink-dataomformer", + "type-http": "HTTP", + "type-ocean-connect": "OceanConnect", + "type-sigfox": "SigFox", + "type-thingpark": "ThingPark", + "type-loriot": "Loriot", + "type-thingpark-enterprise": "ThingParkEnterprise", + "type-tmobile-iot-cdp": "T-Mobile – IoT CDP", + "type-mqtt": "MQTT", + "type-aws-iot": "AWS IoT", + "type-aws-sqs": "AWS SQS", + "type-aws-kinesis": "AWS-kinese", + "type-ibm-watson-iot": "IBM Watson IoT", + "type-ttn": "TheThingsNetwork", + "type-tti": "The Things Stack", + "type-chirpstack": "ChirpStack", + "type-azure-event-hub": "Azure-begivenhedshub", + "type-azure-iot-hub": "Azure IoT-hub", + "type-opc-ua": "OPC-UA", + "type-custom": "Brugerdefineret", + "type-udp": "UDP", + "type-tcp": "TCP", + "type-kafka": "Kafka", + "type-rabbitmq": "RabbitMQ", + "type-pubsub": "Pub/Sub", + "opc-ua-application-name": "Applikationsnavn", + "opc-ua-application-uri": "Applikation uri", + "opc-ua-scan-period-in-seconds": "Scanningsperiode i sekunder", + "opc-ua-scan-period-in-seconds-required": "Scanningsperiode er påkrævet", + "opc-ua-timeout": "Timeout i millisekunder", + "opc-ua-timeout-required": "Timeout er påkrævet", + "opc-ua-security": "Sikkerhed", + "opc-ua-security-required": "Sikkerhed er påkrævet", + "opc-ua-identity": "Identitet", + "opc-ua-identity-required": "Identitet er påkrævet", + "opc-ua-keystore": "Keystore", + "add-opc-ua-keystore-prompt": "Tilføj venligst keystore-fil", + "opc-ua-keystore-required": "Keystore er påkrævet", + "opc-ua-type": "Type", + "opc-ua-keystore-type": "Type", + "opc-ua-keystore-type-required": "Type er påkrævet", + "opc-ua-keystore-location": "Placering *", + "opc-ua-keystore-password": "Adgangskode", + "opc-ua-keystore-password-required": "Adgangskode er påkrævet", + "opc-ua-keystore-alias": "Alias", + "opc-ua-keystore-alias-required": "Alias er påkrævet", + "opc-ua-keystore-key-password": "Nøgleadgangskode", + "opc-ua-keystore-key-password-required": "Adgangskode er påkrævet", + "opc-ua-mapping": "Tilknytning", + "add-opc-ua-mapping-prompt": "Tilføj tilknytning", + "opc-ua-mapping-type": "Tilknytningstype", + "opc-ua-mapping-type-required": "Tilknytningstype er påkrævet", + "opc-ua-device-node-pattern": "Enhedsknudemønster", + "opc-ua-device-node-pattern-required": "Enhedsknudemønster er påkrævet", + "opc-ua-namespace": "Namespace", + "opc-ua-add-map": "Tilføj tilknytningselement", + "kinesis-stream-name": "Streamnavn", + "kinesis-stream-name-required": "Streamnavn er påkrævet", + "kinesis-region": "Region", + "kinesis-region-required": "Region er påkrævet", + "kinesis-access-key-id": "Adgangsnøgle-id", + "kinesis-access-key-id-required": "Adgangsnøgle-id er påkrævet", + "kinesis-secret-access-key": "Hemmelig adgangsnøgle", + "kinesis-secret-access-key-required": "Hemmelig adgangsnøgle er påkrævet", + "kinesis-use-consumers-with-enhanced-fan-out": "Anvend forbrugere med forbedret Fan-Out", + "kinesis-use-credentials-from-instance-metadata": "Anvend brugeroplysninger fra Amazon EC2 Instance Metadata Service", + "kinesis-application-name": "Applikationsnavn (som standard lig med Streamnavn)", + "kinesis-initial-position-in-stream": "Startposition i stream", + "kinesis-initial-position-in-stream-required": "Startposition i stream påkrævet", + "kinesis-max-records": "Maks. poster", + "kinesis-max-records-required": "Maks. poster er påkrævet", + "kinesis-max-records-length-range": "Maks. længde for poster skal ligge i et område fra 1 til 10000", + "kinesis-request-timeout": "Anmodningstimeout i sekunder", + "kinesis-request-timeout-required": "Anmodningstimeout er påkrævet", + "other-properties": "Andre egenskaber", + "subscription-tags": "Abonnementstags", + "remove-subscription-tag": "Fjern abonnementstags", + "add-subscription-tag": "Tilføj abonnementstags", + "add-subscription-tag-prompt": "Tilføj venligst abonnementstags", + "key": "Nøgle", + "path": "Sti", + "required": "Påkrævet", + "integration-key": "Integrationsnøgle", + "copy-integration-key": "Kopiér integrationsnøgle", + "integration-key-copied-message": "Integrationsnøgle er blevet kopieret til udklipsholder", + "integration-secret": "Integration hemmelig", + "copy-integration-secret": "Kopiér integration hemmelig", + "integration-secret-copied-message": "Integration hemmelig er kopieret til udklipsholder", + "execute-remotely": "Fjernbetjent udførelse", + "handler-configuration": "Handler-konfiguration", + "handler-configuration-type": "Handler-type", + "so-broadcast": "Aktivér broadcast – integration accepterer adressepakker for broadcast", + "so-keepalive-option": "Muliggør afsendelse af keepalive-meddelelser på tilslutningsorienterede stik", + "so-reuse-addr": "Bind processen til en port", + "tcp-no-delay": "Tvinger et stik til at sende data uden buffer (deaktiver Nagle's bufferalgoritme)", + "fail-fast": "Undtagelse, når dekoderen bemærker, at rammelængden vil overstige maksimumstørrelse", + "strip-delimiter": "Fjern skilletegn", + "length-field-offset": "Feltforskydning for længde", + "length-field-offset-required": "Feltforskydning for længde er påkrævet.", + "length-field-offset-range": "Feltforskydning for længde skal ligge i et område fra 0 til 8.", + "length-field-length": "Længdefeltlængde", + "length-field-length-required": "Længdefeltlængde er påkrævet.", + "length-field-length-range": "Længdefeltlængde skal ligge i et område fra 0 til 8.", + "length-adjustment": "Længdejustering (kompenseringsværdien, der skal lægges til værdien af længdefeltet)", + "length-adjustment-required": "Længdejustering er påkrævet.", + "length-adjustment-range": "Længdejustering skal ligge i et område fra 0 til 8.", + "byte-order": "Byterækkefølge for længdefeltet", + "initial-bytes-to-strip": "Antal første bytes, der skal fjernes fra den afkodede ramme", + "initial-bytes-to-strip-required": "Antal første bytes, der skal fjernes fra den afkodede ramme, er påkrævet.", + "initial-bytes-to-strip-range": "Antal første bytes, der skal fjernes fra den afkodede ramme, skal ligge i området fra 0 til 8.", + "so-backlog-option": "Maks. antal ventende tilslutninger på stikket", + "so-backlog-option-required": "Maks. antal ventende tilslutninger på stikket er påkrævet.", + "so-backlog-option-range": "Maks. antal ventende tilslutninger på stikket skal ligge i området fra 1 til 65535.", + "so-rcv-buf": "Bufferens størrelse til indgående stik (i KB)", + "so-rcv-buf-required": "Bufferens størrelse til indgående stik (i KB) er påkrævet.", + "so-rcv-buf-range": "Bufferens størrelse til indgående stik (i KB) skal ligge i området fra 1 til 65535.", + "so-snd-buf": "Bufferens størrelse til udgående stik (i KB)", + "so-snd-buf-required": "Bufferens størrelse til udgående stik (i KB) er påkrævet.", + "so-snd-buf-range": "Bufferens størrelse til udgående stik (i KB) skal ligge i et område fra 1 til 65535.", + "charset-name": "Tegnsætnavn", + "charset-name-required": "Tegnsætnavn er påkrævet.", + "message-separator": "Meddelelsesseparator", + "message-separator-required": "Meddelelsesseparator er påkrævet.", + "character-sequence": "Tegnsekvens", + "character-sequence-required": "Tegnsekvens er påkrævet.", + "max-frame-length": "Maks. rammelængde (i bytes)", + "max-frame-length-required": "Maks. rammelængde (i bytes) er påkrævet.", + "max-frame-length-range": "Maks. rammelængde (i byte) skal ligge i området fra 1 til 65535.", + "handler-type": "Handler-type", + "message-size": "Meddelelsesstørrelse", + "message-size-required": "Meddelelsesstørrelse er påkrævet.", + "type-apache-pulsar": "Apache Pulsar", + "service-url": "Service-URL", + "service-url-required": "Service-URL er påkrævet.", + "subscription-name": "Abonnementsnavn", + "subscription-name-required": "Abonnementsnavn er påkrævet.", + "max-num-messages": "Maks. antal meddelelser", + "max-num-messages-required": "Maks. antal meddelelser er påkrævet.", + "max-num-bytes": "Maks. antal bytes", + "max-num-bytes-required": "Maks. antal bytes påkrævet.", + "timeout-in-ms": "Timeout i millisekunder", + "timeout-in-ms-required": "Timeout i millisekunder er påkrævet.", + "user-id": "Bruger-id", + "user-id-required": "Bruger-id er påkrævet.", + "token": "Token", + "token-required": "Token er påkrævet.", + "project-id": "Projekt-id", + "project-id-required": "Projekt-id er påkrævet.", + "subscription-id": "Abonnements-id", + "subscription-id-required": "Abonnements-id er påkrævet.", + "service-account-key": "Nøglefil til servicekonto", + "service-account-key-required": "Nøglefil til servicekonto er påkrævet.", + "tcp": { + "system-line-separator": "Systemlinjeseparator", + "nul-delimiter": "Nul-skilletegn", + "byte-order-little-endian": "Little Endian", + "byte-order-big-endian": "Big Endian" + }, + "cache-size": "Cachestørrelse", + "cache-time-to-live": "Cache time-to-live i minutter", + "min-cache-size": "Cachestørrelse kan ikke være lavere 0", + "min-cache-time-to-live": "Cache time-to-live kan ikke være lavere 0", + "max-cache-time-to-live": "Ugyldigt cache time-to-live, vælg mellem 0 og 525600" + }, + "item": { + "selected": "Valgt" + }, + "js-func": { + "no-return-error": "Funktionen skal returnere værdi!", + "return-type-mismatch": "", + "tidy": "Tidy", + "mini": "Mini" + }, + "key-val": { + "key": "Nøgle", + "value": "Værdi", + "remove-entry": "Fjern post", + "add-entry": "Tilføj post", + "no-data": "Ingen poster" + }, + "layout": { + "layout": "Layout", + "manage": "Administrer layouts", + "settings": "Layoutindstillinger", + "color": "Farve", + "main": "Hoved", + "right": "Højre", + "select": "Vælg mållayout" + }, + "legend": { + "direction": "Signaturforklaringens retning", + "position": "Signaturforklaringens placering", + "sort-legend": "Sortér datanøgler i signaturforklaring", + "show-max": "Vis maks. værdi", + "show-min": "Vis min. værdi", + "show-avg": "Vis gennemsnitsværdi", + "show-total": "Vis samlet værdi", + "settings": "Indstillinger for signaturforklaring", + "min": "min.", + "max": "maks.", + "avg": "gns.", + "total": "i alt", + "comparison-time-ago": { + "previousInterval": "(tidligere interval)", + "days": "(dag siden)", + "weeks": "(uge siden)", + "months": "(måned siden)", + "years": "(år siden)" + } + }, + "login": { + "login": "Log på", + "request-password-reset": "Anmod om nulstilling af adgangskode", + "reset-password": "Nulstil adgangskode", + "create-password": "Opret adgangskode", + "passwords-mismatch-error": "De indtastede adgangskoder skal være ens!", + "password-again": "Gentag adgangskode", + "sign-in": "Log på", + "username": "Brugernavn (e-mail)", + "remember-me": "Husk mig", + "forgot-password": "Glemt adgangskode?", + "password-reset": "Nulstilling af adgangskode", + "expired-password-reset-message": "Dine brugeroplysninger er udløbet! Opret venligst en ny adgangskode.", + "new-password": "Ny adgangskode", + "new-password-again": "Gentag ny adgangskode", + "password-link-sent-message": "Link til nulstilling af adgangskode blev sendt!", + "email": "E-mail", + "no-account": "Har du ikke en konto?", + "create-account": "Opret en konto", + "login-with": "Log ind med din e-mail", + "or": "eller", + "error": "Login-fejl" + }, + "signup": { + "firstname": "Fornavn", + "lastname": "Efternavn", + "email": "E-mail", + "signup": "Tilmeld", + "create-password": "Opret en adgangskode", + "repeat-password": "Gentag din adgangskode", + "have-account": "Har du allerede en konto?", + "signin": "Log på", + "no-captcha-message": "Du skal bekræfte, at du ikke er en robot", + "password-length-message": "Din adgangskode skal bestå af mindst 6 tegn", + "email-verification": "E-mailbekræftelse", + "email-verification-message": "Der er sendt en e-mail med bekræftelsesoplysninger til den angivne e-mailadresse.
Følg instruktionerne i e-mailen for at fuldføre din tilmeldingsprocedure.
Bemærk: Hvis du ikke har set e-mailen efter et stykke tid, skal du tjekke din 'spam'-mappe eller forsøge at sende e-mailen igen ved at klikke på knappen 'Send igen'.", + "account-activation-title": "Aktivering af konto", + "account-activated": "Kontoen er aktiveret!", + "account-activated-text": "Tillykke!
Din konto er blevet aktiveret.", + "resend": "Send igen", + "inactive-user-exists-title": "Inaktiv bruger findes allerede", + "inactive-user-exists-text": "Der er allerede registreret en bruger med en ikke-bekræftet e-mailadresse.
Klik på knappen \"Send igen\", hvis du ønsker at sende bekræftelses-e-mailen igen.", + "activating-account": "Aktiverer konto...", + "activating-account-text": "Din konto er i øjeblikket ved at blive aktiveret. Vent venligst...", + "accept-privacy-policy": "Accepter fortrolighedspolitik", + "accept": "Accepter", + "privacy-policy": "Fortrolighedspolitik" + }, + "position": { + "top": "Top", + "bottom": "Bund", + "left": "Venstre", + "right": "Højre" + }, + "profile": { + "profile": "Profil", + "last-login-time": "Sidste login", + "change-password": "Skift adgangskode", + "current-password": "Nuværende adgangskode" + }, + "relation": { + "relations": "Relationer", + "direction": "Retning", + "search-direction": { + "FROM": "Fra", + "TO": "Til" + }, + "direction-type": { + "FROM": "fra", + "TO": "til" + }, + "from-relations": "Udgående relationer", + "to-relations": "Indgående relationer", + "selected-relations": "", + "type": "Type", + "to-entity-type": "Til entitetstype", + "to-entity-name": "Til entitetsnavn", + "from-entity-type": "Fra entitetstype", + "from-entity-name": "Fra entitetsnavn", + "to-entity": "Til entitet", + "from-entity": "Fra entitet", + "delete": "Slet relation", + "relation-type": "Relationstype", + "relation-type-required": "Relationstype er påkrævet.", + "any-relation-type": "Enhver type", + "add": "Tilføj relation", + "edit": "Rediger relation", + "delete-to-relation-title": "", + "delete-to-relation-text": "", + "delete-to-relations-title": "", + "delete-to-relations-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte relationer blive fjernet, og tilsvarende entiteter vil ikke være relaterede til den aktuelle entitet.", + "delete-from-relation-title": "", + "delete-from-relation-text": "", + "delete-from-relations-title": "", + "delete-from-relations-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte relationer blive fjernet, og den aktuelle entitet vil ikke være relateret til de tilsvarende entiteter.", + "remove-relation-filter": "Fjern relationsfilter", + "add-relation-filter": "Tilføj relationsfilter", + "any-relation": "Enhver relation", + "relation-filters": "Relationsfiltre", + "additional-info": "Yderligere info (JSON)", + "invalid-additional-info": "Kan ikke parse yderligere info-json.", + "no-relations-text": "Ingen relationer fundet" + }, + "rulechain": { + "rulechain": "Regelkæde", + "rulechains": "Regelkæder", + "root": "Rod", + "delete": "Slet regelkæde", + "name": "Navn", + "name-required": "Navn er påkrævet.", + "description": "Beskrivelse", + "add": "Tilføj regelkæde", + "set-root": "Lav regelkæde for rod", + "set-root-rulechain-title": "", + "set-root-rulechain-text": "Efter bekræftelsen vil regelkæden være rod og håndtere alle indgående transportmeddelelser.", + "delete-rulechain-title": "", + "delete-rulechain-text": "Vær forsigtig. Efter bekræftelsen vil regelkæden og alle relaterede data være uoprettelige.", + "delete-rulechains-title": "", + "delete-rulechains-action-title": "", + "delete-rulechains-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte regelkæder blive fjernet, og alle relaterede data vil være uoprettelige.", + "add-rulechain-text": "Tilføj ny regelkæde", + "no-rulechains-text": "Ingen regelkæder fundet", + "rulechain-details": "Oplysninger om regelkæde", + "details": "Oplysninger", + "events": "Begivenheder", + "system": "System", + "import": "Importér regelkæde", + "export": "Eksportér regelkæde", + "export-failed-error": "", + "create-new-rulechain": "Opret ny regelkæde", + "rulechain-file": "Regelkædefil", + "invalid-rulechain-file-error": "Regelkæden kunne ikke importeres: Ugyldig datastruktur for regelkæde.", + "copyId": "Kopiér regelkæde-id", + "idCopiedMessage": "Regelkæde-id er blevet kopieret til udklipsholder", + "select-rulechain": "Vælg regelkæde", + "no-rulechains-matching": "", + "rulechain-required": "Regelkæde er påkrævet", + "management": "Regelstyring", + "debug-mode": "Debug-tilstand", + "search": "Søg efter regelkæder", + "selected-rulechains": "", + "open-rulechain": "Åbn regelkæde" + }, + "rulenode": { + "details": "Oplysninger", + "events": "Begivenheder", + "search": "Søg efter knuder", + "open-node-library": "Åbn knudebibliotek", + "add": "Tilføj regelknude", + "name": "Navn", + "name-required": "Navn er påkrævet.", + "type": "Type", + "description": "Beskrivelse", + "delete": "Slet regelknude", + "select-all-objects": "Vælg alle knuder og tilslutninger", + "deselect-all-objects": "Fravælg alle knuder og tilslutninger", + "delete-selected-objects": "Slet valgte knuder og tilslutninger", + "delete-selected": "Slet valgte", + "select-all": "Vælg alle", + "copy-selected": "Kopiér valgte", + "deselect-all": "Fravælg alle", + "rulenode-details": "Oplysninger om regelknude", + "debug-mode": "Debug-tilstand", + "configuration": "Konfiguration", + "link": "Link", + "link-details": "Oplysninger om regelknudelink", + "add-link": "Tilføj link", + "link-label": "Link-etiket", + "link-label-required": "Link-etiket er påkrævet.", + "custom-link-label": "Brugerdefineret link-etiket", + "custom-link-label-required": "Brugerdefineret link-etiket er påkrævet.", + "link-labels": "Link-etiketter", + "link-labels-required": "Link-etiketter er påkrævet.", + "no-link-labels-found": "Ingen link-etiketter fundet", + "no-link-label-matching": "", + "create-new-link-label": "Opret en ny!", + "type-filter": "Filter", + "type-filter-details": "Filtrer indgående meddelelser med konfigurerede betingelser", + "type-enrichment": "Berigelse", + "type-enrichment-details": "Tilføj yderligere oplysninger i meddelelsesmetadata", + "type-transformation": "Omdannelse", + "type-transformation-details": "Skift meddelelsesdata og metadata", + "type-action": "Handling", + "type-action-details": "Gennemfør ekstrahandling", + "type-analytics": "Analytik", + "type-analytics-details": "Udfør analyse af streamede eller vedvarende data", + "type-external": "Ekstern", + "type-external-details": "Interagerer med eksternt system", + "type-rule-chain": "Regelkæde", + "type-rule-chain-details": "Videresender indgående meddelelser til specificeret regelkæde", + "type-input": "Input", + "type-input-details": "Logisk input af regelkæde, videresender indgående meddelelser til næste relaterede regelknude", + "type-unknown": "Ukendt", + "type-unknown-details": "Uløst regelknude", + "directive-is-not-loaded": "", + "ui-resources-load-error": "Kunne ikke indlæse konfigurations-UI-ressourcer.", + "invalid-target-rulechain": "Kan ikke løse målregelkæde!", + "test-script-function": "Testscriptfunktion", + "message": "Meddelelse", + "message-type": "Meddelelsestype", + "select-message-type": "Vælg meddelelsestype", + "message-type-required": "Meddelelsestype er påkrævet", + "metadata": "Metadata", + "metadata-required": "Metadataposter må ikke være tomme.", + "output": "Output", + "test": "Test", + "help": "Hjælp", + "reset-debug-mode": "Nulstil debug-tilstand i alle knuder" + }, + "role": { + "role": "Rolle", + "roles": "Roller", + "management": "Rollestyring", + "view-roles": "Vis roller", + "no-roles-matching": "", + "role-list": "Rolleliste", + "add": "Tilføj rolle", + "view": "Vis rolle", + "search": "Søg efter roller", + "selected-roles": "", + "no-roles-text": "Ingen roller fundet", + "role-details": "Rolleoplysninger", + "add-role-text": "Tilføj ny rolle", + "delete": "Slet rolle", + "delete-roles": "Slet roller", + "delete-role-title": "", + "delete-role-text": "Vær forsigtig. Efter bekræftelsen vil rollen og alle relaterede data være uoprettelige.", + "delete-roles-title": "", + "delete-roles-action-title": "", + "delete-roles-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte roller blive fjernet, og alle relaterede data vil være uoprettelige.", + "role-type": "Rolletype", + "role-type-required": "Rolletype er påkrævet.", + "select-role-type": "Vælg rolletype", + "enter-role-type": "Indtast rolletype", + "any-role": "Enhver rolle", + "no-role-types-matching": "", + "role-type-list-empty": "Ingen rolletyper valgt.", + "role-types": "Rolletyper", + "created-time": "Oprettelsestidspunkt", + "name": "Navn", + "name-required": "Navn er påkrævet.", + "description": "Beskrivelse", + "events": "Begivenheder", + "details": "Oplysninger", + "copyId": "Kopiér rolle-id", + "idCopiedMessage": "Rolle-id er blevet kopieret til udklipsholder", + "permissions": "Tilladelser", + "role-required": "Rolle påkrævet", + "roles-required": "Roller påkrævet", + "display-type": { + "GENERIC": "Generisk", + "GROUP": "Gruppe" + } + }, + "group-permission": { + "user-group-roles": "Brugergrupperoller", + "entity-group-permissions": "Tilladelser for entitetsgruppe", + "role-type": "Rolletype", + "role-name": "Rollenavn", + "group-type": "Gruppetype", + "group-name": "Gruppenavn", + "group-owner": "Gruppeejer", + "user-group-name": "Brugergruppenavn", + "user-group-owner": "Brugergruppeejer", + "edit": "Rediger tilladelser", + "delete": "Slet tilladelser", + "selected-group-permissions": "", + "delete-group-permission-title": "", + "delete-group-permission-text": "Vær forsigtig. Efter bekræftelsen vil gruppetilladelsen og alle relaterede data være uoprettelige.", + "delete-group-permission": "Slet gruppetilladelse", + "delete-group-permissions-title": "", + "delete-group-permissions-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte gruppetilladelser blive fjernet, og tilsvarende brugere vil miste adgang til specificerede ressourcer.", + "delete-group-permissions": "Slet gruppetilladelser", + "add-group-permission": "Tilføj gruppetilladelse", + "edit-group-permission": "Rediger gruppetilladelse", + "entity-group": "Entitetsgruppe", + "user-group": "Brugergruppe", + "no-owners-matching": "", + "target-owner-required": "Entitetsgruppeejer er påkrævet.", + "target-user-group-owner-required": "Brugergruppeejer er påkrævet.", + "no-group-permissions-text": "Ingen gruppetilladelser fundet" + }, + "permission": { + "permissions-required": "Mindst én tilladelsespost skal angives.", + "remove-permission": "Fjern tilladelsespost", + "add-permission": "Tilføj tilladelsespost", + "other": "Andet", + "resource": { + "resource": "Ressource", + "select-resource": "Vælg ressource", + "resource-required": "Ressource er påkrævet", + "no-resources-matching": "", + "display-type": { + "ALL": "Alle", + "PROFILE": "Profil", + "ADMIN_SETTINGS": "Admin-indstillinger", + "ALARM": "Alarm", + "DEVICE": "Enhed", + "DEVICE_PROFILE": "Enhedsprofil", + "ASSET": "Aktiv", + "CUSTOMER": "Kunde", + "DASHBOARD": "Dashboard", + "ENTITY_VIEW": "Entitetsvisning", + "TENANT": "Lejer", + "TENANT_PROFILE": "Lejerprofil", + "RULE_CHAIN": "Regelkæde", + "USER": "Bruger", + "WIDGETS_BUNDLE": "Widgets-bundt", + "WIDGET_TYPE": "Widget-type", + "CONVERTER": "Omformer", + "INTEGRATION": "Integration", + "SCHEDULER_EVENT": "Planlægningsbegivenheder", + "BLOB_ENTITY": "Blob-entitet", + "CUSTOMER_GROUP": "Kundegruppe", + "DEVICE_GROUP": "Enhedsgruppe", + "ASSET_GROUP": "Aktivgruppe", + "USER_GROUP": "Brugergruppe", + "ENTITY_VIEW_GROUP": "Entitetsvisningsgruppe", + "DASHBOARD_GROUP": "Dashboardgruppe", + "ROLE": "Rolle", + "GROUP_PERMISSION": "Gruppetilladelse", + "WHITE_LABELING": "Hvid mærkning", + "AUDIT_LOG": "Auditlog", + "API_USAGE_STATE": "API-brugstilstand" + } + }, + "operation": { + "operation": "Driftsopgave", + "operations": "Driftsopgaver", + "operations-required": "Der skal angives mindst én driftsopgave.", + "enter-operation": "Indtast driftsopgave.", + "no-operations-matching": "", + "display-type": { + "ALL": "Alle", + "CREATE": "Opret", + "READ": "Læs", + "WRITE": "Skriv", + "DELETE": "Slet", + "ASSIGN_TO_CUSTOMER": "Tildel til kunde", + "UNASSIGN_FROM_CUSTOMER": "Fjern tildeling fra kunde", + "RPC_CALL": "RPC-opkald", + "READ_CREDENTIALS": "Læs brugeroplysninger", + "WRITE_CREDENTIALS": "Skriv brugeroplysninger", + "READ_ATTRIBUTES": "Læs attributter", + "WRITE_ATTRIBUTES": "Skriv attributter", + "READ_TELEMETRY": "Læs telemetri", + "WRITE_TELEMETRY": "Skriv telemetri", + "CLAIM_DEVICES": "Gør krav på enheder", + "IMPERSONATE": "Efterlign", + "CHANGE_OWNER": "Skift ejer", + "ADD_TO_GROUP": "Tilføj til gruppe", + "REMOVE_FROM_GROUP": "Fjern fra gruppe", + "SHARE_GROUP": "Del gruppe", + "ASSIGN_TO_TENANT": "Tildel til lejer" + } + } + }, + "scheduler": { + "scheduler": "Planlægger", + "scheduler-event": "Planlægningsbegivenhed", + "select-scheduler-event": "Vælg planlægningsbegivenhed", + "no-scheduler-events-matching": "", + "scheduler-event-required": "Planlægningsbegivenhed er påkrævet", + "management": "Tidsplansstyring", + "scheduler-events": "Planlægningsbegivenheder", + "add-scheduler-event": "Tilfjøj planlægningsbegivenhed", + "search-scheduler-events": "Søg efter planlægningsbegivenheder", + "created-time": "Oprettelsestidspunkt", + "name": "Navn", + "type": "Type", + "created_customer": "Oprettet af kunde", + "edit-scheduler-event": "Rediger planlægningsbegivenhed", + "view-scheduler-event": "Vis planlægningsbegivenhed", + "delete-scheduler-event": "Slet planlægningsbegivenhed", + "no-scheduler-events": "Ingen planlægningsbegivenheder fundet", + "selected-scheduler-events": "", + "delete-scheduler-event-title": "", + "delete-scheduler-event-text": "Vær forsigtig. Efter bekræftelsen vil planlægningsbegivenheden og alle relaterede data være uoprettelige.", + "delete-scheduler-events-title": "", + "delete-scheduler-events-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte planlægningsbegivenheder blive fjernet, og alle relaterede data vil være uoprettelige.", + "create": "Opret planlægningsbegivenhed", + "edit": "Rediger planlægningsbegivenhed", + "view": "Vis planlægningsbegivenhed", + "name-required": "Navn er påkrævet.", + "configuration": "Konfiguration", + "schedule": "Tidsplan", + "start-time": "Starttid", + "repeat": "Gentag", + "repeats": "Gentagelser", + "daily": "Daglig", + "weekly": "Ugentlig", + "monthly": "Månedlig", + "yearly": "Årlig", + "timer": "Timerbaseret", + "repeats-required": "Gentagelser er påkrævet.", + "repeat-on": "Gentag den", + "repeat-every": "Gentag hver", + "ends-on": "Slutter den", + "sunday-label": "L", + "monday-label": "M", + "tuesday-label": "T", + "wednesday-label": "O", + "thursday-label": "T", + "friday-label": "F", + "saturday-label": "L", + "repeat-on-sunday": "Gentag på søndag", + "repeat-on-monday": "Gentag på mandag", + "repeat-on-tuesday": "Gentag på tirsdag", + "repeat-on-wednesday": "Gentag på onsdag", + "repeat-on-thursday": "Gentag på torsdag", + "repeat-on-friday": "Gentag på fredag", + "repeat-on-saturday": "Gentag på lørdag", + "event-type": "Begivenhedstype", + "select-event-type": "Vælg begivenhedstype", + "event-type-required": "Begivenhedstype er påkrævet.", + "list-mode": "Listevisning", + "calendar-mode": "Kalendervisning", + "calendar-view-type": "Kalendervisningstype", + "month": "Måned", + "week": "Uge", + "day": "Dag", + "agenda-week": "Program for uge", + "agenda-day": "Program for dag", + "list-year": "Liste for år", + "list-month": "Liste for måned", + "list-week": "Liste for uge", + "list-day": "Liste for dag", + "today": "I dag", + "navigate-before": "Naviger før", + "navigate-next": "Naviger næste", + "starting-from": "Starter fra", + "until": "til og med", + "on": "den", + "sunday": "Søndag", + "monday": "Mandag", + "tuesday": "Tirsdag", + "wednesday": "Onsdag", + "thursday": "Torsdag", + "friday": "Fredag", + "saturday": "Lørdag", + "originator": "Ophavsmand", + "single-entity": "Enkelt entitet", + "group-of-entities": "Gruppe af entiteter", + "entities-group-owner": "Ejer af gruppe af entiteter", + "single-device": "Enkelt enhed", + "group-of-devices": "Gruppe af enheder", + "devices-group-owner": "Ejer af gruppe af enheder", + "message-body": "Meddelelsestekst", + "target": "Mål", + "rpc-method": "Metode", + "rpc-method-required": "Metode er påkrævet", + "rpc-params": "Parametre", + "select-dashboard-state": "Vælg dashboardtilstand", + "hours": "Timer", + "minutes": "Minutter", + "seconds": "Sekunder", + "time-interval-required": "Tidsinterval er påkrævet", + "time-unit-required": "Tidsenhed er påkrævet", + "every-hour": "", + "every-minute": "", + "every-second": "" + }, + "report": { + "report-config": "Rapportkonfiguration", + "email-config": "E-mailkonfiguration", + "dashboard-state-param": "Parameterværdi for dashboardtilstand", + "base-url": "Basis-URL", + "base-url-required": "Basis-URL er påkrævet.", + "use-dashboard-timewindow": "Brug dashboardtidsvindue", + "timewindow": "Tidsvindue", + "name-pattern": "Rapportnavnsmønster", + "name-pattern-required": "Rapportnavnsmønster er påkrævet", + "type": "Rapporttype", + "use-current-user-credentials": "Brug aktuelle brugeroplysninger", + "customer-user-credentials": "Kundens brugeroplysninger", + "customer-user-credentials-required": "Kundens brugeroplysninger er påkrævet", + "generate-test-report": "Generer testrapport", + "send-email": "Send e-mail", + "from": "Fra", + "from-required": "Fra er påkrævet.", + "to": "Til", + "to-required": "Til er påkrævet.", + "cc": "Cc", + "bcc": "Bcc", + "subject": "Emne", + "subject-required": "Emne er påkrævet.", + "body": "Tekst", + "body-required": "Tekst er påkrævet." + }, + "blob-entity": { + "blob-entity": "Blob-entitet", + "select-blob-entity": "Vælg blob-entitet", + "no-blob-entities-matching": "", + "blob-entity-required": "Blob-entitet er påkrævet", + "files": "Filer", + "search": "Søg efter filer", + "clear-search": "Ryd søgning", + "no-blob-entities-prompt": "Ingen filer fundet", + "report": "Rapport", + "created-time": "Oprettelsestidspunkt", + "name": "Navn", + "type": "Type", + "created_customer": "Oprettet af kunde", + "selected-blob-entities": "", + "download-blob-entity": "Download fil", + "delete-blob-entity": "Slet fil", + "delete-blob-entity-title": "", + "delete-blob-entity-text": "Vær forsigtig. Efter bekræftelsen vil fildata være uoprettelige.", + "delete-blob-entities-title": "", + "delete-blob-entities-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte filer blive fjernet, og alle relaterede data vil være uoprettelige." + }, + "timezone": { + "timezone": "Tidszone", + "select-timezone": "Vælg tidszone", + "no-timezones-matching": "", + "timezone-required": "Tidszone er påkrævet.", + "browser-time": "Browsertid" + }, + "queue": { + "select_name": "Vælg kønavn", + "name": "Kønavn", + "name_required": "Kønavn er påkrævet." + }, + "tenant": { + "tenant": "Lejer", + "tenants": "Lejere", + "management": "Administration af lejer", + "add": "Tilføj lejer", + "admins": "Admin.", + "manage-tenant-admins": "Administrer lejeradmin.", + "delete": "Slet lejer", + "add-tenant-text": "Tilføj ny lejer", + "no-tenants-text": "Ingen lejere fundet", + "tenant-details": "Lejeroplysninger", + "delete-tenant-title": "", + "delete-tenant-text": "Vær forsigtig. Efter bekræftelsen vil lejeren og alle relaterede data være uoprettelige.", + "delete-tenants-title": "", + "delete-tenants-action-title": "", + "delete-tenants-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte lejere blive fjernet, og alle relaterede data vil være uoprettelige.", + "title": "Titel", + "title-required": "Titel er påkrævet.", + "description": "Beskrivelse", + "details": "Oplysninger", + "events": "Begivenheder", + "copyId": "Kopiér lejer-id", + "idCopiedMessage": "Lejer-id er blevet kopieret til udklipsholder", + "select-tenant": "Vælg lejer", + "no-tenants-matching": "", + "tenant-required": "Lejer er påkrævet", + "selected-tenants": "", + "search": "Søg efter lejere", + "allow-white-labeling": "Tillad hvid mærkning", + "allow-customer-white-labeling": "Tillad hvid mærkning af kunder", + "isolated-tb-core": "Behandling i isoleret ThingsBoard Core-beholder", + "isolated-tb-rule-engine": "Behandling i isoleret ThingsBoard regelmotor-beholder", + "isolated-tb-core-details": "Kræver separat(e) microserviceydelse(r) pr. isoleret lejer", + "isolated-tb-rule-engine-details": "Kræver separat(e) microserviceydelse(r) pr. isoleret lejer" + }, + "tenant-profile": { + "tenant-profile": "Lejerprofil", + "tenant-profiles": "Lejerprofiler", + "add": "Tilføj lejerprofil", + "edit": "Rediger lejerprofil", + "tenant-profile-details": "Oplysninger om lejerprofil", + "no-tenant-profiles-text": "Ingen lejerprofiler fundet", + "search": "Søg efter lejerprofiler", + "selected-tenant-profiles": "", + "no-tenant-profiles-matching": "", + "tenant-profile-required": "Lejerprofil er påkrævet", + "idCopiedMessage": "Lejerprofil-id er blevet kopieret til udklipsholder", + "set-default": "Gør lejerprofil til standard", + "delete": "Slet lejerprofil", + "copyId": "Kopiér lejerprofil-id", + "name": "Navn", + "name-required": "Navn er påkrævet.", + "data": "Profildata", + "profile-configuration": "Profilkonfiguration", + "description": "Beskrivelse", + "default": "Standard", + "delete-tenant-profile-title": "", + "delete-tenant-profile-text": "Vær forsigtig. Efter bekræftelsen vil lejerprofilen og alle relaterede data være uoprettelige.", + "delete-tenant-profiles-title": "", + "delete-tenant-profiles-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte lejerprofiler blive fjernet, og alle relaterede data vil være uoprettelige.", + "set-default-tenant-profile-title": "", + "set-default-tenant-profile-text": "Efter bekræftelsen vil lejerprofilen blive markeret som standard og vil blive brugt til nye lejere, hvor der ikke er angivet nogen profil.", + "no-tenant-profiles-found": "Ingen lejerprofiler fundet.", + "create-new-tenant-profile": "Opret en ny!", + "maximum-devices": "Maks. antal enheder (0 – ubegrænset)", + "maximum-devices-required": "Maks. antal enheder er påkrævet.", + "maximum-devices-range": "Min. antal enheder kan ikke være negativt", + "maximum-assets": "Maks. antal aktiver (0 – ubegrænset)", + "maximum-assets-required": "Maks. antal aktiver er påkrævet.", + "maximum-assets-range": "Maks. antal aktiver kan ikke være negativt", + "maximum-customers": "Maks. antal kunder (0 – ubegrænset)", + "maximum-customers-required": "Maks. antal kunder er påkrævet.", + "maximum-customers-range": "Maks. antal kunder kan ikke være negativt", + "maximum-users": "Maks. antal brugere (0 – ubegrænset)", + "maximum-users-required": "Maks. antal brugere er påkrævet.", + "maximum-users-range": "Maks. antal brugere kan ikke være negativt", + "maximum-dashboards": "Maks. antal dashboards (0 – ubegrænset)", + "maximum-dashboards-required": "Maks. antal dashboards er påkrævet.", + "maximum-dashboards-range": "Maks. antal dashboards kan ikke være negativt", + "maximum-rule-chains": "Maks. antal regelkæder (0 – ubegrænset)", + "maximum-rule-chains-required": "Maks. antal regelkæder er påkrævet.", + "maximum-rule-chains-range": "Maks. antal regelkæder kan ikke være negativt", + "maximum-integrations": "Maks. antal integrationer (0 – ubegrænset)", + "maximum-integrations-required": "Maks. antal integrationer er påkrævet.", + "maximum-integrations-range": "Maks. antal integrationer kan ikke være negativt", + "maximum-converters": "Maks. antal omformere (0 – ubegrænset)", + "maximum-converters-required": "Maks. antal omformere er påkrævet.", + "maximum-converters-range": "Maks. antal omformere kan ikke være negativt", + "maximum-scheduler-events": "Maks. antal planlægningsbegivenheder (0 – ubegrænset)", + "maximum-scheduler-events-required": "Maks. antal planlægningsbegivenheder er påkrævet.", + "maximum-scheduler-events-range": "Maks. antal planlægningsbegivenheder kan ikke være negativt", + "transport-tenant-msg-rate-limit": "Hastighedsgrænse for transport af lejermeddelelser.", + "transport-tenant-telemetry-msg-rate-limit": "Hastighedsgrænse for transport af lejertelemetrimeddelelser.", + "transport-tenant-telemetry-data-points-rate-limit": "Hastighedsgrænse for transport af lejertelemetridatapunkter.", + "transport-device-msg-rate-limit": "Hastighedsgrænse for transport af enhedsmeddelelser.", + "transport-device-telemetry-msg-rate-limit": "Hastighedsgrænse for transport af enhedstelemetrimeddelelser.", + "transport-device-telemetry-data-points-rate-limit": "Hastighedsgrænse for transport af enhedstelemetridatapunkter.", + "max-transport-messages": "Maks. antal transportmeddelelser (0 – ubegrænset)", + "max-transport-messages-required": "Maks. antal transportmeddelelser er påkrævet.", + "max-transport-messages-range": "Maks. antal transportmeddelelser kan ikke være negativt", + "max-transport-data-points": "Maks. antal transportdatapunkter (0 – ubegrænset)", + "max-transport-data-points-required": "Maks. antal transportdatapunkter er påkrævet.", + "max-transport-data-points-range": "Maks. antal transportdatapunkter kan ikke være negativt", + "max-r-e-executions": "Maks. antal regelmotor-udførelser (0 – ubegrænset)", + "max-r-e-executions-required": "Maks. antal regelmotor-udførelser er påkrævet.", + "max-r-e-executions-range": "Maks. antal regelmotor-udførelser kan ikke være negativt", + "max-j-s-executions": "Maks. antal JavaScript-udførelser (0 – ubegrænset)", + "max-j-s-executions-required": "Maks. antal JavaScript-udførelser er påkrævet.", + "max-j-s-executions-range": "Maks. antal JavaScript-udførelser kan ikke være negativt", + "max-d-p-storage-days": "Maks. antal lagringsdage for datapunkter (0 – ubegrænset)", + "max-d-p-storage-days-required": "Maks. antal lagringsdage for datapunkter er påkrævet.", + "max-d-p-storage-days-range": "Maks. antal lagringsdage for datapunkter kan ikke være negativt", + "default-storage-ttl-days": "Standard lagringsdage for TTL (0 – ubegrænset)", + "default-storage-ttl-days-required": "Standard lagringsdage for TTL er påkrævet.", + "default-storage-ttl-days-range": "Standard lagringsdage for TTL kan ikke være negative", + "max-rule-node-executions-per-message": "Maks. antal regelknudeudførelser pr. meddelelse (0 – ubegrænset)", + "max-rule-node-executions-per-message-required": "Maks. antal regelknudeudførelser pr. meddelelse er påkrævet.", + "max-rule-node-executions-per-message-range": "Maks. antal regelknudeudførelser pr. meddelelse kan ikke være negativt", + "max-emails": "Maks. antal sendte e-mails (0 – ubegrænset)", + "max-emails-required": "Maks. antal sendte e-mails er påkrævet.", + "max-emails-range": "Maks. antal sendte e-mails kan ikke være negativt", + "max-sms": "Maks. antal sendte SMS'er (0 – ubegrænset)", + "max-sms-required": "Maks. antal sendte SMS'er er påkrævet.", + "max-sms-range": "Maks. antal sendte SMS'er kan ikke være negativt" + }, + "timeinterval": { + "seconds-interval": "{ seconds, plural, 1 {1 sekund} other {# sekunder} }", + "minutes-interval": "{ minutes, plural, 1 {1 minut} other {# minutter} }", + "hours-interval": "{ hours, plural, 1 {1 time} other {# timer} }", + "days-interval": "{ days, plural, 1 {1 dag} other {# dage} }", + "days": "Dage", + "hours": "Timer", + "minutes": "Minutter", + "seconds": "Sekunder", + "advanced": "Fremskreden", + "predefined": { + "yesterday": "I går", + "day-before-yesterday": "Dagen før i går", + "this-day-last-week": "Denne dag i sidste uge", + "previous-week": "Forrige uge (søn – lør)", + "previous-week-iso": "Forrige uge (man – søn)", + "previous-month": "Forrige måned", + "previous-year": "Forrige år", + "current-hour": "Aktuel time", + "current-day": "Aktuel dag", + "current-day-so-far": "Aktuel dag indtil nu", + "current-week": "Aktuel uge (søn – lør)", + "current-week-iso": "Aktuel uge (man – søn)", + "current-week-so-far": "Aktuel uge indtil videre (søn – lør)", + "current-week-iso-so-far": "Aktuel uge indtil videre (man– søn)", + "current-month": "Aktuel måned", + "current-month-so-far": "Aktuel måned indtil nu", + "current-year": "Aktuelt år", + "current-year-so-far": "Aktuelt år indtil nu" + } + }, + "timeunit": { + "seconds": "Sekunder", + "minutes": "Minutter", + "hours": "Timer", + "days": "Dage" + }, + "timewindow": { + "days": "{ days, plural, 1 { dag } other {# dage } }", + "hours": "{ hours, plural, 0 { time } 1 {1 time } other {# timer } }", + "minutes": "{ minutes, plural, 0 { minut } 1 {1 minut } other {# minutter } }", + "seconds": "{ seconds, plural, 0 { sekund } 1 {1 sekund } other {# sekunder } }", + "realtime": "Realtid", + "history": "Historie", + "last-prefix": "sidst", + "period": "fra {{ startTime }} til {{ endTime }}", + "edit": "Rediger tidsvindue", + "date-range": "Datointerval", + "last": "Sidst", + "time-period": "Tidsperiode", + "hide": "Skjul", + "interval": "Interval" + }, + "user": { + "user": "Bruger", + "users": "Brugere", + "management": "Brugeradministration", + "customer-users": "Kundebrugere", + "tenant-admins": "Lejeradmin.", + "sys-admin": "Systemadministrator", + "tenant-admin": "Bruger", + "customer": "Kunde", + "anonymous": "Anonym", + "add": "Tilføj bruger", + "delete": "Slet bruger", + "add-user-text": "Tilføj ny bruger", + "no-users-text": "Ingen brugere fundet", + "user-details": "Brugerdetaljer", + "delete-users": "Slet brugere", + "delete-user-title": "", + "delete-user-text": "Vær forsigtig. Efter bekræftelsen vil brugeren og alle relaterede data være uoprettelige.", + "delete-users-title": "", + "delete-users-action-title": "", + "delete-users-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte brugere blive fjernet, og alle relaterede data vil være uoprettelige.", + "activation-email-sent-message": "Aktiverings-e-mail blev sendt!", + "resend-activation": "Gensend aktivering", + "email": "E-mail", + "email-required": "E-mail er påkrævet.", + "invalid-email-format": "Ugyldigt e-mailformat.", + "first-name": "Fornavn", + "last-name": "Efternavn", + "description": "Beskrivelse", + "default-dashboard": "Standard dashboard", + "always-fullscreen": "Altid fuld skærm", + "select-user": "Vælg bruger", + "no-users-matching": "", + "user-required": "Bruger er påkrævet", + "activation-method": "Aktiveringsmetode", + "display-activation-link": "Vis aktiveringslink", + "send-activation-mail": "Send aktiverings-e-mail", + "activation-link": "Link til brugeraktivering", + "activation-link-text": "", + "copy-activation-link": "Kopiér aktiveringslink", + "activation-link-copied-message": "Brugeraktiveringslinket er blevet kopieret til udklipsholderen", + "selected-users": "", + "search": "Søg efter brugere", + "details": "Oplysninger", + "login-as-tenant-admin": "Log ind som lejeradministrator", + "login-as-customer-user": "Log ind som kundebruger", + "select-group-to-add": "Vælg målgruppe for at tilføje valgte brugere", + "select-group-to-move": "Vælg målgruppe for at flytte valgte brugere", + "remove-users-from-group": "", + "group": "Gruppe af brugere", + "list-of-groups": "", + "group-name-starts-with": "", + "disable-account": "Deaktiver brugerkonto", + "enable-account": "Aktivér brugerkonto", + "enable-account-message": "Brugerkontoen er blevet aktiveret!", + "disable-account-message": "Brugerkontoen blev deaktiveret!" + }, + "value": { + "type": "Værditype", + "string": "Streng", + "string-value": "Strengværdi", + "string-value-required": "Strengværdi er påkrævet", + "integer": "Heltal", + "integer-value": "Heltalsværdi", + "integer-value-required": "Heltalsværdi er påkrævet", + "invalid-integer-value": "Ugyldig heltalsværdi", + "double": "Dobbelt", + "double-value": "Dobbelt værdi", + "double-value-required": "Dobbelt værdi er påkrævet", + "boolean": "Boolesk", + "boolean-value": "Boolesk værdi", + "false": "FALSK", + "true": "SANDT", + "long": "Lang", + "json": "JSON", + "json-value": "JSON-værdi", + "json-value-invalid": "JSON-værdi har et ugyldigt format", + "json-value-required": "JSON-værdi er påkrævet." + }, + "widget": { + "widget-library": "Widgets-bibliotek", + "widget-bundle": "Widgets-bundt", + "all-bundles": "Alle bundter", + "select-widgets-bundle": "Vælg widgets-bundt", + "management": "Widget-administration", + "editor": "Widget-editor", + "widget-type-not-found": "Problem under indlæsning af widget-konfiguration.
Sandsynligvis tilknyttet\r\n widget-type blev fjernet.", + "widget-type-load-error": "Widget blev ikke indlæst pga. følgende fejl:", + "remove": "Fjern widget", + "edit": "Rediger widget", + "remove-widget-title": "", + "remove-widget-text": "Efter bekræftelsen vil widgeten og alle relaterede data være uoprettelige.", + "timeseries": "Tidsserier", + "search-data": "Søg efter data", + "no-data-found": "Ingen data fundet", + "latest": "Seneste værdier", + "rpc": "Styring af widget", + "alarm": "Alarm-widget", + "static": "Statisk widget", + "select-widget-type": "Vælg widget-type", + "missing-widget-title-error": "Widget-titel skal angives!", + "widget-saved": "Widget gemt", + "unable-to-save-widget-error": "Widget kunne ikke gemmes! Widget har fejl!", + "save": "Gem widget", + "saveAs": "Gem widget som", + "save-widget-type-as": "Gem widget-type som", + "save-widget-type-as-text": "Indtast en ny widget-titel, og/eller vælg målwidget-bundt", + "toggle-fullscreen": "Skift til fuld skærm", + "run": "Kør widget", + "title": "Widget-titel", + "title-required": "Widget-titel er påkrævet.", + "type": "Widget-type", + "resources": "Ressourcer", + "resource-url": "JavaScript/CSS URL", + "resource-is-module": "Er modul", + "remove-resource": "Fjern ressource", + "add-resource": "Tilføj ressource", + "html": "HTML", + "tidy": "Tidy", + "css": "CSS", + "settings-schema": "Indstillingsskema", + "datakey-settings-schema": "Skema over datanøgleindstillinger", + "widget-settings": "Widget-indstillinger", + "description": "Beskrivelse", + "image-preview": "Forhåndsvisning af billede", + "javascript": "Javascript", + "js": "JS", + "remove-widget-type-title": "", + "remove-widget-type-text": "Efter bekræftelsen vil widget-typen og alle relaterede data være uoprettelige.", + "remove-widget-type": "Fjern widget-type", + "add-widget-type": "Tilføj ny widget-type", + "widget-type-load-failed-error": "Kunne ikke indlæse widget-type!", + "widget-template-load-failed-error": "Kunne ikke indlæse widget-skabelon!", + "add": "Tilføj widget", + "undo": "Fortryd widget-ændringer", + "export": "Eksportér widget", + "export-data": "Eksportér widget-data", + "export-to-csv": "Eksportér data til CSV...", + "export-to-excel": "Eksportér data til XLS...", + "export-to-excel-xlsx": "Eksportér data til XLSX...", + "no-data": "Ingen data at vise på widget", + "data-overflow": "", + "alarm-data-overflow": "", + "search": "Søg efter widget", + "filter": "Widget-filtertype", + "loading-widgets": "Indlæser widgets..." + }, + "widget-action": { + "header-button": "Widget-overskriftsknap", + "open-dashboard-state": "Naviger til ny dashboardtilstand", + "update-dashboard-state": "Opdater aktuel dashboardtilstand", + "open-dashboard": "Naviger til et andet dashboard", + "custom": "Brugerdefineret handling", + "custom-pretty": "Brugerdefineret handling (med HTML-skabelon)", + "target-dashboard-state": "Mål-dashboardtilstand", + "target-dashboard-state-required": "Mål-dashboardtilstand er påkrævet", + "set-entity-from-widget": "Angiv entitet fra widget", + "target-dashboard": "Mål-dashboard", + "open-right-layout": "Åbn højre dashboardlayout (mobilvisning)", + "open-in-separate-dialog": "Åbn i separat dialogboks", + "dialog-title": "Dialogbokstitel", + "dialog-hide-dashboard-toolbar": "Skjul dashboardets værktøjslinje i dialogboks", + "dialog-width": "Dialogboksbredde i procent i forhold til visningsportens bredde", + "dialog-height": "Dialogbokshøjde i procent i forhold til visningsportens højde", + "dialog-size-range-error": "Dialogboksstørrelsens procentværdi skal ligge i området fra 1 til 100.", + "open-new-browser-tab": "Åbn i en ny browserfane" + }, + "widgets-bundle": { + "current": "Nuværende bundt", + "widgets-bundles": "Widgets-bundter", + "add": "Tilføj widgets-bundt", + "delete": "Slet widgets-bundt", + "title": "Titel", + "title-required": "Titel er påkrævet.", + "description": "Beskrivelse", + "image-preview": "Forhåndsvisning af billede", + "add-widgets-bundle-text": "Tilføj nye widgets-bundter", + "no-widgets-bundles-text": "Ingen widgets-bundter fundet", + "empty": "Widgets-bundt er tomt", + "details": "Oplysninger", + "widgets-bundle-details": "Oplysninger om widgets-bundt", + "delete-widgets-bundle-title": "", + "delete-widgets-bundle-text": "Vær forsigtig. Efter bekræftelsen vil widgets-bundtet og alle relaterede data være uoprettelige.", + "delete-widgets-bundles-title": "", + "delete-widgets-bundles-action-title": "", + "delete-widgets-bundles-text": "Vær forsigtig. Efter bekræftelsen vil alle valgte widgets-bundter blive fjernet, og alle relaterede data vil være uoprettelige.", + "no-widgets-bundles-matching": "", + "widgets-bundle-required": "Widgets-bundt er påkrævet.", + "system": "System", + "import": "Importér widgets-bundt", + "export": "Eksportér widgets-bundt", + "export-failed-error": "", + "create-new-widgets-bundle": "Opret nyt widgets-bundt", + "widgets-bundle-file": "Widgets-bundtfil", + "invalid-widgets-bundle-file-error": "Widgets-bundt kunne ikke importeres: Ugyldig datastruktur for widgets-bundt.", + "search": "Søg efter widget-bundter", + "selected-widgets-bundles": "", + "open-widgets-bundle": "Åbn widgets-bundt", + "loading-widgets-bundles": "Indlæser widgets-bundter..." + }, + "widget-config": { + "data": "Data", + "settings": "Indstillinger", + "advanced": "Fremskreden", + "title": "Titel", + "title-tooltip": "Værktøjstip for titel", + "general-settings": "Generelle indstillinger", + "display-title": "Vis titel", + "drop-shadow": "Slip skygge", + "enable-fullscreen": "Aktivér fuldskærm", + "enable-data-export": "Aktivér dataeksport", + "background-color": "Baggrundsfarve", + "text-color": "Tekstfarve", + "padding": "Padding", + "margin": "Margin", + "widget-style": "Widget-stil", + "title-style": "Titeltype", + "mobile-mode-settings": "Indstillinger for mobiltilstand", + "order": "Rækkefølge", + "height": "Højde", + "units": "Specielt symbol, der vises ved siden af værdi", + "decimals": "Antal cifre efter flydende punkt", + "timewindow": "Tidsvindue", + "use-dashboard-timewindow": "Brug dashboardtidsvindue", + "display-timewindow": "Vis tidsvindue", + "display-legend": "Vis siganturforklaring", + "datasources": "Datakilder", + "maximum-datasources": "", + "datasource-type": "Type", + "datasource-parameters": "Parametre", + "remove-datasource": "Fjern datakilde", + "add-datasource": "Tilføj datakilde", + "target-device": "Målenhed", + "alarm-source": "Alarmkilde", + "actions": "Handlinger", + "action": "Handling", + "add-action": "Tilføj handling", + "search-actions": "Søg efter handlinger", + "no-actions-text": "Ingen handlinger fundet", + "action-source": "Handlingskilde", + "action-source-required": "Handlingskilde er påkrævet.", + "action-name": "Navn", + "action-name-required": "Handlingsnavn er påkrævet.", + "action-name-not-unique": "Der findes allerede en anden handling med samme navn.
Handlingsnavnet skal være unikt inden for den samme handlingskilde.", + "action-icon": "Ikon", + "action-type": "Type", + "action-type-required": "Handlingstype er påkrævet.", + "edit-action": "Rediger handling", + "delete-action": "Slet handling", + "delete-action-title": "Slet widget-handling", + "delete-action-text": "", + "display-icon": "Vis titelikon", + "icon-color": "Ikonfarve", + "icon-size": "Ikonstørrelse" + }, + "widget-type": { + "import": "Importér widget-type", + "export": "Eksportér widget-type", + "export-failed-error": "", + "create-new-widget-type": "Opret ny widget-type", + "widget-type-file": "Widget-typefil", + "invalid-widget-type-file-error": "Kan ikke importere widget-type: Ugyldig datastruktur for widget-type." + }, + "self-registration": { + "self-registration": "Selvregistrering", + "self-registration-url": "Selvregistrerings-URL", + "captcha-site-key": "reCAPTCHA site-nøgle", + "captcha-secret-key": "reCAPTCHA hemmelig nøgle", + "notification-email": "Notifikations-e-mail", + "privacy-policy-text": "Fortrolighedspolitik tekst", + "text-message-page": "Tekstmeddelelse til tilmeldingsside" + }, + "white-labeling": { + "white-labeling": "Hvid mærkning", + "login-white-labeling": "Login for hvid mærkning", + "preview": "Forhåndsvisning", + "app-title": "Applikationstitel", + "favicon": "Website-ikon", + "favicon-description": "", + "favicon-size-error": "", + "favicon-type-error": "Ugyldigt filformat for website-billede. Kun ICO-, GIF- eller PNG-billeder accepteres.", + "drop-favicon-image": "Træk og slip et website-ikonbillede, eller klik for at vælge en fil, der skal uploades.", + "no-favicon-image": "Intet ikon valgt", + "logo": "Logo", + "logo-description": "", + "logo-size-error": "", + "logo-type-error": "Ugyldigt logofilformat. Kun billeder accepteres.", + "drop-logo-image": "Træk og slip et logobillede, eller klik for at vælge en fil, der skal uploades.", + "no-logo-image": "Intet logo valgt", + "logo-height": "Logohøjde, px", + "primary-palette": "Primær palet", + "accent-palette": "Accent palet", + "customize-palette": "Tilpas", + "advanced-css": "Avanceret CSS", + "edit-palette": "Rediger palet", + "save-palette": "Gem palet", + "primary-background": "Primær baggrund", + "secondary-background": "Sekundær baggrund", + "hue1": "HUE 1", + "hue2": "HUE 2", + "hue3": "HUE 3", + "page-background-color": "Baggrundsfarve for side", + "dark-foreground": "Mørk forgrund", + "domain-name": "Domænenavn", + "base-url": "Basis-URL", + "base-url-required": "Basis-URL er påkrævet.", + "prohibit-different-url": "Det er ikke tilladt at bruge værtsnavn fra overskrifterne for klientanmodninger", + "prohibit-different-url-hint": "Denne indstilling skal aktiveres for produktionsmiljøer. Kan forårsage sikkerhedsproblemer ved deaktivering", + "help-link-base-url": "Basis-URL for hjælpelinks", + "enable-help-links": "Aktivér hjælpelinks", + "error-verification-url": "Et domænenavn må ikke indeholde symbolerne '/' og ':'. Eksempel: thingsboard.io", + "show-platform-name-version": "Vis platformnavn og version", + "platform-name": "Platformnavn", + "platform-version": "Platformversion", + "version-mask": "", + "position": { + "label": "Platformnavn og versionsposition", + "under-logo": "Under logoet", + "bottom": "Nederst i login-formularen" + } + }, + "widgets": { + "date-range-navigator": { + "localizationMap": { + "Sun": "Søn", + "Mon": "Man", + "Tue": "Tir", + "Wed": "Ons", + "Thu": "Tor", + "Fri": "Fre", + "Sat": "Lør", + "Jan": "Jan", + "Feb": "Feb", + "Mar": "Mar", + "Apr": "Apr", + "May": "Maj", + "Jun": "Jun", + "Jul": "Jul", + "Aug": "Aug", + "Sep": "Sep", + "Oct": "Okt", + "Nov": "Nov", + "Dec": "Dec", + "January": "Januar", + "February": "Februar", + "March": "Marts", + "April": "April", + "June": "Juni", + "July": "Juli", + "August": "August", + "September": "September", + "October": "Oktober", + "November": "November", + "December": "December", + "Custom Date Range": "Brugerdefineret datointerval", + "Date Range Template": "Skabelon for datointerval", + "Today": "I dag", + "Yesterday": "I går", + "This Week": "Denne uge", + "Last Week": "Sidste uge", + "This Month": "Denne måned", + "Last Month": "Sidste måned", + "Year": "År", + "This Year": "I år", + "Last Year": "Sidste år", + "Date picker": "Datovælger", + "Hour": "Time", + "Day": "Dag", + "Week": "Uge", + "2 weeks": "2 uger", + "Month": "Måned", + "3 months": "3 måneder", + "6 months": "6 måneder", + "Custom interval": "Brugerdefineret interval", + "Interval": "Interval", + "Step size": "Trinstørrelse", + "Ok": "Okay" + } + }, + "input-widgets": { + "attribute-not-allowed": "Attributparameter kan ikke bruges i denne widget", + "blocked-location": "Geoplaceringen er blokeret i din browser", + "claim-device": "Gør krav på enhed", + "claim-failed": "Kunne ikke gøre krav på enheden!", + "claim-not-found": "Enhed ikke fundet!", + "claim-successful": "Enheden er blevet krævet!", + "date": "Dato", + "device-name": "Enhedsnavn", + "device-name-required": "Enhedsnavn er påkrævet", + "discard-changes": "Kassér ændringer", + "entity-attribute-required": "Entitetsattribut er påkrævet", + "entity-coordinate-required": "Både felter, breddegrad og længdegrad er påkrævet", + "entity-timeseries-required": "Tidsserie for entitet er påkrævet", + "get-location": "Få den aktuelle placering", + "invalid-date": "Ugyldig dato", + "latitude": "Breddegrad", + "longitude": "Længde", + "min-value-error": "", + "max-value-error": "", + "not-allowed-entity": "Den valgte entitet kan ikke have delte attributter", + "no-attribute-selected": "Ingen attribut er valgt", + "no-datakey-selected": "Ingen datanøgle er valgt", + "no-coordinate-specified": "Datanøgle for breddegrad/længdegrad er ikke angivet", + "no-entity-selected": "Ingen entitet valgt", + "no-image": "Intet billede", + "no-support-geolocation": "Din browser understøtter ikke geoplacering", + "no-support-web-camera": "Din browser understøtter ikke kameraer", + "enable-https-use-widget": "Aktivér HTTPS for at bruge denne widget", + "no-found-your-camera": "Kan ikke finde dit kamera", + "no-permission-camera": "Tilladelse blev nægtet af brugeren / Dette website har ikke tilladelse til at bruge kameraet", + "no-timeseries-selected": "Ingen tidsserier valgt", + "secret-key": "Hemmelig nøgle", + "secret-key-required": "Hemmelig nøgle er påkrævet", + "switch-attribute-value": "Skift entitetsattributværdi", + "switch-camera": "Skift kamera", + "switch-timeseries-value": "Skift entitetstidsserieværdi", + "take-photo": "Tag et billede", + "time": "Tid", + "timeseries-not-allowed": "Tidsserieparameter kan ikke bruges i denne widget", + "update-failed": "Opdatering mislykkedes", + "update-successful": "Opdatering lykkedes", + "update-attribute": "Opdatering", + "update-timeseries": "Opdater tidsserier", + "value": "Værdi" + } + }, + "icon": { + "icon": "Ikon", + "select-icon": "Vælg ikon", + "material-icons": "Materialeikoner", + "show-all": "Vis alle ikoner" + }, + "subscription": { + "entity-limit-text": "Du kan dog opgradere din abonnementsordning for at øge dine begrænsninger.", + "upgrade-your-plan": "Opgrader abonnementsordning", + "white-labeling-feature": "Funktion til hvid mærkning", + "white-labeling-text-full": "Rebrand ThingsBoard-platformens webinterface med dit virksomheds- eller produktlogo og farveskema på 2 minutter.

Fjern “Powered By” i dashboardets sidefod.
Ingen kodning eller genstart af tjeneste påkrævet. Giv også dine kunder mulighed for at hvidmærke deres interface.", + "enable-white-labeling": "Aktivér hvidmærkningsfunktionen nu ved at opgradere din abonnementsordning!", + "read-more": "Læs mere", + "white-labeling-video-text": "Se videovejledningen nedenfor for at se, hvordan denne funktion fungerer!" + }, + "subscription-error": { + "title": "Misligholdelse af abonnement", + "warning-title": "Abonnementsadvarsel", + "limit-reached": { + "device-count": "", + "asset-count": "" + }, + "feature-disabled": { + "white-labeling": "Hvidmærkningsfunktionen er ikke tilladt af din abonnementsordning!" + } + }, + "custom": { + "widget-action": { + "action-cell-button": "Handlingscelleknap", + "row-click": "Ved klik på række", + "polygon-click": "Ved klik på polygon", + "marker-click": "Ved klik på markør", + "tooltip-tag-action": "Værktøjstip for taghandling", + "node-selected": "På valgt knude", + "element-click": "Ved klik på HTML-element", + "pie-slice-click": "Ved klik på udsnit", + "row-double-click": "Ved dobbeltklik på række" + }, + "add-new-facility": { + "add-entity": "Tilføj placering", + "facility-name": "placeringsnavn", + "facility-name-required": "placeringsnavn er påkrævet.", + "title": "Tilføj ny placering" + }, + "delete-facility": { + "are-you-sure-question": "Er du sikker på, at du vil slette placering '{{facilityName}}'?", + "title": "Slet placering" + }, + "facilities": { + "set-location-and-facility-map": "Indstil placering" + }, + "general": { + "account": "Konto", + "accounts": "Konti", + "activation-link-is-sent-to-the-email-address": "Aktiveringslink er sendt til e-mailadressen: '{{email}}'", + "add-ecl": "Tilføj ECL", + "add-ecl-device": "Tilføj ECL-enhed", + "add-edit-ally-email": "Tilføj Ally™ konto", + "add-edit-entity-ally-account": "Tilføj {{ entityName }}'s Ally™ konto", + "add-home": "Tilføj Hjem", + "add-home-area": "Tilføj Hjemmeområde", + "add-new-ally-account": "Tilføj ny konto", + "add-new-location": "Tilføj ny placering", + "add-new-read-only-user": "Tilføj ny skrivebeskyttet bruger", + "add-new-read-only-user-for-facility": "Tilføj ny skrivebeskyttet bruger for '{{facilityName}}'", + "add-vacation-for-zone": "Tilføj ferie for denne zone", + "open-calendar": "Åbn kalender", + "add-zone": "Tilføj zone", + "alarm-code": "Alarmkode", + "alarm-description": "Beskrivelse", + "alarm-message": "Meddelelse", + "alarms-disabled-msg": "Alarmer er deaktiveret.", + "alarms-disabled-state": "Deaktiveret", + "alarms-enabled-msg": "Alarmer er aktiveret.", + "alarms-enabled-state": "Aktiveret", + "all-devices-in-home": "Alle enheder i hjemmet", + "ally-email": "Ally™ e-mail", + "ally-email-access-check-email": "Tjek din e-mail {{ allyEmail }} for at se den 4-cifrede kode fra Ally™ Pro", + "ally-email-access-code-label": "Indtast din adgangskode (4 cifre)", + "ally-email-account-is-missing-or-is-not-valid": "Ally™ e-mailkonto mangler eller er ikke gyldig", + "an-error-occurred-entities-try-again": "Der opstod en fejl under sletning af enhederne. Prøv igen.", + "an-error-occurred-entity-try-again": "Der opstod en fejl under sletning af enheden. Prøv igen.", + "an-error-occurred-please-try-again": "Der opstod en fejl. Prøv igen.", + "app": "App", + "app-version": "Appversion", + "area-name-is-required": "Områdenavn er påkrævet.", + "assign-existing-user-to-facility": "Tildel eksisterende bruger til placering", + "assign-user-to-facility": "Tildel bruger til '{{facilityName}}'", + "available-devices": "Tilgængelige enheder", + "battery": "Batteri", + "calendar": "Kalender", + "cant-remove-yourself": "Du kan ikke fjerne dig selv fra placeringen.", + "change-temperature": "Ændr temperatur", + "change-zone-map": "Skift zonekort", + "child-lock": "Børnesikring", + "child-lock-disabled": "Deaktiveret", + "child-lock-enabled": "Aktiveret", + "circuit": "Kreds", + "comfort": "Komfort", + "comfort-dhw-setpoint": "Sætpunkt for Komfort varmt brugsvand", + "comfort-dhw-setpoint-is-required": "Sætpunkt for Komfort varmt brugsvand er påkrævet.", + "comfort-room": "Komfort rum", + "comfort-room-setpoint": "Sætpunkt for Komfort rum", + "comfort-room-setpoint-is-required": "Sætpunkt for Komfort rum er påkrævet.", + "confirm-btn": "Bekræft", + "confirm-delete-device": "Er du sikker på, du ønsker at slette enhed '{{deviceName}}'?", + "confirm-delete-devices": "Er du sikker på, du ønsker at slette {{numberOfDevices}} enheder?", + "confirm-delete-home": "Er du sikker på, du ønsker at slette hjem '{{homeName}}'; deres zoner og enheder?", + "confirm-delete-zone": "Er du sikker på, du ønsker at slette zonen '{{zoneName}}'?", + "confirm-remove-user": "Er du sikker på, du ønsker at fjerne {{ thisUser }} fra lokation {{ locationName }}", + "constant-comfort-temperature": "Konstant komforttemperatur", + "constant-setback-temperature": "Konstant sænkningstemperatur", + "coordinates": "Koordinater", + "create-ecl-home-without-ally-account": "Opret ECL hjem uden Ally™ konto", + "create-vacation-event": "Opret feriebegivenhed", + "current-humidity": "Luftfugtighed", + "current-temp": "Aktuel temp.", + "current-temperature": "Aktuel temperatur", + "default-flow-temperature-at-minus-30": "Standard fremløbstemperatur ved -30 °C", + "default-flow-temperature-at-minus-15": "Standard fremløbstemperatur ved -15 °C", + "default-flow-temperature-at-minus-5": "Standard fremløbstemperatur ved -5 °C", + "default-flow-temperature-at-zero": "Standard fremløbstemperatur ved 0 °C", + "default-flow-temperature-at-plus-5": "Standard fremløbstemperatur ved 5 °C", + "default-flow-temperature-at-plus-15": "Standard fremløbstemperatur ved 15 °C", + "delete-account": "Slet konto", + "delete-all-devices": "Slet alle enheder", + "delete-device-from-home": "Slet enhed fra hjem", + "delete-devices": "Slet enheder", + "delete-facility-account": "Slet konto", + "delete-home": "Slet hjem", + "delete-user": "Slet bruger", + "delete-zone": "Slet zone", + "device-id": "Enheds-id", + "device-is-now-removed-from-this-zone": "Enheden er nu fjernet fra denne zone.", + "device-manual_mode-updated": "Manuel tilstand er indstillet for denne enhed.", + "device-name": "Enhedsnavn", + "device-status-updated": "Enhedsstatus opdateret!", + "device-type": "Enhedstype", + "devices-found-in-home": "Enheder fundet i {{ homeName }}", + "devices-imported": "Enheder importeret!", + "devices-in-zone": "Enheder i zone", + "devices-placed-into-zone": "{{numberOfDevices}} enhed(er) placeret i zone.", + "dhw-circuit": "Varmt brugsvandskreds", + "domestic-hot-water-circuit-menu": "Varmt brugsvand (DHW), menu for kreds", + "duplicate-devices": "Duplikerede enheder", + "duplicate-devices-list": "Du har allerede importeret enheder: {{listOfDevices}}", + "duplicate-devices-were-not-imported": "Duplikerede enheder: {{listOfDevices}} blev ikke importeret.", + "ecl-access-code": "ECL-adgangskode", + "ecl-device-added": "Din ECL-enhed {{device}} er blevet tilføjet.", + "ecl-diagram-title": "Nyt ECL-diagram", + "ecl-diagram-title-a-230-1": "Nyt ECL-diagram A230.1", + "ecl-diagram-title-a-247-1": "Nyt ECL-diagram A247.1", + "ecl-diagram-title-a-260-1": "Nyt ECL-diagram A260.1", + "ecl-diagram-title-a-266-1": "Nyt ECL-diagram A266.1", + "ecl-diagram-title-a-347-1": "Nyt ECL-diagram A347.1", + "ecl-diagram-title-a-376-1": "Nyt ECL-diagram A376.1", + "ecl-diagram-title-a-390-1": "Nyt ECL-diagram A390.1", + "ecl-heating-circuit-has-been-successfully-set": "ECL-varmekredsen er blevet indstillet.", + "ecl-menu": "ECL-menu", + "ecl-mode": "Tilstand", + "ecl-mvp-menu": "ECL MVP-menu", + "ecl-status": "Status", + "edit-facilities-access": "Rediger adgang til faciliteter", + "edit-facility-permission": "Rediger placeringstilladelse", + "edit-user": "Rediger bruger", + "edit-zone": "Rediger zone", + "eg-read-only": "f.eks. skrivebeskyttet", + "energy": "Energi", + "error-occurred": "Der opstod en fejl", + "etrv-update-temperature": "Opdater temperatur", + "facilities": "Faciliteter", + "facilities-for-entity-as-read-only-user": "Faciliteter for '{{entityName}}' som skrivebeskyttet bruger", + "facility-area-name": "placeringsområdenavn", + "facility-managers": "Facility Managers", + "facility-name-is-required": "placeringsnavn er påkrævet.", + "floor-map": "Plantegning", + "floors-in-the-room": "Gulve i rummet", + "flow-heating-curve-parameters-history": "Historik over parametre for flowvarmekurve", + "flow-temperature": "Fremløbstemperatur", + "flow-temperature-at-minus-15": "Fremløbstemperatur ved -150 °C", + "flow-temperature-at-minus-30": "Fremløbstemperatur ved -30 °C", + "flow-temperature-at-minus-5": "Fremløbstemperatur ved -5 °C", + "flow-temperature-at-plus-15": "Fremløbstemperatur ved 15 °C", + "flow-temperature-at-plus-5": "Fremløbstemperatur ved 5 °C", + "flow-temperature-at-zero": "Fremløbstemperatur ved 0 °C", + "flow-temperature-curve": "Fremløbstemperaturkurve", + "flow-temperature-values": "Fremløbstemperaturværdier", + "flow-temperature-without-optimization": "Fremløbstemperatur uden optimering", + "gateway-subdevices": "Gateway-underenheder", + "get-subdevices": "Hent underenheder", + "global-temp-set-msg": "Global temperatur er indstillet.", + "go-to-manual": "Gå til manuel tilstand", + "hardware": "Hardware", + "heating-circuit": "Varmekreds", + "heating-circuit-menu": "Menu for varmekreds", + "holiday-7-23h-comfort-temperature": "Ferie 7-23 t komforttemperatur", + "holiday-constant-comfort-temperature": "Ferie, konstant komforttemperatur", + "holiday-constant-setback-temperature": "Ferie, konstant sænkningstemperatur", + "holiday-frost-protection-standby": "Ferie, frostsikring/standby", + "home-alarms": "Hjemmealarmer", + "home-map": "Hjemmekort", + "home-map-with-zones": "Zoner", + "home-name": "Hjemmenavn", + "home-name-is-required": "Hjemmenavn er påkrævet", + "homes": "Hjem", + "homes-and-zones": "Hjem og zoner", + "homes-imported": "Hjem importeret!", + "homes-successfully-imported": "Hjem blev importeret!", + "import-ally-homes-from-the-button": "Importér Ally™ hjem fra knappen med ikonet 'hus'.", + "import-devices": "Importér enheder", + "import-devices-from-home": "Importer enheder fra hjem", + "import-homes": "Importer hjem", + "information": "Information", + "information-will-be-sent-via-email-to-this-user": "Information sendes via e-mail til denne bruger", + "invalid-temp": "Ugyldig temperaturværdi", + "link-to-ecl": "Link til ECL", + "linked-devices": "Tilknyttede enheder", + "list-of-subdevices": "Liste over underenheder", + "location-city": "Placering, by", + "location-country": "Placering, landområder", + "location-on-maps": "Placering på kort", + "location-street": "Placering, vej", + "location-street-number": "Placering, vejnummer", + "location-successfully-created": "Placeringen blev oprettet!", + "location-zip": "Placering, postnummer", + "locations": "Placeringer", + "lower-temperature": "Lavere temperatur", + "manage-home": "Administrer hjem", + "manual-operation": "Manuel drift", + "manual-temp": "Manuel temp.", + "manual-temperature": "Manuel temperatur", + "map": "Kort", + "max-flow-temperature": "Maks. Fremløbstemperatur", + "min-flow-temperature": "Min. Fremløbstemperatur", + "mode": "Tilstand", + "mode-at-home": "Hjemme", + "mode-leaving-home": "Ikke til stede", + "mode-manual": "Manuel", + "mode-pause": "Pause", + "mode-vacation": "Ferie", + "new-entities-table": "Tabel over nye enheder", + "new-led-indicator": "Ny LED-indikator", + "new-scheduler-events": "Nye planlægningsbegivenheder", + "no-devices-found": "Ingen enheder fundet.", + "no-ecl-devices-found": "Ingen ECL-enheder fundet", + "no-vacations": "Ingen planlagte begivenheder", + "number-of-devices-imported": "{{numberOfDevices}} enhed(er) importeret.", + "offline-status": "Offline", + "online": "Online", + "online-status": "Online", + "outdoor-temperature": "Udendørstemperatur", + "override-temperature": "Overstyringstemperatur", + "overview": "Oversigt", + "owner-name": "Ejerens navn", + "parent-facility-name": "Overordnet placeringsnavn", + "pi-heating-demand": "Pi Heating Demand", + "pi-heating-demand-history": "Pi Heating Demand History", + "pi-heating-demand-values-history": "Pi Heating Demand Values History", + "place-devices-in-this-zone": "Placer enheder i denne zone", + "place-into-zone": "Placer i zone", + "please-choose-user-role": "Vælg brugerrolle", + "pre-comfort": "Forkomfort", + "pre-setback": "Forsænkning", + "production-week": "Produktionsuge", + "read-only-users": "Skrivebeskyttede brugere", + "real-etrv-current-temp": "Termostattemperatur", + "refresh-device-status": "Opdater enhedsstatus", + "remove-from-zone": "Fjern fra zone", + "remove-user-from-loc": "Fjern bruger fra denne placering", + "remove-user-title": "Fjern bruger", + "resend-code": "Send kode igen", + "resend-code-msg": "Din kode er sendt! Tjek din e-mail.", + "return-temp": "Returløbstemperatur", + "room-map": "Kort over rum", + "save-comfort-dhw-setpoint": "Gem sætpunkt for 'Komfort varmt brugsvand'", + "save-saving-dhw-setpoint": "Gem sætpunktet 'Gemmer varmt brugsvand'", + "saving-dhw-setpoint": "Gemmer sætpunktet varmt brugsvand", + "saving-room": "Gemmer rum", + "saving-room-setpoint": "Gemmer sætpunkt for rum", + "saving-room-setpoint-is-required": "Gemmer sætpunkt for rum er påkrævet.", + "scheduled-operation": "Planlagt drift", + "scheduler-events": "Planlægningsbegivenheder", + "see-advanced-settings-for-details": "Se avancerede indstillinger for at få yderligere oplysninger", + "see-areas": "se områder", + "see-devices-in-home": "Se enheder i hjemmet", + "see-information": "Se oplysninger", + "selected-devices-are-successfully-linked-with-ecl-device": "Selected device(s) are successfully linked with ECL device.", + "serial-number": "Serienummer", + "set-ecl-heating-circuit": "Set ECL heating circuit", + "select-ecl-device": "Vælg ECL-enhed...", + "device-are-linked-to-ecl": "Den eller de valgte enheder er med succes forbundet med ECL-enhed.", + "unlink-all-devices": "Fjern linket til alle enheder fra ECL", + "unlink-device": "Fjern forbindelsen mellem enhed fra ECL", + "see-pi-history": "Se PI-historik", + "device-unlinked-msg": "Enheden er fjernet fra ECL", + "set-global-temp": "Indstil den globale temperatur", + "are-you-sure-unlink-all": "Er du sikker på at fjerne linket til ALLE enheder fra ECL?", + "are-you-sure-unlink-device": "Er du sikker på at fjerne linket mellem enhed {{device}} og ECL-controlleren?", + "set-temp": "Indstil temp.", + "set-temperature": "Ønsket temperatur", + "set-vacation": "Indstil ferie", + "setback": "Sænkning", + "setback-dhw-setpoint-is-required": "Gemmer sætpunktet varmt brugsvand er påkrævet.", + "software": "Software", + "software-build-no": "Softwarebuildnr.", + "something-went-wrong": "Noget gik galt!", + "subdevices-information-saved": "Gateway-underenheder gemt.", + "successfully-inserted-devices": "{{numberOfDevices}} enhed(er) blev indsat.", + "temp-required": "Temperaturværdi er påkrævet", + "temperature": "Temperatur", + "this-user": "denne bruger", + "title-homes": "Hjem", + "title-location": "Placering", + "update-area-map": "Opdater områdekort", + "update-facilities": "Opdater faciliteter", + "update-home-map": "Opdater hjemmekort", + "update-zone-map": "Opdater zonekort", + "upper-temperature": "Øvre temperatur", + "user-activation-link-has-been-copied-to-clipboard": "Brugeraktiveringslinket er blevet kopieret til udklipsholderen", + "user-removed-fm": "Bruger fjernet som Facility Manager fra denne placering.", + "user-removed-ro": "Bruger fjernet som skrivebeskyttet bruger fra denne placering.", + "user-was-successfully-assigned-to-the-facility": "Brugeren blev tildelt {{facilityName}}", + "user-with-email-already-exists": "Bruger med e-mail '{{email}}' findes allerede!", + "user-with-this-email-is-already-assigned-to-the-facility": "Bruger med denne e-mail er allerede tildelt '{{facilityName}}'.", + "user-with-this-email-was-not-found": "Bruger med denne e-mail blev ikke fundet.", + "vacation-plan": "Ferieplan", + "view-details": "Vis detaljer", + "view-device-information": "Vis enhedsoplysninger", + "view-home": "Vis hjem", + "view-information": "Vis oplysninger", + "view-users": "Brugere", + "view-zone": "Vis zone", + "warning-uppercase": "ADVARSEL", + "were-not-imported": "blev ikke importeret", + "window-state": "Vinduestilstand", + "work-state": "Arbejdstilstand", + "you-dont-have-attribute-free": "Du har ikke en attribut, der er ledig til placeringsnavn!", + "you-have-valid-ally-account": "Du har en gyldig Ally™ konto.", + "your-ally-email-account": "Din Ally™ e-mailkonto", + "your-facilities": "Dine faciliteter", + "your-home-was-successfully-deleted": "Dit hjem blev slettet.", + "zone": "zone", + "zone-have-no-devices-msg": "Der er ingen enheder placeret i zonen. Placer venligst nogle enheder.", + "zone-management": "Zonestyring", + "zone-name": "Navn", + "zone-name-is-required": "Zonenavn er påkrævet.", + "zone-temp-not-enabled": " ikke aktiveret.", + "zone-temp-sett": "Indstilling af temperaturen", + "zone-temp-sett-tooltip": "Ændr temperaturen", + "zone-temperature": "Zonetemperatur", + "zone-view": "Zonevisning" + } + }, + "language": { + "language": "Sprog" + } +} diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 3df8a15e52..3ca19d0744 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -4803,7 +4803,8 @@ "lv_LV": "Latviešu", "ka_GE": "ქართული", "pt_BR": "Português do Brasil", - "sl_SI": "Slovenščina" + "sl_SI": "Slovenščina", + "da_DK": "Dansk" } } } From 0cd2ad03ad2d20d6d6052d8dfc2bab05483b07d6 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Tue, 13 Dec 2022 14:42:36 +0200 Subject: [PATCH 41/66] Added support of USER entity in Push to Edge / Push to Cloud rule nodes --- .../engine/edge/AbstractTbMsgPushNode.java | 1 + .../engine/edge/TbMsgPushToEdgeNodeTest.java | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/AbstractTbMsgPushNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/AbstractTbMsgPushNode.java index f120276df3..73d540ff1d 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/AbstractTbMsgPushNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/AbstractTbMsgPushNode.java @@ -168,6 +168,7 @@ public abstract class AbstractTbMsgPushNode edgePageData = new PageData<>(List.of(edgeId), 1, 1, false); + Mockito.when(edgeService.findRelatedEdgeIdsByEntityId(tenantId, userId, new PageLink(TbMsgPushToEdgeNode.DEFAULT_PAGE_SIZE))).thenReturn(edgePageData); + + TbMsg msg = TbMsg.newMsg(DataConstants.ATTRIBUTES_UPDATED, userId, new TbMsgMetaData(), + TbMsgDataType.JSON, "{}", null, null); + + node.onMsg(ctx, msg); + + verify(edgeEventService).saveAsync(any()); + } } From 055fbce062fdcc3c62c2e9429c6373f96d775d84 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Tue, 13 Dec 2022 15:41:53 +0200 Subject: [PATCH 42/66] Edge telemetry processor - added support of USER entity --- .../rpc/processor/TelemetryEdgeProcessor.java | 7 ++- .../server/edge/BaseTelemetryEdgeTest.java | 59 +++++++++++-------- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryEdgeProcessor.java index f4d713b40f..481ee7762e 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryEdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/TelemetryEdgeProcessor.java @@ -48,7 +48,7 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.kv.AttributeKey; +import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; @@ -71,9 +71,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import javax.annotation.Nullable; import javax.annotation.PostConstruct; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; @Component @Slf4j @@ -325,6 +323,9 @@ public class TelemetryEdgeProcessor extends BaseEdgeProcessor { case CUSTOMER: entityId = new CustomerId(edgeEvent.getEntityId()); break; + case USER: + entityId = new UserId(edgeEvent.getEntityId()); + break; case EDGE: entityId = new EdgeId(edgeEvent.getEntityId()); break; diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseTelemetryEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseTelemetryEdgeTest.java index 8930166396..4da9f9a001 100644 --- a/application/src/test/java/org/thingsboard/server/edge/BaseTelemetryEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/BaseTelemetryEdgeTest.java @@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.edge.EdgeEventType; +import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.gen.edge.v1.AttributeDeleteMsg; import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.v1.EntityDataProto; @@ -67,36 +68,11 @@ abstract public class BaseTelemetryEdgeTest extends AbstractEdgeTest { public void testAttributes() throws Exception { Device device = findDeviceByName("Edge Device 1"); - testAttributesUpdatedMsg(device); + testAttributesUpdatedMsg(device.getId()); testPostAttributesMsg(device); testAttributesDeleteMsg(device); } - private void testAttributesUpdatedMsg(Device device) throws Exception { - String attributesData = "{\"scope\":\"SERVER_SCOPE\",\"kv\":{\"key1\":\"value1\"}}"; - JsonNode attributesEntityData = mapper.readTree(attributesData); - EdgeEvent edgeEvent1 = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.ATTRIBUTES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, attributesEntityData); - edgeImitator.expectMessageAmount(1); - edgeEventService.saveAsync(edgeEvent1).get(); - clusterService.onEdgeEventUpdate(tenantId, edge.getId()); - Assert.assertTrue(edgeImitator.waitForMessages()); - - AbstractMessage latestMessage = edgeImitator.getLatestMessage(); - Assert.assertTrue(latestMessage instanceof EntityDataProto); - EntityDataProto latestEntityDataMsg = (EntityDataProto) latestMessage; - Assert.assertEquals(device.getUuidId().getMostSignificantBits(), latestEntityDataMsg.getEntityIdMSB()); - Assert.assertEquals(device.getUuidId().getLeastSignificantBits(), latestEntityDataMsg.getEntityIdLSB()); - Assert.assertEquals(device.getId().getEntityType().name(), latestEntityDataMsg.getEntityType()); - Assert.assertEquals("SERVER_SCOPE", latestEntityDataMsg.getPostAttributeScope()); - Assert.assertTrue(latestEntityDataMsg.hasAttributesUpdatedMsg()); - - TransportProtos.PostAttributeMsg attributesUpdatedMsg = latestEntityDataMsg.getAttributesUpdatedMsg(); - Assert.assertEquals(1, attributesUpdatedMsg.getKvCount()); - TransportProtos.KeyValueProto keyValueProto = attributesUpdatedMsg.getKv(0); - Assert.assertEquals("key1", keyValueProto.getKey()); - Assert.assertEquals("value1", keyValueProto.getStringV()); - } - private void testPostAttributesMsg(Device device) throws Exception { String postAttributesData = "{\"scope\":\"SERVER_SCOPE\",\"kv\":{\"key2\":\"value2\"}}"; JsonNode postAttributesEntityData = mapper.readTree(postAttributesData); @@ -226,4 +202,35 @@ abstract public class BaseTelemetryEdgeTest extends AbstractEdgeTest { edgeImitator.setRandomFailuresOnTimeseriesDownlink(false); } + + @Test + public void testAttributesUpdatedMsg_userEntity() throws Exception { + testAttributesUpdatedMsg(tenantAdmin.getId()); + } + + private void testAttributesUpdatedMsg(EntityId entityId) throws Exception { + String attributesData = "{\"scope\":\"SERVER_SCOPE\",\"kv\":{\"key1\":\"value1\"}}"; + JsonNode attributesEntityData = mapper.readTree(attributesData); + EdgeEvent edgeEvent1 = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.ATTRIBUTES_UPDATED, entityId.getId(), EdgeEventType.valueOf(entityId.getEntityType().name()), attributesEntityData); + edgeImitator.expectMessageAmount(1); + edgeEventService.saveAsync(edgeEvent1).get(); + clusterService.onEdgeEventUpdate(tenantId, edge.getId()); + Assert.assertTrue(edgeImitator.waitForMessages()); + + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof EntityDataProto); + EntityDataProto latestEntityDataMsg = (EntityDataProto) latestMessage; + Assert.assertEquals(entityId.getId().getMostSignificantBits(), latestEntityDataMsg.getEntityIdMSB()); + Assert.assertEquals(entityId.getId().getLeastSignificantBits(), latestEntityDataMsg.getEntityIdLSB()); + Assert.assertEquals(entityId.getEntityType().name(), latestEntityDataMsg.getEntityType()); + Assert.assertEquals("SERVER_SCOPE", latestEntityDataMsg.getPostAttributeScope()); + Assert.assertTrue(latestEntityDataMsg.hasAttributesUpdatedMsg()); + + TransportProtos.PostAttributeMsg attributesUpdatedMsg = latestEntityDataMsg.getAttributesUpdatedMsg(); + Assert.assertEquals(1, attributesUpdatedMsg.getKvCount()); + TransportProtos.KeyValueProto keyValueProto = attributesUpdatedMsg.getKv(0); + Assert.assertEquals("key1", keyValueProto.getKey()); + Assert.assertEquals("value1", keyValueProto.getStringV()); + } + } From 10ab64b0d564e6d11b7c03a574c255b10ff3f405 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Tue, 13 Dec 2022 15:55:00 +0200 Subject: [PATCH 43/66] Device Edge Service - push inactivityTimeout to edge --- .../edge/rpc/sync/DefaultEdgeRequestsService.java | 3 ++- .../thingsboard/server/edge/BaseDeviceEdgeTest.java | 13 ++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/sync/DefaultEdgeRequestsService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/sync/DefaultEdgeRequestsService.java index 9210d3ceec..4be7ddb1c8 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/sync/DefaultEdgeRequestsService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/sync/DefaultEdgeRequestsService.java @@ -165,7 +165,8 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { Map entityData = new HashMap<>(); ObjectNode attributes = JacksonUtil.OBJECT_MAPPER.createObjectNode(); for (AttributeKvEntry attr : ssAttributes) { - if (DefaultDeviceStateService.PERSISTENT_ATTRIBUTES.contains(attr.getKey())) { + if (DefaultDeviceStateService.PERSISTENT_ATTRIBUTES.contains(attr.getKey()) + && !DefaultDeviceStateService.INACTIVITY_TIMEOUT.equals(attr.getKey())) { continue; } if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) { diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseDeviceEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseDeviceEdgeTest.java index a3162ebc5f..e5fe165a1e 100644 --- a/application/src/test/java/org/thingsboard/server/edge/BaseDeviceEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/BaseDeviceEdgeTest.java @@ -319,6 +319,8 @@ abstract public class BaseDeviceEdgeTest extends AbstractEdgeTest { Device device = findDeviceByName("Edge Device 1"); sendAttributesRequestAndVerify(device, DataConstants.SERVER_SCOPE, "{\"key1\":\"value1\"}", "key1", "value1"); + sendAttributesRequestAndVerify(device, DataConstants.SERVER_SCOPE, "{\"inactivityTimeout\":3600000}", + "inactivityTimeout", "3600000"); sendAttributesRequestAndVerify(device, DataConstants.SHARED_SCOPE, "{\"key2\":\"value2\"}", "key2", "value2"); } @@ -576,7 +578,16 @@ abstract public class BaseDeviceEdgeTest extends AbstractEdgeTest { for (TransportProtos.KeyValueProto keyValueProto : attributesUpdatedMsg.getKvList()) { if (keyValueProto.getKey().equals(expectedKey)) { Assert.assertEquals(expectedKey, keyValueProto.getKey()); - Assert.assertEquals(expectedValue, keyValueProto.getStringV()); + switch (keyValueProto.getType()) { + case STRING_V: + Assert.assertEquals(expectedValue, keyValueProto.getStringV()); + break; + case LONG_V: + Assert.assertEquals(Long.parseLong(expectedValue), keyValueProto.getLongV()); + break; + default: + Assert.fail("Unexpected data type: " + keyValueProto.getType()); + } found = true; } } From 4c60bd1a4ee614a6767152ac61cd6e14a812728f Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Tue, 13 Dec 2022 16:15:33 +0200 Subject: [PATCH 44/66] Edge rule chain service - fixed update of root rule chain in runtime --- .../edge/DefaultEdgeNotificationService.java | 8 +++- .../service/edge/rpc/EdgeGrpcSession.java | 2 +- .../constructor/RuleChainMsgConstructor.java | 4 +- .../rpc/processor/RuleChainEdgeProcessor.java | 13 ++++-- .../server/edge/BaseRuleChainEdgeTest.java | 45 +++++++++++++++++++ 5 files changed, 65 insertions(+), 7 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 1bb30d6960..6d368fbed8 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -16,6 +16,7 @@ package org.thingsboard.server.service.edge; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -23,6 +24,7 @@ import lombok.extern.slf4j.Slf4j; import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.EdgeUtils; @@ -67,6 +69,8 @@ import java.util.concurrent.Executors; @Slf4j public class DefaultEdgeNotificationService implements EdgeNotificationService { + public static final String EDGE_IS_ROOT_BODY_KEY = "isRoot"; + @Autowired private EdgeService edgeService; @@ -142,7 +146,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { public Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws Exception { edge.setRootRuleChainId(ruleChainId); Edge savedEdge = edgeService.saveEdge(edge); - saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.RULE_CHAIN, EdgeEventActionType.UPDATED, ruleChainId, null).get(); + ObjectNode isRootBody = JacksonUtil.OBJECT_MAPPER.createObjectNode(); + isRootBody.put(EDGE_IS_ROOT_BODY_KEY, Boolean.TRUE); + saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.RULE_CHAIN, EdgeEventActionType.UPDATED, ruleChainId, isRootBody).get(); return savedEdge; } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 9571319226..28cc32efa3 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -524,7 +524,7 @@ public final class EdgeGrpcSession implements Closeable { case CUSTOMER: return ctx.getCustomerProcessor().convertCustomerEventToDownlink(edgeEvent); case RULE_CHAIN: - return ctx.getRuleChainProcessor().convertRuleChainEventToDownlink(edge, edgeEvent); + return ctx.getRuleChainProcessor().convertRuleChainEventToDownlink(edgeEvent); case RULE_CHAIN_METADATA: return ctx.getRuleChainProcessor().convertRuleChainMetadataEventToDownlink(edgeEvent, this.edgeVersion); case ALARM: diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainMsgConstructor.java index 35ac760faa..7f5ae72511 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainMsgConstructor.java @@ -35,13 +35,13 @@ import org.thingsboard.server.service.edge.rpc.constructor.rule.RuleChainMetadat @TbCoreComponent public class RuleChainMsgConstructor { - public RuleChainUpdateMsg constructRuleChainUpdatedMsg(RuleChainId edgeRootRuleChainId, UpdateMsgType msgType, RuleChain ruleChain) { + public RuleChainUpdateMsg constructRuleChainUpdatedMsg(UpdateMsgType msgType, RuleChain ruleChain, boolean isRoot) { RuleChainUpdateMsg.Builder builder = RuleChainUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(ruleChain.getId().getId().getMostSignificantBits()) .setIdLSB(ruleChain.getId().getId().getLeastSignificantBits()) .setName(ruleChain.getName()) - .setRoot(ruleChain.getId().equals(edgeRootRuleChainId)) + .setRoot(isRoot) .setDebugMode(ruleChain.isDebugMode()) .setConfiguration(JacksonUtil.toString(ruleChain.getConfiguration())); if (ruleChain.getFirstRuleNodeId() != null) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/RuleChainEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/RuleChainEdgeProcessor.java index 5704e7d30d..22d8005472 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/RuleChainEdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/RuleChainEdgeProcessor.java @@ -19,7 +19,6 @@ import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.EdgeUtils; -import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; @@ -33,12 +32,14 @@ import org.thingsboard.server.gen.edge.v1.UpdateMsgType; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.util.TbCoreComponent; +import static org.thingsboard.server.service.edge.DefaultEdgeNotificationService.EDGE_IS_ROOT_BODY_KEY; + @Component @Slf4j @TbCoreComponent public class RuleChainEdgeProcessor extends BaseEdgeProcessor { - public DownlinkMsg convertRuleChainEventToDownlink(Edge edge, EdgeEvent edgeEvent) { + public DownlinkMsg convertRuleChainEventToDownlink(EdgeEvent edgeEvent) { RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId()); DownlinkMsg downlinkMsg = null; switch (edgeEvent.getAction()) { @@ -47,9 +48,15 @@ public class RuleChainEdgeProcessor extends BaseEdgeProcessor { case ASSIGNED_TO_EDGE: RuleChain ruleChain = ruleChainService.findRuleChainById(edgeEvent.getTenantId(), ruleChainId); if (ruleChain != null) { + boolean isRoot = false; + if (edgeEvent.getBody() != null && edgeEvent.getBody().get(EDGE_IS_ROOT_BODY_KEY) != null) { + try { + isRoot = Boolean.parseBoolean(edgeEvent.getBody().get(EDGE_IS_ROOT_BODY_KEY).asText()); + } catch (Exception ignored) {} + } UpdateMsgType msgType = getUpdateMsgType(edgeEvent.getAction()); RuleChainUpdateMsg ruleChainUpdateMsg = - ruleChainMsgConstructor.constructRuleChainUpdatedMsg(edge.getRootRuleChainId(), msgType, ruleChain); + ruleChainMsgConstructor.constructRuleChainUpdatedMsg(msgType, ruleChain, isRoot); downlinkMsg = DownlinkMsg.newBuilder() .setDownlinkMsgId(EdgeUtils.nextPositiveInt()) .addRuleChainUpdateMsg(ruleChainUpdateMsg) diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseRuleChainEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseRuleChainEdgeTest.java index 712beeb019..a3539f8053 100644 --- a/application/src/test/java/org/thingsboard/server/edge/BaseRuleChainEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/BaseRuleChainEdgeTest.java @@ -18,6 +18,7 @@ package org.thingsboard.server.edge; import com.google.protobuf.AbstractMessage; import org.junit.Assert; import org.junit.Test; +import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainMetaData; @@ -165,4 +166,48 @@ abstract public class BaseRuleChainEdgeTest extends AbstractEdgeTest { doPost("/api/ruleChain/metadata", ruleChainMetaData, RuleChainMetaData.class); } + @Test + public void testSetRootRuleChain() throws Exception { + // create rule chain + edgeImitator.expectMessageAmount(1); + RuleChain ruleChain = new RuleChain(); + ruleChain.setName("Edge New Root Rule Chain"); + ruleChain.setType(RuleChainType.EDGE); + RuleChain savedRuleChain = doPost("/api/ruleChain", ruleChain, RuleChain.class); + doPost("/api/edge/" + edge.getUuidId() + + "/ruleChain/" + savedRuleChain.getUuidId(), RuleChain.class); + Assert.assertTrue(edgeImitator.waitForMessages()); + + // set new rule chain as root + RuleChainId currentRootRuleChainId = edge.getRootRuleChainId(); + edgeImitator.expectMessageAmount(1); + doPost("/api/edge/" + edge.getUuidId() + + "/" + savedRuleChain.getUuidId() + "/root", Edge.class); + Assert.assertTrue(edgeImitator.waitForMessages()); + Optional ruleChainUpdateMsgOpt = edgeImitator.findMessageByType(RuleChainUpdateMsg.class); + Assert.assertTrue(ruleChainUpdateMsgOpt.isPresent()); + RuleChainUpdateMsg ruleChainUpdateMsg = ruleChainUpdateMsgOpt.get(); + Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, ruleChainUpdateMsg.getMsgType()); + Assert.assertEquals(ruleChainUpdateMsg.getIdMSB(), savedRuleChain.getUuidId().getMostSignificantBits()); + Assert.assertEquals(ruleChainUpdateMsg.getIdLSB(), savedRuleChain.getUuidId().getLeastSignificantBits()); + Assert.assertTrue(ruleChainUpdateMsg.getRoot()); + + // revert root rule chain + edgeImitator.expectMessageAmount(1); + doPost("/api/edge/" + edge.getUuidId() + + "/" + currentRootRuleChainId.getId() + "/root", Edge.class); + Assert.assertTrue(edgeImitator.waitForMessages()); + + // unassign rule chain from edge + edgeImitator.expectMessageAmount(1); + doDelete("/api/edge/" + edge.getUuidId() + + "/ruleChain/" + savedRuleChain.getUuidId(), RuleChain.class); + Assert.assertTrue(edgeImitator.waitForMessages()); + + // delete rule chain + edgeImitator.expectMessageAmount(1); + doDelete("/api/ruleChain/" + savedRuleChain.getUuidId()) + .andExpect(status().isOk()); + Assert.assertFalse(edgeImitator.waitForMessages(1)); + } } From 93fb9754ef6f2222878bb766b31adf8f2e39eaa1 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 14 Dec 2022 13:14:58 +0200 Subject: [PATCH 45/66] UI: Always visible action button in multiple input widgets --- .../lib/multiple-input-widget.component.html | 28 +++++++++---------- .../lib/multiple-input-widget.component.scss | 11 ++++++-- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html index 550f7cde49..93453521c2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html @@ -19,7 +19,7 @@ [formGroup]="multipleInputFormGroup" tb-toast toastTarget="{{ toastTargetId }}" (ngSubmit)="saveForm()" novalidate autocomplete="off"> -
+
{{ getGroupTitle(source.datasource) }} @@ -142,19 +142,19 @@
-
- - -
+ +
+ +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.scss index 37e8d5ad8b..f99671bed5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.scss @@ -17,8 +17,15 @@ .tb-multiple-input { height: 100%; - overflow-x: hidden; - overflow-y: auto; + display: flex; + flex-direction: column; + + .tb-multiple-input-container { + padding: 0 8px; + flex: 1 1 100%; + overflow-x: hidden; + overflow-y: auto; + } .fields-group { padding: 0 8px; From b56734148146e2c81bceba1d30ec16185cfa2520 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 15 Dec 2022 12:36:23 +0200 Subject: [PATCH 46/66] added DeviceProfileService and AssetProfileService to TBContext --- .../server/actors/ActorSystemContext.java | 10 ++++++++++ .../server/actors/ruleChain/DefaultTbContext.java | 12 ++++++++++++ .../org/thingsboard/rule/engine/api/TbContext.java | 6 ++++++ 3 files changed, 28 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java index e1a41fe401..8b19a6954c 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -50,6 +50,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.tools.TbRateLimits; import org.thingsboard.server.common.stats.TbApiUsageReportClient; +import org.thingsboard.server.dao.asset.AssetProfileService; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.audit.AuditLogService; @@ -58,6 +59,7 @@ import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.device.ClaimDevicesService; import org.thingsboard.server.dao.device.DeviceCredentialsService; +import org.thingsboard.server.dao.device.DeviceProfileService; import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.dao.edge.EdgeService; @@ -176,6 +178,14 @@ public class ActorSystemContext { @Getter private DeviceService deviceService; + @Autowired + @Getter + private DeviceProfileService deviceProfileService; + + @Autowired + @Getter + private AssetProfileService assetProfileService; + @Autowired @Getter private DeviceCredentialsService deviceCredentialsService; diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java index ef2de35912..ba1c4e9796 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java @@ -71,12 +71,14 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.TbMsgProcessingStackItem; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; +import org.thingsboard.server.dao.asset.AssetProfileService; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.cassandra.CassandraCluster; import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.device.DeviceCredentialsService; +import org.thingsboard.server.dao.device.DeviceProfileService; import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.dao.edge.EdgeService; @@ -559,6 +561,16 @@ class DefaultTbContext implements TbContext { return mainCtx.getDeviceService(); } + @Override + public DeviceProfileService getDeviceProfileService() { + return mainCtx.getDeviceProfileService(); + } + + @Override + public AssetProfileService getAssetProfileService() { + return mainCtx.getAssetProfileService(); + } + @Override public DeviceCredentialsService getDeviceCredentialsService() { return mainCtx.getDeviceCredentialsService(); diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java index 9851eead80..1786fd08be 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java @@ -42,12 +42,14 @@ import org.thingsboard.server.common.data.rule.RuleNodeState; import org.thingsboard.server.common.data.script.ScriptLanguage; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.dao.asset.AssetProfileService; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.cassandra.CassandraCluster; import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.device.DeviceCredentialsService; +import org.thingsboard.server.dao.device.DeviceProfileService; import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.dao.edge.EdgeService; @@ -223,6 +225,10 @@ public interface TbContext { DeviceService getDeviceService(); + DeviceProfileService getDeviceProfileService(); + + AssetProfileService getAssetProfileService(); + DeviceCredentialsService getDeviceCredentialsService(); TbClusterService getClusterService(); From df28b217330062e8cbb3560d05d1be7be736e8f6 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Thu, 15 Dec 2022 13:19:03 +0100 Subject: [PATCH 47/66] fixed bulk import test infinite await --- .../sync/ie/importing/csv/AbstractBulkImportService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java index 37d3cd2e71..d78403a884 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java @@ -87,7 +87,7 @@ public abstract class AbstractBulkImportService Date: Thu, 15 Dec 2022 15:10:38 +0200 Subject: [PATCH 48/66] updated logic & fix typos after review --- .../update/DefaultDataUpdateService.java | 2 +- common/dao-api/pom.xml | 4 --- .../server/dao/alarm/AlarmService.java | 4 +-- .../server/dao/asset/AssetProfileService.java | 4 +-- .../server/dao/asset/AssetService.java | 4 +-- .../server/dao/audit/AuditLogService.java | 4 +-- .../server/dao/customer/CustomerService.java | 4 +-- .../dao/dashboard/DashboardService.java | 4 +-- .../dao/device/DeviceProfileService.java | 4 +-- .../server/dao/device/DeviceService.java | 4 +-- .../server/dao/edge/EdgeService.java | 4 +-- ...tityService.java => EntityDaoService.java} | 4 +-- .../server/dao/entity/EntityService.java | 2 +- .../dao/entity/EntityServiceRegistry.java | 24 +++++++++++++ .../dao/entityview/EntityViewService.java | 4 +-- .../server/dao/event/EventService.java | 4 +-- .../server/dao/ota/OtaPackageService.java | 4 +-- .../server/dao/queue/QueueService.java | 4 +-- .../server/dao/resource/ResourceService.java | 4 +-- .../server/dao/rpc/RpcService.java | 4 +-- .../server/dao/rule/RuleChainService.java | 4 +-- .../dao/tenant/TenantProfileService.java | 4 +-- .../server/dao/tenant/TenantService.java | 4 +-- .../dao/usagerecord/ApiUsageStateService.java | 4 +-- .../server/dao/user/UserService.java | 4 +-- .../server/dao/widget/WidgetTypeService.java | 4 +-- .../dao/widget/WidgetsBundleService.java | 4 +-- .../server/dao/alarm/BaseAlarmService.java | 12 +++---- .../dao/asset/AssetProfileServiceImpl.java | 2 +- .../server/dao/asset/BaseAssetService.java | 2 +- .../server/dao/audit/AuditLogServiceImpl.java | 5 ++- .../dao/audit/DummyAuditLogServiceImpl.java | 2 +- .../dao/customer/CustomerServiceImpl.java | 2 +- .../dao/dashboard/DashboardServiceImpl.java | 2 +- .../dao/device/DeviceProfileServiceImpl.java | 2 +- .../server/dao/device/DeviceServiceImpl.java | 2 +- .../server/dao/edge/EdgeServiceImpl.java | 2 +- .../server/dao/entity/BaseEntityService.java | 20 ++++++----- .../entity/DefaultEntityServiceRegistry.java | 35 +++++++++++++++---- .../dao/entityview/EntityViewServiceImpl.java | 2 +- .../server/dao/event/BaseEventService.java | 2 +- .../server/dao/ota/BaseOtaPackageService.java | 2 +- .../server/dao/queue/BaseQueueService.java | 2 +- .../dao/relation/BaseRelationService.java | 4 +-- .../dao/resource/BaseResourceService.java | 2 +- .../server/dao/rpc/BaseRpcService.java | 2 +- .../server/dao/rule/BaseRuleChainService.java | 2 +- .../dao/tenant/TenantProfileServiceImpl.java | 2 +- .../server/dao/tenant/TenantServiceImpl.java | 2 +- .../usagerecord/ApiUsageStateServiceImpl.java | 2 +- .../server/dao/user/UserServiceImpl.java | 2 +- .../util/AbstractBufferedRateExecutor.java | 6 ++-- .../dao/widget/WidgetTypeServiceImpl.java | 2 +- .../dao/widget/WidgetsBundleServiceImpl.java | 2 +- ...ava => BaseEntityServiceRegistryTest.java} | 20 +++++------ ...java => EntityServiceRegistrySqlTest.java} | 4 +-- 56 files changed, 158 insertions(+), 114 deletions(-) rename common/dao-api/src/main/java/org/thingsboard/server/dao/entity/{TbEntityService.java => EntityDaoService.java} (88%) create mode 100644 common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityServiceRegistry.java rename common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityServiceBeanFactory.java => dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java (55%) rename dao/src/test/java/org/thingsboard/server/dao/service/{BaseEntityServiceBeanFactoryTest.java => BaseEntityServiceRegistryTest.java} (62%) rename dao/src/test/java/org/thingsboard/server/dao/service/sql/{EntityServiceBeanFactorySqlTest.java => EntityServiceRegistrySqlTest.java} (81%) diff --git a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java index ee34bd7f23..9532bc3044 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java @@ -561,7 +561,7 @@ public class DefaultDataUpdateService implements DataUpdateService { while (hasNext) { for (Alarm alarm : alarms.getData()) { if (alarm.getCustomerId() == null && alarm.getOriginator() != null) { - alarm.setCustomerId(entityService.fetchEntityCustomerId(tenantId, alarm.getOriginator())); + alarm.setCustomerId(entityService.fetchEntityCustomerId(tenantId, alarm.getOriginator()).get()); alarmDao.save(tenantId, alarm); } if (processed.incrementAndGet() % 1000 == 0) { diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index a748c33ac6..527249e999 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -115,10 +115,6 @@ awaitility test - - org.apache.commons - commons-text - diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java index 4bd1eb79fc..70f8f00ebb 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java @@ -30,14 +30,14 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.query.AlarmData; import org.thingsboard.server.common.data.query.AlarmDataQuery; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.Collection; /** * Created by ashvayka on 11.05.17. */ -public interface AlarmService extends TbEntityService { +public interface AlarmService extends EntityDaoService { AlarmOperationResult createOrUpdateAlarm(Alarm alarm); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetProfileService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetProfileService.java index c8200812dc..1d702c7ec0 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetProfileService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetProfileService.java @@ -21,9 +21,9 @@ import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; -public interface AssetProfileService extends TbEntityService { +public interface AssetProfileService extends EntityDaoService { AssetProfile findAssetProfileById(TenantId tenantId, AssetProfileId assetProfileId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetService.java index fc8f8ca88e..721386b2c7 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetService.java @@ -27,11 +27,11 @@ import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; -public interface AssetService extends TbEntityService { +public interface AssetService extends EntityDaoService { AssetInfo findAssetInfoById(TenantId tenantId, AssetId assetId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/audit/AuditLogService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/audit/AuditLogService.java index c810971ee5..27f9cfbb48 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/audit/AuditLogService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/audit/AuditLogService.java @@ -25,11 +25,11 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; -public interface AuditLogService extends TbEntityService { +public interface AuditLogService extends EntityDaoService { PageData findAuditLogsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, List actionTypes, TimePageLink pageLink); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/customer/CustomerService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/customer/CustomerService.java index d8a904d7c1..12fcc04768 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/customer/CustomerService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/customer/CustomerService.java @@ -21,11 +21,11 @@ import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.Optional; -public interface CustomerService extends TbEntityService { +public interface CustomerService extends EntityDaoService { Customer findCustomerById(TenantId tenantId, CustomerId customerId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java index 9f7f3ae3e0..e718e53367 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java @@ -24,11 +24,11 @@ import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; -public interface DashboardService extends TbEntityService { +public interface DashboardService extends EntityDaoService { Dashboard findDashboardById(TenantId tenantId, DashboardId dashboardId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java index ec5673ce15..2e65e159cd 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java @@ -21,9 +21,9 @@ import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; -public interface DeviceProfileService extends TbEntityService { +public interface DeviceProfileService extends EntityDaoService { DeviceProfile findDeviceProfileById(TenantId tenantId, DeviceProfileId deviceProfileId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java index 9ce266e12a..4c4bcd4d40 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java @@ -33,12 +33,12 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.dao.device.provision.ProvisionRequest; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; import java.util.UUID; -public interface DeviceService extends TbEntityService { +public interface DeviceService extends EntityDaoService { DeviceInfo findDeviceInfoById(TenantId tenantId, DeviceId deviceId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java index b9fb6d8fcf..b7f5ecfc45 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java @@ -26,12 +26,12 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; import java.util.Optional; -public interface EdgeService extends TbEntityService { +public interface EdgeService extends EntityDaoService { Edge findEdgeById(TenantId tenantId, EdgeId edgeId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/entity/TbEntityService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityDaoService.java similarity index 88% rename from common/dao-api/src/main/java/org/thingsboard/server/dao/entity/TbEntityService.java rename to common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityDaoService.java index 0ce6a75b80..ce181e6d5a 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/entity/TbEntityService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityDaoService.java @@ -21,8 +21,8 @@ import org.thingsboard.server.common.data.id.TenantId; import java.util.Optional; -public interface TbEntityService { +public interface EntityDaoService { - Optional> fetchEntity(TenantId tenantId, EntityId entityId); + Optional> findEntity(TenantId tenantId, EntityId entityId); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityService.java index 9362dbef7a..aa5c70867f 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityService.java @@ -29,7 +29,7 @@ public interface EntityService { Optional fetchEntityName(TenantId tenantId, EntityId entityId); - CustomerId fetchEntityCustomerId(TenantId tenantId, EntityId entityId); + Optional fetchEntityCustomerId(TenantId tenantId, EntityId entityId); long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityServiceRegistry.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityServiceRegistry.java new file mode 100644 index 0000000000..3bbaa8f06e --- /dev/null +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityServiceRegistry.java @@ -0,0 +1,24 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.entity; + +import org.thingsboard.server.common.data.EntityType; + +public interface EntityServiceRegistry { + + EntityDaoService getServiceByEntityType(EntityType entityType); + +} diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java index 7d0cb1211d..f3efd99528 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java @@ -27,14 +27,14 @@ import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; /** * Created by Victor Basanets on 8/27/2017. */ -public interface EntityViewService extends TbEntityService { +public interface EntityViewService extends EntityDaoService { EntityView saveEntityView(EntityView entityView); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/event/EventService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/event/EventService.java index 00e6bea2de..095cdea30d 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/event/EventService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/event/EventService.java @@ -24,11 +24,11 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; -public interface EventService extends TbEntityService { +public interface EventService extends EntityDaoService { ListenableFuture saveAsync(Event event); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/ota/OtaPackageService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/ota/OtaPackageService.java index fe44038ccb..09d37fd81a 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/ota/OtaPackageService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/ota/OtaPackageService.java @@ -25,11 +25,11 @@ import org.thingsboard.server.common.data.ota.ChecksumAlgorithm; import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.nio.ByteBuffer; -public interface OtaPackageService extends TbEntityService { +public interface OtaPackageService extends EntityDaoService { OtaPackageInfo saveOtaPackageInfo(OtaPackageInfo otaPackageInfo, boolean isUrl); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/queue/QueueService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/queue/QueueService.java index 02b465602e..f9bb3e834d 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/queue/QueueService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/queue/QueueService.java @@ -20,11 +20,11 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.queue.Queue; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; -public interface QueueService extends TbEntityService { +public interface QueueService extends EntityDaoService { Queue saveQueue(Queue queue); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java index 1f6cba7062..fcb8ecebab 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java @@ -23,11 +23,11 @@ import org.thingsboard.server.common.data.id.TbResourceId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; -public interface ResourceService extends TbEntityService { +public interface ResourceService extends EntityDaoService { TbResource saveResource(TbResource resource); TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/rpc/RpcService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/rpc/RpcService.java index 431fdb5bda..727a1aadb8 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/rpc/RpcService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/rpc/RpcService.java @@ -23,9 +23,9 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.rpc.Rpc; import org.thingsboard.server.common.data.rpc.RpcStatus; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; -public interface RpcService extends TbEntityService { +public interface RpcService extends EntityDaoService { Rpc save(Rpc rpc); void deleteRpc(TenantId tenantId, RpcId id); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java index 8baf3783e7..20d4667a3c 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java @@ -31,7 +31,7 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.rule.RuleChainUpdateResult; import org.thingsboard.server.common.data.rule.RuleNode; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.Collection; import java.util.List; @@ -39,7 +39,7 @@ import java.util.List; /** * Created by igor on 3/12/18. */ -public interface RuleChainService extends TbEntityService { +public interface RuleChainService extends EntityDaoService { RuleChain saveRuleChain(RuleChain ruleChain); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileService.java index 91b1d70a61..1728837569 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileService.java @@ -21,9 +21,9 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; -public interface TenantProfileService extends TbEntityService { +public interface TenantProfileService extends EntityDaoService { TenantProfile findTenantProfileById(TenantId tenantId, TenantProfileId tenantProfileId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantService.java index 8186623ed2..af7c4c5892 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantService.java @@ -22,11 +22,11 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; -public interface TenantService extends TbEntityService { +public interface TenantService extends EntityDaoService { Tenant findTenantById(TenantId tenantId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateService.java index 93fd1d1f00..50208c859d 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateService.java @@ -19,9 +19,9 @@ import org.thingsboard.server.common.data.ApiUsageState; import org.thingsboard.server.common.data.id.ApiUsageStateId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; -public interface ApiUsageStateService extends TbEntityService { +public interface ApiUsageStateService extends EntityDaoService { ApiUsageState createDefaultApiUsageState(TenantId id, EntityId entityId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java index 53e89d7a51..d52f11e548 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java @@ -24,9 +24,9 @@ import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.UserCredentials; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; -public interface UserService extends TbEntityService { +public interface UserService extends EntityDaoService { User findUserById(TenantId tenantId, UserId userId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeService.java index d2a4e8ee2a..52beb62a25 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeService.java @@ -20,11 +20,11 @@ import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetTypeInfo; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; -public interface WidgetTypeService extends TbEntityService { +public interface WidgetTypeService extends EntityDaoService { WidgetType findWidgetTypeById(TenantId tenantId, WidgetTypeId widgetTypeId); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java index d0ef55a91e..c037cfb612 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java @@ -20,11 +20,11 @@ import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.widget.WidgetsBundle; -import org.thingsboard.server.dao.entity.TbEntityService; +import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; -public interface WidgetsBundleService extends TbEntityService { +public interface WidgetsBundleService extends EntityDaoService { WidgetsBundle findWidgetsBundleById(TenantId tenantId, WidgetsBundleId widgetsBundleId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java index abc2712bbc..30be664bc3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java @@ -114,7 +114,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ if (alarm.getEndTs() == 0L) { alarm.setEndTs(alarm.getStartTs()); } - alarm.setCustomerId(entityService.fetchEntityCustomerId(alarm.getTenantId(), alarm.getOriginator())); + alarm.setCustomerId(entityService.fetchEntityCustomerId(alarm.getTenantId(), alarm.getOriginator()).get()); if (alarm.getId() == null) { Alarm existing = alarmDao.findLatestByOriginatorAndType(alarm.getTenantId(), alarm.getOriginator(), alarm.getType()); if (existing == null || existing.getStatus().isCleared()) { @@ -284,8 +284,8 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ return Futures.transform(alarmDao.findAlarmByIdAsync(tenantId, alarmId.getId()), a -> { AlarmInfo alarmInfo = new AlarmInfo(a); - Optional originatorNameOpt = entityService.fetchEntityName(tenantId, alarmInfo.getOriginator()); - alarmInfo.setOriginatorName(originatorNameOpt.isEmpty() ? "N/A" : originatorNameOpt.get()); + alarmInfo.setOriginatorName( + entityService.fetchEntityName(tenantId, alarmInfo.getOriginator()).orElse("N/A")); return alarmInfo; }, MoreExecutors.directExecutor()); } @@ -311,8 +311,8 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ private ListenableFuture> fetchAlarmsOriginators(TenantId tenantId, PageData alarms) { List> alarmFutures = new ArrayList<>(alarms.getData().size()); for (AlarmInfo alarmInfo : alarms.getData()) { - Optional originatorNameOpt = entityService.fetchEntityName(tenantId, alarmInfo.getOriginator()); - alarmInfo.setOriginatorName(originatorNameOpt.isEmpty() ? "Deleted" : originatorNameOpt.get()); + alarmInfo.setOriginatorName( + entityService.fetchEntityName(tenantId, alarmInfo.getOriginator()).orElse("Deleted")); alarmFutures.add(Futures.immediateFuture(alarmInfo)); } return Futures.transform(Futures.successfulAsList(alarmFutures), @@ -405,7 +405,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ } @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findAlarmById(tenantId, new AlarmId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java index 75de5ba5d0..b7bd6afd75 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java @@ -268,7 +268,7 @@ public class AssetProfileServiceImpl extends AbstractCachedEntityService> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findAssetProfileById(tenantId, new AssetProfileId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java index e65a886833..4bc91f1d47 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java @@ -433,7 +433,7 @@ public class BaseAssetService extends AbstractCachedEntityService> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findAssetById(tenantId, new AssetId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java index 2ee07fd30c..883789d189 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java @@ -128,8 +128,7 @@ public class AuditLogServiceImpl implements AuditLogService { entityName = entity.getName(); } else { try { - Optional entityNameOpt = entityService.fetchEntityName(tenantId, entityId); - entityName = entityNameOpt.orElse(entityName); + entityName = entityService.fetchEntityName(tenantId, entityId).orElse(entityName); } catch (Exception ignored) { } } @@ -407,7 +406,7 @@ public class AuditLogServiceImpl implements AuditLogService { } @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.empty(); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java index 40b3b77c2e..094929c06a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java @@ -62,7 +62,7 @@ public class DummyAuditLogServiceImpl implements AuditLogService { } @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.empty(); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java index aad5de33f7..1f99c08be4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java @@ -182,7 +182,7 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom }; @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findCustomerById(tenantId, new CustomerId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java index d40c559856..b5093299fe 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java @@ -311,7 +311,7 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb }; @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findDashboardById(tenantId, new DashboardId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java index e459d3f48d..ed8c30af06 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java @@ -290,7 +290,7 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findDeviceProfileById(tenantId, new DeviceProfileId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java index d095e3d96c..56ffea98be 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java @@ -709,7 +709,7 @@ public class DeviceServiceImpl extends AbstractCachedEntityService> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findDeviceById(tenantId, new DeviceId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java index 68763786ef..834e733bdc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java @@ -522,7 +522,7 @@ public class EdgeServiceImpl extends AbstractCachedEntityService> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findEdgeById(tenantId, new EdgeId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java b/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java index 6d76785792..6626ec81ed 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java @@ -54,7 +54,7 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe private EntityQueryDao entityQueryDao; @Autowired - EntityServiceBeanFactory entityServiceBeanFactory; + DefaultEntityServiceRegistry entityServiceRegistry; @Override public long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query) { @@ -77,8 +77,8 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe @Override public Optional fetchEntityName(TenantId tenantId, EntityId entityId) { log.trace("Executing fetchEntityName [{}]", entityId); - TbEntityService tbEntityService = entityServiceBeanFactory.getServiceByEntityType(entityId.getEntityType()); - Optional> hasIdOpt = tbEntityService.fetchEntity(tenantId, entityId); + EntityDaoService entityDaoService = entityServiceRegistry.getServiceByEntityType(entityId.getEntityType()); + Optional> hasIdOpt = entityDaoService.findEntity(tenantId, entityId); if (hasIdOpt.isPresent()) { HasId hasId = hasIdOpt.get(); if (hasId instanceof HasName) { @@ -90,18 +90,22 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe } @Override - public CustomerId fetchEntityCustomerId(TenantId tenantId, EntityId entityId) { + public Optional fetchEntityCustomerId(TenantId tenantId, EntityId entityId) { log.trace("Executing fetchEntityCustomerId [{}]", entityId); - TbEntityService tbEntityService = entityServiceBeanFactory.getServiceByEntityType(entityId.getEntityType()); - Optional> hasIdOpt = tbEntityService.fetchEntity(tenantId, entityId); + EntityDaoService entityDaoService = entityServiceRegistry.getServiceByEntityType(entityId.getEntityType()); + Optional> hasIdOpt = entityDaoService.findEntity(tenantId, entityId); if (hasIdOpt.isPresent()) { HasId hasId = hasIdOpt.get(); if (hasId instanceof HasCustomerId) { HasCustomerId hasCustomerId = (HasCustomerId) hasId; - return hasCustomerId.getCustomerId(); + CustomerId customerId = hasCustomerId.getCustomerId(); + if (customerId == null) { + customerId = NULL_CUSTOMER_ID; + } + return Optional.of(customerId); } } - return NULL_CUSTOMER_ID; + return Optional.of(NULL_CUSTOMER_ID); } private static void validateEntityCountQuery(EntityCountQuery query) { diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityServiceBeanFactory.java b/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java similarity index 55% rename from common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityServiceBeanFactory.java rename to dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java index ff91d16d72..9ac76b0575 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityServiceBeanFactory.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java @@ -15,25 +15,46 @@ */ package org.thingsboard.server.dao.entity; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.text.CaseUtils; -import org.springframework.beans.factory.BeanFactory; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.EntityType; +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import java.util.Map; + +@Slf4j @Service -public class EntityServiceBeanFactory { +public class DefaultEntityServiceRegistry implements EntityServiceRegistry { private static final String SERVICE_SUFFIX = "DaoService"; - private final BeanFactory beanFactory; + private Map entityDaoServicesMap; + + private final ApplicationContext applicationContext; + + public DefaultEntityServiceRegistry(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + @PostConstruct + public void init() { + entityDaoServicesMap = applicationContext.getBeansOfType(EntityDaoService.class); + } - public EntityServiceBeanFactory(BeanFactory beanFactory) { - this.beanFactory = beanFactory; + @PreDestroy + public void destroy() { + if (entityDaoServicesMap != null) { + entityDaoServicesMap.clear(); + } } - public TbEntityService getServiceByEntityType(EntityType entityType) { + @Override + public EntityDaoService getServiceByEntityType(EntityType entityType) { String beanName = EntityType.RULE_NODE.equals(entityType) ? getBeanName(EntityType.RULE_CHAIN) : getBeanName(entityType); - return beanFactory.getBean(beanName, TbEntityService.class); + return entityDaoServicesMap.get(beanName); } private String getBeanName(EntityType entityType) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java index f828be9235..ef72b01ff8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java @@ -412,7 +412,7 @@ public class EntityViewServiceImpl extends AbstractCachedEntityService> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findEntityViewById(tenantId, new EntityViewId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java b/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java index de4683f6b4..5ec83c0f5b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java @@ -152,7 +152,7 @@ public class BaseEventService implements EventService { } @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.empty(); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/ota/BaseOtaPackageService.java b/dao/src/main/java/org/thingsboard/server/dao/ota/BaseOtaPackageService.java index 0345ed2369..b1422100d8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/ota/BaseOtaPackageService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/ota/BaseOtaPackageService.java @@ -237,7 +237,7 @@ public class BaseOtaPackageService extends AbstractCachedEntityService> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findOtaPackageInfoById(tenantId, new OtaPackageId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/queue/BaseQueueService.java b/dao/src/main/java/org/thingsboard/server/dao/queue/BaseQueueService.java index a05eb12218..5953e31c83 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/queue/BaseQueueService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/queue/BaseQueueService.java @@ -123,7 +123,7 @@ public class BaseQueueService extends AbstractEntityService implements QueueServ } @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findQueueById(tenantId, new QueueId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java index 320e7661fc..5cd57b557e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java @@ -375,9 +375,9 @@ public class BaseRelationService implements RelationService { private ListenableFuture fetchRelationInfoAsync(TenantId tenantId, EntityRelation relation, Function entityIdGetter, BiConsumer entityNameSetter) { - Optional entityNameOpt = entityService.fetchEntityName(tenantId, entityIdGetter.apply(relation)); EntityRelationInfo relationInfo = new EntityRelationInfo(relation); - entityNameSetter.accept(relationInfo, entityNameOpt.orElse("N/A")); + entityNameSetter.accept(relationInfo, + entityService.fetchEntityName(tenantId, entityIdGetter.apply(relation)).orElse("N/A")); return Futures.immediateFuture(relationInfo); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java index 9d72a331de..d144c18ab7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java @@ -137,7 +137,7 @@ public class BaseResourceService implements ResourceService { } @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findResourceInfoById(tenantId, new TbResourceId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/rpc/BaseRpcService.java b/dao/src/main/java/org/thingsboard/server/dao/rpc/BaseRpcService.java index e56fd832ec..24e9843849 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rpc/BaseRpcService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rpc/BaseRpcService.java @@ -98,7 +98,7 @@ public class BaseRpcService implements RpcService { } @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findById(tenantId, new RpcId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java index d6b9e123fb..8ee3f4d0a9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java @@ -761,7 +761,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { HasId hasId = EntityType.RULE_NODE.equals(entityId.getEntityType()) ? findRuleNodeById(tenantId, new RuleNodeId(entityId.getId())) : findRuleChainById(tenantId, new RuleChainId(entityId.getId())); diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileServiceImpl.java index 03479e4483..f6e9e29ed0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileServiceImpl.java @@ -208,7 +208,7 @@ public class TenantProfileServiceImpl extends AbstractCachedEntityService> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findTenantProfileById(tenantId, new TenantProfileId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java index 04f42ed3e2..595673fb79 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java @@ -261,7 +261,7 @@ public class TenantServiceImpl extends AbstractCachedEntityService> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findTenantById(new TenantId(entityId.getId()))); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java index 4c6a3472ee..d956a007a8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java @@ -164,7 +164,7 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A } @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findApiUsageStateById(tenantId, new ApiUsageStateId(entityId.getId()))); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java index 28912d3571..12348cb74b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java @@ -401,7 +401,7 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic }; @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findUserById(tenantId, new UserId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java b/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java index 26ae0de259..b6b6c5efa7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java +++ b/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java @@ -327,12 +327,12 @@ public abstract class AbstractBufferedRateExecutor { + String defaultName = "N/A"; try { - Optional entityNameOpt = entityService.fetchEntityName(TenantId.SYS_TENANT_ID, tenantId); - return entityNameOpt.orElse("N/A"); + return entityService.fetchEntityName(TenantId.SYS_TENANT_ID, tenantId).orElse(defaultName); } catch (Exception e) { log.error("[{}] Failed to get tenant name", tenantId, e); - return "N/A"; + return defaultName; } }); log.info("[{}][{}] Rate limited requests: {}", tenantId, name, rateLimitedRequests); diff --git a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeServiceImpl.java index e5e9360698..921344bd43 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeServiceImpl.java @@ -116,7 +116,7 @@ public class WidgetTypeServiceImpl implements WidgetTypeService { } @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findWidgetTypeById(tenantId, new WidgetTypeId(entityId.getId()))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java index 474ac247ba..719f250dca 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java @@ -155,7 +155,7 @@ public class WidgetsBundleServiceImpl implements WidgetsBundleService { } @Override - public Optional> fetchEntity(TenantId tenantId, EntityId entityId) { + public Optional> findEntity(TenantId tenantId, EntityId entityId) { return Optional.ofNullable(findWidgetsBundleById(tenantId, new WidgetsBundleId(entityId.getId()))); } diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceBeanFactoryTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceRegistryTest.java similarity index 62% rename from dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceBeanFactoryTest.java rename to dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceRegistryTest.java index d9b907d825..dbd53c9a3f 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceBeanFactoryTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceRegistryTest.java @@ -16,31 +16,31 @@ package org.thingsboard.server.dao.service; import lombok.extern.slf4j.Slf4j; -import org.assertj.core.api.Assertions; import org.junit.Assert; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.dao.entity.EntityServiceBeanFactory; -import org.thingsboard.server.dao.rule.BaseRuleChainService; +import org.thingsboard.server.dao.entity.DefaultEntityServiceRegistry; +import org.thingsboard.server.dao.entity.EntityDaoService; +import org.thingsboard.server.dao.rule.RuleChainService; @Slf4j -public abstract class BaseEntityServiceBeanFactoryTest extends AbstractServiceTest { +public abstract class BaseEntityServiceRegistryTest extends AbstractServiceTest { @Autowired - private EntityServiceBeanFactory entityServiceBeanFactory; + private DefaultEntityServiceRegistry entityServiceRegistry; @Test - public void givenAllEntityTypes_whenGetServiceByEntityTypeCalled_thenNoExceptionsThrows() { + public void givenAllEntityTypes_whenGetServiceByEntityTypeCalled_thenAllBeansExists() { for (EntityType entityType : EntityType.values()) { - Assertions.assertThatCode(() -> entityServiceBeanFactory.getServiceByEntityType(entityType)) - .doesNotThrowAnyException(); + EntityDaoService entityDaoService = entityServiceRegistry.getServiceByEntityType(entityType); + Assert.assertNotNull(entityDaoService); } } @Test - public void givenRuleNodeEntityType_whenGetServiceByEntityTypeCalled_thenReturnedRuleChainDaoService() { - Assert.assertTrue(entityServiceBeanFactory.getServiceByEntityType(EntityType.RULE_NODE) instanceof BaseRuleChainService); + public void givenRuleNodeEntityType_whenGetServiceByEntityTypeCalled_thenReturnedRuleChainService() { + Assert.assertTrue(entityServiceRegistry.getServiceByEntityType(EntityType.RULE_NODE) instanceof RuleChainService); } } diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/sql/EntityServiceBeanFactorySqlTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/sql/EntityServiceRegistrySqlTest.java similarity index 81% rename from dao/src/test/java/org/thingsboard/server/dao/service/sql/EntityServiceBeanFactorySqlTest.java rename to dao/src/test/java/org/thingsboard/server/dao/service/sql/EntityServiceRegistrySqlTest.java index 48fd73db75..40d6d2ae77 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/sql/EntityServiceBeanFactorySqlTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/sql/EntityServiceRegistrySqlTest.java @@ -15,10 +15,10 @@ */ package org.thingsboard.server.dao.service.sql; -import org.thingsboard.server.dao.service.BaseEntityServiceBeanFactoryTest; +import org.thingsboard.server.dao.service.BaseEntityServiceRegistryTest; import org.thingsboard.server.dao.service.DaoSqlTest; @DaoSqlTest -public class EntityServiceBeanFactorySqlTest extends BaseEntityServiceBeanFactoryTest { +public class EntityServiceRegistrySqlTest extends BaseEntityServiceRegistryTest { } From da0a0aed309321bdf6f5f6bbd4fc01e975ae621a Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Thu, 15 Dec 2022 15:18:01 +0200 Subject: [PATCH 49/66] fix typo after refactoring --- .../org/thingsboard/server/dao/entity/BaseEntityService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java b/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java index 6626ec81ed..4c5df0c7e7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java @@ -54,7 +54,7 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe private EntityQueryDao entityQueryDao; @Autowired - DefaultEntityServiceRegistry entityServiceRegistry; + EntityServiceRegistry entityServiceRegistry; @Override public long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query) { From 1d5bf98504d5e20efd01533f20a8f822359d4166 Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Thu, 15 Dec 2022 15:22:53 +0200 Subject: [PATCH 50/66] removed unused import in DefaultEntityServiceRegistry --- .../server/dao/entity/DefaultEntityServiceRegistry.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java b/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java index 9ac76b0575..b51697d405 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.entity; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.text.CaseUtils; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; @@ -25,7 +24,6 @@ import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.util.Map; -@Slf4j @Service public class DefaultEntityServiceRegistry implements EntityServiceRegistry { From e74a5686a2272f91852dd78abbd803b150974eed Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Thu, 15 Dec 2022 16:32:39 +0200 Subject: [PATCH 51/66] added message for assertNotNull check in BaseEntityServiceRegistryTest --- .../server/dao/service/BaseEntityServiceRegistryTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceRegistryTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceRegistryTest.java index dbd53c9a3f..f72c2ce2bc 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceRegistryTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceRegistryTest.java @@ -34,7 +34,7 @@ public abstract class BaseEntityServiceRegistryTest extends AbstractServiceTest public void givenAllEntityTypes_whenGetServiceByEntityTypeCalled_thenAllBeansExists() { for (EntityType entityType : EntityType.values()) { EntityDaoService entityDaoService = entityServiceRegistry.getServiceByEntityType(entityType); - Assert.assertNotNull(entityDaoService); + Assert.assertNotNull("entityDaoService bean is missed for type: " + entityType.name(), entityDaoService); } } From 9e33a8d7be38fb899f51fdf7c4dffa9a87536dbe Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Thu, 15 Dec 2022 16:59:26 +0200 Subject: [PATCH 52/66] fix typo after refactoring in BaseEntityServiceRegistryTest --- .../server/dao/service/BaseEntityServiceRegistryTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceRegistryTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceRegistryTest.java index f72c2ce2bc..81c6159d4a 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceRegistryTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceRegistryTest.java @@ -20,15 +20,15 @@ import org.junit.Assert; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.dao.entity.DefaultEntityServiceRegistry; import org.thingsboard.server.dao.entity.EntityDaoService; +import org.thingsboard.server.dao.entity.EntityServiceRegistry; import org.thingsboard.server.dao.rule.RuleChainService; @Slf4j public abstract class BaseEntityServiceRegistryTest extends AbstractServiceTest { @Autowired - private DefaultEntityServiceRegistry entityServiceRegistry; + private EntityServiceRegistry entityServiceRegistry; @Test public void givenAllEntityTypes_whenGetServiceByEntityTypeCalled_thenAllBeansExists() { From 3d27340cb5f6d73859b944195512c958c29f18ec Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Fri, 16 Dec 2022 15:52:20 +0200 Subject: [PATCH 53/66] fix audit log tests --- .../thingsboard/server/dao/audit/AuditLogService.java | 3 +-- .../org/thingsboard/server/dao/event/EventService.java | 3 +-- .../server/dao/audit/AuditLogServiceImpl.java | 9 +-------- .../server/dao/audit/DummyAuditLogServiceImpl.java | 9 +-------- .../thingsboard/server/dao/event/BaseEventService.java | 9 +-------- 5 files changed, 5 insertions(+), 28 deletions(-) diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/audit/AuditLogService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/audit/AuditLogService.java index 27f9cfbb48..01b3bf4b5e 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/audit/AuditLogService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/audit/AuditLogService.java @@ -25,11 +25,10 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; -import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; -public interface AuditLogService extends EntityDaoService { +public interface AuditLogService { PageData findAuditLogsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, List actionTypes, TimePageLink pageLink); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/event/EventService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/event/EventService.java index 095cdea30d..3b0de80811 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/event/EventService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/event/EventService.java @@ -24,11 +24,10 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; -import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; -public interface EventService extends EntityDaoService { +public interface EventService { ListenableFuture saveAsync(Event event); diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java index 883789d189..8e7a1cdd17 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java @@ -36,7 +36,6 @@ import org.thingsboard.server.common.data.audit.AuditLog; import org.thingsboard.server.common.data.id.AuditLogId; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; @@ -54,7 +53,6 @@ import org.thingsboard.server.dao.service.DataValidator; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; -import java.util.Optional; import java.util.UUID; import java.util.stream.Collectors; @@ -62,7 +60,7 @@ import static org.thingsboard.server.dao.service.Validator.validateEntityId; import static org.thingsboard.server.dao.service.Validator.validateId; @Slf4j -@Service("AuditLogDaoService") +@Service @ConditionalOnProperty(prefix = "audit-log", value = "enabled", havingValue = "true") public class AuditLogServiceImpl implements AuditLogService { @@ -405,9 +403,4 @@ public class AuditLogServiceImpl implements AuditLogService { return Futures.allAsList(futures); } - @Override - public Optional> findEntity(TenantId tenantId, EntityId entityId) { - return Optional.empty(); - } - } diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java index 094929c06a..0b1efaf82e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java @@ -23,16 +23,14 @@ import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.AuditLog; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; import java.util.List; -import java.util.Optional; -@Service("AuditLogDaoService") +@Service @ConditionalOnProperty(prefix = "audit-log", value = "enabled", havingValue = "false") public class DummyAuditLogServiceImpl implements AuditLogService { @@ -61,9 +59,4 @@ public class DummyAuditLogServiceImpl implements AuditLogService { return null; } - @Override - public Optional> findEntity(TenantId tenantId, EntityId entityId) { - return Optional.empty(); - } - } diff --git a/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java b/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java index 5ec83c0f5b..55a98a9549 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/event/BaseEventService.java @@ -31,19 +31,17 @@ import org.thingsboard.server.common.data.event.LifecycleEvent; import org.thingsboard.server.common.data.event.RuleChainDebugEvent; import org.thingsboard.server.common.data.event.RuleNodeDebugEvent; import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.dao.service.DataValidator; import java.util.List; -import java.util.Optional; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.stream.Collectors; -@Service("EventDaoService") +@Service @Slf4j public class BaseEventService implements EventService { @@ -151,9 +149,4 @@ public class BaseEventService implements EventService { return list == null ? null : list.stream().map(e -> e.toInfo(entityType)).collect(Collectors.toList()); } - @Override - public Optional> findEntity(TenantId tenantId, EntityId entityId) { - return Optional.empty(); - } - } From 55fc7131fbbbe6dcaadffbf1c4633a37c5d1bb8d Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Sat, 17 Dec 2022 16:58:58 +0200 Subject: [PATCH 54/66] Validation for rule node configuration; improve validation error message --- .../controller/AbstractNotifyEntityTest.java | 2 +- .../BaseRuleChainControllerTest.java | 31 +++++++++ .../server/common/data/alarm/Alarm.java | 2 + .../common/data/rule/RuleChainMetaData.java | 1 - .../common/data/util/ReflectionUtils.java | 31 +++++++++ .../server/common/data/validation/Length.java | 2 +- .../server/common/data/validation/NoXss.java | 2 +- .../server/dao/audit/AuditLogServiceImpl.java | 2 +- .../server/dao/rule/BaseRuleChainService.java | 37 +---------- .../dao/service/ConstraintValidator.java | 28 +++++--- .../validator/RuleChainDataValidator.java | 65 +++++++++++++++++++ .../service/BaseOtaPackageServiceTest.java | 4 +- .../dao/service/NoXssValidatorTest.java | 4 +- .../TbAbstractAlarmNodeConfiguration.java | 2 + .../TbCreateAlarmNodeConfiguration.java | 2 + 15 files changed, 164 insertions(+), 51 deletions(-) create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/util/ReflectionUtils.java diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java index 39421a4364..8de7157b52 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java @@ -597,7 +597,7 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest { } protected String msgErrorFieldLength(String fieldName) { - return "length of " + fieldName + " must be equal or less than 255"; + return fieldName + " length must be equal or less than 255"; } protected String msgErrorNoFound(String entityClassName, String assetIdStr) { diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseRuleChainControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseRuleChainControllerTest.java index d32b1baa6b..8daf8356ea 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseRuleChainControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseRuleChainControllerTest.java @@ -26,6 +26,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.test.context.ContextConfiguration; +import org.thingsboard.rule.engine.action.TbCreateAlarmNode; +import org.thingsboard.rule.engine.action.TbCreateAlarmNodeConfiguration; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; @@ -35,7 +37,9 @@ import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainType; +import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.rule.RuleChainDao; @@ -44,6 +48,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.containsString; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -254,9 +259,35 @@ public abstract class BaseRuleChainControllerTest extends AbstractControllerTest testEntityDaoWithRelationsTransactionalException(ruleChainDao, savedTenant.getId(), ruleChainId, "/api/ruleChain/" + ruleChainId); } + @Test + public void givenRuleNodeWithInvalidConfiguration_thenReturnError() throws Exception { + RuleChain ruleChain = createRuleChain("Rule chain with invalid nodes"); + RuleChainMetaData ruleChainMetaData = new RuleChainMetaData(); + ruleChainMetaData.setRuleChainId(ruleChain.getId()); + + RuleNode createAlarmNode = new RuleNode(); + createAlarmNode.setName("Create alarm"); + createAlarmNode.setType(TbCreateAlarmNode.class.getName()); + TbCreateAlarmNodeConfiguration invalidCreateAlarmNodeConfiguration = new TbCreateAlarmNodeConfiguration(); + invalidCreateAlarmNodeConfiguration.setSeverity("