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 4de6fbaf17..dddd30b8db 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 @@ -55,6 +55,7 @@ import java.io.ByteArrayInputStream; import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -157,6 +158,20 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { .findFirst().orElse(null); } + public List getDevicesByName(String... deviceNames) { + List matchingDevicesByName = new ArrayList<>(); + List allDevices = testRestClient.getDevices(pageLink).getData(); + for (Device device : allDevices) { + for (String name : deviceNames) { + if (device.getName().equals(name)) { + matchingDevicesByName.add(device); + break; + } + } + } + return matchingDevicesByName; + } + public List getRuleChainsByName(String name) { return testRestClient.getRuleChains(pageLink).getData().stream() .filter(s -> s.getName().equals(name)) @@ -174,13 +189,10 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { } public DeviceProfile getDeviceProfileByName(String name) { - try { - return testRestClient.getDeviceProfiles(pageLink).getData().stream() - .filter(x -> x.getName().equals(name)).collect(Collectors.toList()).get(0); - } catch (Exception e) { - log.error("No such device profile with name: " + name); - return null; - } + return testRestClient.getDeviceProfiles(pageLink).getData().stream() + .filter(x -> x.getName().equals(name)) + .findFirst() + .orElse(null); } public AssetProfile getAssetProfileByName(String name) { @@ -291,6 +303,15 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { } } + public void deleteDevicesByName(String... deviceName) { + List devices = getDevicesByName(deviceName); + for (Device device : devices) { + if (device != null) { + testRestClient.deleteDevice(device.getId()); + } + } + } + public void deleteDeviceProfileByTitle(String deviceProfileTitle) { DeviceProfile deviceProfile = getDeviceProfileByName(deviceProfileTitle); if (deviceProfile != null) { 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 a4404858d9..e400a67567 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 @@ -18,6 +18,8 @@ package org.thingsboard.server.msa.ui.pages; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import java.util.List; + public class DevicePageElements extends OtherPageElementsHelper { public DevicePageElements(WebDriver driver) { super(driver); @@ -31,7 +33,7 @@ public class DevicePageElements extends OtherPageElementsHelper { private static final String CHOOSE_CUSTOMER_FOR_ASSIGN_FIELD = "//input[@formcontrolname='entity']"; private static final String ENTITY_FROM_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']"; + private static final String SUBMIT_BTN = "//button[@type='submit']"; private static final String ADD_DEVICE_BTN = "//mat-icon[text() = 'insert_drive_file']/parent::button"; private static final String HEADER_NAME_VIEW = "//header//div[@class='tb-details-title']/span"; private static final String ADD_DEVICE_VIEW = "//tb-device-wizard"; @@ -47,12 +49,17 @@ public class DevicePageElements extends OtherPageElementsHelper { private static final String DEVICE_CUSTOMER_PAGE = DEVICE + "/ancestor::mat-row//mat-cell[contains(@class,'cdk-column-customerTitle')]/span"; private static final String DEVICE_LABEL_EDIT = "//input[@formcontrolname='label']"; private static final String DEVICE_DEVICE_PROFILE_PAGE = DEVICE + "/ancestor::mat-row//mat-cell[contains(@class,'cdk-column-deviceProfileName')]/span"; - protected static final String ASSIGN_BTN = ENTITY + "/ancestor::mat-row//mat-icon[contains(text(),'assignment_ind')]/ancestor::button"; - protected static final String UNASSIGN_BTN = ENTITY + "/ancestor::mat-row//mat-icon[contains(text(),' assignment_return')]/ancestor::button"; - protected static final String ASSIGN_BTN_DETAILS_TAB = "//span[contains(text(),'Assign to customer')]/parent::button"; - protected static final String UNASSIGN_BTN_DETAILS_TAB = "//span[contains(text(),'Unassign from customer')]/parent::button"; - protected static final String ASSIGNED_FIELD_DETAILS_TAB = "//mat-label[text() = 'Assigned to customer']/parent::label/parent::div/input"; - protected static final String ASSIGN_MARKED_DEVICE_BTN = "//mat-icon[text() = 'assignment_ind']/parent::button"; + private static final String ASSIGN_BTN = ENTITY + "/ancestor::mat-row//mat-icon[contains(text(),'assignment_ind')]/ancestor::button"; + private static final String UNASSIGN_BTN = ENTITY + "/ancestor::mat-row//mat-icon[contains(text(),' assignment_return')]/ancestor::button"; + private static final String ASSIGN_BTN_DETAILS_TAB = "//span[contains(text(),'Assign to customer')]/parent::button"; + private static final String UNASSIGN_BTN_DETAILS_TAB = "//span[contains(text(),'Unassign from customer')]/parent::button"; + private static final String ASSIGNED_FIELD_DETAILS_TAB = "//mat-label[text() = 'Assigned to customer']/parent::label/parent::div/input"; + private static final String ASSIGN_MARKED_DEVICE_BTN = "//mat-icon[text() = 'assignment_ind']/parent::button"; + private static final String FILTER_BTN = "//tb-device-info-filter/button"; + private static final String DEVICE_PROFILE_FIELD = "(//input[@formcontrolname='deviceProfile'])[2]"; + private static final String DEVICE_STATE_SELECT = "//div[contains(@class,'tb-filter-panel')]//mat-select[@role='combobox']"; + private static final String LIST_OF_DEVICES_STATE = "//div[@class='status']"; + private static final String LIST_OF_DEVICES_PROFILE = "//mat-cell[contains(@class,'deviceProfileName')]"; public WebElement device(String deviceName) { return waitUntilElementToBeClickable(String.format(DEVICE, deviceName)); @@ -82,8 +89,8 @@ public class DevicePageElements extends OtherPageElementsHelper { return waitUntilElementToBeClickable(CLOSE_DEVICE_DETAILS_VIEW); } - public WebElement submitAssignToCustomerBtn() { - return waitUntilElementToBeClickable(SUBMIT_ASSIGN_TO_CUSTOMER_BTN); + public WebElement submitBtn() { + return waitUntilElementToBeClickable(SUBMIT_BTN); } public WebElement addDeviceBtn() { @@ -177,4 +184,24 @@ public class DevicePageElements extends OtherPageElementsHelper { public WebElement assignMarkedDeviceBtn() { return waitUntilVisibilityOfElementLocated(ASSIGN_MARKED_DEVICE_BTN); } + + public WebElement filterBtn() { + return waitUntilElementToBeClickable(FILTER_BTN); + } + + public WebElement deviceProfileField() { + return waitUntilElementToBeClickable(DEVICE_PROFILE_FIELD); + } + + public WebElement deviceStateSelect() { + return waitUntilElementToBeClickable(DEVICE_STATE_SELECT); + } + + public List listOfDevicesState() { + return waitUntilVisibilityOfElementsLocated(LIST_OF_DEVICES_STATE); + } + + public List listOfDevicesProfile() { + return waitUntilVisibilityOfElementsLocated(LIST_OF_DEVICES_PROFILE); + } } 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 3239bb5484..80f4ff49b3 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 @@ -35,7 +35,7 @@ public class DevicePageHelper extends DevicePageElements { public void assignToCustomer(String customerTitle) { chooseCustomerForAssignField().click(); entityFromDropdown(customerTitle).click(); - submitAssignToCustomerBtn().click(); + submitBtn().click(); } public void openCreateDeviceView() { @@ -101,4 +101,26 @@ public class DevicePageHelper extends DevicePageElements { deleteSelectedBtn().click(); warningPopUpYesBtn().click(); } + + public void filterDeviceByDeviceProfile(String deviceProfileTitle) { + clearProfileFieldBtn().click(); + entityFromDropdown(deviceProfileTitle).click(); + submitBtn().click(); + } + + public void filterDeviceByState(String state) { + deviceStateSelect().click(); + entityFromDropdown(" " + state + " ").click(); + sleep(2); //wait until the action is counted + submitBtn().click(); + } + + public void filterDeviceByDeviceProfileAndState(String deviceProfileTitle, String state) { + clearProfileFieldBtn().click(); + entityFromDropdown(deviceProfileTitle).click(); + deviceStateSelect().click(); + entityFromDropdown(" " + state + " ").click(); + sleep(2); //wait until the action is counted + submitBtn().click(); + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/AbstractDeviceTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/AbstractDeviceTest.java index 5b4f1c0685..d173de961e 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/AbstractDeviceTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/AbstractDeviceTest.java @@ -45,9 +45,5 @@ abstract public class AbstractDeviceTest extends AbstractDriverBaseTest { public void delete() { deleteDeviceByName(deviceName); deviceName = null; - if (deviceProfileTitle != null) { - deleteDeviceProfileByTitle(deviceProfileTitle); - deviceProfileTitle = null; - } } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/CreateDeviceTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/CreateDeviceTest.java index 7f13614b37..64b965ac58 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/CreateDeviceTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/CreateDeviceTest.java @@ -17,6 +17,7 @@ package org.thingsboard.server.msa.ui.tests.devicessmoke; import io.qameta.allure.Description; import io.qameta.allure.Feature; +import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.msa.ui.pages.ProfilesPageElements; @@ -33,6 +34,16 @@ import static org.thingsboard.server.msa.ui.utils.Const.SAME_NAME_WARNING_DEVICE @Feature("Create device") public class CreateDeviceTest extends AbstractDeviceTest { + @AfterMethod + public void delete() { + deleteDeviceByName(deviceName); + deviceName = null; + if (deviceProfileTitle != null) { + deleteDeviceProfileByTitle(deviceProfileTitle); + deviceProfileTitle = null; + } + } + @Test(groups = "smoke") @Description("Add device after specifying the name (text/numbers /special characters)") public void createDevice() { diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/DeviceFilterTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/DeviceFilterTest.java new file mode 100644 index 0000000000..0b49ca39c2 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/DeviceFilterTest.java @@ -0,0 +1,127 @@ +/** + * 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.devicessmoke; + +import com.fasterxml.jackson.core.JsonProcessingException; +import io.qameta.allure.Description; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.DeviceProfile; +import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.msa.ui.utils.EntityPrototypes; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.thingsboard.server.msa.ui.base.AbstractBasePage.random; +import static org.thingsboard.server.msa.ui.utils.Const.DEVICE_ACTIVE_STATE; +import static org.thingsboard.server.msa.ui.utils.Const.DEVICE_INACTIVE_STATE; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; + +public class DeviceFilterTest extends AbstractDeviceTest { + + private String activeDeviceName; + private String deviceWithProfileName; + private String activeDeviceWithProfileName; + + @BeforeClass + public void create() throws JsonProcessingException { + DeviceProfile deviceProfile = testRestClient.postDeviceProfile(EntityPrototypes.defaultDeviceProfile(ENTITY_NAME + random())); + deviceProfileTitle = deviceProfile.getName(); + Device deviceWithProfile = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME + random(), deviceProfile.getId())); + deviceWithProfileName = deviceWithProfile.getName(); + Device activeDevice = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME + random())); + activeDeviceName = activeDevice.getName(); + Device activeDeviceWithProfile = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME + random(), deviceProfile.getId())); + activeDeviceWithProfileName = activeDeviceWithProfile.getName(); + DeviceCredentials deviceCredentials = testRestClient.getDeviceCredentialsByDeviceId(activeDevice.getId()); + DeviceCredentials deviceCredentials1 = testRestClient.getDeviceCredentialsByDeviceId(activeDeviceWithProfile.getId()); + testRestClient.postTelemetry(deviceCredentials.getCredentialsId(), mapper.readTree(createPayload().toString())); + testRestClient.postTelemetry(deviceCredentials1.getCredentialsId(), mapper.readTree(createPayload().toString())); + } + + @AfterClass + public void delete() { + deleteDevicesByName(deviceWithProfileName, activeDeviceName, activeDeviceWithProfileName); + deleteDeviceProfileByTitle(deviceProfileTitle); + } + + @Test(groups = "smoke") + @Description("Filter by device profile") + public void filterDevicesByProfile() { + sideBarMenuView.goToDevicesPage(); + devicePage.filterBtn().click(); + devicePage.filterDeviceByDeviceProfile(deviceProfileTitle); + + devicePage.listOfDevicesProfile().forEach(d -> assertThat(d.getText()) + .as("There are only devices with the selected profile on the page") + .isEqualTo(deviceProfileTitle)); + } + + @Test(groups = "smoke") + @Description("Filter by state (Active)") + public void filterDevicesByActiveState() { + sideBarMenuView.goToDevicesPage(); + devicePage.filterBtn().click(); + devicePage.filterDeviceByState(DEVICE_ACTIVE_STATE); + + devicePage.listOfDevicesState().forEach(d -> assertThat(d.getText()) + .as("There are only devices with active state on the page") + .isEqualTo(DEVICE_ACTIVE_STATE)); + } + + @Test(groups = "smoke") + @Description("Filter by state (Inactive)") + public void filterDevicesByInactiveState() { + sideBarMenuView.goToDevicesPage(); + devicePage.filterBtn().click(); + devicePage.filterDeviceByState(DEVICE_INACTIVE_STATE); + + devicePage.listOfDevicesState().forEach(d -> assertThat(d.getText()) + .as("There are only devices with inactive state on the page") + .isEqualTo(DEVICE_INACTIVE_STATE)); + } + + @Test(groups = "smoke") + @Description("Filter device by device profile and active state") + public void filterDevicesByDeviceProfileAndActiveState() { + sideBarMenuView.goToDevicesPage(); + devicePage.filterBtn().click(); + devicePage.filterDeviceByDeviceProfileAndState(deviceProfileTitle, DEVICE_ACTIVE_STATE); + + devicePage.listOfDevicesProfile().forEach(d -> assertThat(d.getText()) + .as("There are only devices with the selected profile on the page") + .isEqualTo(deviceProfileTitle)); + devicePage.listOfDevicesState().forEach(d -> assertThat(d.getText()) + .as("There are only devices with active state on the page") + .isEqualTo(DEVICE_ACTIVE_STATE)); + } + + @Test(groups = "smoke") + @Description("Filter device by device profile and inactive state") + public void filterDevicesByDeviceProfileAndInactiveState() { + sideBarMenuView.goToDevicesPage(); + devicePage.filterBtn().click(); + devicePage.filterDeviceByDeviceProfileAndState(deviceProfileTitle, DEVICE_INACTIVE_STATE); + + devicePage.listOfDevicesProfile().forEach(d -> assertThat(d.getText()) + .as("There are only devices with the selected profile on the page") + .isEqualTo(deviceProfileTitle)); + devicePage.listOfDevicesState().forEach(d -> assertThat(d.getText()) + .as("There are only devices with inactive state on the page") + .isEqualTo(DEVICE_INACTIVE_STATE)); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/Const.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/Const.java index 28bdac556f..0b9e173e6d 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/Const.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/Const.java @@ -45,4 +45,6 @@ public class Const { public static final String PHONE_NUMBER_ERROR_MESSAGE = "Phone number is invalid or not possible"; public static final String NAME_IS_REQUIRED_MESSAGE = "Name is required."; public static final String DEVICE_PROFILE_IS_REQUIRED_MESSAGE = "Device profile is required"; + public static final String DEVICE_ACTIVE_STATE = "Active"; + public static final String DEVICE_INACTIVE_STATE = "Inactive"; } 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 ec66442bd2..252061fca8 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 @@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTra 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.DeviceProfileId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.rule.RuleChain; @@ -227,6 +228,14 @@ public class EntityPrototypes { return device; } + public static Device defaultDevicePrototype(String name, DeviceProfileId deviceProfileId) { + Device device = new Device(); + device.setName(name + RandomStringUtils.randomAlphanumeric(7)); + device.setType("DEFAULT"); + device.setDeviceProfileId(deviceProfileId); + return device; + } + public static Asset defaultAssetPrototype(String name, CustomerId id) { Asset asset = new Asset(); asset.setName(name + RandomStringUtils.randomAlphanumeric(7));