From f4f4c07177948e8dede6d807650dd9c8f774d3d4 Mon Sep 17 00:00:00 2001 From: Nicolas QUINQUENEL Date: Wed, 13 Nov 2024 12:19:10 +0100 Subject: [PATCH] SLI-1704 Add tests for notifications --- clion-common/build.gradle.kts | 2 - .../SonarLintProjectNotifications.kt | 13 - .../SonarLintProjectNotificationsTests.kt | 275 ++++++++++++++++++ 3 files changed, 275 insertions(+), 15 deletions(-) create mode 100644 src/test/java/org/sonarlint/intellij/notifications/SonarLintProjectNotificationsTests.kt diff --git a/clion-common/build.gradle.kts b/clion-common/build.gradle.kts index cfe90c86a..a0eab8024 100644 --- a/clion-common/build.gradle.kts +++ b/clion-common/build.gradle.kts @@ -18,8 +18,6 @@ dependencies { implementation(project(":common")) testImplementation(libs.junit.api) testImplementation(libs.mockito.core) - testImplementation(libs.junit.api) - testRuntimeOnly(libs.junit.engine) testRuntimeOnly(libs.junit.engine) compileOnly(libs.findbugs.jsr305) } diff --git a/src/main/java/org/sonarlint/intellij/notifications/SonarLintProjectNotifications.kt b/src/main/java/org/sonarlint/intellij/notifications/SonarLintProjectNotifications.kt index eedc64c15..7f6af42f2 100644 --- a/src/main/java/org/sonarlint/intellij/notifications/SonarLintProjectNotifications.kt +++ b/src/main/java/org/sonarlint/intellij/notifications/SonarLintProjectNotifications.kt @@ -268,19 +268,6 @@ class SonarLintProjectNotifications(private val myProject: Project) { } } - fun showTaintNotification(message: String, action: AnAction) { - taintGroup.createNotification( - "Taint vulnerabilities", - message, - NotificationType.ERROR - ).apply { - icon = SonarLintIcons.SONARLINT - isImportant = true - addAction(action) - notify(myProject) - } - } - fun createNotificationOnce(title: String, content: String, vararg actions: NotificationAction) { analyzerRequirementGroup.createNotification( title, diff --git a/src/test/java/org/sonarlint/intellij/notifications/SonarLintProjectNotificationsTests.kt b/src/test/java/org/sonarlint/intellij/notifications/SonarLintProjectNotificationsTests.kt new file mode 100644 index 000000000..bae6765be --- /dev/null +++ b/src/test/java/org/sonarlint/intellij/notifications/SonarLintProjectNotificationsTests.kt @@ -0,0 +1,275 @@ +package org.sonarlint.intellij.notifications + +import com.google.common.collect.Lists +import com.intellij.notification.Notification +import com.intellij.notification.NotificationGroup +import com.intellij.notification.NotificationType +import com.intellij.notification.Notifications +import com.intellij.notification.NotificationsManager +import com.intellij.util.messages.MessageBusConnection +import java.util.stream.Stream +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.sonarlint.intellij.AbstractSonarLintLightTests +import org.sonarlint.intellij.SonarLintIcons +import org.sonarlint.intellij.config.global.ServerConnection +import org.sonarsource.sonarlint.core.rpc.protocol.client.smartnotification.ShowSmartNotificationParams + +class SonarLintProjectNotificationsTests : AbstractSonarLintLightTests() { + + private lateinit var notifications: MutableList + private lateinit var busConnection: MessageBusConnection + private lateinit var sonarLintProjectNotifications: SonarLintProjectNotifications + + @BeforeEach + fun before() { + sonarLintProjectNotifications = SonarLintProjectNotifications(project) + + // register a listener to catch all notifications + notifications = Lists.newCopyOnWriteArrayList() + val project = project + busConnection = project.messageBus.connect(project) + busConnection.subscribe(Notifications.TOPIC, object : Notifications { + override fun notify(notification: Notification) { + notifications.add(notification) + } + }) + } + + @AfterEach + fun expireAfterTest() { + val mgr = NotificationsManager.getNotificationsManager() + val notifs = mgr.getNotificationsOfType(Notification::class.java, project) + Stream.of(*notifs).forEach { notification -> mgr.expire(notification) } + busConnection.disconnect() + } + + @Test + fun should_notify_project_binding_invalid_and_unbound() { + sonarLintProjectNotifications.notifyProjectBindingInvalidAndUnbound() + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].title).isEqualTo("SonarLint - Invalid binding") + Assertions.assertThat(notifications[0].content) + .isEqualTo("Project binding is invalid and has been removed, the connection has probably been deleted previously.") + Assertions.assertThat(notifications[0].type).isEqualTo(NotificationType.WARNING) + Assertions.assertThat(notifications[0].icon).isEqualTo(SonarLintIcons.SONARLINT) + Assertions.assertThat(notifications[0].actions.size).isEqualTo(1) + } + + @Test + fun should_notify_language_promotion() { + val content = "content" + + sonarLintProjectNotifications.notifyLanguagePromotion(content) + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].title).isEqualTo("SonarLint suggestions") + Assertions.assertThat(notifications[0].content).isEqualTo(content) + Assertions.assertThat(notifications[0].type).isEqualTo(NotificationType.INFORMATION) + Assertions.assertThat(notifications[0].icon).isEqualTo(SonarLintIcons.SONARLINT) + Assertions.assertThat(notifications[0].actions.size).isEqualTo(4) + } + + @Test + fun should_notify_unable_to_open_finding() { + val type = "issue" + val message = "message" + + sonarLintProjectNotifications.notifyUnableToOpenFinding(type, message) + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].title).isEqualTo("SonarLint - Unable to open $type") + Assertions.assertThat(notifications[0].content).isEqualTo(message) + Assertions.assertThat(notifications[0].type).isEqualTo(NotificationType.INFORMATION) + Assertions.assertThat(notifications[0].isExpired).isEqualTo(false) + Assertions.assertThat(notifications[0].icon).isEqualTo(SonarLintIcons.SONARLINT) + Assertions.assertThat(notifications[0].actions).isEmpty() + } + + @Test + fun should_expire_current_finding_notification() { + val type = "issue" + val message = "message" + sonarLintProjectNotifications.notifyUnableToOpenFinding(type, message) + + sonarLintProjectNotifications.expireCurrentFindingNotificationIfNeeded() + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].isExpired).isEqualTo(true) + } + + @Test + fun should_handle_sonarqube_smart_notification() { + val connection = ServerConnection.newBuilder().setName("connectionId").setHostUrl("url").build() + globalSettings.serverConnections = listOf(connection) + + val param = ShowSmartNotificationParams( + "text", + "link", + setOf("scopeId"), + "category", + "connectionId" + ) + + sonarLintProjectNotifications.handle(param) + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].title).isEqualTo("SonarQube Notification") + Assertions.assertThat(notifications[0].content).isEqualTo("text") + Assertions.assertThat(notifications[0].type).isEqualTo(NotificationType.INFORMATION) + Assertions.assertThat(notifications[0].icon).isEqualTo(SonarLintIcons.ICON_SONARQUBE_16) + Assertions.assertThat(notifications[0].actions.size).isEqualTo(2) + } + + @Test + fun should_handle_sonarcloud_smart_notification() { + val connection = ServerConnection.newBuilder().setName("connectionId").setHostUrl("https://sonarcloud.io").build() + globalSettings.serverConnections = listOf(connection) + + val param = ShowSmartNotificationParams( + "text", + "link", + setOf("scopeId"), + "category", + "connectionId" + ) + + sonarLintProjectNotifications.handle(param) + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].title).isEqualTo("SonarCloud Notification") + Assertions.assertThat(notifications[0].content).isEqualTo("text") + Assertions.assertThat(notifications[0].type).isEqualTo(NotificationType.INFORMATION) + Assertions.assertThat(notifications[0].icon).isEqualTo(SonarLintIcons.ICON_SONARCLOUD_16) + Assertions.assertThat(notifications[0].actions.size).isEqualTo(2) + } + + @Test + fun should_display_successful_notification() { + val content = "content" + val group = NotificationGroup.allRegisteredGroups.first() + + sonarLintProjectNotifications.displaySuccessfulNotification(content, group) + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].title).isBlank() + Assertions.assertThat(notifications[0].content).isEqualTo(content) + Assertions.assertThat(notifications[0].type).isEqualTo(NotificationType.INFORMATION) + Assertions.assertThat(notifications[0].icon).isEqualTo(SonarLintIcons.SONARLINT) + Assertions.assertThat(notifications[0].actions).isEmpty() + } + + @Test + fun should_display_error_notification() { + val title = "title" + val content = "content" + val group = NotificationGroup.allRegisteredGroups.first() + + sonarLintProjectNotifications.displayErrorNotification(title, content, group) + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].title).isEqualTo(title) + Assertions.assertThat(notifications[0].content).isEqualTo(content) + Assertions.assertThat(notifications[0].type).isEqualTo(NotificationType.ERROR) + Assertions.assertThat(notifications[0].icon).isEqualTo(SonarLintIcons.SONARLINT) + Assertions.assertThat(notifications[0].actions.size).isEqualTo(1) + } + + @Test + fun should_display_warning_notification() { + val content = "content" + val group = NotificationGroup.allRegisteredGroups.first() + + sonarLintProjectNotifications.displayWarningNotification(content, group) + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].title).isBlank() + Assertions.assertThat(notifications[0].content).isEqualTo(content) + Assertions.assertThat(notifications[0].type).isEqualTo(NotificationType.WARNING) + Assertions.assertThat(notifications[0].icon).isEqualTo(SonarLintIcons.SONARLINT) + Assertions.assertThat(notifications[0].actions.size).isEqualTo(1) + } + + @Test + fun should_send_notification_for_secret() { + sonarLintProjectNotifications.sendNotification() + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].title).isEqualTo("SonarLint: secret(s) detected") + Assertions.assertThat(notifications[0].content).isEqualTo( + "SonarLint detected some secrets in one of the open files. " + + "We strongly advise you to review those secrets and ensure they are not committed into repositories. " + + "Please refer to the SonarLint tool window for more information." + ) + Assertions.assertThat(notifications[0].type).isEqualTo(NotificationType.WARNING) + Assertions.assertThat(notifications[0].icon).isEqualTo(SonarLintIcons.SONARLINT) + Assertions.assertThat(notifications[0].actions).isEmpty() + } + + @Test + fun should_display_one_time_balloon() { + val message = "message" + val doNotShowAgainId = "id" + + sonarLintProjectNotifications.showOneTimeBalloon(message, doNotShowAgainId, null) + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].title).isBlank() + Assertions.assertThat(notifications[0].content).isEqualTo(message) + Assertions.assertThat(notifications[0].type).isEqualTo(NotificationType.WARNING) + Assertions.assertThat(notifications[0].icon).isEqualTo(SonarLintIcons.SONARLINT) + Assertions.assertThat(notifications[0].actions.size).isEqualTo(1) + } + + @Test + fun should_show_shared_configuration() { + val title = "title" + val message = "message" + val doNotShowAgainId = "id" + + sonarLintProjectNotifications.showSharedConfigurationNotification(title, message, doNotShowAgainId) + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].title).isEqualTo(title) + Assertions.assertThat(notifications[0].content).isEqualTo(message) + Assertions.assertThat(notifications[0].type).isEqualTo(NotificationType.WARNING) + Assertions.assertThat(notifications[0].icon).isEqualTo(SonarLintIcons.SONARLINT) + Assertions.assertThat(notifications[0].actions.size).isEqualTo(2) + } + + @Test + fun should_show_auto_shared_configuration() { + val title = "title" + val message = "message" + val doNotShowAgainId = "id" + + sonarLintProjectNotifications.showAutoSharedConfigurationNotification(title, message, doNotShowAgainId, null) + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].title).isEqualTo(title) + Assertions.assertThat(notifications[0].content).isEqualTo(message) + Assertions.assertThat(notifications[0].type).isEqualTo(NotificationType.INFORMATION) + Assertions.assertThat(notifications[0].icon).isEqualTo(SonarLintIcons.SONARLINT) + Assertions.assertThat(notifications[0].actions.size).isEqualTo(1) + } + + @Test + fun should_display_simple_notification() { + val title = "title" + val message = "message" + val type = NotificationType.INFORMATION + + sonarLintProjectNotifications.simpleNotification(title, message, type) + + Assertions.assertThat(notifications).hasSize(1) + Assertions.assertThat(notifications[0].title).isEqualTo(title) + Assertions.assertThat(notifications[0].content).isEqualTo(message) + Assertions.assertThat(notifications[0].type).isEqualTo(type) + Assertions.assertThat(notifications[0].icon).isEqualTo(SonarLintIcons.SONARLINT) + Assertions.assertThat(notifications[0].actions).isEmpty() + } + +}