Browse Source

Add tests for mobile app notifications

pull/8522/head
ViacheslavKlimov 3 years ago
parent
commit
17a3065c64
  1. 3
      application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
  2. 4
      application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java
  3. 9
      application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java
  4. 26
      application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java
  5. 60
      application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java

3
application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java

@ -280,9 +280,6 @@ public class ThingsboardInstallService {
log.info("Upgrading ThingsBoard from version 3.6.2 to 3.6.3 ...");
databaseEntitiesUpgradeService.upgradeDatabase("3.6.2");
//TODO DON'T FORGET to update switch statement in the CacheCleanupService if you need to clear the cache
case "3.6.2":
log.info("Upgrading ThingsBoard from version 3.6.2 to 3.6.3 ...");
databaseEntitiesUpgradeService.upgradeDatabase("3.6.2");
break;
default:
throw new RuntimeException("Unable to upgrade ThingsBoard, unsupported fromVersion: " + upgradeFromVersion);

4
application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java

@ -245,11 +245,11 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
if (targetConfig.getUsersFilter().getType().isForRules() && ctx.getRequest().getInfo() instanceof RuleOriginatedNotificationInfo) {
recipients = new PageDataIterable<>(pageLink -> {
return notificationTargetService.findRecipientsForRuleNotificationTargetConfig(ctx.getTenantId(), targetConfig, (RuleOriginatedNotificationInfo) ctx.getRequest().getInfo(), pageLink);
}, 500);
}, 256);
} else {
recipients = new PageDataIterable<>(pageLink -> {
return notificationTargetService.findRecipientsForNotificationTargetConfig(ctx.getTenantId(), targetConfig, pageLink);
}, 500);
}, 256);
}
break;
}

9
application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java

@ -26,6 +26,7 @@ import com.google.firebase.messaging.FirebaseMessagingException;
import com.google.firebase.messaging.Message;
import com.google.firebase.messaging.Notification;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;
import org.thingsboard.rule.engine.api.notification.FirebaseService;
@ -36,6 +37,7 @@ import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
@Service
@Slf4j
public class DefaultFirebaseService implements FirebaseService {
private final Cache<String, FirebaseContext> contexts = Caffeine.newBuilder()
@ -66,6 +68,7 @@ public class DefaultFirebaseService implements FirebaseService {
.setToken(fcmToken)
.build();
firebaseContext.getMessaging().send(message);
log.trace("[{}] Sent message for FCM token {}", tenantId, fcmToken);
}
public static class FirebaseContext {
@ -100,13 +103,16 @@ public class DefaultFirebaseService implements FirebaseService {
} catch (IllegalStateException alreadyExists) { // should never normally happen
messaging = FirebaseMessaging.getInstance(app);
}
log.debug("[{}] Initialized new FirebaseContext", key);
}
public void check(String credentials) {
if (!this.credentials.equals(credentials)) {
app.delete();
destroy();
this.credentials = credentials;
init();
} else if (app == null || messaging == null) {
throw new IllegalStateException("Firebase app couldn't be initialized");
}
}
@ -114,6 +120,7 @@ public class DefaultFirebaseService implements FirebaseService {
app.delete();
app = null;
messaging = null;
log.debug("[{}] Destroyed FirebaseContext", key);
}
}

26
application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java

@ -41,6 +41,7 @@ import org.thingsboard.server.common.data.notification.rule.DefaultNotificationR
import org.thingsboard.server.common.data.notification.rule.NotificationRule;
import org.thingsboard.server.common.data.notification.rule.NotificationRuleInfo;
import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.settings.NotificationDeliveryMethodConfig;
import org.thingsboard.server.common.data.notification.settings.NotificationSettings;
import org.thingsboard.server.common.data.notification.targets.NotificationTarget;
import org.thingsboard.server.common.data.notification.targets.platform.PlatformUsersNotificationTargetConfig;
@ -48,6 +49,8 @@ import org.thingsboard.server.common.data.notification.targets.platform.UserList
import org.thingsboard.server.common.data.notification.targets.platform.UsersFilter;
import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.notification.template.EmailDeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.notification.template.HasSubject;
import org.thingsboard.server.common.data.notification.template.MobileAppDeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig;
import org.thingsboard.server.common.data.notification.template.SmsDeliveryMethodNotificationTemplate;
@ -168,26 +171,28 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest
DeliveryMethodNotificationTemplate deliveryMethodNotificationTemplate;
switch (deliveryMethod) {
case WEB: {
WebDeliveryMethodNotificationTemplate template = new WebDeliveryMethodNotificationTemplate();
template.setSubject(subject);
deliveryMethodNotificationTemplate = template;
deliveryMethodNotificationTemplate = new WebDeliveryMethodNotificationTemplate();
break;
}
case EMAIL: {
EmailDeliveryMethodNotificationTemplate template = new EmailDeliveryMethodNotificationTemplate();
template.setSubject(subject);
deliveryMethodNotificationTemplate = template;
deliveryMethodNotificationTemplate = new EmailDeliveryMethodNotificationTemplate();
break;
}
case SMS: {
deliveryMethodNotificationTemplate = new SmsDeliveryMethodNotificationTemplate();
break;
}
case MOBILE_APP:
deliveryMethodNotificationTemplate = new MobileAppDeliveryMethodNotificationTemplate();
break;
default:
throw new IllegalArgumentException("Unsupported delivery method " + deliveryMethod);
}
deliveryMethodNotificationTemplate.setEnabled(true);
deliveryMethodNotificationTemplate.setBody(text);
if (deliveryMethodNotificationTemplate instanceof HasSubject) {
((HasSubject) deliveryMethodNotificationTemplate).setSubject(subject);
}
config.getDeliveryMethodsTemplates().put(deliveryMethod, deliveryMethodNotificationTemplate);
}
notificationTemplate.setConfiguration(config);
@ -202,6 +207,15 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest
doPost("/api/notification/settings", notificationSettings).andExpect(status().isOk());
}
protected void saveNotificationSettings(NotificationDeliveryMethodConfig... configs) throws Exception {
NotificationSettings settings = new NotificationSettings();
settings.setDeliveryMethodsConfigs(Arrays.stream(configs)
.collect(Collectors.toMap(
NotificationDeliveryMethodConfig::getMethod, config -> config
)));
saveNotificationSettings(settings);
}
protected Pair<User, NotificationApiWsClient> createUserAndConnectWsClient(Authority authority) throws Exception {
User user = new User();
user.setTenantId(tenantId);

60
application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java

@ -24,10 +24,14 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.web.client.RestTemplate;
import org.thingsboard.rule.engine.api.NotificationCenter;
import org.thingsboard.rule.engine.api.notification.FirebaseService;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.UserMobileInfo;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.NotificationRequestId;
@ -44,11 +48,13 @@ import org.thingsboard.server.common.data.notification.NotificationRequestStats;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.notification.NotificationType;
import org.thingsboard.server.common.data.notification.info.EntityActionNotificationInfo;
import org.thingsboard.server.common.data.notification.settings.MobileAppNotificationDeliveryMethodConfig;
import org.thingsboard.server.common.data.notification.settings.NotificationSettings;
import org.thingsboard.server.common.data.notification.settings.SlackNotificationDeliveryMethodConfig;
import org.thingsboard.server.common.data.notification.settings.UserNotificationSettings;
import org.thingsboard.server.common.data.notification.targets.MicrosoftTeamsNotificationTargetConfig;
import org.thingsboard.server.common.data.notification.targets.NotificationTarget;
import org.thingsboard.server.common.data.notification.targets.platform.AllUsersFilter;
import org.thingsboard.server.common.data.notification.targets.platform.CustomerUsersFilter;
import org.thingsboard.server.common.data.notification.targets.platform.PlatformUsersNotificationTargetConfig;
import org.thingsboard.server.common.data.notification.targets.platform.SystemAdministratorsFilter;
@ -91,6 +97,8 @@ import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@DaoSqlTest
@Slf4j
@ -104,6 +112,8 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
private DbCallbackExecutorService executor;
@Autowired
private MicrosoftTeamsNotificationChannel microsoftTeamsNotificationChannel;
@MockBean
private FirebaseService firebaseService;
@Before
public void beforeEach() throws Exception {
@ -708,6 +718,56 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
assertThat(message.getPotentialAction().get(0).getTargets().get(0).getUri()).isEqualTo("https://" + expectedParams);
}
@Test
public void testMobileAppNotifications() throws Exception {
loginSysAdmin();
MobileAppNotificationDeliveryMethodConfig config = new MobileAppNotificationDeliveryMethodConfig();
config.setFirebaseServiceAccountCredentials("testCredentials");
saveNotificationSettings(config);
loginCustomerUser();
UserMobileInfo customerMobileInfo = new UserMobileInfo();
customerMobileInfo.setFcmToken("customerFcmToken");
doPost("/api/user/mobile/info", customerMobileInfo).andExpect(status().isOk());
loginTenantAdmin();
UserMobileInfo tenantMobileInfo = new UserMobileInfo();
tenantMobileInfo.setFcmToken("tenantFcmToken");
doPost("/api/user/mobile/info", tenantMobileInfo).andExpect(status().isOk());
loginDifferentCustomer(); // with no mobile info
loginTenantAdmin();
NotificationTarget target = createNotificationTarget(new AllUsersFilter());
NotificationTemplate template = createNotificationTemplate(NotificationType.GENERAL, "Title", "Message", NotificationDeliveryMethod.MOBILE_APP);
NotificationRequest request = submitNotificationRequest(List.of(target.getId()), template.getId(), 0);
NotificationRequestStats stats = awaitNotificationRequest(request.getId());
assertThat(stats.getSent().get(NotificationDeliveryMethod.MOBILE_APP)).hasValue(2);
assertThat(stats.getErrors().get(NotificationDeliveryMethod.MOBILE_APP).get(differentCustomerUser.getEmail()))
.contains("doesn't use the mobile app");
verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"),
eq("tenantFcmToken"), eq("Title"), eq("Message"));
verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"),
eq("customerFcmToken"), eq("Title"), eq("Message"));
verifyNoMoreInteractions(firebaseService);
}
@Test
public void testMobileSettings_tenantLevel() throws Exception {
MobileAppNotificationDeliveryMethodConfig config = new MobileAppNotificationDeliveryMethodConfig();
config.setFirebaseServiceAccountCredentials("testCredentials");
NotificationSettings settings = new NotificationSettings();
settings.setDeliveryMethodsConfigs(Map.of(
NotificationDeliveryMethod.MOBILE_APP, config
));
ResultActions result = doPost("/api/notification/settings", settings)
.andExpect(status().isBadRequest());
assertThat(getErrorMessage(result)).contains("can only be configured by system administrator");
}
private NotificationRequestStats submitNotificationRequestAndWait(NotificationRequest notificationRequest) throws Exception {
SettableFuture<NotificationRequestStats> future = SettableFuture.create();
notificationCenter.processNotificationRequest(notificationRequest.getTenantId(), notificationRequest, new FutureCallback<>() {

Loading…
Cancel
Save