Merge pull request #8526 from Seraphym-Tuhai/ui-smoke-tests-devices

[3.5.1] Added UI smoke tests on devices
This commit is contained in:
Andrew Shvayka 2023-05-17 17:48:16 +03:00 committed by GitHub
commit 1ac4fe91ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 903 additions and 8 deletions

View File

@ -132,6 +132,18 @@ public class TestRestClient {
.as(Device.class);
}
public PageData<Device> getDevices(PageLink pageLink) {
Map<String, String> params = new HashMap<>();
addPageLinkToParam(params, pageLink);
return given().spec(requestSpec).queryParams(params)
.get("/api/tenant/devices")
.then()
.statusCode(HTTP_OK)
.extract()
.as(new TypeRef<PageData<Device>>() {
});
}
public DeviceCredentials getDeviceCredentialsByDeviceId(DeviceId deviceId) {
return given().spec(requestSpec).get("/api/device/{deviceId}/credentials", deviceId.getId())
.then()

View File

@ -37,6 +37,7 @@ import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
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.asset.AssetProfile;
import org.thingsboard.server.common.data.id.AlarmId;
@ -150,6 +151,12 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest {
.findFirst().orElse(null);
}
public Device getDeviceByName(String name) {
return testRestClient.getDevices(pageLink).getData().stream()
.filter(s -> s.getName().equals(name))
.findFirst().orElse(null);
}
public List<RuleChain> getRuleChainsByName(String name) {
return testRestClient.getRuleChains(pageLink).getData().stream()
.filter(s -> s.getName().equals(name))
@ -269,4 +276,11 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest {
testRestClient.deleteDashboard(dashboardId);
}
}
public void deleteDeviceByName(String deviceName) {
Device device = getDeviceByName(deviceName);
if (device != null) {
testRestClient.deleteDevice(device.getId());
}
}
}

View File

@ -119,6 +119,7 @@ public class CustomerPageHelper extends CustomerPageElements {
public void createCustomersUser() {
plusBtn().click();
addUserEmailField().click();
addUserEmailField().sendKeys(getRandomNumber() + "@gmail.com");
addBtnC().click();
activateWindowOkBtn().click();

View File

@ -18,7 +18,7 @@ package org.thingsboard.server.msa.ui.pages;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
public class DevicePageElements extends OtherPageElements {
public class DevicePageElements extends OtherPageElementsHelper {
public DevicePageElements(WebDriver driver) {
super(driver);
}
@ -29,9 +29,30 @@ public class DevicePageElements extends OtherPageElements {
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 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 ADD_DEVICE_BTN = "//mat-icon[text() = 'insert_drive_file']/parent::button";
private static final String CREATE_DEVICE_NAME_FIELD = "//tb-device-wizard//input[@formcontrolname='name']";
private static final String HEADER_NAME_VIEW = "//header//div[@class='tb-details-title']/span";
private static final String DESCRIPTION_FIELD_CREATE_VIEW = "//tb-device-wizard//textarea[@formcontrolname='description']";
private static final String ADD_DEVICE_VIEW = "//tb-device-wizard";
private static final String DELETE_BTN_DETAILS_TAB = "//span[contains(text(),'Delete device')]/parent::button";
private static final String CHECKBOX_GATEWAY_EDIT = "//mat-checkbox[@formcontrolname='gateway']//label";
private static final String CHECKBOX_GATEWAY_CREATE = "//tb-device-wizard//mat-checkbox[@formcontrolname='gateway']//label";
private static final String CHECKBOX_OVERWRITE_ACTIVITY_TIME_EDIT = "//mat-checkbox[@formcontrolname='overwriteActivityTime']//label";
private static final String CHECKBOX_OVERWRITE_ACTIVITY_TIME_CREATE = "//tb-device-wizard//mat-checkbox[@formcontrolname='overwriteActivityTime']//label";
private static final String CHECKBOX_GATEWAY_DETAILS = "//mat-checkbox[@formcontrolname='gateway']//input";
private static final String CHECKBOX_GATEWAY_PAGE = DEVICE + "/ancestor::mat-row//mat-cell[contains(@class,'cdk-column-gateway')]//mat-icon[text() = 'check_box']";
private static final String CHECKBOX_OVERWRITE_ACTIVITY_TIME_DETAILS = "//mat-checkbox[@formcontrolname='overwriteActivityTime']//input";
private static final String CLEAR_PROFILE_FIELD_BTN = "//button[@aria-label='Clear']";
private static final String DEVICE_PROFILE_REDIRECTED_BTN = "//a[@aria-label='Open device profile']";
private static final String DEVICE_LABEL_FIELD_CREATE = "//tb-device-wizard//input[@formcontrolname='label']";
private static final String DEVICE_LABEL_PAGE = DEVICE + "/ancestor::mat-row//mat-cell[contains(@class,'cdk-column-label')]/span";
private static final String DEVICE_CUSTOMER_PAGE = DEVICE + "/ancestor::mat-row//mat-cell[contains(@class,'cdk-column-customerTitle')]/span";
private static final String CUSTOMER_OPTION_BNT = "//div[text() = 'Customer']/ancestor::mat-step-header";
private static final String ASSIGN_ON_CUSTOMER_FIELD = "//input[@formcontrolname='entity']";
private static final String DEVICE_LABEL_EDIT = "//input[@formcontrolname='label']";
public WebElement device(String deviceName) {
return waitUntilElementToBeClickable(String.format(DEVICE, deviceName));
@ -53,8 +74,8 @@ public class DevicePageElements extends OtherPageElements {
return waitUntilElementToBeClickable(CHOOSE_CUSTOMER_FOR_ASSIGN_FIELD);
}
public WebElement customerFromAssignDropdown(String customerTitle) {
return waitUntilElementToBeClickable(String.format(CUSTOMER_FROM_ASSIGN_DROPDOWN, customerTitle));
public WebElement entityFromDropdown(String customerTitle) {
return waitUntilElementToBeClickable(String.format(ENTITY_FROM_DROPDOWN, customerTitle));
}
public WebElement closeDeviceDetailsViewBtn() {
@ -64,4 +85,92 @@ public class DevicePageElements extends OtherPageElements {
public WebElement submitAssignToCustomerBtn() {
return waitUntilElementToBeClickable(SUBMIT_ASSIGN_TO_CUSTOMER_BTN);
}
public WebElement addDeviceBtn() {
return waitUntilElementToBeClickable(ADD_DEVICE_BTN);
}
public WebElement nameField() {
return waitUntilElementToBeClickable(CREATE_DEVICE_NAME_FIELD);
}
public WebElement headerNameView() {
return waitUntilVisibilityOfElementLocated(HEADER_NAME_VIEW);
}
public WebElement descriptionFieldCreateField() {
return waitUntilElementToBeClickable(DESCRIPTION_FIELD_CREATE_VIEW);
}
public WebElement addDeviceView() {
return waitUntilPresenceOfElementLocated(ADD_DEVICE_VIEW);
}
public WebElement deleteBtnDetailsTab() {
return waitUntilElementToBeClickable(DELETE_BTN_DETAILS_TAB);
}
public WebElement checkboxGatewayEdit() {
return waitUntilElementToBeClickable(CHECKBOX_GATEWAY_EDIT);
}
public WebElement checkboxGatewayCreate() {
return waitUntilElementToBeClickable(CHECKBOX_GATEWAY_CREATE);
}
public WebElement checkboxOverwriteActivityTimeEdit() {
return waitUntilElementToBeClickable(CHECKBOX_OVERWRITE_ACTIVITY_TIME_EDIT);
}
public WebElement checkboxOverwriteActivityTimeCreate() {
return waitUntilElementToBeClickable(CHECKBOX_OVERWRITE_ACTIVITY_TIME_CREATE);
}
public WebElement checkboxGatewayDetailsTab() {
return waitUntilPresenceOfElementLocated(CHECKBOX_GATEWAY_DETAILS);
}
public WebElement checkboxGatewayPage(String deviceName) {
return waitUntilPresenceOfElementLocated(String.format(CHECKBOX_GATEWAY_PAGE, deviceName));
}
public WebElement checkboxOverwriteActivityTimeDetails() {
return waitUntilPresenceOfElementLocated(CHECKBOX_OVERWRITE_ACTIVITY_TIME_DETAILS);
}
public WebElement clearProfileFieldBtn() {
return waitUntilElementToBeClickable(CLEAR_PROFILE_FIELD_BTN);
}
public WebElement deviceProfileRedirectedBtn() {
return waitUntilElementToBeClickable(DEVICE_PROFILE_REDIRECTED_BTN);
}
public WebElement deviceLabelFieldCreate() {
return waitUntilElementToBeClickable(DEVICE_LABEL_FIELD_CREATE);
}
public WebElement deviceLabelOnPage(String deviceName) {
return waitUntilVisibilityOfElementLocated(String.format(DEVICE_LABEL_PAGE, deviceName));
}
public WebElement customerOptionBtn() {
return waitUntilElementToBeClickable(CUSTOMER_OPTION_BNT);
}
public WebElement assignOnCustomerField() {
return waitUntilElementToBeClickable(ASSIGN_ON_CUSTOMER_FIELD);
}
public WebElement deviceCustomerOnPage(String deviceName) {
return waitUntilVisibilityOfElementLocated(String.format(DEVICE_CUSTOMER_PAGE, deviceName));
}
public WebElement deviceLabelEditField() {
return waitUntilElementToBeClickable(DEVICE_LABEL_EDIT);
}
public WebElement deviceLabelDetailsField() {
return waitUntilVisibilityOfElementLocated(DEVICE_LABEL_EDIT);
}
}

View File

@ -22,6 +22,9 @@ public class DevicePageHelper extends DevicePageElements {
super(driver);
}
private String description;
private String label;
public void openDeviceAlarms(String deviceName) {
if (!deviceDetailsView().isDisplayed()) {
device(deviceName).click();
@ -31,7 +34,63 @@ public class DevicePageHelper extends DevicePageElements {
public void assignToCustomer(String customerTitle) {
chooseCustomerForAssignField().click();
customerFromAssignDropdown(customerTitle).click();
entityFromDropdown(customerTitle).click();
submitAssignToCustomerBtn().click();
}
public void openCreateDeviceView() {
plusBtn().click();
addDeviceBtn().click();
}
public void enterName(String deviceName) {
enterText(nameField(), deviceName);
}
public void enterDescription(String description) {
enterText(descriptionFieldCreateField(), description);
}
public void enterLabel(String label) {
enterText(deviceLabelFieldCreate(), label);
}
public void deleteDeviceByRightSideBtn(String deviceName) {
deleteBtn(deviceName).click();
warningPopUpYesBtn().click();
}
public void deleteDeviceFromDetailsTab() {
deleteBtnDetailsTab().click();
warningPopUpYesBtn().click();
}
public void setDescription() {
scrollToElement(descriptionEntityView());
description = descriptionEntityView().getAttribute("value");
}
public void setLabel() {
label = deviceLabelDetailsField().getAttribute("value");
}
public String getDescription() {
return description;
}
public String getLabel() {
return label;
}
public void changeDeviceProfile(String deviceProfileName) {
clearProfileFieldBtn().click();
entityFromDropdown(deviceProfileName).click();
}
public void assignOnCustomer(String customerTitle) {
customerOptionBtn().click();
assignOnCustomerField().click();
entityFromList(customerTitle).click();
sleep(2); //waiting for the action to count
}
}

View File

@ -0,0 +1,45 @@
/**
* 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 io.qameta.allure.Epic;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest;
import org.thingsboard.server.msa.ui.pages.DevicePageHelper;
import org.thingsboard.server.msa.ui.pages.LoginPageHelper;
import org.thingsboard.server.msa.ui.pages.SideBarMenuViewHelper;
@Epic("Device smoke tests")
abstract public class AbstractDeviceTest extends AbstractDriverBaseTest {
protected SideBarMenuViewHelper sideBarMenuView;
protected DevicePageHelper devicePage;
protected String deviceName;
@BeforeClass
public void login() {
new LoginPageHelper(driver).authorizationTenant();
sideBarMenuView = new SideBarMenuViewHelper(driver);
devicePage = new DevicePageHelper(driver);
}
@AfterMethod
public void delete() {
deleteDeviceByName(deviceName);
deviceName = null;
}
}

View File

@ -0,0 +1,214 @@
/**
* 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 io.qameta.allure.Description;
import io.qameta.allure.Feature;
import org.testng.annotations.Test;
import org.thingsboard.server.common.data.Device;
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_PROFILE_IS_REQUIRED_MESSAGE;
import static org.thingsboard.server.msa.ui.utils.Const.EMPTY_DEVICE_MESSAGE;
import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME;
import static org.thingsboard.server.msa.ui.utils.Const.NAME_IS_REQUIRED_MESSAGE;
import static org.thingsboard.server.msa.ui.utils.Const.SAME_NAME_WARNING_DEVICE_MESSAGE;
@Feature("Create device")
public class CreateDeviceTest extends AbstractDeviceTest {
@Test(groups = "smoke")
@Description("Add device after specifying the name (text/numbers /special characters)")
public void createDevice() {
deviceName = ENTITY_NAME + random();
sideBarMenuView.goToDevicesPage();
devicePage.openCreateDeviceView();
devicePage.enterName(deviceName);
devicePage.addBtnC().click();
devicePage.refreshBtn().click();
assertIsDisplayed(devicePage.entity(deviceName));
}
@Test(groups = "smoke")
@Description("Add device after specifying the name and description (text/numbers /special characters)")
public void createDeviceWithDescription() {
deviceName = ENTITY_NAME + random();
sideBarMenuView.goToDevicesPage();
devicePage.openCreateDeviceView();
devicePage.enterName(deviceName);
devicePage.enterDescription(deviceName);
devicePage.addBtnC().click();
devicePage.refreshBtn().click();
devicePage.entity(deviceName).click();
devicePage.setHeaderName();
assertThat(devicePage.getHeaderName()).as("Header of device details tab").isEqualTo(deviceName);
assertThat(devicePage.descriptionEntityView().getAttribute("value"))
.as("Description in device details tab").isEqualTo(deviceName);
}
@Test(groups = "smoke")
@Description("Add device without the name")
public void createDeviceWithoutName() {
sideBarMenuView.goToDevicesPage();
devicePage.openCreateDeviceView();
devicePage.nameField().click();
devicePage.addBtnC().click();
assertIsDisplayed(devicePage.addDeviceView());
assertThat(devicePage.errorMessage().getText()).as("Text of warning message").isEqualTo(NAME_IS_REQUIRED_MESSAGE);
}
@Test(groups = "smoke")
@Description("Create device only with spase in name")
public void createDeviceWithOnlySpace() {
sideBarMenuView.goToDevicesPage();
devicePage.openCreateDeviceView();
devicePage.enterName(" ");
devicePage.addBtnC().click();
assertIsDisplayed(devicePage.warningMessage());
assertThat(devicePage.warningMessage().getText()).as("Text of warning message").isEqualTo(EMPTY_DEVICE_MESSAGE);
assertIsDisplayed(devicePage.addDeviceView());
}
@Test(groups = "smoke")
@Description("Create a device with the same name")
public void createDeviceWithSameName() {
Device device = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME));
deviceName = device.getName();
sideBarMenuView.goToDevicesPage();
devicePage.openCreateDeviceView();
devicePage.enterName(deviceName);
devicePage.addBtnC().click();
assertIsDisplayed(devicePage.warningMessage());
assertThat(devicePage.warningMessage().getText()).as("Text of warning message").isEqualTo(SAME_NAME_WARNING_DEVICE_MESSAGE);
assertIsDisplayed(devicePage.addDeviceView());
}
@Test(groups = "smoke")
@Description("Add device after specifying the name (text/numbers /special characters) without refresh")
public void createDeviceWithoutRefresh() {
deviceName = ENTITY_NAME + random();
sideBarMenuView.goToDevicesPage();
devicePage.openCreateDeviceView();
devicePage.enterName(deviceName);
devicePage.addBtnC().click();
assertIsDisplayed(devicePage.entity(deviceName));
}
@Test(groups = "smoke")
@Description("Add device without device profile")
public void createDeviceWithoutDeviceProfile() {
deviceName = ENTITY_NAME + random();
sideBarMenuView.goToDevicesPage();
devicePage.openCreateDeviceView();
devicePage.enterName(deviceName);
devicePage.clearProfileFieldBtn().click();
devicePage.addBtnC().click();
assertIsDisplayed(devicePage.errorMessage());
assertThat(devicePage.errorMessage().getText()).as("Text of warning message").isEqualTo(DEVICE_PROFILE_IS_REQUIRED_MESSAGE);
assertIsDisplayed(devicePage.addDeviceView());
}
@Test(groups = "smoke")
@Description("Add device with enabled gateway")
public void createDeviceWithEnableGateway() {
deviceName = ENTITY_NAME + random();
sideBarMenuView.goToDevicesPage();
devicePage.openCreateDeviceView();
devicePage.enterName(deviceName);
devicePage.checkboxGatewayCreate().click();
devicePage.addBtnC().click();
assertIsDisplayed(devicePage.device(deviceName));
assertIsDisplayed(devicePage.checkboxGatewayPage(deviceName));
}
@Test(groups = "smoke")
@Description("Add device with enabled overwrite activity time for connected")
public void createDeviceWithEnableOverwriteActivityTimeForConnected() {
deviceName = ENTITY_NAME + random();
sideBarMenuView.goToDevicesPage();
devicePage.openCreateDeviceView();
devicePage.enterName(deviceName);
devicePage.checkboxGatewayCreate().click();
devicePage.checkboxOverwriteActivityTimeCreate().click();
devicePage.addBtnC().click();
devicePage.device(deviceName).click();
assertThat(devicePage.checkboxOverwriteActivityTimeDetails().getAttribute("class").contains("selected"))
.as("Overwrite activity time for connected is enable").isTrue();
}
@Test(groups = "smoke")
@Description("Add device with label")
public void createDeviceWithLabel() {
deviceName = ENTITY_NAME + random();
String deviceLabel = "device label " + random();
sideBarMenuView.goToDevicesPage();
devicePage.openCreateDeviceView();
devicePage.enterName(deviceName);
devicePage.enterLabel(deviceLabel);
devicePage.addBtnC().click();
assertIsDisplayed(devicePage.deviceLabelOnPage(deviceName));
assertThat(devicePage.deviceLabelOnPage(deviceName).getText()).as("Label added correctly").isEqualTo(deviceLabel);
}
@Test(groups = "smoke")
@Description("Add device with assignee on customer")
public void createDeviceWithAssignee() {
deviceName = ENTITY_NAME + random();
String customer = "Customer A";
sideBarMenuView.goToDevicesPage();
devicePage.openCreateDeviceView();
devicePage.enterName(deviceName);
devicePage.assignOnCustomer(customer);
devicePage.addBtnC().click();
assertIsDisplayed(devicePage.deviceCustomerOnPage(deviceName));
assertThat(devicePage.deviceCustomerOnPage(deviceName).getText())
.as("Customer added correctly").isEqualTo(customer);
}
@Test(groups = "smoke")
@Description("Go to devices documentation page")
public void documentation() {
String urlPath = "docs/user-guide/ui/devices/";
sideBarMenuView.goToDevicesPage();
devicePage.entity("Thermostat T1").click();
devicePage.goToHelpPage();
assertThat(urlContains(urlPath)).as("Redirected URL contains " + urlPath).isTrue();
}
}

View File

@ -0,0 +1,75 @@
/**
* 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 io.qameta.allure.Description;
import io.qameta.allure.Feature;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.msa.ui.utils.EntityPrototypes;
import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME;
@Feature("Delete device")
public class DeleteDeviceTest extends AbstractDeviceTest {
@BeforeMethod
public void createDevice() {
Device device = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME));
deviceName = device.getName();
}
@Test(groups = "smoke")
@Description("Remove the device by clicking on the trash icon in the right side of device")
public void deleteDeviceByRightSideBtn() {
sideBarMenuView.goToDevicesPage();
devicePage.deleteDeviceByRightSideBtn(deviceName);
devicePage.refreshBtn().click();
devicePage.assertEntityIsNotPresent(deviceName);
}
@Test(groups = "smoke")
@Description("Remove device by mark in the checkbox and then click on the trash can icon in the menu that appears at the top")
public void deleteSelectedDevice() {
sideBarMenuView.goToDevicesPage();
devicePage.deleteSelected(deviceName);
devicePage.refreshBtn().click();
devicePage.assertEntityIsNotPresent(deviceName);
}
@Test(groups = "smoke")
@Description("Remove the device by clicking on the 'Delete device' btn in the entity view")
public void deleteDeviceFromDetailsTab() {
sideBarMenuView.goToDevicesPage();
devicePage.entity(deviceName).click();
devicePage.deleteDeviceFromDetailsTab();
devicePage.refreshBtn();
devicePage.assertEntityIsNotPresent(deviceName);
}
@Test(groups = "smoke")
@Description("Remove the device by clicking on the trash icon in the right side of device without refresh")
public void deleteDeviceWithoutRefresh() {
sideBarMenuView.goToDevicesPage();
devicePage.deleteDeviceByRightSideBtn(deviceName);
devicePage.assertEntityIsNotPresent(deviceName);
}
}

View File

@ -0,0 +1,84 @@
/**
* 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 io.qameta.allure.Description;
import io.qameta.allure.Feature;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.msa.ui.utils.EntityPrototypes;
import static org.assertj.core.api.Assertions.assertThat;
import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME;
@Feature("Delete several devices")
public class DeleteSeveralDevicesTest extends AbstractDeviceTest {
private String deviceName1;
private String deviceName2;
@BeforeMethod
public void createDevices() {
Device device = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME));
Device device1 = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME));
deviceName1 = device.getName();
deviceName2 = device1.getName();
}
@AfterMethod
public void deleteDevices() {
deleteDeviceByName(deviceName1);
deleteDeviceByName(deviceName2);
}
@Test(groups = "smoke")
@Description("Remove several devices by mark in the checkbox and then click on the trash can icon in the menu " +
"that appears at the top")
public void deleteSeveralDevicesByTopBtn() {
sideBarMenuView.goToDevicesPage();
devicePage.deleteSelected(2);
devicePage.refreshBtn().click();
devicePage.assertEntityIsNotPresent(deviceName1);
devicePage.assertEntityIsNotPresent(deviceName2);
}
@Test(groups = "smoke")
@Description("Remove several devices by mark all the devices on the page by clicking in the topmost checkbox" +
" and then clicking on the trash icon in the menu that appears")
public void selectAllDevices() {
sideBarMenuView.goToDevicesPage();
devicePage.selectAllCheckBox().click();
devicePage.deleteSelectedBtn().click();
assertIsDisplayed(devicePage.warningPopUpTitle());
assertThat(devicePage.warningPopUpTitle().getText()).as("Warning title contains true correct of selected devices")
.contains(String.valueOf(devicePage.markCheckbox().size()));
}
@Test(groups = "smoke")
@Description("Remove several devices by mark in the checkbox and then click on the trash can icon in the menu " +
"that appears at the top without refresh")
public void deleteSeveralWithoutRefresh() {
sideBarMenuView.goToDevicesPage();
devicePage.deleteSelected(2);
devicePage.assertEntityIsNotPresent(deviceName1);
devicePage.assertEntityIsNotPresent(deviceName2);
}
}

View File

@ -0,0 +1,179 @@
/**
* 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 io.qameta.allure.Description;
import io.qameta.allure.Feature;
import org.testng.annotations.Test;
import org.thingsboard.server.msa.ui.utils.DataProviderCredential;
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.getRandomNumber;
import static org.thingsboard.server.msa.ui.utils.Const.EMPTY_DEVICE_MESSAGE;
import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME;
@Feature("Edit device")
public class EditDeviceTest extends AbstractDeviceTest {
@Test(groups = "smoke")
@Description("Change name by edit menu")
public void changeName() {
String newDeviceName = "Changed" + getRandomNumber();
deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)).getName();
sideBarMenuView.goToDevicesPage();
devicePage.entity(deviceName).click();
devicePage.setHeaderName();
String nameBefore = devicePage.getHeaderName();
devicePage.editPencilBtn().click();
devicePage.changeNameEditMenu(newDeviceName);
devicePage.doneBtnEditView().click();
deviceName = newDeviceName;
devicePage.setHeaderName();
String nameAfter = devicePage.getHeaderName();
assertThat(nameAfter).as("The name has changed").isNotEqualTo(nameBefore);
assertThat(nameAfter).as("The name has changed correctly").isEqualTo(newDeviceName);
}
@Test(groups = "smoke")
@Description("Delete name and save")
public void deleteName() {
deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)).getName();
sideBarMenuView.goToDevicesPage();
devicePage.entity(deviceName).click();
devicePage.editPencilBtn().click();
devicePage.changeNameEditMenu("");
assertIsDisable(devicePage.doneBtnEditViewVisible());
}
@Test(groups = "smoke")
@Description("Save only with space")
public void saveOnlyWithSpace() {
deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)).getName();
sideBarMenuView.goToDevicesPage();
devicePage.entity(deviceName).click();
devicePage.editPencilBtn().click();
devicePage.changeNameEditMenu(" ");
devicePage.doneBtnEditView().click();
assertIsDisplayed(devicePage.warningMessage());
assertThat(devicePage.warningMessage().getText()).as("Text of warning message").isEqualTo(EMPTY_DEVICE_MESSAGE);
}
@Test(groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "editMenuDescription")
@Description("Write the description and save the changes/Change the description and save the changes/Delete the description and save the changes")
public void editDescription(String description, String newDescription, String finalDescription) {
deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME, description)).getName();
sideBarMenuView.goToDevicesPage();
devicePage.entity(deviceName).click();
devicePage.editPencilBtn().click();
devicePage.descriptionEntityView().sendKeys(newDescription);
devicePage.doneBtnEditView().click();
devicePage.setDescription();
assertThat(devicePage.getDescription()).as("The description changed correctly").isEqualTo(finalDescription);
}
@Test(groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "enable")
@Description("Enable gateway mode/Disable gateway")
public void isGateway(boolean isGateway) {
deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME, isGateway)).getName();
sideBarMenuView.goToDevicesPage();
devicePage.entity(deviceName).click();
devicePage.editPencilBtn().click();
devicePage.checkboxGatewayEdit().click();
devicePage.doneBtnEditView().click();
if (isGateway) {
assertThat(devicePage.checkboxGatewayDetailsTab().getAttribute("class").contains("selected"))
.as("Gateway is disable").isFalse();
} else {
assertThat(devicePage.checkboxGatewayDetailsTab().getAttribute("class").contains("selected"))
.as("Gateway is enable").isTrue();
}
}
@Test(groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "enable")
@Description("Enable overwrite activity time for connected/Disable overwrite activity time for connected")
public void isOverwriteActivityTimeForConnectedDevice(boolean isOverwriteActivityTimeForConnected) {
deviceName = testRestClient.postDevice("",
EntityPrototypes.defaultDevicePrototype(ENTITY_NAME, true, isOverwriteActivityTimeForConnected)).getName();
sideBarMenuView.goToDevicesPage();
devicePage.entity(deviceName).click();
devicePage.editPencilBtn().click();
devicePage.checkboxOverwriteActivityTimeEdit().click();
devicePage.doneBtnEditView().click();
if (isOverwriteActivityTimeForConnected) {
assertThat(devicePage.checkboxOverwriteActivityTimeDetails().getAttribute("class").contains("selected"))
.as("Overwrite activity time for connected is disable").isFalse();
} else {
assertThat(devicePage.checkboxOverwriteActivityTimeDetails().getAttribute("class").contains("selected"))
.as("Overwrite activity time for connected is enable").isTrue();
}
}
@Test(groups = "smoke")
@Description("Change device profile")
public void changeDeviceProfile() {
deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)).getName();
sideBarMenuView.goToDevicesPage();
devicePage.entity(deviceName).click();
devicePage.editPencilBtn().click();
devicePage.changeDeviceProfile("DEFAULT");
devicePage.doneBtnEditView().click();
assertIsDisplayed(devicePage.deviceProfileRedirectedBtn());
assertThat(devicePage.deviceProfileRedirectedBtn().getText()).as("Profile changed correctly").isEqualTo("DEFAULT");
}
@Test(groups = "smoke")
@Description("Save without device profile")
public void saveWithoutDeviceProfile() {
deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)).getName();
sideBarMenuView.goToDevicesPage();
devicePage.entity(deviceName).click();
devicePage.editPencilBtn().click();
devicePage.clearProfileFieldBtn().click();
assertIsDisable(devicePage.doneBtnEditViewVisible());
}
@Test(groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "editDeviceLabel")
@Description("Write the label and save the changes/Change the label and save the changes/Delete the label and save the changes")
public void editLabel(String label, String newLabel, String finalLabel) {
deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME, "", label)).getName();
sideBarMenuView.goToDevicesPage();
devicePage.entity(deviceName).click();
devicePage.editPencilBtn().click();
devicePage.deviceLabelEditField().sendKeys(newLabel);
devicePage.doneBtnEditView().click();
devicePage.setLabel();
assertThat(devicePage.getLabel()).as("The label changed correctly").isEqualTo(finalLabel);
}
}

View File

@ -99,7 +99,7 @@ public class RuleChainEditMenuTest extends AbstractRuleChainTest {
assertThat(ruleChainsPage.getDescription()).as("The description changed correctly").isEqualTo(finalDescription);
}
@Test(priority = 20, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "debugMode")
@Test(priority = 20, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "enable")
@Description("Enable debug mode/Disable debug mode")
public void debugMode(boolean debugMode) {
ruleChainName = ENTITY_NAME + random();

View File

@ -36,10 +36,13 @@ public class Const {
public static final String EMPTY_CUSTOMER_MESSAGE = "Customer title should be specified!";
public static final String EMPTY_DEVICE_PROFILE_MESSAGE = "Device profile name should be specified!";
public static final String EMPTY_ASSET_PROFILE_MESSAGE = "Asset profile name should be specified!";
public static final String EMPTY_DEVICE_MESSAGE = "Device name should be specified!";
public static final String DELETE_RULE_CHAIN_WITH_PROFILE_MESSAGE = "The rule chain referenced by the device profiles cannot be deleted!";
public static final String SAME_NAME_WARNING_CUSTOMER_MESSAGE = "Customer with such title already exists!";
public static final String SAME_NAME_WARNING_DEVICE_PROFILE_MESSAGE = "Device profile with such name already exists!";
public static final String SAME_NAME_WARNING_ASSET_PROFILE_MESSAGE = "Asset profile with such name already exists!";
public static final String SAME_NAME_WARNING_DEVICE_MESSAGE = "Device with such name already exists!";
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";
}

View File

@ -151,9 +151,19 @@ public class DataProviderCredential {
}
@DataProvider
public static Object[][] debugMode() {
public static Object[][] enable() {
return new Object[][]{
{false},
{true}};
}
@DataProvider
public static Object[][] editDeviceLabel() {
String newLabel = "Label" + getRandomNumber();
String label = "Label";
return new Object[][]{
{"", newLabel, newLabel},
{label, newLabel, label + newLabel},
{label, Keys.CONTROL + "A" + Keys.BACK_SPACE, ""}};
}
}

View File

@ -192,6 +192,41 @@ public class EntityPrototypes {
return device;
}
public static Device defaultDevicePrototype(String name, String description) {
Device device = new Device();
device.setName(name + RandomStringUtils.randomAlphanumeric(7));
device.setType("DEFAULT");
device.setAdditionalInfo(JacksonUtil.newObjectNode().put("description", description));
return device;
}
public static Device defaultDevicePrototype(String name, String description, String label) {
Device device = new Device();
device.setName(name + RandomStringUtils.randomAlphanumeric(7));
device.setType("DEFAULT");
device.setAdditionalInfo(JacksonUtil.newObjectNode().put("description", description));
device.setLabel(label);
return device;
}
public static Device defaultDevicePrototype(String name, boolean gateway) {
Device device = new Device();
device.setName(name + RandomStringUtils.randomAlphanumeric(7));
device.setType("DEFAULT");
device.setAdditionalInfo(JacksonUtil.newObjectNode().put("gateway", gateway));
return device;
}
public static Device defaultDevicePrototype(String name, boolean gateway, boolean overwriteActivityTime) {
Device device = new Device();
device.setName(name + RandomStringUtils.randomAlphanumeric(7));
device.setType("DEFAULT");
device.setAdditionalInfo(JacksonUtil.newObjectNode()
.put("gateway", gateway)
.put("overwriteActivityTime", overwriteActivityTime));
return device;
}
public static Asset defaultAssetPrototype(String name, CustomerId id) {
Asset asset = new Asset();
asset.setName(name + RandomStringUtils.randomAlphanumeric(7));

View File

@ -67,4 +67,14 @@
<package name="org.thingsboard.server.msa.ui.tests.assetProfileSmoke"/>
</packages>
</test>
<test name="Smoke devices tests">
<groups>
<run>
<exclude name="broken"/>
</run>
</groups>
<packages>
<package name="org.thingsboard.server.msa.ui.tests.devicessmoke"/>
</packages>
</test>
</suite>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
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.
-->
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Devices Smoke Tests">
<listeners>
<listener class-name="org.thingsboard.server.msa.ui.listeners.RetryTestListener"/>
</listeners>
<test name="Devices ui smoke tests">
<groups>
<run>
<exclude name="broken"/>
</run>
</groups>
<packages>
<package name="org.thingsboard.server.msa.ui.tests.devicessmoke"/>
</packages>
</test>
</suite>

View File

@ -62,4 +62,14 @@
<package name="org.thingsboard.server.msa.ui.tests.assetProfileSmoke"/>
</packages>
</test>
<test name="Smoke devices tests">
<groups>
<run>
<exclude name="broken"/>
</run>
</groups>
<packages>
<package name="org.thingsboard.server.msa.ui.tests.devicessmoke"/>
</packages>
</test>
</suite>