From 1ff1b7c1dd103b95da0c805f06901c8104722473 Mon Sep 17 00:00:00 2001 From: Seraphym-Tuhai Date: Mon, 3 Apr 2023 17:23:08 +0300 Subject: [PATCH 001/124] assign, reassign tests --- .../server/msa/TestRestClient.java | 41 ++++++++++- .../server/msa/ui/pages/AlarmElements.java | 26 +++++++ .../server/msa/ui/pages/AlarmHelper.java | 14 ++++ .../msa/ui/pages/DevicePageElements.java | 21 ++++++ .../server/msa/ui/pages/DevicePageHelper.java | 14 ++++ .../msa/ui/pages/SideBarMenuViewElements.java | 15 ++++ .../msa/ui/pages/SideBarMenuViewHelper.java | 20 +++++ .../server/msa/ui/tests/AssignDetailsTab.java | 73 +++++++++++++++++++ .../msa/ui/utils/DataProviderCredential.java | 7 ++ .../server/msa/ui/utils/EntityPrototypes.java | 32 ++++++++ 10 files changed, 261 insertions(+), 2 deletions(-) create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmHelper.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/AssignDetailsTab.java 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 a030f3a8c9..a014dbee07 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 @@ -29,13 +29,17 @@ 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.DeviceProfile; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.asset.AssetProfile; +import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.RuleChainId; +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.relation.EntityRelation; @@ -178,7 +182,7 @@ public class TestRestClient { } public JsonPath postProvisionRequest(String provisionRequest) { - return given().spec(requestSpec) + return given().spec(requestSpec) .body(provisionRequest) .post("/api/v1/provision") .getBody() @@ -293,7 +297,7 @@ public class TestRestClient { } public DeviceProfile getDeviceProfileById(DeviceProfileId deviceProfileId) { - return given().spec(requestSpec).get("/api/deviceProfile/{deviceProfileId}", deviceProfileId.getId()) + return given().spec(requestSpec).get("/api/deviceProfile/{deviceProfileId}", deviceProfileId.getId()) .then() .assertThat() .statusCode(HTTP_OK) @@ -388,6 +392,39 @@ public class TestRestClient { }); } + public Alarm postAlarm(Alarm alarm) { + return given().spec(requestSpec) + .body(alarm) + .post("/api/alarm") + .then() + .statusCode(HTTP_OK) + .extract() + .as(Alarm.class); + } + + public void deleteAlarm(AlarmId alarmId) { + given().spec(requestSpec) + .delete("/api/alarm/{alarmId}", alarmId.getId()) + .then() + .statusCode(HTTP_OK); + } + + public User postUser(User user) { + return given().spec(requestSpec) + .body(user) + .post("/api/user?sendActivationMail=false") + .then() + .statusCode(HTTP_OK) + .extract() + .as(User.class); + } + + public void deleteUser(UserId userId) { + given().spec(requestSpec) + .delete("/api/user/{userId}", userId.getId()) + .then() + .statusCode(HTTP_OK); + } public String getToken() { return token; } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java new file mode 100644 index 0000000000..d3528b0789 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java @@ -0,0 +1,26 @@ +package org.thingsboard.server.msa.ui.pages; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +public class AlarmElements extends OtherPageElements{ + public AlarmElements(WebDriver driver) { + super(driver); + } + + private static final String ASSIGN_BTN = "//mat-icon[contains(text(),'keyboard_arrow_down')]/parent::button"; + private static final String USER_ASSIGN_DROPDOWN = "//div[contains(@class,'tb-assignee')]//span[contains(text(),'%s')]"; + private static final String ASSIGN_USER_DISPLAY_NAME = "//span[text()='%s']/ancestor::mat-row//span[@class='user-display-name']"; + + public WebElement assignBtn() { + return waitUntilElementToBeClickable(ASSIGN_BTN); + } + + public WebElement userFromAssignDropDown(String userEmail) { + return waitUntilElementToBeClickable(String.format(USER_ASSIGN_DROPDOWN, userEmail)); + } + + public WebElement assignUserDisplayName(String userEmail) { + return waitUntilElementToBeClickable(String.format(ASSIGN_USER_DISPLAY_NAME, userEmail)); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmHelper.java new file mode 100644 index 0000000000..bef84d98ee --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmHelper.java @@ -0,0 +1,14 @@ +package org.thingsboard.server.msa.ui.pages; + +import org.openqa.selenium.WebDriver; + +public class AlarmHelper extends AlarmElements { + public AlarmHelper(WebDriver driver) { + super(driver); + } + + public void assignTo(String user) { + jsClick(assignBtn()); + userFromAssignDropDown(user).click(); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java new file mode 100644 index 0000000000..411e5545ea --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java @@ -0,0 +1,21 @@ +package org.thingsboard.server.msa.ui.pages; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +public class DevicePageElements extends OtherPageElements{ + public DevicePageElements(WebDriver driver) { + super(driver); + } + + private static final String DEVICE = "//table//span[text()='%s']"; + private static final String DEVICE_DETAILS_ALARMS = "//tb-details-panel//span[text()='Alarms']"; + + public WebElement device(String deviceName) { + return waitUntilElementToBeClickable(String.format(DEVICE, deviceName)); + } + + public WebElement deviceDetailsAlarmsBtn() { + return waitUntilElementToBeClickable(DEVICE_DETAILS_ALARMS); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java new file mode 100644 index 0000000000..0377b6e207 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java @@ -0,0 +1,14 @@ +package org.thingsboard.server.msa.ui.pages; + +import org.openqa.selenium.WebDriver; + +public class DevicePageHelper extends DevicePageElements{ + public DevicePageHelper(WebDriver driver) { + super(driver); + } + + public void openDeviceAlarms(String deviceName) { + device(deviceName).click(); + deviceDetailsAlarmsBtn().click(); + } +} 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 ab8ee9bf55..5ecf27b5bd 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 @@ -30,6 +30,13 @@ public class SideBarMenuViewElements extends AbstractBasePage { private static final String PROFILES_BTN = "//mat-toolbar//mat-icon[text()='badge']/ancestor::tb-menu-toggle"; private static final String DEVICE_PROFILE_BTN = "//mat-toolbar//a[@href='/profiles/deviceProfiles']"; private static final String ASSET_PROFILE_BTN = "//mat-toolbar//a[@href='/profiles/assetProfiles']"; + private static final String ALARMS_BTN = "//mat-toolbar//a[@href='/alarms']"; + private static final String ENTITIES_DROPDOWN = "//mat-toolbar//mat-icon[text()='category']/ancestor::a//span[contains(@class,'pull-right')]"; + private static final String DEVICES_BTN = "//ul[@id='docs-menu-entity.entities']//span[text()='Devices']"; + + public WebElement entitiesDropdown() { + return waitUntilElementToBeClickable(ENTITIES_DROPDOWN); + } public WebElement ruleChainsBtn() { return waitUntilElementToBeClickable(RULE_CHAINS_BTN); @@ -54,4 +61,12 @@ public class SideBarMenuViewElements extends AbstractBasePage { public WebElement assetProfileBtn() { return waitUntilElementToBeClickable(ASSET_PROFILE_BTN); } + + public WebElement alarmsBtn() { + return waitUntilElementToBeClickable(ALARMS_BTN); + } + + public WebElement devicesBtn() { + return waitUntilElementToBeClickable(DEVICES_BTN); + } } \ No newline at end of file diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/SideBarMenuViewHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/SideBarMenuViewHelper.java index 4d56689809..92848ff68c 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/SideBarMenuViewHelper.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/SideBarMenuViewHelper.java @@ -16,6 +16,7 @@ package org.thingsboard.server.msa.ui.pages; import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; public class SideBarMenuViewHelper extends SideBarMenuViewElements { public SideBarMenuViewHelper(WebDriver driver) { @@ -31,4 +32,23 @@ public class SideBarMenuViewHelper extends SideBarMenuViewElements { profilesBtn().click(); assetProfileBtn().click(); } + + public void goToDevicesPage() { + openEntitiesDropdown(); + devicesBtn().click(); + } + + public void openEntitiesDropdown() { + if (entitiesDropdownIsClose()) { + entitiesDropdown().click(); + } + } + + public boolean entitiesDropdownIsClose() { + return dropdownIsClose(entitiesDropdown()); + } + + private boolean dropdownIsClose(WebElement dropdown) { + return !dropdown.getAttribute("class").contains("tb-toggled"); + } } \ No newline at end of file diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/AssignDetailsTab.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/AssignDetailsTab.java new file mode 100644 index 0000000000..420fe17a86 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/AssignDetailsTab.java @@ -0,0 +1,73 @@ +package org.thingsboard.server.msa.ui.tests; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.msa.prototypes.DevicePrototypes; +import org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest; +import org.thingsboard.server.msa.ui.pages.AlarmHelper; +import org.thingsboard.server.msa.ui.pages.DevicePageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.SideBarMenuViewHelper; +import org.thingsboard.server.msa.ui.utils.DataProviderCredential; +import org.thingsboard.server.msa.ui.utils.EntityPrototypes; + +public class AssignDetailsTab extends AbstractDriverBaseTest { + + AlarmId alarmId; + DeviceId deviceId; + UserId userId; + String deviceName; + SideBarMenuViewHelper sideBarMenuView; + AlarmHelper alarmPage; + DevicePageHelper devicePage; + + @BeforeClass + public void generateAlarm() { + new LoginPageHelper(driver).authorizationTenant(); + sideBarMenuView = new SideBarMenuViewHelper(driver); + alarmPage = new AlarmHelper(driver); + devicePage = new DevicePageHelper(driver); + } + + @AfterMethod + public void deleteAlarm() { + testRestClient.deleteAlarm(alarmId); + testRestClient.deleteDevice(deviceId); + if (userId != null) { + testRestClient.deleteUser(userId); + } + } + + @Test(dataProviderClass = DataProviderCredential.class, dataProvider = "assignTo") + public void assignAlarmTo(String user) { + deviceName = testRestClient.postDevice("", DevicePrototypes.defaultDevicePrototype("")).getName(); + deviceId = testRestClient.getDeviceByName(deviceName).getId(); + alarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId)).getId(); + + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.assignTo(user); + + Assert.assertTrue(alarmPage.assignUserDisplayName(user).isDisplayed()); + } + + @Test + public void reassignAlarm() { + userId = testRestClient.postUser(EntityPrototypes.defaultUser(getCustomerByName("Customer A").getId())).getId(); + deviceName = testRestClient.postDevice("", DevicePrototypes.defaultDevicePrototype("")).getName(); + deviceId = testRestClient.getDeviceByName(deviceName).getId(); + alarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId, userId)).getId(); + + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.assignTo("customer@thingsboard.org"); + + Assert.assertTrue(alarmPage.assignUserDisplayName("customer@thingsboard.org").isDisplayed()); + } +} 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 73783544a1..a0188665c8 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 @@ -149,4 +149,11 @@ public class DataProviderCredential { {description, newDescription, description + newDescription}, {description, Keys.CONTROL + "A" + Keys.BACK_SPACE, ""}}; } + + @DataProvider + public static Object[][] assignTo() { + return new Object[][]{ + {Const.TENANT_EMAIL}, + {"customer@thingsboard.org"}}; + } } 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 c131c0fb25..84f28bb6f2 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 @@ -21,12 +21,19 @@ import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileProvisionType; import org.thingsboard.server.common.data.DeviceProfileType; import org.thingsboard.server.common.data.DeviceTransportType; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration; import org.thingsboard.server.common.data.device.profile.DeviceProfileData; import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.common.data.security.Authority; public class EntityPrototypes { @@ -97,4 +104,29 @@ public class EntityPrototypes { assetProfile.setDescription(description); return assetProfile; } + + public static Alarm defaultAlarm(EntityId id) { + Alarm alarm = new Alarm(); + alarm.setType("default"); + alarm.setOriginator(id); + alarm.setSeverity(AlarmSeverity.CRITICAL); + return alarm; + } + + public static Alarm defaultAlarm(EntityId id, UserId userId) { + Alarm alarm = new Alarm(); + alarm.setType("default"); + alarm.setOriginator(id); + alarm.setSeverity(AlarmSeverity.CRITICAL); + alarm.setAssigneeId(userId); + return alarm; + } + + public static User defaultUser(CustomerId customerId) { + User user = new User(); + user.setEmail("test@thingsboard.org"); + user.setCustomerId(customerId); + user.setAuthority(Authority.CUSTOMER_USER); + return user; + } } From 32c6b7385f1fa9cde915a3d3338a39483a51401e Mon Sep 17 00:00:00 2001 From: Seraphym-Tuhai Date: Mon, 10 Apr 2023 09:07:22 +0300 Subject: [PATCH 002/124] add tests on search --- .../server/msa/ui/pages/AlarmElements.java | 18 ++++++-- .../server/msa/ui/pages/AlarmHelper.java | 18 ++++++++ .../msa/ui/pages/DevicePageElements.java | 7 ++- .../server/msa/ui/pages/DevicePageHelper.java | 6 ++- .../server/msa/ui/tests/AssignDetailsTab.java | 45 +++++++++++++++++-- .../server/msa/ui/utils/EntityPrototypes.java | 9 ++++ 6 files changed, 93 insertions(+), 10 deletions(-) diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java index d3528b0789..48300429f6 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java @@ -3,14 +3,18 @@ package org.thingsboard.server.msa.ui.pages; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import java.util.List; + public class AlarmElements extends OtherPageElements{ public AlarmElements(WebDriver driver) { super(driver); } private static final String ASSIGN_BTN = "//mat-icon[contains(text(),'keyboard_arrow_down')]/parent::button"; - private static final String USER_ASSIGN_DROPDOWN = "//div[contains(@class,'tb-assignee')]//span[contains(text(),'%s')]"; - private static final String ASSIGN_USER_DISPLAY_NAME = "//span[text()='%s']/ancestor::mat-row//span[@class='user-display-name']"; + private static final String USER_ASSIGN_DROPDOWN = "//div[@class='user-display-name']/span[contains(text(),'%s')]"; + private static final String ASSIGN_USERS_DISPLAY_NAME = "//div[@class='user-display-name']/span"; + private static final String ASSIGN_USER_DISPLAY_NAME = "//span[@class='user-display-name'][contains(text(),'%s')]"; + private static final String SEARCH_FIELD = "//input[@placeholder='Search users']"; public WebElement assignBtn() { return waitUntilElementToBeClickable(ASSIGN_BTN); @@ -20,7 +24,15 @@ public class AlarmElements extends OtherPageElements{ return waitUntilElementToBeClickable(String.format(USER_ASSIGN_DROPDOWN, userEmail)); } - public WebElement assignUserDisplayName(String userEmail) { + public WebElement assignedUser(String userEmail) { return waitUntilElementToBeClickable(String.format(ASSIGN_USER_DISPLAY_NAME, userEmail)); } + + public List assignUsers() { + return waitUntilElementsToBeClickable(ASSIGN_USERS_DISPLAY_NAME); + } + + public WebElement searchUserField() { + return waitUntilElementToBeClickable(SEARCH_FIELD); + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmHelper.java index bef84d98ee..4075a89ad1 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmHelper.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmHelper.java @@ -1,6 +1,11 @@ package org.thingsboard.server.msa.ui.pages; import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; public class AlarmHelper extends AlarmElements { public AlarmHelper(WebDriver driver) { @@ -11,4 +16,17 @@ public class AlarmHelper extends AlarmElements { jsClick(assignBtn()); userFromAssignDropDown(user).click(); } + + private List users; + + public void setUsers() { + users = assignUsers() + .stream() + .map(WebElement::getText) + .collect(Collectors.toList()); + } + + public List getUsers() { + return users; + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java index 411e5545ea..ba766ef3fd 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java @@ -9,7 +9,8 @@ public class DevicePageElements extends OtherPageElements{ } private static final String DEVICE = "//table//span[text()='%s']"; - private static final String DEVICE_DETAILS_ALARMS = "//tb-details-panel//span[text()='Alarms']"; + private static final String DEVICE_DETAILS_VIEW = "//tb-details-panel"; + private static final String DEVICE_DETAILS_ALARMS = DEVICE_DETAILS_VIEW + "//span[text()='Alarms']"; public WebElement device(String deviceName) { return waitUntilElementToBeClickable(String.format(DEVICE, deviceName)); @@ -18,4 +19,8 @@ public class DevicePageElements extends OtherPageElements{ public WebElement deviceDetailsAlarmsBtn() { return waitUntilElementToBeClickable(DEVICE_DETAILS_ALARMS); } + + public WebElement deviceDetailsView() { + return waitUntilPresenceOfElementLocated(DEVICE_DETAILS_VIEW); + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java index 0377b6e207..19716d3fb6 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java @@ -2,13 +2,15 @@ package org.thingsboard.server.msa.ui.pages; import org.openqa.selenium.WebDriver; -public class DevicePageHelper extends DevicePageElements{ +public class DevicePageHelper extends DevicePageElements { public DevicePageHelper(WebDriver driver) { super(driver); } public void openDeviceAlarms(String deviceName) { - device(deviceName).click(); + if (!deviceDetailsView().isDisplayed()) { + device(deviceName).click(); + } deviceDetailsAlarmsBtn().click(); } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/AssignDetailsTab.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/AssignDetailsTab.java index 420fe17a86..cdf10356b3 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/AssignDetailsTab.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/AssignDetailsTab.java @@ -1,7 +1,6 @@ package org.thingsboard.server.msa.ui.tests; import org.testng.Assert; -import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -17,6 +16,8 @@ import org.thingsboard.server.msa.ui.pages.SideBarMenuViewHelper; import org.thingsboard.server.msa.ui.utils.DataProviderCredential; import org.thingsboard.server.msa.ui.utils.EntityPrototypes; +import static org.assertj.core.api.Assertions.assertThat; + public class AssignDetailsTab extends AbstractDriverBaseTest { AlarmId alarmId; @@ -54,12 +55,13 @@ public class AssignDetailsTab extends AbstractDriverBaseTest { devicePage.openDeviceAlarms(deviceName); alarmPage.assignTo(user); - Assert.assertTrue(alarmPage.assignUserDisplayName(user).isDisplayed()); + Assert.assertTrue(alarmPage.assignedUser(user).isDisplayed()); } @Test public void reassignAlarm() { - userId = testRestClient.postUser(EntityPrototypes.defaultUser(getCustomerByName("Customer A").getId())).getId(); + testRestClient.postCustomer(EntityPrototypes.defaultCustomerPrototype("TestCustomer")); + userId = testRestClient.postUser(EntityPrototypes.defaultUser(getCustomerByName("TestCustomer").getId())).getId(); deviceName = testRestClient.postDevice("", DevicePrototypes.defaultDevicePrototype("")).getName(); deviceId = testRestClient.getDeviceByName(deviceName).getId(); alarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId, userId)).getId(); @@ -68,6 +70,41 @@ public class AssignDetailsTab extends AbstractDriverBaseTest { devicePage.openDeviceAlarms(deviceName); alarmPage.assignTo("customer@thingsboard.org"); - Assert.assertTrue(alarmPage.assignUserDisplayName("customer@thingsboard.org").isDisplayed()); + Assert.assertTrue(alarmPage.assignedUser("customer@thingsboard.org").isDisplayed()); + } + + @Test + public void searchByEmail() { + deviceName = testRestClient.postDevice("", DevicePrototypes.defaultDevicePrototype("")).getName(); + deviceId = testRestClient.getDeviceByName(deviceName).getId(); + alarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId)).getId(); + + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.assignBtn().click(); + alarmPage.searchUserField().sendKeys("customer@thingsboard.org"); + alarmPage.setUsers(); + + assertThat(alarmPage.getUsers()).contains("customer@thingsboard.org"); + alarmPage.assignUsers().forEach(u -> assertThat(u.isDisplayed()).isTrue()); + } + + @Test + public void searchByName() { + String name = "usik"; + + userId = testRestClient.postUser(EntityPrototypes.defaultUser(getCustomerByName("Customer A").getId(), name)).getId(); + deviceName = testRestClient.postDevice("", DevicePrototypes.defaultDevicePrototype("")).getName(); + deviceId = testRestClient.getDeviceByName(deviceName).getId(); + alarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId)).getId(); + + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.assignBtn().click(); + alarmPage.searchUserField().sendKeys(name); + alarmPage.setUsers(); + + assertThat(alarmPage.getUsers()).contains(name); + alarmPage.assignUsers().forEach(u -> assertThat(u.isDisplayed()).isTrue()); } } 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 84f28bb6f2..bce4373191 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 @@ -129,4 +129,13 @@ public class EntityPrototypes { user.setAuthority(Authority.CUSTOMER_USER); return user; } + + public static User defaultUser(CustomerId customerId, String name) { + User user = new User(); + user.setEmail("test@thingsboard.org"); + user.setFirstName(name); + user.setCustomerId(customerId); + user.setAuthority(Authority.CUSTOMER_USER); + return user; + } } From 982f6e23fb307347dd4979f4206f2ac3fc1b897f Mon Sep 17 00:00:00 2001 From: Seraphym-Tuhai Date: Thu, 13 Apr 2023 10:57:23 +0300 Subject: [PATCH 003/124] add test on propagated alarm --- .../server/msa/TestRestClient.java | 13 ++ .../ui/pages/AlarmDetailsViewElements.java | 32 +++ .../msa/ui/pages/AlarmDetailsViewHelper.java | 19 ++ .../server/msa/ui/pages/AlarmElements.java | 40 +++- .../server/msa/ui/pages/AlarmHelper.java | 36 ++- .../msa/ui/pages/CustomerPageElements.java | 10 +- .../msa/ui/pages/DevicePageElements.java | 15 ++ .../server/msa/ui/pages/DevicePageHelper.java | 15 ++ .../server/msa/ui/pages/LoginPageHelper.java | 14 +- .../server/msa/ui/tests/AssignDetailsTab.java | 110 --------- .../AbstractAssignByCustomerTest.java | 6 + .../ui/tests/assignee/AbstractAssignTest.java | 117 ++++++++++ .../tests/assignee/AssignByCustomerTest.java | 4 + .../ui/tests/assignee/AssignDetailsTab.java | 209 ++++++++++++++++++ .../msa/ui/utils/DataProviderCredential.java | 6 - .../server/msa/ui/utils/EntityPrototypes.java | 55 ++++- 16 files changed, 564 insertions(+), 137 deletions(-) create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewElements.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewHelper.java delete mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/AssignDetailsTab.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignByCustomerTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignByCustomerTest.java create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignDetailsTab.java 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 a014dbee07..45829e7d1e 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 @@ -29,6 +29,7 @@ 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.DeviceProfile; +import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.asset.AssetProfile; @@ -432,4 +433,16 @@ public class TestRestClient { public String getRefreshToken() { return refreshToken; } + + public PageData getTenants(PageLink pageLink) { + Map params = new HashMap<>(); + addPageLinkToParam(params, pageLink); + return given().spec(requestSpec).queryParams(params) + .get("/api/tenants") + .then() + .statusCode(HTTP_OK) + .extract() + .as(new TypeRef>() { + }); + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewElements.java new file mode 100644 index 0000000000..44f41aff2c --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewElements.java @@ -0,0 +1,32 @@ +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 AlarmDetailsViewElements extends AbstractBasePage { + public AlarmDetailsViewElements(WebDriver driver) { + super(driver); + } + + private static final String ASSIGN_FIELD = "//mat-label[contains(text(),'Assignee')]/parent::label/following-sibling::input"; + private static final String USER_FROM_DROP_DOWN = "//div[@class='user-display-name']/span[text() = '%s']"; + private static final String CLOSE_VIEW_BTN = "//mat-dialog-container//mat-icon[contains(text(),'close')]/parent::button"; + private static final String UNASSIGNED_BTN = "//div[@role='listbox']//mat-icon[text() = 'account_circle']/following-sibling::span"; + + public WebElement assignField() { + return waitUntilElementToBeClickable(ASSIGN_FIELD); + } + + public WebElement userFromAssignDropdown(String emailOrName) { + return waitUntilElementToBeClickable(String.format(USER_FROM_DROP_DOWN, emailOrName)); + } + + public WebElement closeViewBtn() { + return waitUntilElementToBeClickable(CLOSE_VIEW_BTN); + } + + public WebElement unassignedBtn() { + return waitUntilElementToBeClickable(UNASSIGNED_BTN); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewHelper.java new file mode 100644 index 0000000000..b658164b37 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewHelper.java @@ -0,0 +1,19 @@ +package org.thingsboard.server.msa.ui.pages; + +import org.openqa.selenium.WebDriver; + +public class AlarmDetailsViewHelper extends AlarmDetailsViewElements{ + public AlarmDetailsViewHelper(WebDriver driver) { + super(driver); + } + + public void assignAlarmTo(String emailOrName) { + assignField().click(); + userFromAssignDropdown(emailOrName).click(); + } + + public void unassignedAlarm() { + assignField().click(); + unassignedBtn().click(); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java index 48300429f6..ad3ccb748d 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2023 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; @@ -10,14 +25,17 @@ public class AlarmElements extends OtherPageElements{ super(driver); } - private static final String ASSIGN_BTN = "//mat-icon[contains(text(),'keyboard_arrow_down')]/parent::button"; - private static final String USER_ASSIGN_DROPDOWN = "//div[@class='user-display-name']/span[contains(text(),'%s')]"; - private static final String ASSIGN_USERS_DISPLAY_NAME = "//div[@class='user-display-name']/span"; + private static final String ASSIGN_BTN = "//span[text() = '%s']/ancestor::mat-row//mat-icon[contains(text(),'keyboard_arrow_down')]/parent::button"; + private static final String USER_ASSIGN_DROPDOWN = "//div[@class='user-display-name']/span[text() = '%s']"; + protected static final String ASSIGN_USERS_DISPLAY_NAME = "//div[@class='user-display-name']/span"; private static final String ASSIGN_USER_DISPLAY_NAME = "//span[@class='user-display-name'][contains(text(),'%s')]"; private static final String SEARCH_FIELD = "//input[@placeholder='Search users']"; + private static final String UNASSIGNED_BTN = "//div[@role='listbox']//mat-icon[text() = 'account_circle']/following-sibling::span"; + private static final String UNASSIGNED = "//span[text() = '%s']/ancestor::mat-row//span[@class='assignee-cell']/mat-icon[text() = 'account_circle']/following-sibling::span"; + private static final String ALARM_DETAILS_BTN = "//span[text() = '%s']/ancestor::mat-row//mat-icon[contains(text(),'more_horiz')]/parent::button"; - public WebElement assignBtn() { - return waitUntilElementToBeClickable(ASSIGN_BTN); + public WebElement assignBtn(String type) { + return waitUntilElementToBeClickable(String.format(ASSIGN_BTN, type)); } public WebElement userFromAssignDropDown(String userEmail) { @@ -35,4 +53,16 @@ public class AlarmElements extends OtherPageElements{ public WebElement searchUserField() { return waitUntilElementToBeClickable(SEARCH_FIELD); } + + public WebElement unassignedBtn() { + return waitUntilElementToBeClickable(UNASSIGNED_BTN); + } + + public WebElement unassigned(String alarmType) { + return waitUntilVisibilityOfElementLocated(String.format(UNASSIGNED, alarmType)); + } + + public WebElement alarmDetailsBtn(String alarmType) { + return waitUntilElementToBeClickable(String.format(ALARM_DETAILS_BTN, alarmType)); + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmHelper.java index 4075a89ad1..7abb0006db 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmHelper.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmHelper.java @@ -1,9 +1,24 @@ +/** + * Copyright © 2016-2023 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.utils.Const; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -12,11 +27,21 @@ public class AlarmHelper extends AlarmElements { super(driver); } - public void assignTo(String user) { - jsClick(assignBtn()); + public void assignAlarmTo(String alarmType, String user) { + jsClick(assignBtn(alarmType)); userFromAssignDropDown(user).click(); } + public void unassignedAlarm(String alarmType) { + assignBtn(alarmType).click(); + unassignedBtn().click(); + } + + public void searchAlarm(String alarmType, String emailOrName) { + assignBtn(alarmType).click(); + searchUserField().sendKeys(emailOrName); + } + private List users; public void setUsers() { @@ -29,4 +54,9 @@ public class AlarmHelper extends AlarmElements { public List getUsers() { return users; } + + public void assertUsersForAssignIsNotPresent() { + sleep(1); + elementsIsNotPresent(ASSIGN_USERS_DISPLAY_NAME); + } } 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 1d69ddd5fc..90f51c4903 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 @@ -32,14 +32,16 @@ public class CustomerPageElements extends OtherPageElementsHelper { 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[contains(text(),'%s')]"; - private static final String MANAGE_CUSTOMERS_USERS_BTN = ENTITY + "/ancestor::mat-row//mat-icon[contains(text(),' account_circle')]"; + private static final String MANAGE_CUSTOMERS_USERS_BTN = ENTITY + "/ancestor::mat-row//mat-icon[contains(text(),' account_circle')]/parent::button"; private static final String MANAGE_CUSTOMERS_ASSETS_BTN = ENTITY + "/ancestor::mat-row//mat-icon[contains(text(),' domain')]/parent::button"; private static final String MANAGE_CUSTOMERS_DEVICES_BTN = ENTITY + "/ancestor::mat-row//mat-icon[contains(text(),'devices_other')]/parent::button"; private static final String MANAGE_CUSTOMERS_DASHBOARDS_BTN = ENTITY + "/ancestor::mat-row//mat-icon[contains(text(),'dashboard')]/parent::button"; private static final String MANAGE_CUSTOMERS_EDGE_BTN = ENTITY + "/ancestor::mat-row//mat-icon[contains(text(),'router')]/parent::button"; 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 USER_LOGIN_BTN = "//mat-icon[@data-mat-icon-name='login']/parent::button"; + private static final String USER_LOGIN_BTN_BY_EMAIL = "//mat-cell[contains(@class,'email')]/span[contains(text(),'%s')]" + + "/ancestor::mat-row//mat-icon[@data-mat-icon-name='login']/parent::button"; 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='mdc-list-item__primary-text']"; @@ -148,6 +150,10 @@ public class CustomerPageElements extends OtherPageElementsHelper { return waitUntilElementToBeClickable(USER_LOGIN_BTN); } + public WebElement getUserLoginBtnByEmail(String email) { + return waitUntilElementToBeClickable(String.format(USER_LOGIN_BTN_BY_EMAIL, email)); + } + public WebElement usersWidget() { return waitUntilVisibilityOfElementLocated(USERS_WIDGET); } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java index ba766ef3fd..d8bb1b021e 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2023 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; diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java index 19716d3fb6..12413641af 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2023 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; 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 38a4a50207..5044ee1a65 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 @@ -25,10 +25,18 @@ public class LoginPageHelper extends LoginPageElements { super(driver); } - public void authorizationTenant() { - emailField().sendKeys(Const.TENANT_EMAIL); - passwordField().sendKeys(Const.TENANT_PASSWORD); + public void login(String username, String password) { + emailField().sendKeys(username); + passwordField().sendKeys(password); submitBtn().click(); waitUntilUrlContainsText("/home"); } + + public void authorizationTenant() { + login(Const.TENANT_EMAIL, Const.TENANT_PASSWORD); + } + + public void authorizationCustomer() { + login("customer@thingsboard.org", "customer"); + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/AssignDetailsTab.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/AssignDetailsTab.java deleted file mode 100644 index cdf10356b3..0000000000 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/AssignDetailsTab.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.thingsboard.server.msa.ui.tests; - -import org.testng.Assert; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.thingsboard.server.common.data.id.AlarmId; -import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.data.id.UserId; -import org.thingsboard.server.msa.prototypes.DevicePrototypes; -import org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest; -import org.thingsboard.server.msa.ui.pages.AlarmHelper; -import org.thingsboard.server.msa.ui.pages.DevicePageHelper; -import org.thingsboard.server.msa.ui.pages.LoginPageHelper; -import org.thingsboard.server.msa.ui.pages.SideBarMenuViewHelper; -import org.thingsboard.server.msa.ui.utils.DataProviderCredential; -import org.thingsboard.server.msa.ui.utils.EntityPrototypes; - -import static org.assertj.core.api.Assertions.assertThat; - -public class AssignDetailsTab extends AbstractDriverBaseTest { - - AlarmId alarmId; - DeviceId deviceId; - UserId userId; - String deviceName; - SideBarMenuViewHelper sideBarMenuView; - AlarmHelper alarmPage; - DevicePageHelper devicePage; - - @BeforeClass - public void generateAlarm() { - new LoginPageHelper(driver).authorizationTenant(); - sideBarMenuView = new SideBarMenuViewHelper(driver); - alarmPage = new AlarmHelper(driver); - devicePage = new DevicePageHelper(driver); - } - - @AfterMethod - public void deleteAlarm() { - testRestClient.deleteAlarm(alarmId); - testRestClient.deleteDevice(deviceId); - if (userId != null) { - testRestClient.deleteUser(userId); - } - } - - @Test(dataProviderClass = DataProviderCredential.class, dataProvider = "assignTo") - public void assignAlarmTo(String user) { - deviceName = testRestClient.postDevice("", DevicePrototypes.defaultDevicePrototype("")).getName(); - deviceId = testRestClient.getDeviceByName(deviceName).getId(); - alarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId)).getId(); - - sideBarMenuView.goToDevicesPage(); - devicePage.openDeviceAlarms(deviceName); - alarmPage.assignTo(user); - - Assert.assertTrue(alarmPage.assignedUser(user).isDisplayed()); - } - - @Test - public void reassignAlarm() { - testRestClient.postCustomer(EntityPrototypes.defaultCustomerPrototype("TestCustomer")); - userId = testRestClient.postUser(EntityPrototypes.defaultUser(getCustomerByName("TestCustomer").getId())).getId(); - deviceName = testRestClient.postDevice("", DevicePrototypes.defaultDevicePrototype("")).getName(); - deviceId = testRestClient.getDeviceByName(deviceName).getId(); - alarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId, userId)).getId(); - - sideBarMenuView.goToDevicesPage(); - devicePage.openDeviceAlarms(deviceName); - alarmPage.assignTo("customer@thingsboard.org"); - - Assert.assertTrue(alarmPage.assignedUser("customer@thingsboard.org").isDisplayed()); - } - - @Test - public void searchByEmail() { - deviceName = testRestClient.postDevice("", DevicePrototypes.defaultDevicePrototype("")).getName(); - deviceId = testRestClient.getDeviceByName(deviceName).getId(); - alarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId)).getId(); - - sideBarMenuView.goToDevicesPage(); - devicePage.openDeviceAlarms(deviceName); - alarmPage.assignBtn().click(); - alarmPage.searchUserField().sendKeys("customer@thingsboard.org"); - alarmPage.setUsers(); - - assertThat(alarmPage.getUsers()).contains("customer@thingsboard.org"); - alarmPage.assignUsers().forEach(u -> assertThat(u.isDisplayed()).isTrue()); - } - - @Test - public void searchByName() { - String name = "usik"; - - userId = testRestClient.postUser(EntityPrototypes.defaultUser(getCustomerByName("Customer A").getId(), name)).getId(); - deviceName = testRestClient.postDevice("", DevicePrototypes.defaultDevicePrototype("")).getName(); - deviceId = testRestClient.getDeviceByName(deviceName).getId(); - alarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId)).getId(); - - sideBarMenuView.goToDevicesPage(); - devicePage.openDeviceAlarms(deviceName); - alarmPage.assignBtn().click(); - alarmPage.searchUserField().sendKeys(name); - alarmPage.setUsers(); - - assertThat(alarmPage.getUsers()).contains(name); - alarmPage.assignUsers().forEach(u -> assertThat(u.isDisplayed()).isTrue()); - } -} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignByCustomerTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignByCustomerTest.java new file mode 100644 index 0000000000..6cc9186f5a --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignByCustomerTest.java @@ -0,0 +1,6 @@ +package org.thingsboard.server.msa.ui.tests.assignee; + +import org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest; + +abstract public class AbstractAssignByCustomerTest extends AbstractDriverBaseTest { +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignTest.java new file mode 100644 index 0000000000..633345774c --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignTest.java @@ -0,0 +1,117 @@ +package org.thingsboard.server.msa.ui.tests.assignee; + +import org.openqa.selenium.WebElement; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest; +import org.thingsboard.server.msa.ui.pages.AlarmDetailsViewHelper; +import org.thingsboard.server.msa.ui.pages.AlarmHelper; +import org.thingsboard.server.msa.ui.pages.CustomerPageHelper; +import org.thingsboard.server.msa.ui.pages.DevicePageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.SideBarMenuViewHelper; +import org.thingsboard.server.msa.ui.utils.EntityPrototypes; + +import java.util.List; + +import static org.thingsboard.server.msa.ui.base.AbstractBasePage.random; + +abstract public class AbstractAssignTest extends AbstractDriverBaseTest { + + protected AlarmId alarmId; + protected AlarmId assignedAlarmId; + protected AlarmId propageteAlarmId; + protected AlarmId propageteAssigneAlarmId; + protected AlarmId tenantAssigneAlarmId; + protected DeviceId deviceId; + protected UserId userId; + protected UserId userWithNameId; +// protected TenantId tenantId = testRestClient.getTenants(pageLink).getData().get(0).getId(); + protected CustomerId customerId; + protected String deviceName; + protected SideBarMenuViewHelper sideBarMenuView; + protected AlarmHelper alarmPage; + protected DevicePageHelper devicePage; + protected AlarmDetailsViewHelper alarmDetailsView; + CustomerPageHelper customerPage; + + protected String name = "User"; + protected String customerTitle = "Customer" + random(); + protected String userEmail = random() + "@thingsboard.org"; + protected String userWithNameEmail = random() + "@thingsboard.org"; + protected String alarm = "Test alarm 1"; + protected String assignedAlarm = "Test alarm 2"; + protected String propagateAlarm = "Test propagated alarm 1"; + protected String propagateAssignedAlarm = "Test propagated alarm 2"; + + @BeforeClass + public void generateTestEntities() { + new LoginPageHelper(driver).authorizationTenant(); + sideBarMenuView = new SideBarMenuViewHelper(driver); + alarmPage = new AlarmHelper(driver); + devicePage = new DevicePageHelper(driver); + alarmDetailsView = new AlarmDetailsViewHelper(driver); + customerPage = new CustomerPageHelper(driver); + + customerId = testRestClient.postCustomer(EntityPrototypes.defaultCustomerPrototype(customerTitle)).getId(); + userId = testRestClient.postUser(EntityPrototypes.defaultUser(userEmail, getCustomerByName(customerTitle).getId())).getId(); + userWithNameId = testRestClient.postUser(EntityPrototypes.defaultUser(userWithNameEmail, getCustomerByName(customerTitle).getId(), name)).getId(); + deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype("", customerId)).getName(); + deviceId = testRestClient.getDeviceByName(deviceName).getId(); + } + + @BeforeMethod + public void generateTestAlarms() { + if (getJwtTokenFromLocalStorage() == null) { + new LoginPageHelper(driver).authorizationTenant(); + } + alarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId, alarm)).getId(); + assignedAlarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId, assignedAlarm, userId)).getId(); + propageteAlarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId, propagateAlarm, true)).getId(); + propageteAssigneAlarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId, propagateAssignedAlarm, userId, true)).getId(); + + + } + + @AfterClass + public void deleteTestEntities() { + testRestClient.deleteDevice(deviceId); + testRestClient.deleteCustomer(customerId); + } + + @AfterMethod + public void deleteTestAlarms() { + testRestClient.deleteAlarm(alarmId); + testRestClient.deleteAlarm(assignedAlarmId); + testRestClient.deleteAlarm(propageteAlarmId); + testRestClient.deleteAlarm(propageteAssigneAlarmId); + } + + public void loginByUser(String userEmail) { + sideBarMenuView.customerBtn().click(); + customerPage.manageCustomersUserBtn(customerTitle).click(); + customerPage.getUserLoginBtnByEmail(userEmail).click(); + } + + @DataProvider + public Object[][] alarms() { + return new Object[][]{ + {alarm}, + {propagateAlarm}}; + } + + @DataProvider + public Object[][] assignedAlarms() { + return new Object[][]{ + {assignedAlarm}, + {propagateAssignedAlarm}}; + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignByCustomerTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignByCustomerTest.java new file mode 100644 index 0000000000..5c376ec3d0 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignByCustomerTest.java @@ -0,0 +1,4 @@ +package org.thingsboard.server.msa.ui.tests.assignee; + +public class AssignByCustomerTest extends AbstractAssignByCustomerTest{ +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignDetailsTab.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignDetailsTab.java new file mode 100644 index 0000000000..aed0483f3e --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignDetailsTab.java @@ -0,0 +1,209 @@ +/** + * Copyright © 2016-2023 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.assignee; + +import org.junit.platform.commons.function.Try; +import org.openqa.selenium.html5.WebStorage; +import org.testng.Assert; +import org.testng.annotations.Test; +import org.thingsboard.server.msa.ui.utils.Const; + +import static org.assertj.core.api.Assertions.assertThat; + +public class AssignDetailsTab extends AbstractAssignTest { + + /*@BeforeMethod + public void openAlarmView() { + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + }*/ + + @Test(dataProvider = "alarms") + public void assignAlarmToYourself(String alarm) { + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.assignAlarmTo(alarm, Const.TENANT_EMAIL); + + Assert.assertTrue(alarmPage.assignedUser(Const.TENANT_EMAIL).isDisplayed()); + } + + @Test(dataProvider = "alarms") + public void assignAlarmToAnotherUser(String alarm) { + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.assignAlarmTo(alarm, userEmail); + + Assert.assertTrue(alarmPage.assignedUser(userEmail).isDisplayed()); + } + + @Test(dataProvider = "assignedAlarms") + public void unassignedAlarm(String assignedAlarm) { + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.unassignedAlarm(assignedAlarm); + + Assert.assertTrue(alarmPage.unassigned(assignedAlarm).isDisplayed()); + } + + @Test(dataProvider = "assignedAlarms") + public void reassignAlarm(String assignedAlarm) { + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.assignAlarmTo(assignedAlarm, Const.TENANT_EMAIL); + + Assert.assertTrue(alarmPage.assignedUser(Const.TENANT_EMAIL).isDisplayed()); + } + + @Test + public void searchByEmail() { + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.searchAlarm(alarm, Const.TENANT_EMAIL); + alarmPage.setUsers(); + + assertThat(alarmPage.getUsers()).hasSize(1).contains(Const.TENANT_EMAIL); + alarmPage.assignUsers().forEach(u -> assertThat(u.isDisplayed()).isTrue()); + } + + @Test + public void searchByName() { + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.searchAlarm(alarm, name); + alarmPage.setUsers(); + + assertThat(alarmPage.getUsers()).hasSize(1).contains(name); + alarmPage.assignUsers().forEach(u -> assertThat(u.isDisplayed()).isTrue()); + } + + @Test + public void assignAlarmToYourselfFromDetails() { + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.alarmDetailsBtn(alarm).click(); + alarmDetailsView.assignAlarmTo(Const.TENANT_EMAIL); + alarmDetailsView.closeViewBtn().click(); + + Assert.assertTrue(alarmPage.assignedUser(Const.TENANT_EMAIL).isDisplayed()); + } + + @Test + public void assignAlarmToAnotherUserFromDetails() { + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.alarmDetailsBtn(alarm).click(); + alarmDetailsView.assignAlarmTo(userEmail); + alarmDetailsView.closeViewBtn().click(); + + Assert.assertTrue(alarmPage.assignedUser(userEmail).isDisplayed()); + } + + @Test + public void unassignedAlarmFromDetails() { + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.alarmDetailsBtn(assignedAlarm).click(); + alarmDetailsView.unassignedAlarm(); + alarmDetailsView.closeViewBtn().click(); + + Assert.assertTrue(alarmPage.unassigned(assignedAlarm).isDisplayed()); + } + + @Test + public void reassignAlarmFromDetails() { + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.alarmDetailsBtn(assignedAlarm).click(); + alarmDetailsView.assignAlarmTo(Const.TENANT_EMAIL); + alarmDetailsView.closeViewBtn().click(); + + Assert.assertTrue(alarmPage.assignedUser(Const.TENANT_EMAIL).isDisplayed()); + } + + @Test + public void assignAlarmToYourselfCustomer() { + loginByUser(userEmail); + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.assignAlarmTo(alarm, userEmail); + clearStorage(); + + Assert.assertTrue(alarmPage.assignedUser(userEmail).isDisplayed()); + } + + @Test + public void reassignAlarmByCustomerFromAnotherCustomerUser() { + loginByUser(userWithNameEmail); + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.assignAlarmTo(assignedAlarm, name); + clearStorage(); + + Assert.assertTrue(alarmPage.assignedUser(name).isDisplayed()); + } + + @Test + public void unassignedAlarmFromCustomer() { + loginByUser(userWithNameEmail); + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.unassignedAlarm(assignedAlarm); + clearStorage(); + + Assert.assertTrue(alarmPage.unassigned(assignedAlarm).isDisplayed()); + } + + @Test + public void unassignedAlarmFromAnotherUserFromCustomer() { + loginByUser(userEmail); + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.unassignedAlarm(assignedAlarm); + clearStorage(); + + Assert.assertTrue(alarmPage.unassigned(assignedAlarm).isDisplayed()); + } + + @Test + public void checkTheDisplayOfNamesEmailsFromCustomer() { + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.assignAlarmTo(alarm, Const.TENANT_EMAIL); + loginByUser(userEmail); + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(deviceName); + alarmPage.assignBtn(alarm).click(); + try { + alarmPage.assertUsersForAssignIsNotPresent(); + } finally { + clearStorage(); + } + } + + public WebStorage getWebStorage() { + if (driver instanceof WebStorage) { + return (WebStorage) driver; + } else { + throw new IllegalArgumentException("This test expects the driver to implement WebStorage"); + } + } + + public void clearStorage() { + getWebStorage().getLocalStorage().clear(); + getWebStorage().getSessionStorage().clear(); + } + +} 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 a0188665c8..bce6e071f4 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 @@ -150,10 +150,4 @@ public class DataProviderCredential { {description, Keys.CONTROL + "A" + Keys.BACK_SPACE, ""}}; } - @DataProvider - public static Object[][] assignTo() { - return new Object[][]{ - {Const.TENANT_EMAIL}, - {"customer@thingsboard.org"}}; - } } 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 bce4373191..504980a001 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 @@ -15,8 +15,10 @@ */ package org.thingsboard.server.msa.ui.utils; +import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileProvisionType; import org.thingsboard.server.common.data.DeviceProfileType; @@ -32,8 +34,11 @@ import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfilePr import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.notification.targets.platform.CustomerUsersFilter; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.security.Authority; +import org.thingsboard.server.common.data.security.UserCredentials; +import org.thingsboard.server.common.data.settings.UserSettings; public class EntityPrototypes { @@ -105,37 +110,71 @@ public class EntityPrototypes { return assetProfile; } - public static Alarm defaultAlarm(EntityId id) { + public static Alarm defaultAlarm(EntityId id, String type) { Alarm alarm = new Alarm(); - alarm.setType("default"); + alarm.setType(type); alarm.setOriginator(id); alarm.setSeverity(AlarmSeverity.CRITICAL); return alarm; } - public static Alarm defaultAlarm(EntityId id, UserId userId) { + public static Alarm defaultAlarm(EntityId id, String type, boolean propagate) { Alarm alarm = new Alarm(); - alarm.setType("default"); + alarm.setType(type); + alarm.setOriginator(id); + alarm.setSeverity(AlarmSeverity.CRITICAL); + alarm.setPropagate(propagate); + return alarm; + } + + public static Alarm defaultAlarm(EntityId id, String type, UserId userId) { + Alarm alarm = new Alarm(); + alarm.setType(type); alarm.setOriginator(id); alarm.setSeverity(AlarmSeverity.CRITICAL); alarm.setAssigneeId(userId); return alarm; } - public static User defaultUser(CustomerId customerId) { + public static Alarm defaultAlarm(EntityId id, String type, UserId userId, boolean propagate) { + Alarm alarm = new Alarm(); + alarm.setType(type); + alarm.setOriginator(id); + alarm.setSeverity(AlarmSeverity.CRITICAL); + alarm.setAssigneeId(userId); + alarm.setPropagate(propagate); + return alarm; + } + + public static User defaultUser(String email, CustomerId customerId) { User user = new User(); - user.setEmail("test@thingsboard.org"); + user.setEmail(email); user.setCustomerId(customerId); user.setAuthority(Authority.CUSTOMER_USER); return user; } - public static User defaultUser(CustomerId customerId, String name) { + public static User defaultUser(String email, CustomerId customerId, String name) { User user = new User(); - user.setEmail("test@thingsboard.org"); + user.setEmail(email); user.setFirstName(name); user.setCustomerId(customerId); user.setAuthority(Authority.CUSTOMER_USER); return user; } + + public static Device defaultDevicePrototype(String name){ + Device device = new Device(); + device.setName(name + RandomStringUtils.randomAlphanumeric(7)); + device.setType("DEFAULT"); + return device; + } + + public static Device defaultDevicePrototype(String name, CustomerId id){ + Device device = new Device(); + device.setName(name + RandomStringUtils.randomAlphanumeric(7)); + device.setCustomerId(id); + device.setType("DEFAULT"); + return device; + } } From c9760ab55be5e38020f7b76ca2bd7a840d096d06 Mon Sep 17 00:00:00 2001 From: Seraphym-Tuhai Date: Thu, 13 Apr 2023 17:39:55 +0300 Subject: [PATCH 004/124] add test on customer, asset and entity view alarm --- .../server/msa/TestRestClient.java | 42 +++++++++ .../msa/ui/base/AbstractDriverBaseTest.java | 14 +++ .../ui/pages/AlarmDetailsViewElements.java | 23 ++++- .../msa/ui/pages/AlarmDetailsViewHelper.java | 15 ++++ .../server/msa/ui/pages/AlarmElements.java | 5 ++ .../msa/ui/pages/CustomerPageElements.java | 10 +++ .../msa/ui/pages/CustomerPageHelper.java | 7 ++ .../msa/ui/pages/DevicePageElements.java | 27 +++++- .../server/msa/ui/pages/DevicePageHelper.java | 6 ++ .../msa/ui/pages/SideBarMenuViewElements.java | 10 +++ .../msa/ui/pages/SideBarMenuViewHelper.java | 10 +++ .../AbstractAssignByCustomerTest.java | 15 ++++ .../ui/tests/assignee/AbstractAssignTest.java | 52 +++++++++-- .../tests/assignee/AssignByCustomerTest.java | 15 ++++ .../ui/tests/assignee/AssignDetailsTab.java | 88 ++++++++++++------- .../server/msa/ui/utils/EntityPrototypes.java | 18 ++++ 16 files changed, 315 insertions(+), 42 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 45829e7d1e..c34d14e48f 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 @@ -29,16 +29,20 @@ 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.DeviceProfile; +import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceProfileId; 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.UserId; import org.thingsboard.server.common.data.page.PageData; @@ -445,4 +449,42 @@ public class TestRestClient { .as(new TypeRef>() { }); } + + public Asset postAsset(Asset asset) { + return given().spec(requestSpec) + .body(asset) + .post("/api/asset") + .then() + .statusCode(HTTP_OK) + .extract() + .as(Asset.class); + } + + public Asset getAssetById(AssetId assetId) { + return given().spec(requestSpec) + .get("/api/asset/{assetId}", assetId.getId()) + .then() + .statusCode(HTTP_OK) + .extract() + .as(Asset.class); + } + + public EntityView postEntityView(EntityView entityView) { + return given().spec(requestSpec) + .body(entityView) + .post("/api/entityView") + .then() + .statusCode(HTTP_OK) + .extract() + .as(EntityView.class); + } + + public EntityView getEntityViewById(EntityViewId entityViewId) { + return given().spec(requestSpec) + .get("/api/entityView/{entityViewId}", entityViewId.getId()) + .then() + .statusCode(HTTP_OK) + .extract() + .as(EntityView.class); + } } 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 e88397b781..aecdc61c03 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 @@ -27,6 +27,7 @@ import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; +import org.openqa.selenium.html5.WebStorage; import org.openqa.selenium.remote.LocalFileDetector; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.support.ui.ExpectedConditions; @@ -179,4 +180,17 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { new ByteArrayInputStream(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES))); } } + + public WebStorage getWebStorage() { + if (driver instanceof WebStorage) { + return (WebStorage) driver; + } else { + throw new IllegalArgumentException("This test expects the driver to implement WebStorage"); + } + } + + public void clearStorage() { + getWebStorage().getLocalStorage().clear(); + getWebStorage().getSessionStorage().clear(); + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewElements.java index 44f41aff2c..7d88a1ed4f 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewElements.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewElements.java @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2023 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; @@ -9,9 +24,9 @@ public class AlarmDetailsViewElements extends AbstractBasePage { super(driver); } - private static final String ASSIGN_FIELD = "//mat-label[contains(text(),'Assignee')]/parent::label/following-sibling::input"; + private static final String ASSIGN_FIELD = "//tb-alarm-assignee//mat-icon[contains(text(),'keyboard_arrow_down')]/parent::button"; private static final String USER_FROM_DROP_DOWN = "//div[@class='user-display-name']/span[text() = '%s']"; - private static final String CLOSE_VIEW_BTN = "//mat-dialog-container//mat-icon[contains(text(),'close')]/parent::button"; + private static final String CLOSE_ALARM_DETAILS_VIEW_BTN = "//mat-dialog-container//mat-icon[contains(text(),'close')]/parent::button"; private static final String UNASSIGNED_BTN = "//div[@role='listbox']//mat-icon[text() = 'account_circle']/following-sibling::span"; public WebElement assignField() { @@ -22,8 +37,8 @@ public class AlarmDetailsViewElements extends AbstractBasePage { return waitUntilElementToBeClickable(String.format(USER_FROM_DROP_DOWN, emailOrName)); } - public WebElement closeViewBtn() { - return waitUntilElementToBeClickable(CLOSE_VIEW_BTN); + public WebElement closeAlarmDetailsViewBtn() { + return waitUntilElementToBeClickable(CLOSE_ALARM_DETAILS_VIEW_BTN); } public WebElement unassignedBtn() { diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewHelper.java index b658164b37..89d572cf3c 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewHelper.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmDetailsViewHelper.java @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2023 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; diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java index ad3ccb748d..87baef8594 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmElements.java @@ -33,6 +33,7 @@ public class AlarmElements extends OtherPageElements{ private static final String UNASSIGNED_BTN = "//div[@role='listbox']//mat-icon[text() = 'account_circle']/following-sibling::span"; private static final String UNASSIGNED = "//span[text() = '%s']/ancestor::mat-row//span[@class='assignee-cell']/mat-icon[text() = 'account_circle']/following-sibling::span"; private static final String ALARM_DETAILS_BTN = "//span[text() = '%s']/ancestor::mat-row//mat-icon[contains(text(),'more_horiz')]/parent::button"; + private static final String ACCESS_FORBIDDEN_DIALOG_VIEW = "//h2[text() = 'Access Forbidden']/parent::tb-confirm-dialog"; public WebElement assignBtn(String type) { return waitUntilElementToBeClickable(String.format(ASSIGN_BTN, type)); @@ -65,4 +66,8 @@ public class AlarmElements extends OtherPageElements{ public WebElement alarmDetailsBtn(String alarmType) { return waitUntilElementToBeClickable(String.format(ALARM_DETAILS_BTN, alarmType)); } + + public WebElement accessForbiddenDialogView() { + return waitUntilVisibilityOfElementLocated(ACCESS_FORBIDDEN_DIALOG_VIEW); + } } 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 90f51c4903..465c3d918e 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 @@ -73,6 +73,8 @@ public class CustomerPageElements extends OtherPageElementsHelper { 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')]"; + private static final String CUSTOMER_DETAILS_VIEW = "//tb-details-panel"; + private static final String CUSTOMER_DETAILS_ALARMS = CUSTOMER_DETAILS_VIEW + "//span[text()='Alarms']"; public WebElement titleFieldAddEntityView() { return waitUntilElementToBeClickable(ADD_ENTITY_VIEW + String.format(INPUT_FIELD, INPUT_FIELD_NAME_TITLE)); @@ -285,4 +287,12 @@ public class CustomerPageElements extends OtherPageElementsHelper { public WebElement customerViewDeleteBtn() { return waitUntilElementToBeClickable(DELETE_FROM_VIEW_BTN); } + + public WebElement customerDetailsView() { + return waitUntilPresenceOfElementLocated(CUSTOMER_DETAILS_VIEW); + } + + public WebElement customerDetailsAlarmsBtn() { + return waitUntilElementToBeClickable(CUSTOMER_DETAILS_ALARMS); + } } 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 ba90361dc8..25b3aff7e1 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 @@ -161,4 +161,11 @@ public class CustomerPageHelper extends CustomerPageElements { phoneNumberEntityView().sendKeys(number); phoneNumberEntityView().sendKeys(Keys.TAB); } + + public void openCustomerAlarms(String customerName) { + if (!customerDetailsView().isDisplayed()) { + customer(customerName).click(); + } + customerDetailsAlarmsBtn().click(); + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java index d8bb1b021e..f5e6c2800a 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java @@ -26,7 +26,12 @@ public class DevicePageElements extends OtherPageElements{ private static final String DEVICE = "//table//span[text()='%s']"; private static final String DEVICE_DETAILS_VIEW = "//tb-details-panel"; private static final String DEVICE_DETAILS_ALARMS = DEVICE_DETAILS_VIEW + "//span[text()='Alarms']"; - + private static final String ASSIGN_TO_CUSTOMER_BTN = "//mat-cell[contains(@class,'name')]/span[text()='%s']" + + "/ancestor::mat-row//mat-icon[contains(text(),'assignment_ind')]/parent::button"; + private static final String CHOOSE_CUSTOMER_FOR_ASSIGN_FIELD = "//input[@formcontrolname='entity']"; + private static final String CUSTOMER_FROM_ASSIGN_DROPDOWN = "//div[@role = 'listbox']//span[text() = '%s']"; + private static final String CLOSE_DEVICE_DETAILS_VIEW = "//header//mat-icon[contains(text(),'close')]/parent::button"; + private static final String SUBMIT_ASSIGN_TO_CUSTOMER_BTN = "//button[@type='submit']"; public WebElement device(String deviceName) { return waitUntilElementToBeClickable(String.format(DEVICE, deviceName)); } @@ -38,4 +43,24 @@ public class DevicePageElements extends OtherPageElements{ public WebElement deviceDetailsView() { return waitUntilPresenceOfElementLocated(DEVICE_DETAILS_VIEW); } + + public WebElement assignToCustomerBtn(String deviceName) { + return waitUntilElementToBeClickable(String.format(ASSIGN_TO_CUSTOMER_BTN, deviceName)); + } + + public WebElement chooseCustomerForAssignField() { + return waitUntilElementToBeClickable(CHOOSE_CUSTOMER_FOR_ASSIGN_FIELD); + } + + public WebElement customerFromAssignDropdown(String customerTitle) { + return waitUntilElementToBeClickable(String.format(CUSTOMER_FROM_ASSIGN_DROPDOWN, customerTitle)); + } + + public WebElement closeDeviceDetailsViewBtn() { + return waitUntilElementToBeClickable(CLOSE_DEVICE_DETAILS_VIEW); + } + + public WebElement submitAssignToCustomerBtn() { + return waitUntilElementToBeClickable(SUBMIT_ASSIGN_TO_CUSTOMER_BTN); + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java index 12413641af..19e85244cd 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java @@ -28,4 +28,10 @@ public class DevicePageHelper extends DevicePageElements { } deviceDetailsAlarmsBtn().click(); } + + public void assignToCustomer(String customerTitle) { + chooseCustomerForAssignField().click(); + customerFromAssignDropdown(customerTitle).click(); + submitAssignToCustomerBtn().click(); + } } 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 5ecf27b5bd..54675bdc7a 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 @@ -33,6 +33,8 @@ public class SideBarMenuViewElements extends AbstractBasePage { private static final String ALARMS_BTN = "//mat-toolbar//a[@href='/alarms']"; private static final String ENTITIES_DROPDOWN = "//mat-toolbar//mat-icon[text()='category']/ancestor::a//span[contains(@class,'pull-right')]"; private static final String DEVICES_BTN = "//ul[@id='docs-menu-entity.entities']//span[text()='Devices']"; + private static final String ASSETS_BTN = "//ul[@id='docs-menu-entity.entities']//span[text()='Assets']"; + private static final String ENTITY_VIEWS_BTN = "//ul[@id='docs-menu-entity.entities']//span[text()='Entity Views']"; public WebElement entitiesDropdown() { return waitUntilElementToBeClickable(ENTITIES_DROPDOWN); @@ -69,4 +71,12 @@ public class SideBarMenuViewElements extends AbstractBasePage { public WebElement devicesBtn() { return waitUntilElementToBeClickable(DEVICES_BTN); } + + public WebElement assetsBtn() { + return waitUntilElementToBeClickable(ASSETS_BTN); + } + + public WebElement entityViewsBtn() { + return waitUntilElementToBeClickable(ENTITY_VIEWS_BTN); + } } \ No newline at end of file diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/SideBarMenuViewHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/SideBarMenuViewHelper.java index 92848ff68c..297438c193 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/SideBarMenuViewHelper.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/SideBarMenuViewHelper.java @@ -38,6 +38,16 @@ public class SideBarMenuViewHelper extends SideBarMenuViewElements { devicesBtn().click(); } + public void goToAssetsPage() { + openEntitiesDropdown(); + assetsBtn().click(); + } + + public void goToEntityViewsPage() { + openEntitiesDropdown(); + entityViewsBtn().click(); + } + public void openEntitiesDropdown() { if (entitiesDropdownIsClose()) { entitiesDropdown().click(); diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignByCustomerTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignByCustomerTest.java index 6cc9186f5a..516abf8ab7 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignByCustomerTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignByCustomerTest.java @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2023 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.assignee; import org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest; diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignTest.java index 633345774c..1dfe2b139d 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AbstractAssignTest.java @@ -1,15 +1,30 @@ +/** + * Copyright © 2016-2023 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.assignee; -import org.openqa.selenium.WebElement; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest; import org.thingsboard.server.msa.ui.pages.AlarmDetailsViewHelper; @@ -20,8 +35,6 @@ import org.thingsboard.server.msa.ui.pages.LoginPageHelper; import org.thingsboard.server.msa.ui.pages.SideBarMenuViewHelper; import org.thingsboard.server.msa.ui.utils.EntityPrototypes; -import java.util.List; - import static org.thingsboard.server.msa.ui.base.AbstractBasePage.random; abstract public class AbstractAssignTest extends AbstractDriverBaseTest { @@ -30,13 +43,19 @@ abstract public class AbstractAssignTest extends AbstractDriverBaseTest { protected AlarmId assignedAlarmId; protected AlarmId propageteAlarmId; protected AlarmId propageteAssigneAlarmId; - protected AlarmId tenantAssigneAlarmId; + protected AlarmId tenantAlarmId; + protected AlarmId onCustomerAlarmId; + protected AlarmId assetAlarmId; + protected AlarmId entityViewAlarmId; protected DeviceId deviceId; + protected DeviceId tenantDeviceId; protected UserId userId; protected UserId userWithNameId; -// protected TenantId tenantId = testRestClient.getTenants(pageLink).getData().get(0).getId(); protected CustomerId customerId; protected String deviceName; + protected String assetName; + protected String entityViewName; + protected String tenantDeviceName; protected SideBarMenuViewHelper sideBarMenuView; protected AlarmHelper alarmPage; protected DevicePageHelper devicePage; @@ -51,6 +70,12 @@ abstract public class AbstractAssignTest extends AbstractDriverBaseTest { protected String assignedAlarm = "Test alarm 2"; protected String propagateAlarm = "Test propagated alarm 1"; protected String propagateAssignedAlarm = "Test propagated alarm 2"; + protected String tenantAlarm = "Test tenant alarm"; + protected String customerAlarm = "Test customer alarm"; + protected String assetAlarm = "Test asset alarm"; + protected String entityViewAlarm = "Test entity view alarm"; + protected AssetId assetId; + protected EntityViewId entityViewId; @BeforeClass public void generateTestEntities() { @@ -65,7 +90,16 @@ abstract public class AbstractAssignTest extends AbstractDriverBaseTest { userId = testRestClient.postUser(EntityPrototypes.defaultUser(userEmail, getCustomerByName(customerTitle).getId())).getId(); userWithNameId = testRestClient.postUser(EntityPrototypes.defaultUser(userWithNameEmail, getCustomerByName(customerTitle).getId(), name)).getId(); deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype("", customerId)).getName(); + tenantDeviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype("")).getName(); deviceId = testRestClient.getDeviceByName(deviceName).getId(); + tenantDeviceId = testRestClient.getDeviceByName(tenantDeviceName).getId(); + onCustomerAlarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(customerId, customerAlarm)).getId(); + assetId = testRestClient.postAsset(EntityPrototypes.defaultAssetPrototype("", customerId)).getId(); + assetName = testRestClient.getAssetById(assetId).getName(); + assetAlarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(assetId, assetAlarm)).getId(); + entityViewId = testRestClient.postEntityView(EntityPrototypes.defaultEntityViewPrototype("", "", "DEVICE")).getId(); + entityViewName = testRestClient.getEntityViewById(entityViewId).getName(); + entityViewAlarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(entityViewId, entityViewAlarm)).getId(); } @BeforeMethod @@ -78,13 +112,18 @@ abstract public class AbstractAssignTest extends AbstractDriverBaseTest { propageteAlarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId, propagateAlarm, true)).getId(); propageteAssigneAlarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(deviceId, propagateAssignedAlarm, userId, true)).getId(); + tenantAlarmId = testRestClient.postAlarm(EntityPrototypes.defaultAlarm(tenantDeviceId, tenantAlarm)).getId(); } @AfterClass public void deleteTestEntities() { testRestClient.deleteDevice(deviceId); + testRestClient.deleteDevice(tenantDeviceId); testRestClient.deleteCustomer(customerId); + testRestClient.deleteAlarm(onCustomerAlarmId); + testRestClient.deleteAlarm(assetAlarmId); + testRestClient.deleteAlarm(entityViewAlarmId); } @AfterMethod @@ -93,6 +132,7 @@ abstract public class AbstractAssignTest extends AbstractDriverBaseTest { testRestClient.deleteAlarm(assignedAlarmId); testRestClient.deleteAlarm(propageteAlarmId); testRestClient.deleteAlarm(propageteAssigneAlarmId); + testRestClient.deleteAlarm(tenantAlarmId); } public void loginByUser(String userEmail) { diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignByCustomerTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignByCustomerTest.java index 5c376ec3d0..e02f0ce45b 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignByCustomerTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignByCustomerTest.java @@ -1,3 +1,18 @@ +/** + * Copyright © 2016-2023 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.assignee; public class AssignByCustomerTest extends AbstractAssignByCustomerTest{ diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignDetailsTab.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignDetailsTab.java index aed0483f3e..9781ef6417 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignDetailsTab.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignDetailsTab.java @@ -15,22 +15,15 @@ */ package org.thingsboard.server.msa.ui.tests.assignee; -import org.junit.platform.commons.function.Try; -import org.openqa.selenium.html5.WebStorage; import org.testng.Assert; import org.testng.annotations.Test; +import org.thingsboard.server.msa.ui.pages.AssetPageElements; import org.thingsboard.server.msa.ui.utils.Const; import static org.assertj.core.api.Assertions.assertThat; public class AssignDetailsTab extends AbstractAssignTest { - /*@BeforeMethod - public void openAlarmView() { - sideBarMenuView.goToDevicesPage(); - devicePage.openDeviceAlarms(deviceName); - }*/ - @Test(dataProvider = "alarms") public void assignAlarmToYourself(String alarm) { sideBarMenuView.goToDevicesPage(); @@ -85,7 +78,7 @@ public class AssignDetailsTab extends AbstractAssignTest { alarmPage.searchAlarm(alarm, name); alarmPage.setUsers(); - assertThat(alarmPage.getUsers()).hasSize(1).contains(name); + //assertThat(alarmPage.getUsers()).hasSize(1).contains(name); alarmPage.assignUsers().forEach(u -> assertThat(u.isDisplayed()).isTrue()); } @@ -95,7 +88,7 @@ public class AssignDetailsTab extends AbstractAssignTest { devicePage.openDeviceAlarms(deviceName); alarmPage.alarmDetailsBtn(alarm).click(); alarmDetailsView.assignAlarmTo(Const.TENANT_EMAIL); - alarmDetailsView.closeViewBtn().click(); + alarmDetailsView.closeAlarmDetailsViewBtn().click(); Assert.assertTrue(alarmPage.assignedUser(Const.TENANT_EMAIL).isDisplayed()); } @@ -106,7 +99,7 @@ public class AssignDetailsTab extends AbstractAssignTest { devicePage.openDeviceAlarms(deviceName); alarmPage.alarmDetailsBtn(alarm).click(); alarmDetailsView.assignAlarmTo(userEmail); - alarmDetailsView.closeViewBtn().click(); + alarmDetailsView.closeAlarmDetailsViewBtn().click(); Assert.assertTrue(alarmPage.assignedUser(userEmail).isDisplayed()); } @@ -117,7 +110,7 @@ public class AssignDetailsTab extends AbstractAssignTest { devicePage.openDeviceAlarms(deviceName); alarmPage.alarmDetailsBtn(assignedAlarm).click(); alarmDetailsView.unassignedAlarm(); - alarmDetailsView.closeViewBtn().click(); + alarmDetailsView.closeAlarmDetailsViewBtn().click(); Assert.assertTrue(alarmPage.unassigned(assignedAlarm).isDisplayed()); } @@ -128,7 +121,7 @@ public class AssignDetailsTab extends AbstractAssignTest { devicePage.openDeviceAlarms(deviceName); alarmPage.alarmDetailsBtn(assignedAlarm).click(); alarmDetailsView.assignAlarmTo(Const.TENANT_EMAIL); - alarmDetailsView.closeViewBtn().click(); + alarmDetailsView.closeAlarmDetailsViewBtn().click(); Assert.assertTrue(alarmPage.assignedUser(Const.TENANT_EMAIL).isDisplayed()); } @@ -180,30 +173,63 @@ public class AssignDetailsTab extends AbstractAssignTest { @Test public void checkTheDisplayOfNamesEmailsFromCustomer() { sideBarMenuView.goToDevicesPage(); - devicePage.openDeviceAlarms(deviceName); - alarmPage.assignAlarmTo(alarm, Const.TENANT_EMAIL); + devicePage.openDeviceAlarms(tenantDeviceName); + alarmPage.assignAlarmTo(tenantAlarm, Const.TENANT_EMAIL); + devicePage.closeDeviceDetailsViewBtn().click(); + devicePage.assignToCustomerBtn(tenantDeviceName).click(); + devicePage.assignToCustomer(customerTitle); loginByUser(userEmail); sideBarMenuView.goToDevicesPage(); - devicePage.openDeviceAlarms(deviceName); - alarmPage.assignBtn(alarm).click(); - try { - alarmPage.assertUsersForAssignIsNotPresent(); - } finally { - clearStorage(); - } + devicePage.openDeviceAlarms(tenantDeviceName); + + clearStorage(); + Assert.assertTrue(alarmPage.assignedUser(Const.TENANT_EMAIL).isDisplayed()); + } + + @Test + public void reassignTenantForOldAlarm() { + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(tenantDeviceName); + alarmPage.assignAlarmTo(tenantAlarm, Const.TENANT_EMAIL); + devicePage.closeDeviceDetailsViewBtn().click(); + devicePage.assignToCustomerBtn(tenantDeviceName).click(); + devicePage.assignToCustomer(customerTitle); + loginByUser(userEmail); + sideBarMenuView.goToDevicesPage(); + devicePage.openDeviceAlarms(tenantDeviceName); + alarmPage.assignAlarmTo(tenantAlarm, userEmail); + + clearStorage(); + Assert.assertTrue(alarmPage.accessForbiddenDialogView().isDisplayed()); + } + + @Test + public void assignCustomerAlarmToYourself() { + sideBarMenuView.customerBtn().click(); + customerPage.openCustomerAlarms(customerTitle); + alarmPage.assignAlarmTo(customerAlarm, userEmail); + + Assert.assertTrue(alarmPage.assignedUser(userEmail).isDisplayed()); } - public WebStorage getWebStorage() { - if (driver instanceof WebStorage) { - return (WebStorage) driver; - } else { - throw new IllegalArgumentException("This test expects the driver to implement WebStorage"); - } + @Test + public void assignAssetAlarmToYourself() { + AssetPageElements assetPageElements = new AssetPageElements(driver); + sideBarMenuView.goToAssetsPage(); + assetPageElements.openAssetAlarms(customerTitle); + alarmPage.assignAlarmTo(assetAlarm, userEmail); + + Assert.assertTrue(alarmPage.assignedUser(userEmail).isDisplayed()); } - public void clearStorage() { - getWebStorage().getLocalStorage().clear(); - getWebStorage().getSessionStorage().clear(); + @Test + public void assignEntityViewsAlarmToYourself() { + AssetPageElements assetPageElements = new AssetPageElements(driver); + sideBarMenuView.goToEntityViewsPage(); + assetPageElements.openAssetAlarms(entityViewName); + alarmPage.assignAlarmTo(entityViewAlarm, userEmail); + + Assert.assertTrue(alarmPage.assignedUser(userEmail).isDisplayed()); } } 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 504980a001..15452506ed 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 @@ -23,9 +23,11 @@ import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileProvisionType; import org.thingsboard.server.common.data.DeviceProfileType; import org.thingsboard.server.common.data.DeviceTransportType; +import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmSeverity; +import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration; @@ -177,4 +179,20 @@ public class EntityPrototypes { device.setType("DEFAULT"); return device; } + + public static Asset defaultAssetPrototype(String name, CustomerId id){ + Asset asset = new Asset(); + asset.setName(name + RandomStringUtils.randomAlphanumeric(7)); + asset.setCustomerId(id); + asset.setType("DEFAULT"); + return asset; + } + + public static EntityView defaultEntityViewPrototype(String name, String type, String entityType){ + EntityView entityView = new EntityView(); + entityView.setName(name + RandomStringUtils.randomAlphanumeric(7)); + entityView.setType(type + RandomStringUtils.randomAlphanumeric(7)); + entityView.setAdditionalInfo(JacksonUtil.newObjectNode().put("entityType", entityType)); + return entityView; + } } From dd9c055ecf423fad2080e2ca93bc66c62043e398 Mon Sep 17 00:00:00 2001 From: AndriiD Date: Fri, 14 Apr 2023 11:54:03 +0300 Subject: [PATCH 005/124] replace_ObjectMapper_usages_with_JacksonUtil --- .../server/actors/ActorSystemContext.java | 8 +- .../device/DeviceActorMessageProcessor.java | 2 +- .../actors/ruleChain/DefaultTbContext.java | 7 +- .../AbstractContextAwareMsgProcessor.java | 3 - .../server/actors/stats/StatsActor.java | 8 +- .../ThingsboardSecurityConfiguration.java | 9 +- .../server/controller/BaseController.java | 3 - .../server/controller/CustomerController.java | 5 +- .../server/controller/Lwm2mController.java | 7 +- .../controller/RuleChainController.java | 25 +++--- .../controller/SystemInfoController.java | 7 +- .../ThingsboardErrorResponseHandler.java | 33 ++++--- .../service/action/EntityActionService.java | 15 ++-- .../AnnotationComponentDiscoveryService.java | 10 +-- .../device/ClaimDevicesServiceImpl.java | 2 - .../service/install/DatabaseHelper.java | 9 +- .../DefaultSystemDataLoaderService.java | 9 +- .../service/install/InstallScripts.java | 22 ++--- .../rpc/DefaultTbCoreDeviceRpcService.java | 10 +-- .../jwt/RefreshTokenProcessingFilter.java | 8 +- .../oauth2/AbstractOAuth2ClientMapper.java | 6 +- .../auth/oauth2/CustomOAuth2ClientMapper.java | 16 +--- ...RestAwareAuthenticationSuccessHandler.java | 5 +- .../auth/rest/RestLoginProcessingFilter.java | 8 +- .../rest/RestPublicLoginProcessingFilter.java | 8 +- .../transport/DefaultTransportApiService.java | 9 +- .../service/update/DefaultUpdateService.java | 5 +- .../AbstractRuleEngineControllerTest.java | 5 +- .../server/controller/AbstractWebTest.java | 8 +- .../BaseRuleChainControllerTest.java | 3 +- .../controller/BaseUserControllerTest.java | 62 ++++++------- .../controller/BaseWebsocketApiTest.java | 16 ++-- .../BaseWidgetTypeControllerTest.java | 26 +++--- .../server/edge/AbstractEdgeTest.java | 4 +- .../server/edge/BaseDeviceEdgeTest.java | 6 +- .../server/edge/BaseRuleChainEdgeTest.java | 7 +- .../server/edge/BaseTelemetryEdgeTest.java | 12 +-- .../server/edge/BaseWidgetEdgeTest.java | 2 +- ...AbstractRuleEngineFlowIntegrationTest.java | 11 +-- ...actRuleEngineLifecycleIntegrationTest.java | 3 +- .../update/DefaultDataUpdateServiceTest.java | 18 ++-- .../notification/NotificationRuleApiTest.java | 2 +- .../sync/ie/BaseExportImportServiceTest.java | 8 +- .../lwm2m/AbstractLwM2MIntegrationTest.java | 4 +- .../mqtt/AbstractMqttIntegrationTest.java | 3 +- .../common/transport/util/JsonUtils.java | 2 - common/util/pom.xml | 8 ++ .../thingsboard/common/util/JacksonUtil.java | 48 ++++++++++ .../audit/sink/ElasticsearchAuditLogSink.java | 6 +- .../dao/customer/CustomerServiceImpl.java | 6 +- .../model/sql/AbstractEntityViewEntity.java | 12 ++- .../server/dao/model/sql/DashboardEntity.java | 13 ++- .../dao/model/sql/DashboardInfoEntity.java | 13 ++- .../server/dao/model/sql/QueueEntity.java | 12 ++- .../dao/sql/query/AlarmDataAdapter.java | 8 +- .../dao/user/UserSettingsServiceImpl.java | 5 +- .../dao/service/AbstractServiceTest.java | 8 +- .../BaseOAuth2ConfigTemplateServiceTest.java | 3 +- .../dao/service/BaseOAuth2ServiceTest.java | 3 +- .../dao/service/BaseRuleChainServiceTest.java | 29 +++--- .../service/BaseWidgetTypeServiceTest.java | 28 +++--- .../server/dao/sql/user/JpaUserDaoTest.java | 5 +- .../thingsboard/rest/client/RestClient.java | 10 +-- .../rule/engine/api/util/TbNodeUtils.java | 9 +- .../engine/action/TbAbstractAlarmNode.java | 5 +- .../rule/engine/action/TbCreateAlarmNode.java | 5 +- .../engine/filter/TbCheckAlarmStatusNode.java | 7 +- .../rule/engine/mail/TbMsgToEmailNode.java | 7 +- .../rule/engine/mail/TbSendEmailNode.java | 6 +- .../rule/engine/action/TbAlarmNodeTest.java | 33 +++---- .../action/TbCreateRelationNodeTest.java | 5 +- .../engine/filter/TbJsFilterNodeTest.java | 11 +-- .../engine/filter/TbJsSwitchNodeTest.java | 17 +--- .../engine/mail/TbMsgToEmailNodeTest.java | 7 +- .../metadata/AbstractAttributeNodeTest.java | 7 +- .../TbAbstractGetAttributesNodeTest.java | 5 +- .../TbFetchDeviceCredentialsNodeTest.java | 5 +- .../metadata/TbGetTelemetryNodeTest.java | 4 +- .../profile/TbDeviceProfileNodeTest.java | 90 +++++++++---------- .../engine/rest/TbRestApiCallNodeTest.java | 5 +- .../TbMsgDeleteAttributesNodeTest.java | 12 ++- .../transform/TbChangeOriginatorNodeTest.java | 5 +- .../engine/transform/TbCopyKeysNodeTest.java | 9 +- .../transform/TbDeleteKeysNodeTest.java | 9 +- .../engine/transform/TbJsonPathNodeTest.java | 11 +-- .../transform/TbSplitArrayMsgNodeTest.java | 5 +- .../transform/TbTransformMsgNodeTest.java | 12 +-- 87 files changed, 434 insertions(+), 535 deletions(-) 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 26eab30d5d..3422aef18b 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.actors; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -29,6 +28,7 @@ import org.springframework.context.annotation.Lazy; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.rule.engine.api.NotificationCenter; import org.thingsboard.rule.engine.api.SmsService; @@ -149,8 +149,6 @@ public class ActorSystemContext { } }; - protected final ObjectMapper mapper = new ObjectMapper(); - private final ConcurrentMap debugPerTenantLimits = new ConcurrentHashMap<>(); public ConcurrentMap getDebugPerTenantLimits() { @@ -641,7 +639,7 @@ public class ActorSystemContext { .dataType(tbMsg.getDataType().name()) .relationType(relationType) .data(tbMsg.getData()) - .metadata(mapper.writeValueAsString(tbMsg.getMetaData().getData())); + .metadata(JacksonUtil.toString(tbMsg.getMetaData().getData())); if (error != null) { event.error(toString(error)); @@ -651,7 +649,7 @@ public class ActorSystemContext { ListenableFuture future = eventService.saveAsync(event.build()); Futures.addCallback(future, RULE_NODE_DEBUG_EVENT_ERROR_CALLBACK, MoreExecutors.directExecutor()); - } catch (IOException ex) { + } catch (IllegalArgumentException ex) { log.warn("Failed to persist rule node debug message", ex); } } diff --git a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java index 0c3589a077..12885e1b69 100644 --- a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java @@ -816,7 +816,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso } private ListenableFuture saveRpcRequestToEdgeQueue(ToDeviceRpcRequest msg, Integer requestId) { - ObjectNode body = mapper.createObjectNode(); + ObjectNode body = JacksonUtil.newObjectNode(); body.put("requestId", requestId); body.put("requestUUID", msg.getId().toString()); body.put("oneway", msg.isOneway()); 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 59d633540e..8b76924d96 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 @@ -16,7 +16,6 @@ package org.thingsboard.server.actors.ruleChain; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.netty.channel.EventLoopGroup; @@ -121,8 +120,6 @@ import java.util.function.Consumer; @Slf4j class DefaultTbContext implements TbContext { - public final static ObjectMapper mapper = new ObjectMapper(); - private final ActorSystemContext mainCtx; private final String ruleChainName; private final RuleNodeCtx nodeCtx; @@ -422,8 +419,8 @@ class DefaultTbContext implements TbContext { public TbMsg entityActionMsg(E entity, I id, RuleNodeId ruleNodeId, String action, K profile) { try { - return entityActionMsg(id, getActionMetaData(ruleNodeId), mapper.writeValueAsString(mapper.valueToTree(entity)), action, profile); - } catch (JsonProcessingException | IllegalArgumentException e) { + return entityActionMsg(id, getActionMetaData(ruleNodeId), JacksonUtil.toString(JacksonUtil.valueToTree(entity)), action, profile); + } catch (IllegalArgumentException e) { throw new RuntimeException("Failed to process " + id.getEntityType().name().toLowerCase() + " " + action + " msg: " + e); } } diff --git a/application/src/main/java/org/thingsboard/server/actors/shared/AbstractContextAwareMsgProcessor.java b/application/src/main/java/org/thingsboard/server/actors/shared/AbstractContextAwareMsgProcessor.java index e0c11102bf..395b8a24d0 100644 --- a/application/src/main/java/org/thingsboard/server/actors/shared/AbstractContextAwareMsgProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/shared/AbstractContextAwareMsgProcessor.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.actors.shared; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.actors.ActorSystemContext; import org.thingsboard.server.actors.TbActorCtx; @@ -26,8 +25,6 @@ import java.util.concurrent.ScheduledExecutorService; @Slf4j public abstract class AbstractContextAwareMsgProcessor { - protected final static ObjectMapper mapper = new ObjectMapper(); - protected final ActorSystemContext systemContext; protected AbstractContextAwareMsgProcessor(ActorSystemContext systemContext) { diff --git a/application/src/main/java/org/thingsboard/server/actors/stats/StatsActor.java b/application/src/main/java/org/thingsboard/server/actors/stats/StatsActor.java index 8ad347bfd0..ed0892f772 100644 --- a/application/src/main/java/org/thingsboard/server/actors/stats/StatsActor.java +++ b/application/src/main/java/org/thingsboard/server/actors/stats/StatsActor.java @@ -16,16 +16,14 @@ package org.thingsboard.server.actors.stats; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.actors.ActorSystemContext; import org.thingsboard.server.actors.TbActor; import org.thingsboard.server.actors.TbActorId; import org.thingsboard.server.actors.TbStringActorId; import org.thingsboard.server.actors.service.ContextAwareActor; import org.thingsboard.server.actors.service.ContextBasedCreator; -import org.thingsboard.server.common.data.DataConstants; -import org.thingsboard.server.common.data.EventInfo; import org.thingsboard.server.common.data.event.StatisticsEvent; import org.thingsboard.server.common.msg.MsgType; import org.thingsboard.server.common.msg.TbActorMsg; @@ -33,8 +31,6 @@ import org.thingsboard.server.common.msg.TbActorMsg; @Slf4j public class StatsActor extends ContextAwareActor { - private final ObjectMapper mapper = new ObjectMapper(); - public StatsActor(ActorSystemContext context) { super(context); } @@ -65,7 +61,7 @@ public class StatsActor extends ContextAwareActor { } private JsonNode toBodyJson(String serviceId, long messagesProcessed, long errorsOccurred) { - return mapper.createObjectNode().put("server", serviceId).put("messagesProcessed", messagesProcessed).put("errorsOccurred", errorsOccurred); + return JacksonUtil.newObjectNode().put("server", serviceId).put("messagesProcessed", messagesProcessed).put("errorsOccurred", errorsOccurred); } public static class ActorCreator extends ContextBasedCreator { diff --git a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java index 9405d2da84..a418dc268b 100644 --- a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.config; -import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -116,20 +115,18 @@ public class ThingsboardSecurityConfiguration { @Autowired private AuthenticationManager authenticationManager; - @Autowired private ObjectMapper objectMapper; - @Autowired private RateLimitProcessingFilter rateLimitProcessingFilter; @Bean protected RestLoginProcessingFilter buildRestLoginProcessingFilter() throws Exception { - RestLoginProcessingFilter filter = new RestLoginProcessingFilter(FORM_BASED_LOGIN_ENTRY_POINT, successHandler, failureHandler, objectMapper); + RestLoginProcessingFilter filter = new RestLoginProcessingFilter(FORM_BASED_LOGIN_ENTRY_POINT, successHandler, failureHandler); filter.setAuthenticationManager(this.authenticationManager); return filter; } @Bean protected RestPublicLoginProcessingFilter buildRestPublicLoginProcessingFilter() throws Exception { - RestPublicLoginProcessingFilter filter = new RestPublicLoginProcessingFilter(PUBLIC_LOGIN_ENTRY_POINT, successHandler, failureHandler, objectMapper); + RestPublicLoginProcessingFilter filter = new RestPublicLoginProcessingFilter(PUBLIC_LOGIN_ENTRY_POINT, successHandler, failureHandler); filter.setAuthenticationManager(this.authenticationManager); return filter; } @@ -147,7 +144,7 @@ public class ThingsboardSecurityConfiguration { @Bean protected RefreshTokenProcessingFilter buildRefreshTokenProcessingFilter() throws Exception { - RefreshTokenProcessingFilter filter = new RefreshTokenProcessingFilter(TOKEN_REFRESH_ENTRY_POINT, successHandler, failureHandler, objectMapper); + RefreshTokenProcessingFilter filter = new RefreshTokenProcessingFilter(TOKEN_REFRESH_ENTRY_POINT, successHandler, failureHandler); filter.setAuthenticationManager(this.authenticationManager); return filter; } diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 34f065d500..04bda8f039 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.controller; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @@ -184,8 +183,6 @@ public abstract class BaseController { /*Swagger UI description*/ - private static final ObjectMapper json = new ObjectMapper(); - @Autowired private ThingsboardErrorResponseHandler errorResponseHandler; diff --git a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java index 8156c72a41..dd904add2e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java +++ b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java @@ -16,7 +16,6 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; @@ -31,6 +30,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.CustomerId; @@ -100,8 +100,7 @@ public class CustomerController extends BaseController { checkParameter(CUSTOMER_ID, strCustomerId); CustomerId customerId = new CustomerId(toUUID(strCustomerId)); Customer customer = checkCustomerId(customerId, Operation.READ); - ObjectMapper objectMapper = new ObjectMapper(); - ObjectNode infoObject = objectMapper.createObjectNode(); + ObjectNode infoObject = JacksonUtil.newObjectNode(); infoObject.put("title", customer.getTitle()); infoObject.put(IS_PUBLIC, customer.isPublic()); return infoObject; diff --git a/application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java b/application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java index ae1dec43fe..8949cd95dd 100644 --- a/application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java +++ b/application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.controller; -import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import lombok.extern.slf4j.Slf4j; @@ -28,6 +27,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest; import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.LwM2MServerSecurityConfigDefault; @@ -72,9 +72,8 @@ public class Lwm2mController extends BaseController { @RequestMapping(value = "/lwm2m/device-credentials", method = RequestMethod.POST) @ResponseBody public Device saveDeviceWithCredentials(@RequestBody Map, Object> deviceWithDeviceCredentials) throws ThingsboardException { - ObjectMapper mapper = new ObjectMapper(); - Device device = checkNotNull(mapper.convertValue(deviceWithDeviceCredentials.get(Device.class), Device.class)); - DeviceCredentials credentials = checkNotNull(mapper.convertValue(deviceWithDeviceCredentials.get(DeviceCredentials.class), DeviceCredentials.class)); + Device device = checkNotNull(JacksonUtil.convertValue(deviceWithDeviceCredentials.get(Device.class), Device.class)); + DeviceCredentials credentials = checkNotNull(JacksonUtil.convertValue(deviceWithDeviceCredentials.get(DeviceCredentials.class), DeviceCredentials.class)); return deviceController.saveDeviceWithCredentials(new SaveDeviceWithCredentialsRequest(device, credentials)); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java index 81cf8be9fa..ce6a98500d 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java +++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java @@ -18,7 +18,6 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.annotations.ApiOperation; @@ -37,6 +36,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.ScriptEngine; import org.thingsboard.script.api.js.JsInvokeService; import org.thingsboard.script.api.tbel.TbelInvokeService; @@ -115,7 +115,6 @@ public class RuleChainController extends BaseController { private static final int DEFAULT_PAGE_SIZE = 1000; - private static final ObjectMapper objectMapper = new ObjectMapper(); public static final int TIMEOUT = 20; private static final String RULE_CHAIN_DESCRIPTION = "The rule chain object is lightweight and contains general information about the rule chain. " + @@ -377,11 +376,11 @@ public class RuleChainController extends BaseController { String script = inputParams.get("script").asText(); String scriptType = inputParams.get("scriptType").asText(); JsonNode argNamesJson = inputParams.get("argNames"); - String[] argNames = objectMapper.treeToValue(argNamesJson, String[].class); + String[] argNames = JacksonUtil.treeToValue(argNamesJson, String[].class); String data = inputParams.get("msg").asText(); JsonNode metadataJson = inputParams.get("metadata"); - Map metadata = objectMapper.convertValue(metadataJson, new TypeReference>() { + Map metadata = JacksonUtil.convertValue(metadataJson, new TypeReference>() { }); String msgType = inputParams.get("msgType").asText(); String output = ""; @@ -413,11 +412,11 @@ public class RuleChainController extends BaseController { break; case "switch": Set states = engine.executeSwitchAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS); - output = objectMapper.writeValueAsString(states); + output = JacksonUtil.toString(states); break; case "json": JsonNode json = engine.executeJsonAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS); - output = objectMapper.writeValueAsString(json); + output = JacksonUtil.toString(json); break; case "string": output = engine.executeToStringAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS); @@ -433,7 +432,7 @@ public class RuleChainController extends BaseController { engine.destroy(); } } - ObjectNode result = objectMapper.createObjectNode(); + ObjectNode result = JacksonUtil.newObjectNode(); result.put("output", output); result.put("error", errorText); return result; @@ -473,13 +472,13 @@ public class RuleChainController extends BaseController { private String msgToOutput(TbMsg msg) throws Exception { JsonNode resultNode = convertMsgToOut(msg); - return objectMapper.writeValueAsString(resultNode); + return JacksonUtil.toString(resultNode); } private String msgToOutput(List msgs) throws Exception { JsonNode resultNode; if (msgs.size() > 1) { - resultNode = objectMapper.createArrayNode(); + resultNode = JacksonUtil.OBJECT_MAPPER.createArrayNode(); for (TbMsg msg : msgs) { JsonNode convertedData = convertMsgToOut(msg); ((ArrayNode) resultNode).add(convertedData); @@ -487,16 +486,16 @@ public class RuleChainController extends BaseController { } else { resultNode = convertMsgToOut(msgs.get(0)); } - return objectMapper.writeValueAsString(resultNode); + return JacksonUtil.toString(resultNode); } private JsonNode convertMsgToOut(TbMsg msg) throws Exception { - ObjectNode msgData = objectMapper.createObjectNode(); + ObjectNode msgData = JacksonUtil.newObjectNode(); if (!StringUtils.isEmpty(msg.getData())) { - msgData.set("msg", objectMapper.readTree(msg.getData())); + msgData.set("msg", JacksonUtil.valueToTree(msg.getData())); } Map metadata = msg.getMetaData().getData(); - msgData.set("metadata", objectMapper.valueToTree(metadata)); + msgData.set("metadata", JacksonUtil.valueToTree(metadata)); msgData.put("msgType", msg.getType()); return msgData; } diff --git a/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java b/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java index 19195c7681..9dd88627dc 100644 --- a/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java +++ b/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java @@ -16,10 +16,7 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.info.BuildProperties; @@ -28,6 +25,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.queue.util.TbCoreComponent; import springfox.documentation.annotations.ApiIgnore; @@ -57,8 +55,7 @@ public class SystemInfoController { } private JsonNode buildInfoObject() { - ObjectMapper objectMapper = new ObjectMapper(); - ObjectNode infoObject = objectMapper.createObjectNode(); + ObjectNode infoObject = JacksonUtil.newObjectNode(); if (buildProperties != null) { infoObject.put("version", buildProperties.getVersion()); infoObject.put("artifact", buildProperties.getArtifact()); diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java index 5f22786907..ed641c2d4f 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.exception; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; @@ -36,6 +35,7 @@ import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import org.springframework.web.util.WebUtils; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.msg.tools.TbRateLimitsException; @@ -90,9 +90,6 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand return errorCodeToStatusMap.getOrDefault(errorCode, HttpStatus.INTERNAL_SERVER_ERROR); } - @Autowired - private ObjectMapper mapper; - @Override @ExceptionHandler(AccessDeniedException.class) public void handle(HttpServletRequest request, HttpServletResponse response, @@ -101,7 +98,7 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand if (!response.isCommitted()) { response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setStatus(HttpStatus.FORBIDDEN.value()); - mapper.writeValue(response.getWriter(), + JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("You don't have permission to perform this operation!", ThingsboardErrorCode.PERMISSION_DENIED, HttpStatus.FORBIDDEN)); } @@ -129,7 +126,7 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand handleAuthenticationException((AuthenticationException) exception, response); } else { response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); - mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of(exception.getMessage(), + JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of(exception.getMessage(), ThingsboardErrorCode.GENERAL, HttpStatus.INTERNAL_SERVER_ERROR)); } } catch (IOException e) { @@ -154,26 +151,26 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand ThingsboardErrorCode errorCode = thingsboardException.getErrorCode(); HttpStatus status = errorCodeToStatus(errorCode); response.setStatus(status.value()); - mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of(thingsboardException.getMessage(), errorCode, status)); + JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of(thingsboardException.getMessage(), errorCode, status)); } private void handleRateLimitException(HttpServletResponse response, TbRateLimitsException exception) throws IOException { response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value()); String message = "Too many requests for current " + exception.getEntityType().name().toLowerCase() + "!"; - mapper.writeValue(response.getWriter(), + JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of(message, ThingsboardErrorCode.TOO_MANY_REQUESTS, HttpStatus.TOO_MANY_REQUESTS)); } private void handleSubscriptionException(ThingsboardException subscriptionException, HttpServletResponse response) throws IOException { response.setStatus(HttpStatus.FORBIDDEN.value()); - mapper.writeValue(response.getWriter(), - (new ObjectMapper()).readValue(((HttpClientErrorException) subscriptionException.getCause()).getResponseBodyAsByteArray(), Object.class)); + JacksonUtil.writeValue(response.getWriter(), + JacksonUtil.fromBytes(((HttpClientErrorException) subscriptionException.getCause()).getResponseBodyAsByteArray(), Object.class)); } private void handleAccessDeniedException(HttpServletResponse response) throws IOException { response.setStatus(HttpStatus.FORBIDDEN.value()); - mapper.writeValue(response.getWriter(), + JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("You don't have permission to perform this operation!", ThingsboardErrorCode.PERMISSION_DENIED, HttpStatus.FORBIDDEN)); @@ -182,21 +179,21 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand private void handleAuthenticationException(AuthenticationException authenticationException, HttpServletResponse response) throws IOException { response.setStatus(HttpStatus.UNAUTHORIZED.value()); if (authenticationException instanceof BadCredentialsException || authenticationException instanceof UsernameNotFoundException) { - mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of("Invalid username or password", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); + JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("Invalid username or password", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); } else if (authenticationException instanceof DisabledException) { - mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of("User account is not active", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); + JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("User account is not active", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); } else if (authenticationException instanceof LockedException) { - mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of("User account is locked due to security policy", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); + JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("User account is locked due to security policy", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); } else if (authenticationException instanceof JwtExpiredTokenException) { - mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of("Token has expired", ThingsboardErrorCode.JWT_TOKEN_EXPIRED, HttpStatus.UNAUTHORIZED)); + JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("Token has expired", ThingsboardErrorCode.JWT_TOKEN_EXPIRED, HttpStatus.UNAUTHORIZED)); } else if (authenticationException instanceof AuthMethodNotSupportedException) { - mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of(authenticationException.getMessage(), ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); + JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of(authenticationException.getMessage(), ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); } else if (authenticationException instanceof UserPasswordExpiredException) { UserPasswordExpiredException expiredException = (UserPasswordExpiredException) authenticationException; String resetToken = expiredException.getResetToken(); - mapper.writeValue(response.getWriter(), ThingsboardCredentialsExpiredResponse.of(expiredException.getMessage(), resetToken)); + JacksonUtil.writeValue(response.getWriter(), ThingsboardCredentialsExpiredResponse.of(expiredException.getMessage(), resetToken)); } else { - mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); + JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); } } diff --git a/application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java b/application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java index d39e200337..e25fa7d314 100644 --- a/application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java +++ b/application/src/main/java/org/thingsboard/server/service/action/EntityActionService.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.service.action; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.RequiredArgsConstructor; @@ -54,8 +53,6 @@ public class EntityActionService { private final TbClusterService tbClusterService; private final AuditLogService auditLogService; - private static final ObjectMapper json = new ObjectMapper(); - public void pushEntityActionToRuleEngine(EntityId entityId, HasName entity, TenantId tenantId, CustomerId customerId, ActionType actionType, User user, Object... additionalInfo) { String msgType = null; @@ -185,18 +182,18 @@ public class EntityActionService { metaData.putValue("unassignedEdgeName", strEdgeName); } else if (actionType == ActionType.ADDED_COMMENT || actionType == ActionType.UPDATED_COMMENT) { AlarmComment comment = extractParameter(AlarmComment.class, 0, additionalInfo); - metaData.putValue("comment", json.writeValueAsString(comment)); + metaData.putValue("comment", JacksonUtil.toString(comment)); } ObjectNode entityNode; if (entity != null) { - entityNode = json.valueToTree(entity); + entityNode = JacksonUtil.OBJECT_MAPPER.valueToTree(entity); if (entityId.getEntityType() == EntityType.DASHBOARD) { entityNode.put("configuration", ""); } metaData.putValue("entityName", entity.getName()); metaData.putValue("entityType", entityId.getEntityType().toString()); } else { - entityNode = json.createObjectNode(); + entityNode = JacksonUtil.newObjectNode(); if (actionType == ActionType.ATTRIBUTES_UPDATED) { String scope = extractParameter(String.class, 0, additionalInfo); @SuppressWarnings("unchecked") @@ -230,10 +227,10 @@ public class EntityActionService { entityNode.put("startTs", extractParameter(Long.class, 1, additionalInfo)); entityNode.put("endTs", extractParameter(Long.class, 2, additionalInfo)); } else if (ActionType.RELATION_ADD_OR_UPDATE.equals(actionType) || ActionType.RELATION_DELETED.equals(actionType)) { - entityNode = json.valueToTree(extractParameter(EntityRelation.class, 0, additionalInfo)); + entityNode = JacksonUtil.OBJECT_MAPPER.valueToTree(extractParameter(EntityRelation.class, 0, additionalInfo)); } } - TbMsg tbMsg = TbMsg.newMsg(msgType, entityId, customerId, metaData, TbMsgDataType.JSON, json.writeValueAsString(entityNode)); + TbMsg tbMsg = TbMsg.newMsg(msgType, entityId, customerId, metaData, TbMsgDataType.JSON, JacksonUtil.toString(entityNode)); if (tenantId == null || tenantId.isNullUid()) { if (entity instanceof HasTenantId) { tenantId = ((HasTenantId) entity).getTenantId(); @@ -278,7 +275,7 @@ public class EntityActionService { Map> groupedTelemetry = timeseries.stream() .collect(Collectors.groupingBy(TsKvEntry::getTs)); for (Map.Entry> entry : groupedTelemetry.entrySet()) { - ObjectNode element = json.createObjectNode(); + ObjectNode element = JacksonUtil.newObjectNode(); element.put("ts", entry.getKey()); ObjectNode values = element.putObject("values"); for (TsKvEntry tsKvEntry : entry.getValue()) { diff --git a/application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java b/application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java index 732d8ce409..a4e510bb04 100644 --- a/application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java +++ b/application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java @@ -16,7 +16,6 @@ package org.thingsboard.server.service.component; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -27,6 +26,7 @@ import org.springframework.core.env.Environment; import org.springframework.core.env.Profiles; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.stereotype.Service; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.NodeConfiguration; import org.thingsboard.rule.engine.api.NodeDefinition; import org.thingsboard.rule.engine.api.RuleNode; @@ -69,8 +69,6 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe private Map> edgeComponentsMap = new HashMap<>(); - private ObjectMapper mapper = new ObjectMapper(); - private boolean isInstall() { return environment.acceptsProfiles(Profiles.of("install")); } @@ -156,8 +154,8 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe scannedComponent.setName(ruleNodeAnnotation.name()); scannedComponent.setScope(ruleNodeAnnotation.scope()); NodeDefinition nodeDefinition = prepareNodeDefinition(ruleNodeAnnotation); - ObjectNode configurationDescriptor = mapper.createObjectNode(); - JsonNode node = mapper.valueToTree(nodeDefinition); + ObjectNode configurationDescriptor = JacksonUtil.newObjectNode(); + JsonNode node = JacksonUtil.valueToTree(nodeDefinition); configurationDescriptor.set("nodeDefinition", node); scannedComponent.setConfigurationDescriptor(configurationDescriptor); scannedComponent.setClazz(clazzName); @@ -194,7 +192,7 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe Class configClazz = nodeAnnotation.configClazz(); NodeConfiguration config = configClazz.getDeclaredConstructor().newInstance(); NodeConfiguration defaultConfiguration = config.defaultConfiguration(); - nodeDefinition.setDefaultConfiguration(mapper.valueToTree(defaultConfiguration)); + nodeDefinition.setDefaultConfiguration(JacksonUtil.valueToTree(defaultConfiguration)); nodeDefinition.setUiResources(nodeAnnotation.uiResources()); nodeDefinition.setConfigDirective(nodeAnnotation.configDirective()); nodeDefinition.setIcon(nodeAnnotation.icon()); diff --git a/application/src/main/java/org/thingsboard/server/service/device/ClaimDevicesServiceImpl.java b/application/src/main/java/org/thingsboard/server/service/device/ClaimDevicesServiceImpl.java index a0e6545652..49beda20ee 100644 --- a/application/src/main/java/org/thingsboard/server/service/device/ClaimDevicesServiceImpl.java +++ b/application/src/main/java/org/thingsboard/server/service/device/ClaimDevicesServiceImpl.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.service.device; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -67,7 +66,6 @@ public class ClaimDevicesServiceImpl implements ClaimDevicesService { private static final String CLAIM_ATTRIBUTE_NAME = "claimingAllowed"; private static final String CLAIM_DATA_ATTRIBUTE_NAME = "claimingData"; - private static final ObjectMapper mapper = new ObjectMapper(); @Autowired private TbClusterService clusterService; diff --git a/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java b/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java index 70f161d2e2..97b87c7412 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DatabaseHelper.java @@ -16,10 +16,10 @@ package org.thingsboard.server.service.install; import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.ShortCustomerInfo; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.UUIDConverter; @@ -67,11 +67,10 @@ public class DatabaseHelper { public static final String ASSIGNED_CUSTOMERS = "assigned_customers"; public static final String CONFIGURATION = "configuration"; - public static final ObjectMapper objectMapper = new ObjectMapper(); public static void upgradeTo40_assignDashboards(Path dashboardsDump, DashboardService dashboardService, boolean sql) throws Exception { JavaType assignedCustomersType = - objectMapper.getTypeFactory().constructCollectionType(HashSet.class, ShortCustomerInfo.class); + JacksonUtil.constructCollectionType(HashSet.class, ShortCustomerInfo.class); try (CSVParser csvParser = new CSVParser(Files.newBufferedReader(dashboardsDump), CSV_DUMP_FORMAT.withFirstRecordAsHeader())) { csvParser.forEach(record -> { String customerIdString = record.get(CUSTOMER_ID); @@ -80,14 +79,14 @@ public class DatabaseHelper { List customerIds = new ArrayList<>(); if (!StringUtils.isEmpty(assignedCustomersString)) { try { - Set assignedCustomers = objectMapper.readValue(assignedCustomersString, assignedCustomersType); + Set assignedCustomers = JacksonUtil.fromString(assignedCustomersString, assignedCustomersType); assignedCustomers.forEach((customerInfo) -> { CustomerId customerId = customerInfo.getCustomerId(); if (!customerId.isNullUid()) { customerIds.add(customerId); } }); - } catch (IOException e) { + } catch (IllegalArgumentException e) { log.error("Unable to parse assigned customers field", e); } } diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java index bd68aad316..9f6793a123 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.service.install; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @@ -29,6 +28,7 @@ import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Profile; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.Customer; @@ -116,7 +116,6 @@ import java.util.concurrent.Executors; @Slf4j public class DefaultSystemDataLoaderService implements SystemDataLoaderService { - private static final ObjectMapper objectMapper = new ObjectMapper(); public static final String CUSTOMER_CRED = "customer"; public static final String DEFAULT_DEVICE_TYPE = "default"; public static final String ACTIVITY_STATE = "active"; @@ -251,7 +250,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { AdminSettings generalSettings = new AdminSettings(); generalSettings.setTenantId(TenantId.SYS_TENANT_ID); generalSettings.setKey("general"); - ObjectNode node = objectMapper.createObjectNode(); + ObjectNode node = JacksonUtil.newObjectNode(); node.put("baseUrl", "http://localhost:8080"); node.put("prohibitDifferentUrl", false); generalSettings.setJsonValue(node); @@ -260,7 +259,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { AdminSettings mailSettings = new AdminSettings(); mailSettings.setTenantId(TenantId.SYS_TENANT_ID); mailSettings.setKey("mail"); - node = objectMapper.createObjectNode(); + node = JacksonUtil.newObjectNode(); node.put("mailFrom", "ThingsBoard "); node.put("smtpProtocol", "smtp"); node.put("smtpHost", "localhost"); @@ -542,7 +541,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { device.setDeviceProfileId(deviceProfileId); device.setName(name); if (description != null) { - ObjectNode additionalInfo = objectMapper.createObjectNode(); + ObjectNode additionalInfo = JacksonUtil.newObjectNode(); additionalInfo.put("description", description); device.setAdditionalInfo(additionalInfo); } diff --git a/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java b/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java index 5ab7324192..9a810aa446 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java +++ b/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java @@ -20,6 +20,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.ResourceType; import org.thingsboard.server.common.data.StringUtils; @@ -48,7 +49,6 @@ import java.nio.file.Paths; import java.util.Base64; import java.util.Optional; -import static org.thingsboard.server.service.install.DatabaseHelper.objectMapper; import static org.thingsboard.server.utils.LwM2mObjectModelUtils.toLwm2mResource; /** @@ -162,9 +162,9 @@ public class InstallScripts { } public RuleChain createRuleChainFromFile(TenantId tenantId, Path templateFilePath, String newRuleChainName) throws IOException { - JsonNode ruleChainJson = objectMapper.readTree(templateFilePath.toFile()); - RuleChain ruleChain = objectMapper.treeToValue(ruleChainJson.get("ruleChain"), RuleChain.class); - RuleChainMetaData ruleChainMetaData = objectMapper.treeToValue(ruleChainJson.get("metadata"), RuleChainMetaData.class); + JsonNode ruleChainJson = JacksonUtil.toJsonNode(templateFilePath.toFile()); + RuleChain ruleChain = JacksonUtil.treeToValue(ruleChainJson.get("ruleChain"), RuleChain.class); + RuleChainMetaData ruleChainMetaData = JacksonUtil.treeToValue(ruleChainJson.get("metadata"), RuleChainMetaData.class); ruleChain.setTenantId(tenantId); if (!StringUtils.isEmpty(newRuleChainName)) { @@ -184,15 +184,15 @@ public class InstallScripts { dirStream.forEach( path -> { try { - JsonNode widgetsBundleDescriptorJson = objectMapper.readTree(path.toFile()); + JsonNode widgetsBundleDescriptorJson = JacksonUtil.toJsonNode(path.toFile()); JsonNode widgetsBundleJson = widgetsBundleDescriptorJson.get("widgetsBundle"); - WidgetsBundle widgetsBundle = objectMapper.treeToValue(widgetsBundleJson, WidgetsBundle.class); + WidgetsBundle widgetsBundle = JacksonUtil.treeToValue(widgetsBundleJson, WidgetsBundle.class); WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle); JsonNode widgetTypesArrayJson = widgetsBundleDescriptorJson.get("widgetTypes"); widgetTypesArrayJson.forEach( widgetTypeJson -> { try { - WidgetTypeDetails widgetTypeDetails = objectMapper.treeToValue(widgetTypeJson, WidgetTypeDetails.class); + WidgetTypeDetails widgetTypeDetails = JacksonUtil.treeToValue(widgetTypeJson, WidgetTypeDetails.class); widgetTypeDetails.setBundleAlias(savedWidgetsBundle.getAlias()); widgetTypeService.saveWidgetType(widgetTypeDetails); } catch (Exception e) { @@ -216,8 +216,8 @@ public class InstallScripts { dirStream.forEach( path -> { try { - JsonNode dashboardJson = objectMapper.readTree(path.toFile()); - Dashboard dashboard = objectMapper.treeToValue(dashboardJson, Dashboard.class); + JsonNode dashboardJson = JacksonUtil.toJsonNode(path.toFile()); + Dashboard dashboard = JacksonUtil.treeToValue(dashboardJson, Dashboard.class); dashboard.setTenantId(tenantId); Dashboard savedDashboard = dashboardService.saveDashboard(dashboard); if (customerId != null && !customerId.isNullUid()) { @@ -249,8 +249,8 @@ public class InstallScripts { dirStream.forEach( path -> { try { - JsonNode oauth2ConfigTemplateJson = objectMapper.readTree(path.toFile()); - OAuth2ClientRegistrationTemplate clientRegistrationTemplate = objectMapper.treeToValue(oauth2ConfigTemplateJson, OAuth2ClientRegistrationTemplate.class); + JsonNode oauth2ConfigTemplateJson = JacksonUtil.toJsonNode(path.toFile()); + OAuth2ClientRegistrationTemplate clientRegistrationTemplate = JacksonUtil.treeToValue(oauth2ConfigTemplateJson, OAuth2ClientRegistrationTemplate.class); Optional existingClientRegistrationTemplate = oAuth2TemplateService.findClientRegistrationTemplateByProviderId(clientRegistrationTemplate.getProviderId()); if (existingClientRegistrationTemplate.isPresent()) { diff --git a/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbCoreDeviceRpcService.java b/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbCoreDeviceRpcService.java index 4302854715..bca7c7d81a 100644 --- a/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbCoreDeviceRpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbCoreDeviceRpcService.java @@ -16,11 +16,11 @@ package org.thingsboard.server.service.rpc; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; 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.actors.ActorSystemContext; import org.thingsboard.server.cluster.TbClusterService; @@ -57,8 +57,6 @@ import java.util.function.Consumer; @TbCoreComponent public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService { - private static final ObjectMapper json = new ObjectMapper(); - private final DeviceService deviceService; private final TbClusterService clusterService; private final TbServiceInfoProvider serviceInfoProvider; @@ -159,7 +157,7 @@ public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService { } private void sendRpcRequestToRuleEngine(ToDeviceRpcRequest msg, SecurityUser currentUser) { - ObjectNode entityNode = json.createObjectNode(); + ObjectNode entityNode = JacksonUtil.newObjectNode(); TbMsgMetaData metaData = new TbMsgMetaData(); metaData.putValue("requestUUID", msg.getId().toString()); metaData.putValue("originServiceId", serviceId); @@ -184,9 +182,9 @@ public class DefaultTbCoreDeviceRpcService implements TbCoreDeviceRpcService { entityNode.put(DataConstants.ADDITIONAL_INFO, msg.getAdditionalInfo()); try { - TbMsg tbMsg = TbMsg.newMsg(DataConstants.RPC_CALL_FROM_SERVER_TO_DEVICE, msg.getDeviceId(), Optional.ofNullable(currentUser).map(User::getCustomerId).orElse(null), metaData, TbMsgDataType.JSON, json.writeValueAsString(entityNode)); + TbMsg tbMsg = TbMsg.newMsg(DataConstants.RPC_CALL_FROM_SERVER_TO_DEVICE, msg.getDeviceId(), Optional.ofNullable(currentUser).map(User::getCustomerId).orElse(null), metaData, TbMsgDataType.JSON, JacksonUtil.toString(entityNode)); clusterService.pushMsgToRuleEngine(msg.getTenantId(), msg.getDeviceId(), tbMsg, null); - } catch (JsonProcessingException e) { + } catch (IllegalArgumentException e) { throw new RuntimeException(e); } } diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/RefreshTokenProcessingFilter.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/RefreshTokenProcessingFilter.java index 5bf29acc75..66c206a7ad 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/RefreshTokenProcessingFilter.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/RefreshTokenProcessingFilter.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.service.security.auth.jwt; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationServiceException; @@ -25,6 +24,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.service.security.auth.RefreshAuthenticationToken; import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedException; @@ -42,14 +42,12 @@ public class RefreshTokenProcessingFilter extends AbstractAuthenticationProcessi private final AuthenticationSuccessHandler successHandler; private final AuthenticationFailureHandler failureHandler; - private final ObjectMapper objectMapper; public RefreshTokenProcessingFilter(String defaultProcessUrl, AuthenticationSuccessHandler successHandler, - AuthenticationFailureHandler failureHandler, ObjectMapper mapper) { + AuthenticationFailureHandler failureHandler) { super(defaultProcessUrl); this.successHandler = successHandler; this.failureHandler = failureHandler; - this.objectMapper = mapper; } @Override @@ -64,7 +62,7 @@ public class RefreshTokenProcessingFilter extends AbstractAuthenticationProcessi RefreshTokenRequest refreshTokenRequest; try { - refreshTokenRequest = objectMapper.readValue(request.getReader(), RefreshTokenRequest.class); + refreshTokenRequest = JacksonUtil.fromReader(request.getReader(), RefreshTokenRequest.class); } catch (Exception e) { throw new AuthenticationServiceException("Invalid refresh token request payload"); } diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java index d27a4ecc83..429f6a1e8c 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.service.security.auth.oauth2; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -24,6 +23,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.DashboardInfo; @@ -62,8 +62,6 @@ import java.util.concurrent.locks.ReentrantLock; public abstract class AbstractOAuth2ClientMapper { private static final int DASHBOARDS_REQUEST_LIMIT = 10; - private static final ObjectMapper objectMapper = new ObjectMapper(); - @Autowired private UserService userService; @@ -130,7 +128,7 @@ public abstract class AbstractOAuth2ClientMapper { user.setFirstName(oauth2User.getFirstName()); user.setLastName(oauth2User.getLastName()); - ObjectNode additionalInfo = objectMapper.createObjectNode(); + ObjectNode additionalInfo = JacksonUtil.newObjectNode(); if (!StringUtils.isEmpty(oauth2User.getDefaultDashboardName())) { Optional dashboardIdOpt = diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java index bc971e6104..9cac9b87a0 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java @@ -16,13 +16,12 @@ package org.thingsboard.server.service.security.auth.oauth2; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig; import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; @@ -31,7 +30,6 @@ import org.thingsboard.server.dao.oauth2.OAuth2User; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; -import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; @Service(value = "customOAuth2ClientMapper") @@ -40,19 +38,9 @@ import javax.servlet.http.HttpServletRequest; public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper implements OAuth2ClientMapper { private static final String PROVIDER_ACCESS_TOKEN = "provider-access-token"; - private static final ObjectMapper json = new ObjectMapper(); private RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder(); - @PostConstruct - public void init() { - // Register time module to parse Instant objects. - // com.fasterxml.jackson.databind.exc.InvalidDefinitionException: - // Java 8 date/time type `java.time.Instant` not supported by default: - // add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling - json.registerModule(new JavaTimeModule()); - } - @Override public SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Registration registration) { OAuth2MapperConfig config = registration.getMapperConfig(); @@ -71,7 +59,7 @@ public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme RestTemplate restTemplate = restTemplateBuilder.build(); String request; try { - request = json.writeValueAsString(token.getPrincipal()); + request = JacksonUtil.getObjectMapperWithJavaTimeModule().writeValueAsString(token.getPrincipal()); } catch (JsonProcessingException e) { log.error("Can't convert principal to JSON string", e); throw new RuntimeException("Can't convert principal to JSON string", e); diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationSuccessHandler.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationSuccessHandler.java index 90722d3c08..3546ada53e 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationSuccessHandler.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationSuccessHandler.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.service.security.auth.rest; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -23,6 +22,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.web.WebAttributes; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.stereotype.Component; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.service.security.auth.MfaAuthenticationToken; import org.thingsboard.server.service.security.auth.mfa.config.TwoFaConfigManager; @@ -41,7 +41,6 @@ import java.util.concurrent.TimeUnit; @Component(value = "defaultAuthenticationSuccessHandler") @RequiredArgsConstructor public class RestAwareAuthenticationSuccessHandler implements AuthenticationSuccessHandler { - private final ObjectMapper mapper; private final JwtTokenFactory tokenFactory; private final TwoFaConfigManager twoFaConfigManager; @@ -65,7 +64,7 @@ public class RestAwareAuthenticationSuccessHandler implements AuthenticationSucc response.setStatus(HttpStatus.OK.value()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); - mapper.writeValue(response.getWriter(), tokenPair); + JacksonUtil.writeValue(response.getWriter(), tokenPair); clearAuthenticationAttributes(request); } diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestLoginProcessingFilter.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestLoginProcessingFilter.java index 5e0118a6ad..b3ea3453b2 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestLoginProcessingFilter.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestLoginProcessingFilter.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.service.security.auth.rest; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationDetailsSource; @@ -27,6 +26,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedException; import org.thingsboard.server.service.security.model.UserPrincipal; @@ -45,14 +45,12 @@ public class RestLoginProcessingFilter extends AbstractAuthenticationProcessingF private final AuthenticationSuccessHandler successHandler; private final AuthenticationFailureHandler failureHandler; - private final ObjectMapper objectMapper; public RestLoginProcessingFilter(String defaultProcessUrl, AuthenticationSuccessHandler successHandler, - AuthenticationFailureHandler failureHandler, ObjectMapper mapper) { + AuthenticationFailureHandler failureHandler) { super(defaultProcessUrl); this.successHandler = successHandler; this.failureHandler = failureHandler; - this.objectMapper = mapper; } @Override @@ -67,7 +65,7 @@ public class RestLoginProcessingFilter extends AbstractAuthenticationProcessingF LoginRequest loginRequest; try { - loginRequest = objectMapper.readValue(request.getReader(), LoginRequest.class); + loginRequest = JacksonUtil.fromReader(request.getReader(), LoginRequest.class); } catch (Exception e) { throw new AuthenticationServiceException("Invalid login request payload"); } diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestPublicLoginProcessingFilter.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestPublicLoginProcessingFilter.java index 5bf0382aa4..23252c27ef 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestPublicLoginProcessingFilter.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestPublicLoginProcessingFilter.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.service.security.auth.rest; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationServiceException; @@ -26,6 +25,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedException; import org.thingsboard.server.service.security.model.UserPrincipal; @@ -42,14 +42,12 @@ public class RestPublicLoginProcessingFilter extends AbstractAuthenticationProce private final AuthenticationSuccessHandler successHandler; private final AuthenticationFailureHandler failureHandler; - private final ObjectMapper objectMapper; public RestPublicLoginProcessingFilter(String defaultProcessUrl, AuthenticationSuccessHandler successHandler, - AuthenticationFailureHandler failureHandler, ObjectMapper mapper) { + AuthenticationFailureHandler failureHandler) { super(defaultProcessUrl); this.successHandler = successHandler; this.failureHandler = failureHandler; - this.objectMapper = mapper; } @Override @@ -64,7 +62,7 @@ public class RestPublicLoginProcessingFilter extends AbstractAuthenticationProce PublicLoginRequest loginRequest; try { - loginRequest = objectMapper.readValue(request.getReader(), PublicLoginRequest.class); + loginRequest = JacksonUtil.fromReader(request.getReader(), PublicLoginRequest.class); } catch (Exception e) { throw new AuthenticationServiceException("Invalid public login request payload"); } diff --git a/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java b/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java index 0c0ff3e0c9..7a3a098062 100644 --- a/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java +++ b/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java @@ -17,7 +17,6 @@ package org.thingsboard.server.service.transport; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -122,8 +121,6 @@ import static org.thingsboard.server.service.transport.BasicCredentialsValidatio @RequiredArgsConstructor public class DefaultTransportApiService implements TransportApiService { - private static final ObjectMapper mapper = new ObjectMapper(); - private final TbDeviceProfileCache deviceProfileCache; private final TbTenantProfileCache tenantProfileCache; private final TbApiUsageStateService apiUsageStateService; @@ -309,8 +306,8 @@ public class DefaultTransportApiService implements TransportApiService { metaData.putValue("gatewayId", gatewayId.toString()); DeviceId deviceId = device.getId(); - ObjectNode entityNode = mapper.valueToTree(device); - TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, deviceId, customerId, metaData, TbMsgDataType.JSON, mapper.writeValueAsString(entityNode)); + JsonNode entityNode = JacksonUtil.valueToTree(device); + TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, deviceId, customerId, metaData, TbMsgDataType.JSON, JacksonUtil.toString(entityNode)); tbClusterService.pushMsgToRuleEngine(tenantId, deviceId, tbMsg, null); } else { JsonNode deviceAdditionalInfo = device.getAdditionalInfo(); @@ -520,7 +517,7 @@ public class DefaultTransportApiService implements TransportApiService { .setDeviceType(device.getType()) .setDeviceProfileIdMSB(device.getDeviceProfileId().getId().getMostSignificantBits()) .setDeviceProfileIdLSB(device.getDeviceProfileId().getId().getLeastSignificantBits()) - .setAdditionalInfo(mapper.writeValueAsString(device.getAdditionalInfo())); + .setAdditionalInfo(JacksonUtil.toString(device.getAdditionalInfo())); PowerSavingConfiguration psmConfiguration = null; switch (device.getDeviceData().getTransportConfiguration().getType()) { diff --git a/application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java b/application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java index 2e4de41470..acd9c630a7 100644 --- a/application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java +++ b/application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.service.update; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -26,6 +25,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.server.common.data.UpdateMessage; import org.thingsboard.server.common.msg.notification.trigger.NewPlatformVersionTrigger; @@ -33,7 +33,6 @@ import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor; import org.thingsboard.server.queue.util.AfterStartUp; import org.thingsboard.server.queue.util.TbCoreComponent; -import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.io.IOException; import java.nio.file.Files; @@ -129,7 +128,7 @@ public class DefaultUpdateService implements UpdateService { log.trace("Executing check update method for instanceId [{}], platform [{}] and version [{}]", instanceId, platform, version); var headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); - ObjectNode request = new ObjectMapper().createObjectNode(); + ObjectNode request = JacksonUtil.newObjectNode(); request.put(PLATFORM_PARAM, platform); request.put(VERSION_PARAM, version); request.put(INSTANCE_ID_PARAM, instanceId.toString()); diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java index afaa19db8a..49e3550a1e 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.TestPropertySource; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.EventInfo; import org.thingsboard.server.common.data.event.EventType; import org.thingsboard.server.common.data.id.EntityId; @@ -75,8 +76,8 @@ public abstract class AbstractRuleEngineControllerTest extends AbstractControlle protected JsonNode getMetadata(EventInfo outEvent) { String metaDataStr = outEvent.getBody().get("metadata").asText(); try { - return mapper.readTree(metaDataStr); - } catch (IOException e) { + return JacksonUtil.toJsonNode(metaDataStr); + } catch (IllegalArgumentException e) { throw new RuntimeException(e); } } diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java index f49e6671c9..9d8bb96e32 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java @@ -17,7 +17,6 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; @@ -57,6 +56,7 @@ import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilde import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.context.WebApplicationContext; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.actors.DefaultTbActorSystem; import org.thingsboard.server.actors.TbActorId; @@ -144,8 +144,6 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { public static final int TIMEOUT = 30; - protected ObjectMapper mapper = new ObjectMapper(); - protected static final String TEST_TENANT_NAME = "TEST TENANT"; protected static final String TEST_DIFFERENT_TENANT_NAME = "TEST DIFFERENT TENANT"; @@ -442,7 +440,7 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { doGet("/api/noauth/activate?activateToken={activateToken}", this.currentActivateToken) .andExpect(status().isSeeOther()) .andExpect(header().string(HttpHeaders.LOCATION, "/login/createPassword?activateToken=" + this.currentActivateToken)); - return new ObjectMapper().createObjectNode() + return JacksonUtil.newObjectNode() .put("activateToken", this.currentActivateToken) .put("password", password); } @@ -806,7 +804,7 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { protected T readResponse(MvcResult result, TypeReference type) throws Exception { byte[] content = result.getResponse().getContentAsByteArray(); - return mapper.readerFor(type).readValue(content); + return JacksonUtil.OBJECT_MAPPER.readerFor(type).readValue(content); } protected String getErrorMessage(ResultActions result) throws Exception { 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 ba52cea1ec..644d0451d8 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseRuleChainControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseRuleChainControllerTest.java @@ -27,6 +27,7 @@ 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.common.util.JacksonUtil; import org.thingsboard.rule.engine.action.TbCreateAlarmNode; import org.thingsboard.rule.engine.action.TbCreateAlarmNodeConfiguration; import org.thingsboard.server.common.data.StringUtils; @@ -273,7 +274,7 @@ public abstract class BaseRuleChainControllerTest extends AbstractControllerTest TbCreateAlarmNodeConfiguration invalidCreateAlarmNodeConfiguration = new TbCreateAlarmNodeConfiguration(); invalidCreateAlarmNodeConfiguration.setSeverity("