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 d7e5c807d5..76ce467fd9 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 @@ -27,6 +27,7 @@ import io.restassured.path.json.JsonPath; import io.restassured.response.ValidatableResponse; import io.restassured.specification.RequestSpecification; import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.EntityView; @@ -38,6 +39,7 @@ 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.DashboardId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.EntityId; @@ -489,4 +491,21 @@ public class TestRestClient { .then() .statusCode(HTTP_OK); } + + public Dashboard postDashboard(Dashboard dashboard) { + return given().spec(requestSpec) + .body(dashboard) + .post("/api/dashboard") + .then() + .statusCode(HTTP_OK) + .extract() + .as(Dashboard.class); + } + + public void deleteDashboard(DashboardId dashboardId) { + given().spec(requestSpec) + .delete("/api/dashboard/{dashboardId}", dashboardId.getId()) + .then() + .statusCode(HTTP_OK); + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractBasePage.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractBasePage.java index 35639bc19f..cfb282b88c 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractBasePage.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractBasePage.java @@ -185,4 +185,8 @@ abstract public class AbstractBasePage { String s = "~`!@#$^&*()_+=-"; return s.charAt(rand.nextInt(s.length())); } + + public void pull(WebElement element, int xOffset, int yOffset) { + actions.clickAndHold(element).moveByOffset(xOffset, yOffset).release().perform(); + } } 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 27e5e6b978..cd34e69239 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 @@ -42,6 +42,7 @@ 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.CustomerId; +import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.page.PageLink; @@ -262,4 +263,10 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { testRestClient.deleteEntityView(entityViewId); } } + + public void deleteDashboardById(DashboardId dashboardId) { + if (dashboardId != null) { + testRestClient.deleteDashboard(dashboardId); + } + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmWidgetElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmWidgetElements.java new file mode 100644 index 0000000000..344289a3e8 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/AlarmWidgetElements.java @@ -0,0 +1,39 @@ +/** + * 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; + +public class AlarmWidgetElements extends AlarmDetailsEntityTabHelper{ + public AlarmWidgetElements(WebDriver driver) { + super(driver); + } + + private static final String ASSIGN_USER_DISPLAY_NAME = "//span[contains(@class,'assigned-container')]/span[contains(text(),'%s')]"; + private static final String UNASSIGNED = "//span[text() = '%s']/ancestor::mat-row//span[contains(@class,'assigned-container')]" + + "//mat-icon[text() = 'account_circle']/following-sibling::span"; + + @Override + public WebElement assignedUser(String userEmail) { + return waitUntilElementToBeClickable(String.format(ASSIGN_USER_DISPLAY_NAME, userEmail)); + } + + @Override + public WebElement unassigned(String alarmType) { + return waitUntilVisibilityOfElementLocated(String.format(UNASSIGNED, alarmType)); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CreateWidgetPopupElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CreateWidgetPopupElements.java new file mode 100644 index 0000000000..9565ef3ebc --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CreateWidgetPopupElements.java @@ -0,0 +1,72 @@ +/** + * 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.base.AbstractBasePage; + +public class CreateWidgetPopupElements extends AbstractBasePage { + public CreateWidgetPopupElements(WebDriver driver) { + super(driver); + } + + private static final String ENTITY_ALIAS = "//input[@formcontrolname='entityAlias']"; + private static final String CREATE_NEW_ALIAS_BTN = "//a[text() = 'Create a new one!']/parent::span"; + private static final String FILTER_TYPE_FIELD = "//div[contains(@class,'tb-entity-filter')]//mat-select//span"; + private static final String TYPE_FIELD = "//mat-select[@formcontrolname='entityType']//span"; + private static final String OPTION_FROM_DROPDOWN = "//span[text() = ' %s ']"; + private static final String ENTITY_FIELD = "//input[@formcontrolname='entity']"; + private static final String ADD_ALIAS_BTN = "//tb-entity-alias-dialog//span[text() = ' Add ']/parent::button"; + private static final String ADD_WIDGET_BTN = "//tb-add-widget-dialog//span[text() = ' Add ']/parent::button"; + private static final String ENTITY_FROM_DROPDOWN = "//b[text() = '%s']"; + + public WebElement entityAlias() { + return waitUntilElementToBeClickable(ENTITY_ALIAS); + } + + public WebElement createNewAliasBtn() { + return waitUntilElementToBeClickable(CREATE_NEW_ALIAS_BTN); + } + + public WebElement filterTypeFiled() { + return waitUntilElementToBeClickable(FILTER_TYPE_FIELD); + } + + public WebElement typeFiled() { + return waitUntilElementToBeClickable(TYPE_FIELD); + } + + public WebElement optionFromDropdown(String type) { + return waitUntilElementToBeClickable(String.format(OPTION_FROM_DROPDOWN, type)); + } + + public WebElement entityFiled() { + return waitUntilElementToBeClickable(ENTITY_FIELD); + } + + public WebElement addAliasBtn() { + return waitUntilElementToBeClickable(ADD_ALIAS_BTN); + } + + public WebElement addWidgetBtn() { + return waitUntilElementToBeClickable(ADD_WIDGET_BTN); + } + + public WebElement entityFromDropdown(String entityName) { + return waitUntilVisibilityOfElementLocated(String.format(ENTITY_FROM_DROPDOWN, entityName)); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CreateWidgetPopupHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CreateWidgetPopupHelper.java new file mode 100644 index 0000000000..011355cd6e --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CreateWidgetPopupHelper.java @@ -0,0 +1,48 @@ +/** + * 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.Keys; +import org.openqa.selenium.WebDriver; +import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; + +public class CreateWidgetPopupHelper extends CreateWidgetPopupElements{ + public CreateWidgetPopupHelper(WebDriver driver) { + super(driver); + } + + public void goToCreateEntityAliasPopup(String aliasName) { + entityAlias().sendKeys(aliasName + RandomStringUtils.randomAlphanumeric(7)); + createNewAliasBtn().click(); + } + + public void selectFilterType(String filterType) { + filterTypeFiled().click(); + optionFromDropdown(filterType).click(); + } + + public void selectType(String entityType) { + typeFiled().click(); + optionFromDropdown(entityType).click(); + } + + public void selectEntity(String entityName) { + entityFiled().sendKeys(entityName); + entityFromDropdown(entityName); + entityFiled().sendKeys(Keys.ARROW_DOWN); + entityFiled().sendKeys(Keys.ENTER); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageElements.java index 77fb2b6b13..8994b2e748 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageElements.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageElements.java @@ -30,6 +30,13 @@ public class DashboardPageElements extends OtherPageElementsHelper { private static final String MANAGE_ASSIGNED_ENTITY_LIST_FIELD = "//input[@formcontrolname='entity']"; private static final String MANAGE_ASSIGNED_ENTITY = "//mat-option//span[contains(text(),'%s')]"; private static final String MANAGE_ASSIGNED_UPDATE_BTN = "//button[@type='submit']"; + private static final String EDIT_BTN = "//mat-icon[text() = 'edit']/parent::button"; + private static final String ADD_BTN = "//tb-footer-fab-buttons//button"; + private static final String CREAT_NEW_DASHBOARD_BTN = "//mat-icon[text() = 'insert_drive_file']/parent::button"; + private static final String ALARM_WIDGET_BUNDLE = "//mat-card-title[text() = 'Alarm widgets']/ancestor::mat-card"; + private static final String ALARM_TABLE_WIDGET = "//img[@alt='Alarms table']/ancestor::mat-card"; + private static final String WIDGET_SE_CORNER = "//div[contains(@class,'handle-se')]"; + private static final String DONE_BTN = "//tb-footer-fab-buttons/following-sibling::button//mat-icon[text() = 'done']/parent::button"; public List entityTitles() { return waitUntilVisibilityOfElementsLocated(TITLES); @@ -50,4 +57,32 @@ public class DashboardPageElements extends OtherPageElementsHelper { public WebElement manageAssignedUpdateBtn() { return waitUntilElementToBeClickable(MANAGE_ASSIGNED_UPDATE_BTN); } + + public WebElement editBtn() { + return waitUntilElementToBeClickable(EDIT_BTN); + } + + public WebElement addBtn() { + return waitUntilElementToBeClickable(ADD_BTN); + } + + public WebElement createNewDashboardBtn() { + return waitUntilElementToBeClickable(CREAT_NEW_DASHBOARD_BTN); + } + + public WebElement alarmWidgetBundle() { + return waitUntilElementToBeClickable(ALARM_WIDGET_BUNDLE); + } + + public WebElement alarmTableWidget() { + return waitUntilElementToBeClickable(ALARM_TABLE_WIDGET); + } + + public WebElement widgetSECorner() { + return waitUntilElementToBeClickable(WIDGET_SE_CORNER); + } + + public WebElement doneBtn() { + return waitUntilVisibilityOfElementLocated(DONE_BTN); + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageHelper.java index 6449cf0cbb..93e8fa10d4 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageHelper.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DashboardPageHelper.java @@ -37,4 +37,18 @@ public class DashboardPageHelper extends DashboardPageElements { jsClick(manageAssignedEntity(title)); jsClick(manageAssignedUpdateBtn()); } + + public void openSelectWidgetsBundleMenu() { + addBtn().click(); + createNewDashboardBtn().click(); + } + + public void openCreateWidgetPopup() { + alarmWidgetBundle().click(); + alarmTableWidget().click(); + } + + public void increaseSizeOfTheWidget() { + pull(widgetSECorner(), 700, 200); + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignFromAlarmWidgetTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignFromAlarmWidgetTest.java new file mode 100644 index 0000000000..73751d221e --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/assignee/AssignFromAlarmWidgetTest.java @@ -0,0 +1,144 @@ +/** + * 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 io.qameta.allure.Description; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.thingsboard.server.common.data.Dashboard; +import org.thingsboard.server.msa.ui.pages.AlarmWidgetElements; +import org.thingsboard.server.msa.ui.pages.CreateWidgetPopupHelper; +import org.thingsboard.server.msa.ui.pages.DashboardPageHelper; +import org.thingsboard.server.msa.ui.utils.Const; +import org.thingsboard.server.msa.ui.utils.EntityPrototypes; + +import static org.assertj.core.api.Assertions.assertThat; + +public class AssignFromAlarmWidgetTest extends AbstractAssignTest { + + private Dashboard dashboard; + private DashboardPageHelper dashboardPage; + private AlarmWidgetElements alarmWidget; + + @BeforeClass + public void create() { + dashboardPage = new DashboardPageHelper(driver); + CreateWidgetPopupHelper createWidgetPopup = new CreateWidgetPopupHelper(driver); + alarmWidget = new AlarmWidgetElements(driver); + + dashboard = testRestClient.postDashboard(EntityPrototypes.defaultDashboardPrototype("Dashboard")); + sideBarMenuView.dashboardBtn().click(); + dashboardPage.entity(dashboard.getName()).click(); + dashboardPage.editBtn().click(); + dashboardPage.openSelectWidgetsBundleMenu(); + dashboardPage.openCreateWidgetPopup(); + createWidgetPopup.goToCreateEntityAliasPopup("Alias"); + createWidgetPopup.selectFilterType("Single entity"); + createWidgetPopup.selectType("Device"); + createWidgetPopup.selectEntity(deviceName); + createWidgetPopup.addAliasBtn().click(); + createWidgetPopup.addWidgetBtn().click(); + dashboardPage.increaseSizeOfTheWidget(); + dashboardPage.doneBtn().click(); + } + + @AfterClass + public void delete() { + deleteDashboardById(dashboard.getId()); + } + + @BeforeMethod + public void goToDashboardPage() { + sideBarMenuView.dashboardBtn().click(); + dashboardPage.entity(dashboard.getName()).click(); + } + + @Description("Can assign alarm to yourself") + @Test + public void assignAlarmToYourself() { + alarmWidget.assignAlarmTo(alarmType, Const.TENANT_EMAIL); + + assertIsDisplayed(alarmWidget.assignedUser(Const.TENANT_EMAIL)); + } + + @Description("Can reassign alarm to another user") + @Test + public void reassignAlarm() { + alarmWidget.assignAlarmTo(assignedAlarmType, userWithNameEmail); + + assertIsDisplayed(alarmWidget.assignedUser(userName)); + } + + @Description("Can unassign alarm") + @Test + public void unassignedAlarm() { + alarmWidget.unassignedAlarm(assignedAlarmType); + + assertIsDisplayed(alarmWidget.unassigned(assignedAlarmType)); + } + + @Description("Assign alarm to yourself from details of alarm") + @Test + public void assignAlarmToYourselfFromDetails() { + alarmWidget.alarmDetailsBtn(alarmType).click(); + alarmDetailsView.assignAlarmTo(Const.TENANT_EMAIL); + alarmDetailsView.closeAlarmDetailsViewBtn().click(); + + assertIsDisplayed(alarmWidget.assignedUser(Const.TENANT_EMAIL)); + } + + @Description("Reassign alarm to another user from details of alarm") + @Test + public void reassignAlarmFromDetails() { + alarmWidget.alarmDetailsBtn(assignedAlarmType).click(); + alarmDetailsView.assignAlarmTo(userWithNameEmail); + alarmDetailsView.closeAlarmDetailsViewBtn().click(); + + assertIsDisplayed(alarmWidget.assignedUser(userName)); + } + + @Description("Unassign alarm from details of alarm") + @Test + public void unassignedAlarmFromDetails() { + alarmWidget.alarmDetailsBtn(assignedAlarmType).click(); + alarmDetailsView.unassignedAlarm(); + alarmDetailsView.closeAlarmDetailsViewBtn().click(); + + assertIsDisplayed(alarmWidget.unassigned(assignedAlarmType)); + } + + @Description("Search by email") + @Test + public void searchByEmail() { + alarmWidget.searchAlarm(alarmType, Const.TENANT_EMAIL); + alarmWidget.setUsers(); + + assertThat(alarmWidget.getUsers()).hasSize(1).as("Search result contains search input").contains(Const.TENANT_EMAIL); + alarmWidget.assignUsers().forEach(this::assertIsDisplayed); + } + + @Description("Search by name") + @Test(groups = "broken") + public void searchByName() { + alarmWidget.searchAlarm(alarmType, userName); + alarmWidget.setUsers(); + + assertThat(alarmWidget.getUsers()).hasSize(1).as("Search result contains search input").contains(userName); + alarmWidget.assignUsers().forEach(this::assertIsDisplayed); + } +} 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 99f05e6f1d..6f2d9560f4 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 @@ -18,6 +18,7 @@ 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.Dashboard; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileProvisionType; @@ -206,4 +207,10 @@ public class EntityPrototypes { entityView.setAdditionalInfo(JacksonUtil.newObjectNode().put("entityType", entityType)); return entityView; } + + public static Dashboard defaultDashboardPrototype(String title) { + Dashboard dashboard = new Dashboard(); + dashboard.setTitle(title + RandomStringUtils.randomAlphanumeric(7)); + return dashboard; + } }