From 6612fe1124e8ceb5bea1c0cc36d864dedd04aa2b Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Wed, 12 Jun 2024 08:55:48 +0200 Subject: [PATCH 01/12] chore: wip - settings window --- .../ActivatePluginPostStartupActivity.kt | 24 ++++++++++ .../settings/PluginSettingsConfigurable.kt | 46 +++++++++++++++++++ .../jbplugin/settings/PluginSettingsState.kt | 20 ++++++++ ...bplugin.notifications.Telemetry.properties | 1 + .../src/main/resources/META-INF/plugin.xml | 8 ++++ 5 files changed, 99 insertions(+) create mode 100644 packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsConfigurable.kt create mode 100644 packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsState.kt create mode 100644 packages/jetbrains-plugin/src/main/resources/META-INF/com.mongodb.jbplugin.notifications.Telemetry.properties diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt index bec0c1fd..d4a69ed3 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt @@ -1,13 +1,25 @@ package com.mongodb.jbplugin +import com.intellij.notification.NotificationGroupManager +import com.intellij.notification.NotificationType +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.options.ShowSettingsUtil import com.intellij.openapi.project.DumbAware import com.intellij.openapi.project.Project import com.intellij.openapi.startup.StartupActivity import com.mongodb.jbplugin.observability.probe.PluginActivatedProbe +import com.mongodb.jbplugin.settings.PluginSettingsConfigurable +import com.mongodb.jbplugin.settings.useSettings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch +class OpenMongoDBPluginSettingsAction : AnAction("Open Settings") { + override fun actionPerformed(e: AnActionEvent) { + ShowSettingsUtil.getInstance().showSettingsDialog(e.project, PluginSettingsConfigurable::class.java) + } +} /** * This notifies that the plugin has been activated. * @@ -18,6 +30,18 @@ class ActivatePluginPostStartupActivity(private val cs: CoroutineScope) : Startu cs.launch { val pluginActivated = ApplicationManager.getApplication().getService(PluginActivatedProbe::class.java) pluginActivated.pluginActivated() + + val settings = useSettings() + if (!settings.hasTelemetryOptOutputNotificationBeenShown) { + NotificationGroupManager.getInstance() + .getNotificationGroup("com.mongodb.jbplugin.notifications.Telemetry") + .createNotification("MongoDB plugin telemetry", "Anonymous telemetry is enabled by default, as it helps us improve the plugin. However, you can disable it in settings and we won't ask you to enable it again.", NotificationType.INFORMATION) + .setImportant(true) + .addAction(OpenMongoDBPluginSettingsAction()) + .notify(project) + + settings.hasTelemetryOptOutputNotificationBeenShown = true + } } } } diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsConfigurable.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsConfigurable.kt new file mode 100644 index 00000000..214e83df --- /dev/null +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsConfigurable.kt @@ -0,0 +1,46 @@ +package com.mongodb.jbplugin.settings + +import com.intellij.openapi.options.Configurable +import com.intellij.ui.components.JBCheckBox +import com.intellij.util.ui.FormBuilder +import javax.swing.JComponent +import javax.swing.JPanel + +class PluginSettingsConfigurable: Configurable { + private lateinit var settingsComponent: PluginSettingsComponent + + override fun createComponent(): JComponent { + settingsComponent = PluginSettingsComponent() + return settingsComponent.root + } + + override fun isModified(): Boolean { + val savedSettings = useSettings() + return settingsComponent.isTelemetryEnabledCheckBox.isSelected != savedSettings.isTelemetryEnabled + } + + override fun apply() { + val savedSettings = useSettings() + savedSettings.isTelemetryEnabled = settingsComponent.isTelemetryEnabledCheckBox.isSelected + } + + override fun reset() { + val savedSettings = useSettings() + settingsComponent.isTelemetryEnabledCheckBox.isSelected = savedSettings.isTelemetryEnabled + } + + override fun getDisplayName() = "MongoDB" +} + +class PluginSettingsComponent { + internal val root: JPanel + internal val isTelemetryEnabledCheckBox = JBCheckBox("Enable telemetry") + + init { + root = FormBuilder.createFormBuilder() + .addComponent(isTelemetryEnabledCheckBox) + .addTooltip("Allow the collection of anonymous diagnostics and usage telemetry data to help improve the product.") + .addComponentFillVertically(JPanel(), 0) + .panel + } +} \ No newline at end of file diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsState.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsState.kt new file mode 100644 index 00000000..eb620acc --- /dev/null +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsState.kt @@ -0,0 +1,20 @@ +package com.mongodb.jbplugin.settings + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.components.* + +@Service +@State( + name = "com.mongodb.jbplugin.settings.PluginSettings", + storages = [ Storage(value = "MongoDBPluginSettings.xml") ], +) +class PluginSettings : SimplePersistentStateComponent(PluginSettingsState()) + +class PluginSettingsState : BaseState() { + var isTelemetryEnabled by property(true) + var hasTelemetryOptOutputNotificationBeenShown by property(false) +} + +fun useSettings(): PluginSettingsState { + return ApplicationManager.getApplication().getService(PluginSettings::class.java).state +} \ No newline at end of file diff --git a/packages/jetbrains-plugin/src/main/resources/META-INF/com.mongodb.jbplugin.notifications.Telemetry.properties b/packages/jetbrains-plugin/src/main/resources/META-INF/com.mongodb.jbplugin.notifications.Telemetry.properties new file mode 100644 index 00000000..e0b36225 --- /dev/null +++ b/packages/jetbrains-plugin/src/main/resources/META-INF/com.mongodb.jbplugin.notifications.Telemetry.properties @@ -0,0 +1 @@ +notification.group.name=Hey \ No newline at end of file diff --git a/packages/jetbrains-plugin/src/main/resources/META-INF/plugin.xml b/packages/jetbrains-plugin/src/main/resources/META-INF/plugin.xml index 98d97504..9d3ebf15 100644 --- a/packages/jetbrains-plugin/src/main/resources/META-INF/plugin.xml +++ b/packages/jetbrains-plugin/src/main/resources/META-INF/plugin.xml @@ -11,6 +11,14 @@ + + From 8793fc091970546de381204b7d8f8a75d8cd7b6b Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Wed, 12 Jun 2024 09:37:00 +0200 Subject: [PATCH 02/12] chore: do not send telemetry when disabled --- gradle/diktat.yml | 2 + .../ActivatePluginPostStartupActivity.kt | 21 +++++- .../mongodb/jbplugin/i18n/SettingsMessages.kt | 25 +++++++ .../jbplugin/i18n/TelemetryMessages.kt | 25 +++++++ .../observability/TelemetryService.kt | 52 ++++++++----- .../jbplugin/settings/PluginSettings.kt | 44 +++++++++++ .../settings/PluginSettingsConfigurable.kt | 41 ++++++---- .../jbplugin/settings/PluginSettingsState.kt | 20 ----- ...bplugin.notifications.Telemetry.properties | 1 - .../src/main/resources/META-INF/plugin.xml | 2 + .../messages/SettingsBundle.properties | 1 + .../messages/TelemetryBundle.properties | 4 + .../fixtures/IntegrationTestExtensions.kt | 57 +++++++++----- .../observability/TelemetryServiceTest.kt | 75 ++++++++++++++----- 14 files changed, 276 insertions(+), 94 deletions(-) create mode 100644 packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/SettingsMessages.kt create mode 100644 packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/TelemetryMessages.kt create mode 100644 packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettings.kt delete mode 100644 packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsState.kt delete mode 100644 packages/jetbrains-plugin/src/main/resources/META-INF/com.mongodb.jbplugin.notifications.Telemetry.properties create mode 100644 packages/jetbrains-plugin/src/main/resources/messages/SettingsBundle.properties create mode 100644 packages/jetbrains-plugin/src/main/resources/messages/TelemetryBundle.properties diff --git a/gradle/diktat.yml b/gradle/diktat.yml index eca884eb..d4251db8 100644 --- a/gradle/diktat.yml +++ b/gradle/diktat.yml @@ -23,4 +23,6 @@ - name: FILE_NAME_INCORRECT # File name does not need to match class name inside enabled: false - name: LOCAL_VARIABLE_EARLY_DECLARATION # Allow declaring variables at the beginning of a function if they are mutable + enabled: false +- name: USE_DATA_CLASS # Do not force to use data classes, some intellij components won't work if they are data classes enabled: false \ No newline at end of file diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt index d4a69ed3..455bcec0 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt @@ -1,3 +1,7 @@ +/** + * These class implement the balloon that shows the first time that the plugin is activated. + */ + package com.mongodb.jbplugin import com.intellij.notification.NotificationGroupManager @@ -9,17 +13,22 @@ import com.intellij.openapi.options.ShowSettingsUtil import com.intellij.openapi.project.DumbAware import com.intellij.openapi.project.Project import com.intellij.openapi.startup.StartupActivity +import com.mongodb.jbplugin.i18n.TelemetryMessages import com.mongodb.jbplugin.observability.probe.PluginActivatedProbe import com.mongodb.jbplugin.settings.PluginSettingsConfigurable import com.mongodb.jbplugin.settings.useSettings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch -class OpenMongoDBPluginSettingsAction : AnAction("Open Settings") { - override fun actionPerformed(e: AnActionEvent) { - ShowSettingsUtil.getInstance().showSettingsDialog(e.project, PluginSettingsConfigurable::class.java) +/** + * Class that represents the link that opens the settings page for MongoDB. + */ +class OpenMongoDbpluginSettingsAction : AnAction(TelemetryMessages.message("action.disable-telemetry")) { + override fun actionPerformed(event: AnActionEvent) { + ShowSettingsUtil.getInstance().showSettingsDialog(event.project, PluginSettingsConfigurable::class.java) } } + /** * This notifies that the plugin has been activated. * @@ -35,7 +44,11 @@ class ActivatePluginPostStartupActivity(private val cs: CoroutineScope) : Startu if (!settings.hasTelemetryOptOutputNotificationBeenShown) { NotificationGroupManager.getInstance() .getNotificationGroup("com.mongodb.jbplugin.notifications.Telemetry") - .createNotification("MongoDB plugin telemetry", "Anonymous telemetry is enabled by default, as it helps us improve the plugin. However, you can disable it in settings and we won't ask you to enable it again.", NotificationType.INFORMATION) + .createNotification( + "MongoDB plugin telemetry", + "Anonymous telemetry is enabled by default, as it helps us improve the plugin.", + NotificationType.INFORMATION, + ) .setImportant(true) .addAction(OpenMongoDBPluginSettingsAction()) .notify(project) diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/SettingsMessages.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/SettingsMessages.kt new file mode 100644 index 00000000..513c1457 --- /dev/null +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/SettingsMessages.kt @@ -0,0 +1,25 @@ +package com.mongodb.jbplugin.i18n + +import com.intellij.DynamicBundle +import org.jetbrains.annotations.Nls +import org.jetbrains.annotations.NonNls +import org.jetbrains.annotations.PropertyKey +import java.util.function.Supplier + +object SettingsMessages { + @NonNls + private const val BUNDLE = "messages.SettingsBundle" + private val instance = DynamicBundle(SettingsMessages::class.java, BUNDLE) + + fun message( + key: + @PropertyKey(resourceBundle = BUNDLE) + String, + vararg params: Any, + ): @Nls String = instance.getMessage(key, *params) + + fun lazyMessage( + @PropertyKey(resourceBundle = BUNDLE) key: String, + vararg params: Any, + ): Supplier<@Nls String> = instance.getLazyMessage(key, *params) +} diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/TelemetryMessages.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/TelemetryMessages.kt new file mode 100644 index 00000000..6a77e389 --- /dev/null +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/TelemetryMessages.kt @@ -0,0 +1,25 @@ +package com.mongodb.jbplugin.i18n + +import com.intellij.DynamicBundle +import org.jetbrains.annotations.Nls +import org.jetbrains.annotations.NonNls +import org.jetbrains.annotations.PropertyKey +import java.util.function.Supplier + +object TelemetryMessages { + @NonNls + private const val BUNDLE = "messages.TelemetryBundle" + private val instance = DynamicBundle(TelemetryMessages::class.java, BUNDLE) + + fun message( + key: + @PropertyKey(resourceBundle = BUNDLE) + String, + vararg params: Any, + ): @Nls String = instance.getMessage(key, *params) + + fun lazyMessage( + @PropertyKey(resourceBundle = BUNDLE) key: String, + vararg params: Any, + ): Supplier<@Nls String> = instance.getLazyMessage(key, *params) +} diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/TelemetryService.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/TelemetryService.kt index b6b5ba62..aa0ff75d 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/TelemetryService.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/observability/TelemetryService.kt @@ -6,6 +6,7 @@ import com.intellij.openapi.components.Service import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.logger import com.mongodb.jbplugin.meta.BuildInformation +import com.mongodb.jbplugin.settings.useSettings import com.segment.analytics.Analytics import com.segment.analytics.messages.IdentifyMessage import com.segment.analytics.messages.TrackMessage @@ -18,9 +19,10 @@ private val logger: Logger = logger() */ @Service internal class TelemetryService : AppLifecycleListener { - internal var analytics: Analytics = Analytics - .builder(BuildInformation.segmentApiKey) - .build() + internal var analytics: Analytics = + Analytics + .builder(BuildInformation.segmentApiKey) + .build() init { ApplicationManager.getApplication() @@ -28,38 +30,50 @@ internal class TelemetryService : AppLifecycleListener { .connect() .subscribe( AppLifecycleListener.TOPIC, - this + this, ) } fun sendEvent(event: TelemetryEvent) { - val runtimeInformationService = ApplicationManager.getApplication().getService( - RuntimeInformationService::class.java - ) - val runtimeInfo = runtimeInformationService.get() + if (!useSettings().isTelemetryEnabled) { + return + } - val message = when (event) { - is TelemetryEvent.PluginActivated -> IdentifyMessage.builder().userId(runtimeInfo.userId) - else -> - TrackMessage.builder(event.name).userId(runtimeInfo.userId) - .properties(event.properties.entries.associate { - it.key.publicName to it.value - }) + val runtimeInformationService = + ApplicationManager.getApplication().getService( + RuntimeInformationService::class.java, + ) + val runtimeInfo = runtimeInformationService.get() - } + val message = + when (event) { + is TelemetryEvent.PluginActivated -> IdentifyMessage.builder().userId(runtimeInfo.userId) + else -> + TrackMessage.builder(event.name).userId(runtimeInfo.userId) + .properties( + event.properties.entries.associate { + it.key.publicName to it.value + }, + ) + } analytics.enqueue(message) } override fun appWillBeClosed(isRestart: Boolean) { + val telemetryEnabled = useSettings().isTelemetryEnabled val logMessage = ApplicationManager.getApplication().getService(LogMessage::class.java) logger.info( - logMessage.message("Flushing Segment analytics because the IDE is closing.") + logMessage.message("Shutting down Segment analytics because the IDE is closing.") .put("isRestart", isRestart) - .build() + .put("telemetryEnabled", telemetryEnabled) + .build(), ) - analytics.flush() + if (telemetryEnabled) { + analytics.flush() + } + analytics.shutdown() } } diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettings.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettings.kt new file mode 100644 index 00000000..55adfadc --- /dev/null +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettings.kt @@ -0,0 +1,44 @@ +/** + * Settings state for the plugin. These classes are responsible for the persistence of the plugin + * settings. + */ + +package com.mongodb.jbplugin.settings + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.components.* + +/** + * The state component represents the persisting state. Don't use directly, this is only necessary + * for the state to be persisted. Use PluginSettings instead. + * + * @see PluginSettings + */ +@Service +@State( + name = "com.mongodb.jbplugin.settings.PluginSettings", + storages = [Storage(value = "MongoDBPluginSettings.xml")], +) +class PluginSettingsStateComponent : SimplePersistentStateComponent(PluginSettings()) + +/** + * The settings themselves. They are tracked, so any change on the settings properties will be eventually + * persisted by IntelliJ. To access the settings, use the useSettings provider. + * + * @see useSettings + */ +class PluginSettings : BaseState() { + var isTelemetryEnabled by property(true) + var hasTelemetryOptOutputNotificationBeenShown by property(false) +} + +/** + * Function that provides a reference to the current PluginSettings. + * + * @see PluginSettings + * + * @return + */ +fun useSettings(): PluginSettings = ApplicationManager.getApplication().getService( +PluginSettingsStateComponent::class.java +).state diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsConfigurable.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsConfigurable.kt index 214e83df..230acd92 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsConfigurable.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsConfigurable.kt @@ -1,12 +1,22 @@ +/** + * These classes represent the settings modal. + */ + package com.mongodb.jbplugin.settings import com.intellij.openapi.options.Configurable import com.intellij.ui.components.JBCheckBox import com.intellij.util.ui.FormBuilder +import com.mongodb.jbplugin.i18n.SettingsMessages +import com.mongodb.jbplugin.i18n.TelemetryMessages import javax.swing.JComponent import javax.swing.JPanel -class PluginSettingsConfigurable: Configurable { +/** + * This class represents a section in the settings modal. The UI will be implemented by + * PluginSettingsComponent. + */ +class PluginSettingsConfigurable : Configurable { private lateinit var settingsComponent: PluginSettingsComponent override fun createComponent(): JComponent { @@ -20,8 +30,9 @@ class PluginSettingsConfigurable: Configurable { } override fun apply() { - val savedSettings = useSettings() - savedSettings.isTelemetryEnabled = settingsComponent.isTelemetryEnabledCheckBox.isSelected + val savedSettings = useSettings().apply { + isTelemetryEnabled = settingsComponent.isTelemetryEnabledCheckBox.isSelected +} } override fun reset() { @@ -29,18 +40,22 @@ class PluginSettingsConfigurable: Configurable { settingsComponent.isTelemetryEnabledCheckBox.isSelected = savedSettings.isTelemetryEnabled } - override fun getDisplayName() = "MongoDB" + override fun getDisplayName() = SettingsMessages.message("settings.display-name") } -class PluginSettingsComponent { - internal val root: JPanel - internal val isTelemetryEnabledCheckBox = JBCheckBox("Enable telemetry") +/** + * The panel that is shown in the settings section for MongoDB. + */ +private class PluginSettingsComponent { + val root: JPanel + val isTelemetryEnabledCheckBox = JBCheckBox(TelemetryMessages.message("settings.telemetry-collection-checkbox")) init { - root = FormBuilder.createFormBuilder() - .addComponent(isTelemetryEnabledCheckBox) - .addTooltip("Allow the collection of anonymous diagnostics and usage telemetry data to help improve the product.") - .addComponentFillVertically(JPanel(), 0) - .panel + root = + FormBuilder.createFormBuilder() + .addComponent(isTelemetryEnabledCheckBox) + .addTooltip(TelemetryMessages.message("settings.telemetry-collection-tooltip")) + .addComponentFillVertically(JPanel(), 0) + .panel } -} \ No newline at end of file +} diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsState.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsState.kt deleted file mode 100644 index eb620acc..00000000 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsState.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.mongodb.jbplugin.settings - -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.components.* - -@Service -@State( - name = "com.mongodb.jbplugin.settings.PluginSettings", - storages = [ Storage(value = "MongoDBPluginSettings.xml") ], -) -class PluginSettings : SimplePersistentStateComponent(PluginSettingsState()) - -class PluginSettingsState : BaseState() { - var isTelemetryEnabled by property(true) - var hasTelemetryOptOutputNotificationBeenShown by property(false) -} - -fun useSettings(): PluginSettingsState { - return ApplicationManager.getApplication().getService(PluginSettings::class.java).state -} \ No newline at end of file diff --git a/packages/jetbrains-plugin/src/main/resources/META-INF/com.mongodb.jbplugin.notifications.Telemetry.properties b/packages/jetbrains-plugin/src/main/resources/META-INF/com.mongodb.jbplugin.notifications.Telemetry.properties deleted file mode 100644 index e0b36225..00000000 --- a/packages/jetbrains-plugin/src/main/resources/META-INF/com.mongodb.jbplugin.notifications.Telemetry.properties +++ /dev/null @@ -1 +0,0 @@ -notification.group.name=Hey \ No newline at end of file diff --git a/packages/jetbrains-plugin/src/main/resources/META-INF/plugin.xml b/packages/jetbrains-plugin/src/main/resources/META-INF/plugin.xml index 9d3ebf15..855f9d32 100644 --- a/packages/jetbrains-plugin/src/main/resources/META-INF/plugin.xml +++ b/packages/jetbrains-plugin/src/main/resources/META-INF/plugin.xml @@ -18,6 +18,8 @@ displayName="MongoDB"/> diff --git a/packages/jetbrains-plugin/src/main/resources/messages/SettingsBundle.properties b/packages/jetbrains-plugin/src/main/resources/messages/SettingsBundle.properties new file mode 100644 index 00000000..2fdfdfeb --- /dev/null +++ b/packages/jetbrains-plugin/src/main/resources/messages/SettingsBundle.properties @@ -0,0 +1 @@ +settings.display-name=MongoDB \ No newline at end of file diff --git a/packages/jetbrains-plugin/src/main/resources/messages/TelemetryBundle.properties b/packages/jetbrains-plugin/src/main/resources/messages/TelemetryBundle.properties new file mode 100644 index 00000000..c615b5c5 --- /dev/null +++ b/packages/jetbrains-plugin/src/main/resources/messages/TelemetryBundle.properties @@ -0,0 +1,4 @@ +notification.group.name=MongoDB telemetry +action.disable-telemetry=Disable Telemetry +settings.telemetry-collection-tooltip=Allow the collection of anonymous diagnostics and usage telemetry data to help improve the product. +settings.telemetry-collection-checkbox=Enable telemetry \ No newline at end of file diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/IntegrationTestExtensions.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/IntegrationTestExtensions.kt index 4f3eefb9..0a325be6 100644 --- a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/IntegrationTestExtensions.kt +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/IntegrationTestExtensions.kt @@ -17,6 +17,8 @@ import com.mongodb.jbplugin.observability.LogMessage import com.mongodb.jbplugin.observability.LogMessageBuilder import com.mongodb.jbplugin.observability.RuntimeInformation import com.mongodb.jbplugin.observability.RuntimeInformationService +import com.mongodb.jbplugin.settings.PluginSettings +import com.mongodb.jbplugin.settings.PluginSettingsStateComponent import org.junit.jupiter.api.extension.* import org.mockito.Mockito.`when` import org.mockito.Mockito.mock @@ -34,44 +36,60 @@ annotation class IntegrationTest /** * Extension class, should not be used directly. */ -private class IntegrationTestExtension : BeforeTestExecutionCallback, +private class IntegrationTestExtension : + BeforeTestExecutionCallback, AfterTestExecutionCallback, ParameterResolver { private lateinit var application: Application + private lateinit var settings: PluginSettingsStateComponent private lateinit var messageBus: MessageBus private lateinit var project: Project override fun beforeTestExecution(context: ExtensionContext?) { application = mock() project = mock() + settings = PluginSettingsStateComponent() - messageBus = RootBus(mock().apply { - `when`(this.isDisposed()).thenReturn(false) - `when`(this.isParentLazyListenersIgnored()).thenReturn(false) - `when`(this.createListener(any())).then { - val descriptor = it.arguments[0] as ListenerDescriptor - Class.forName(descriptor.listenerClassName).getConstructor().newInstance() - } - }) + messageBus = + RootBus( + mock().apply { + `when`(this.isDisposed()).thenReturn(false) + `when`(this.isParentLazyListenersIgnored()).thenReturn(false) + `when`(this.createListener(any())).then { + val descriptor = it.arguments[0] as ListenerDescriptor + Class.forName(descriptor.listenerClassName).getConstructor().newInstance() + } + }, + ) `when`(application.getMessageBus()).thenReturn(messageBus) `when`(project.getMessageBus()).thenReturn(messageBus) + application.withMockedService(settings) ApplicationManager.setApplication(application) {} } override fun afterTestExecution(context: ExtensionContext?) { } - override fun supportsParameter(parameterContext: ParameterContext?, extensionContext: ExtensionContext?): Boolean = + override fun supportsParameter( + parameterContext: ParameterContext?, + extensionContext: ExtensionContext?, + ): Boolean = parameterContext?.parameter?.type?.run { - equals(Application::class.java) || equals(Project::class.java) + equals(Application::class.java) || + equals(Project::class.java) || + equals(PluginSettings::class.java) } ?: false - override fun resolveParameter(parameterContext: ParameterContext?, extensionContext: ExtensionContext?): Any = + override fun resolveParameter( + parameterContext: ParameterContext?, + extensionContext: ExtensionContext?, + ): Any = when (parameterContext?.parameter?.type) { Application::class.java -> application Project::class.java -> project + PluginSettings::class.java -> settings.state else -> TODO() } } @@ -119,7 +137,7 @@ internal fun mockRuntimeInformationService( jvmVendor: String = "Obelisk", jvmVersion: String = "42", buildVersion: String = "2024.2", - applicationName: String = "Cool IDE" + applicationName: String = "Cool IDE", ) = mock().also { service -> `when`(service.get()).thenReturn( RuntimeInformation( @@ -129,8 +147,8 @@ internal fun mockRuntimeInformationService( jvmVendor = jvmVendor, jvmVersion = jvmVersion, buildVersion = buildVersion, - applicationName = applicationName - ) + applicationName = applicationName, + ), ) } @@ -146,8 +164,9 @@ internal fun mockRuntimeInformationService( * * @return A new mocked LogMessage */ -internal fun mockLogMessage() = mock().also { logMessage -> - `when`(logMessage.message(any())).then { message -> - LogMessageBuilder(Gson(), message.arguments[0].toString()) +internal fun mockLogMessage() = + mock().also { logMessage -> + `when`(logMessage.message(any())).then { message -> + LogMessageBuilder(Gson(), message.arguments[0].toString()) + } } -} \ No newline at end of file diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt index 7dc84a5e..d9a9114d 100644 --- a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt @@ -6,11 +6,10 @@ import com.mongodb.jbplugin.fixtures.IntegrationTest import com.mongodb.jbplugin.fixtures.mockLogMessage import com.mongodb.jbplugin.fixtures.mockRuntimeInformationService import com.mongodb.jbplugin.fixtures.withMockedService +import com.mongodb.jbplugin.settings.PluginSettings import com.segment.analytics.Analytics import org.junit.jupiter.api.Test -import org.mockito.kotlin.argThat -import org.mockito.kotlin.mock -import org.mockito.kotlin.verify +import org.mockito.kotlin.* @IntegrationTest internal class TelemetryServiceTest { @@ -18,18 +17,19 @@ internal class TelemetryServiceTest { fun `sends an identify event when a PluginActivated event is sent`(application: Application) { application.withMockedService(mockRuntimeInformationService(userId = "654321")) - val service = TelemetryService().apply { - analytics = mock() - } + val service = + TelemetryService().apply { + analytics = mock() + } service.sendEvent(TelemetryEvent.PluginActivated) verify(service.analytics).enqueue( argThat { build().let { it.userId() == "654321" && - it.type().name == "identify" + it.type().name == "identify" } - } + }, ) } @@ -37,9 +37,10 @@ internal class TelemetryServiceTest { fun `sends a new connection event as a tracking event`(application: Application) { application.withMockedService(mockRuntimeInformationService(userId = "654321")) - val service = TelemetryService().apply { - analytics = mock() - } + val service = + TelemetryService().apply { + analytics = mock() + } service.sendEvent( TelemetryEvent.NewConnection( @@ -49,17 +50,17 @@ internal class TelemetryServiceTest { isGenuine = true, nonGenuineServerName = null, serverOsFamily = null, - version = "8.0" - ) + version = "8.0", + ), ) verify(service.analytics).enqueue( argThat { build().let { it.userId() == "654321" && - it.type().name == "track" + it.type().name == "track" } - } + }, ) } @@ -68,9 +69,10 @@ internal class TelemetryServiceTest { application.withMockedService(mockRuntimeInformationService(userId = "654321")) application.withMockedService(mockLogMessage()) - val service = TelemetryService().apply { - analytics = mock() - } + val service = + TelemetryService().apply { + analytics = mock() + } val publisher = application.messageBus.syncPublisher(AppLifecycleListener.TOPIC) publisher.appWillBeClosed(true) @@ -78,4 +80,41 @@ internal class TelemetryServiceTest { verify(service.analytics).flush() verify(service.analytics).shutdown() } + + @Test + fun `does not send telemetry events when telemetry is disabled`( + application: Application, + settings: PluginSettings, + ) { + settings.isTelemetryEnabled = false + + val service = + TelemetryService().apply { + analytics = mock() + } + + service.sendEvent(TelemetryEvent.PluginActivated) + + verify(service.analytics, never()).enqueue(any()) + } + + @Test + fun `does not flushes events, but shutdowns, when telemetry is disabled`( + application: Application, + settings: PluginSettings, + ) { + settings.isTelemetryEnabled = false + application.withMockedService(mockLogMessage()) + + val service = + TelemetryService().apply { + analytics = mock() + } + + val publisher = application.messageBus.syncPublisher(AppLifecycleListener.TOPIC) + publisher.appWillBeClosed(true) + + verify(service.analytics, never()).flush() + verify(service.analytics).shutdown() + } } From b37f0e0f407d513341fc7c3468631dae15e3cc03 Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Wed, 12 Jun 2024 09:39:33 +0200 Subject: [PATCH 03/12] chore: add all messages to bundles --- .../mongodb/jbplugin/ActivatePluginPostStartupActivity.kt | 8 ++++---- .../main/resources/messages/TelemetryBundle.properties | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt index 455bcec0..f5f03995 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt @@ -23,7 +23,7 @@ import kotlinx.coroutines.launch /** * Class that represents the link that opens the settings page for MongoDB. */ -class OpenMongoDbpluginSettingsAction : AnAction(TelemetryMessages.message("action.disable-telemetry")) { +class OpenMongoDbPluginSettingsAction : AnAction(TelemetryMessages.message("action.disable-telemetry")) { override fun actionPerformed(event: AnActionEvent) { ShowSettingsUtil.getInstance().showSettingsDialog(event.project, PluginSettingsConfigurable::class.java) } @@ -45,12 +45,12 @@ class ActivatePluginPostStartupActivity(private val cs: CoroutineScope) : Startu NotificationGroupManager.getInstance() .getNotificationGroup("com.mongodb.jbplugin.notifications.Telemetry") .createNotification( - "MongoDB plugin telemetry", - "Anonymous telemetry is enabled by default, as it helps us improve the plugin.", + TelemetryMessages.message("notification.title"), + TelemetryMessages.message("notification.message"), NotificationType.INFORMATION, ) .setImportant(true) - .addAction(OpenMongoDBPluginSettingsAction()) + .addAction(OpenMongoDbPluginSettingsAction()) .notify(project) settings.hasTelemetryOptOutputNotificationBeenShown = true diff --git a/packages/jetbrains-plugin/src/main/resources/messages/TelemetryBundle.properties b/packages/jetbrains-plugin/src/main/resources/messages/TelemetryBundle.properties index c615b5c5..a6e87580 100644 --- a/packages/jetbrains-plugin/src/main/resources/messages/TelemetryBundle.properties +++ b/packages/jetbrains-plugin/src/main/resources/messages/TelemetryBundle.properties @@ -1,4 +1,6 @@ notification.group.name=MongoDB telemetry +notification.title=MongoDB plugin telemetry +notification.message=Anonymous telemetry is enabled by default because it helps us improve the plugin. action.disable-telemetry=Disable Telemetry settings.telemetry-collection-tooltip=Allow the collection of anonymous diagnostics and usage telemetry data to help improve the product. settings.telemetry-collection-checkbox=Enable telemetry \ No newline at end of file From d9196d2f89b3b310b573ca07250fbf5226ee548e Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Wed, 12 Jun 2024 11:15:09 +0200 Subject: [PATCH 04/12] chore: add UI test to toggle telemetry --- .../jbplugin/settings/PluginSettings.kt | 10 +- .../settings/PluginSettingsConfigurable.kt | 10 +- .../jbplugin/fixtures/FixtureExtensions.kt | 39 ++++++-- .../jbplugin/fixtures/UiTestExtensions.kt | 95 +++++++++++++------ .../components/MongoDbSettingsFixture.kt | 72 ++++++++++++++ .../jbplugin/settings/SettingsUiTest.kt | 25 +++++ 6 files changed, 207 insertions(+), 44 deletions(-) create mode 100644 packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/components/MongoDbSettingsFixture.kt create mode 100644 packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/settings/SettingsUiTest.kt diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettings.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettings.kt index 55adfadc..aa3cc5ca 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettings.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettings.kt @@ -7,6 +7,7 @@ package com.mongodb.jbplugin.settings import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.* +import java.io.Serializable /** * The state component represents the persisting state. Don't use directly, this is only necessary @@ -27,7 +28,7 @@ class PluginSettingsStateComponent : SimplePersistentStateComponent RemoteRobot.findVisible(timeout: Duration = Duration.ofMinutes(1)) = run { +inline fun RemoteRobot.findVisible(timeout: Duration = Duration.ofMinutes(1)) = + run { + waitFor( + timeout, + Duration.ofMillis(100), + errorMessage = "Could not find component of class ${T::class.java.canonicalName}", + ) { + runCatching { + find(T::class.java, Duration.ofMillis(100)).callJs("true") + }.getOrDefault(false) + } + + find(T::class.java) + } + +/** + * Returns a fixture by the locator. + * + * @param timeout + * @param locator + * @return + */ +inline fun RemoteRobot.findVisible( + locator: Locator, + timeout: Duration = Duration.ofMinutes(1), +) = run { waitFor( - timeout, Duration.ofMillis(100), - errorMessage = "Could not find component of class ${T::class.java.canonicalName}" + timeout, + Duration.ofMillis(100), + errorMessage = "Could not find component of class ${T::class.java.canonicalName}", ) { runCatching { - find(T::class.java, Duration.ofMillis(100)).callJs("true") + find(T::class.java, locator, Duration.ofMillis(100)).callJs("true") }.getOrDefault(false) } - find(T::class.java) -} \ No newline at end of file + find(T::class.java, locator) +} diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/UiTestExtensions.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/UiTestExtensions.kt index 42986b2c..5342ceca 100644 --- a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/UiTestExtensions.kt +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/UiTestExtensions.kt @@ -45,32 +45,61 @@ annotation class RequiresProject(val value: String) * * @see UiTest */ -private class UiTestExtension : BeforeAllCallback, +private class UiTestExtension : + BeforeAllCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback, ParameterResolver { private val remoteRobotUrl: String = "http://localhost:8082" private lateinit var remoteRobot: RemoteRobot - override fun supportsParameter(parameterContext: ParameterContext?, extensionContext: ExtensionContext?): Boolean = - parameterContext?.parameter?.type?.equals(RemoteRobot::class.java) ?: false + override fun supportsParameter( + parameterContext: ParameterContext?, + extensionContext: ExtensionContext?, + ): Boolean = parameterContext?.parameter?.type?.equals(RemoteRobot::class.java) ?: false - override fun resolveParameter(parameterContext: ParameterContext?, extensionContext: ExtensionContext?): Any = - remoteRobot + override fun resolveParameter( + parameterContext: ParameterContext?, + extensionContext: ExtensionContext?, + ): Any = remoteRobot override fun beforeAll(context: ExtensionContext?) { remoteRobot = RemoteRobot(remoteRobotUrl) } override fun beforeTestExecution(context: ExtensionContext?) { - val requiresProject = context?.requiredTestMethod?.annotations - ?.find { annotation -> annotation.annotationClass == RequiresProject::class } as RequiresProject? + val requiresProject = + context?.requiredTestMethod?.annotations + ?.find { annotation -> annotation.annotationClass == RequiresProject::class } as RequiresProject? CommonSteps(remoteRobot).closeProject() + + remoteRobot.runJs( + """ + importClass(com.intellij.openapi.application.ApplicationManager) + importClass(com.intellij.ide.plugins.PluginManager) + importClass(com.intellij.openapi.extensions.PluginId) + + global.put('loadPlugin', function () { + const pluginManager = PluginManager.getInstance(); + const pluginID = PluginId.findId("com.mongodb.jbplugin"); + return pluginManager.findEnabledPlugin(pluginID); + }); + + global.put('loadPluginClass', function (className) { + return global.get('loadPlugin')().getPluginClassLoader().loadClass(className); + }); + + global.put('loadPluginService', function (className) { + return ApplicationManager.getApplication().getService(global.get("loadPluginClass")(className)); + }); + """.trimIndent(), + ) + requiresProject?.let { // If we have the @RequireProject annotation, load that project on startup CommonSteps(remoteRobot).openProject( - Path("src/test/resources/project-fixtures/${requiresProject.value}").toAbsolutePath().toString() + Path("src/test/resources/project-fixtures/${requiresProject.value}").toAbsolutePath().toString(), ) } } @@ -101,7 +130,7 @@ private class UiTestExtension : BeforeAllCallback, private fun String.saveFile( url: String, - name: String + name: String, ): File { val response = client.newCall(Request.Builder().url(url).build()).execute() return File(this).apply { @@ -112,10 +141,11 @@ private class UiTestExtension : BeforeAllCallback, } private fun BufferedImage.save(name: String) { - val bytes = ByteArrayOutputStream().use { bos -> - ImageIO.write(this, "png", bos) - bos.toByteArray() - } + val bytes = + ByteArrayOutputStream().use { bos -> + ImageIO.write(this, "png", bos) + bos.toByteArray() + } File("build/reports").apply { mkdirs() }.resolve("$name.png").writeBytes(bytes) } @@ -123,9 +153,10 @@ private class UiTestExtension : BeforeAllCallback, private fun saveIdeaFrames(testName: String) { remoteRobot.findAll(byXpath("//div[@class='IdeFrameImpl']")) .forEachIndexed { index, frame -> - val pic = try { - frame.callJs( - """ + val pic = + try { + frame.callJs( + """ importPackage(java.io) importPackage(javax.imageio) importPackage(java.awt.image) @@ -144,20 +175,22 @@ private class UiTestExtension : BeforeAllCallback, baos.close(); } pictureBytes; - """, true - ) - } catch (e: Throwable) { - e.printStackTrace() - throw e - } + """, + true, + ) + } catch (e: Throwable) { + e.printStackTrace() + throw e + } pic.inputStream().use { ImageIO.read(it) }.save(testName + "_" + index) } } - private fun fetchScreenShot(): BufferedImage = remoteRobot.callJs( - """ + private fun fetchScreenShot(): BufferedImage = + remoteRobot.callJs( + """ importPackage(java.io) importPackage(javax.imageio) const screenShot = new java.awt.Robot().createScreenCapture( @@ -172,12 +205,12 @@ private class UiTestExtension : BeforeAllCallback, baos.close(); } pictureBytes; - """ - ) - .inputStream() - .use { - ImageIO.read(it) - } + """, + ) + .inputStream() + .use { + ImageIO.read(it) + } } /** @@ -185,4 +218,4 @@ private class UiTestExtension : BeforeAllCallback, * * @return */ -fun String.stripHtml(): String = Jsoup.clean(this, Safelist.none()) \ No newline at end of file +fun String.stripHtml(): String = Jsoup.clean(this, Safelist.none()) diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/components/MongoDbSettingsFixture.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/components/MongoDbSettingsFixture.kt new file mode 100644 index 00000000..0d2fed00 --- /dev/null +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/components/MongoDbSettingsFixture.kt @@ -0,0 +1,72 @@ +/** + * Fixture that represents the plugin settings page. If you add new settings, + * you should add new properties here. + * + * For usage in tests that work with settings, you can use openSettings, that will open the UI, or + * remoteRobot.useSetting(name), that will give you the value for that specific setting. + */ + +package com.mongodb.jbplugin.fixtures.components + +import com.intellij.remoterobot.RemoteRobot +import com.intellij.remoterobot.data.RemoteComponent +import com.intellij.remoterobot.fixtures.* +import com.mongodb.jbplugin.fixtures.findVisible + +/** + * Component that represents the settings page. + * + * @param remoteRobot + * @param remoteComponent + */ +@DefaultXpath(by = "accessible name", xpath = "//div[@accessiblename='MongoDB Settings']") +@FixtureName("MongoDBSettings") +class MongoDbSettingsFixture(remoteRobot: RemoteRobot, remoteComponent: RemoteComponent) : ContainerFixture(remoteRobot, + remoteComponent) { + val enableTelemetry by lazy { + findAll().find { it.text == "Enable telemetry" } ?: throw NoSuchElementException() + } + val ok by lazy { + remoteRobot.findAll().find { it.text == "OK" } ?: throw NoSuchElementException() + } +} + +/** + * Opens the settings dialog and returns a fixture, so it can be interacted. + * + * @return + */ +fun RemoteRobot.openSettings(): MongoDbSettingsFixture { + this.runJs( + """ + importClass(com.intellij.openapi.application.ApplicationManager) + const runAction = new Runnable({ + run: function() { + com.intellij.openapi.options.ShowSettingsUtil.getInstance().showSettingsDialog( + null, + "MongoDB", + ) + } + }) + ApplicationManager.getApplication().invokeLater(runAction) + """.trimIndent(), + ) + + return findVisible() +} + +/** + * Returns a specific setting value from the plugin settings. + * + * @see com.mongodb.jbplugin.settings.PluginSettings for the possible values. + * + * @param name + * @return + */ +inline fun RemoteRobot.useSetting(name: String): T = callJs( + """ + global.get('loadPluginService')( + 'com.mongodb.jbplugin.settings.PluginSettingsStateComponent' + ).getState().$name() + """.trimIndent(), + ) diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/settings/SettingsUiTest.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/settings/SettingsUiTest.kt new file mode 100644 index 00000000..555a06ff --- /dev/null +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/settings/SettingsUiTest.kt @@ -0,0 +1,25 @@ +package com.mongodb.jbplugin.settings + +import com.intellij.remoterobot.RemoteRobot +import com.mongodb.jbplugin.fixtures.RequiresProject +import com.mongodb.jbplugin.fixtures.UiTest +import com.mongodb.jbplugin.fixtures.components.openSettings +import com.mongodb.jbplugin.fixtures.components.useSetting +import org.junit.jupiter.api.Assertions.assertNotEquals +import org.junit.jupiter.api.Test + +@UiTest +class SettingsUiTest { + @Test + @RequiresProject("basic-java-project-with-mongodb") + fun `allows toggling the telemetry`(remoteRobot: RemoteRobot) { + val telemetryBeforeTest = remoteRobot.useSetting("isTelemetryEnabled") + + val settings = remoteRobot.openSettings() + settings.enableTelemetry.click() + settings.ok.click() + + val telemetryAfterTest = remoteRobot.useSetting("isTelemetryEnabled") + assertNotEquals(telemetryBeforeTest, telemetryAfterTest) + } +} From 049425590440cb0bacbfd99633016b63af2c02c6 Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Wed, 12 Jun 2024 11:21:42 +0200 Subject: [PATCH 05/12] chore: add to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7314f0d..b24e8bab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ MongoDB plugin for IntelliJ IDEA. ## [Unreleased] ### Added +* [INTELLIJ-12](https://jira.mongodb.org/browse/INTELLIJ-11): Notify users about telemetry, and them to disable it. * [INTELLIJ-11](https://jira.mongodb.org/browse/INTELLIJ-11): Flush pending analytics events before closing the IDE. ### Changed From c77b80bc51cd08acd4844ea237f00b936814a888 Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Wed, 12 Jun 2024 11:26:48 +0200 Subject: [PATCH 06/12] chore: typo in changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b24e8bab..dfe18999 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ MongoDB plugin for IntelliJ IDEA. ## [Unreleased] ### Added -* [INTELLIJ-12](https://jira.mongodb.org/browse/INTELLIJ-11): Notify users about telemetry, and them to disable it. +* [INTELLIJ-12](https://jira.mongodb.org/browse/INTELLIJ-11): Notify users about telemetry, and allow them to disable it. * [INTELLIJ-11](https://jira.mongodb.org/browse/INTELLIJ-11): Flush pending analytics events before closing the IDE. ### Changed From 6bd275cdf7f1be25361b6e1b46835ad704bbac60 Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Wed, 12 Jun 2024 13:19:37 +0200 Subject: [PATCH 07/12] chore: fix typo Co-authored-by: Anna Henningsen --- .../com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt index f5f03995..ed8de8d6 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt @@ -1,5 +1,5 @@ /** - * These class implement the balloon that shows the first time that the plugin is activated. + * These classes implement the balloon that shows the first time that the plugin is activated. */ package com.mongodb.jbplugin From 0f8b2c187523baa673b7051a66f0af62f68a01a4 Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Wed, 12 Jun 2024 14:46:45 +0200 Subject: [PATCH 08/12] chore: add privacy policy button, wip --- .../jbplugin/ActivatePluginPostStartupActivity.kt | 11 +++++++++++ .../jbplugin/settings/PluginSettingsConfigurable.kt | 8 ++++++++ .../resources/messages/TelemetryBundle.properties | 4 +++- .../jbplugin/observability/TelemetryServiceTest.kt | 5 +---- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt index ed8de8d6..916c5096 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/ActivatePluginPostStartupActivity.kt @@ -4,6 +4,7 @@ package com.mongodb.jbplugin +import com.intellij.ide.BrowserUtil import com.intellij.notification.NotificationGroupManager import com.intellij.notification.NotificationType import com.intellij.openapi.actionSystem.AnAction @@ -29,6 +30,15 @@ class OpenMongoDbPluginSettingsAction : AnAction(TelemetryMessages.message("acti } } +/** + * Class that represents the link that opens the privacy policy page + */ +class OpenPrivacyPolicyPage : AnAction(TelemetryMessages.message("action.view-privacy-policy")) { + override fun actionPerformed(event: AnActionEvent) { + BrowserUtil.browse(TelemetryMessages.message("settings.telemetry-privacy-policy")) + } +} + /** * This notifies that the plugin has been activated. * @@ -50,6 +60,7 @@ class ActivatePluginPostStartupActivity(private val cs: CoroutineScope) : Startu NotificationType.INFORMATION, ) .setImportant(true) + .addAction(OpenPrivacyPolicyPage()) .addAction(OpenMongoDbPluginSettingsAction()) .notify(project) diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsConfigurable.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsConfigurable.kt index c2f6ead9..2c694537 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsConfigurable.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/settings/PluginSettingsConfigurable.kt @@ -4,11 +4,13 @@ package com.mongodb.jbplugin.settings +import com.intellij.ide.BrowserUtil import com.intellij.openapi.options.Configurable import com.intellij.ui.components.JBCheckBox import com.intellij.util.ui.FormBuilder import com.mongodb.jbplugin.i18n.SettingsMessages import com.mongodb.jbplugin.i18n.TelemetryMessages +import javax.swing.JButton import javax.swing.JComponent import javax.swing.JPanel @@ -50,12 +52,18 @@ class PluginSettingsConfigurable : Configurable { private class PluginSettingsComponent { val root: JPanel val isTelemetryEnabledCheckBox = JBCheckBox(TelemetryMessages.message("settings.telemetry-collection-checkbox")) + val privacyPolicyButton = JButton(TelemetryMessages.message("action.view-privacy-policy")) init { + privacyPolicyButton.addActionListener { + BrowserUtil.browse(TelemetryMessages.message("settings.telemetry-privacy-policy")) + } + root = FormBuilder.createFormBuilder() .addComponent(isTelemetryEnabledCheckBox) .addTooltip(TelemetryMessages.message("settings.telemetry-collection-tooltip")) + .addComponent(privacyPolicyButton) .addComponentFillVertically(JPanel(), 0) .panel diff --git a/packages/jetbrains-plugin/src/main/resources/messages/TelemetryBundle.properties b/packages/jetbrains-plugin/src/main/resources/messages/TelemetryBundle.properties index a6e87580..5dc27671 100644 --- a/packages/jetbrains-plugin/src/main/resources/messages/TelemetryBundle.properties +++ b/packages/jetbrains-plugin/src/main/resources/messages/TelemetryBundle.properties @@ -2,5 +2,7 @@ notification.group.name=MongoDB telemetry notification.title=MongoDB plugin telemetry notification.message=Anonymous telemetry is enabled by default because it helps us improve the plugin. action.disable-telemetry=Disable Telemetry +action.view-privacy-policy=View Privacy Policy settings.telemetry-collection-tooltip=Allow the collection of anonymous diagnostics and usage telemetry data to help improve the product. -settings.telemetry-collection-checkbox=Enable telemetry \ No newline at end of file +settings.telemetry-collection-checkbox=Enable telemetry +settings.telemetry-privacy-policy=https://www.mongodb.com/legal/privacy/privacy-policy \ No newline at end of file diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt index d9a9114d..ce14d681 100644 --- a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt @@ -82,10 +82,7 @@ internal class TelemetryServiceTest { } @Test - fun `does not send telemetry events when telemetry is disabled`( - application: Application, - settings: PluginSettings, - ) { + fun `does not send telemetry events when telemetry is disabled`(settings: PluginSettings) { settings.isTelemetryEnabled = false val service = From 2949ba61ea88b5c520f4019c3f699914f6cef649 Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Wed, 12 Jun 2024 15:55:10 +0200 Subject: [PATCH 09/12] chore: fake browser and e2e policy button --- .gitignore | 4 +- .../jbplugin/fixtures/FixtureExtensions.kt | 24 +++++++ .../components/BrowserSettingsFixture.kt | 71 +++++++++++++++++++ .../components/MongoDbSettingsFixture.kt | 29 +++----- .../jbplugin/settings/SettingsUiTest.kt | 24 +++++++ .../src/test/resources/fake-browser.sh | 9 +++ 6 files changed, 142 insertions(+), 19 deletions(-) create mode 100644 packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/components/BrowserSettingsFixture.kt create mode 100755 packages/jetbrains-plugin/src/test/resources/fake-browser.sh diff --git a/.gitignore b/.gitignore index 07d9be7f..dac423da 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,6 @@ replay_pid* # This file is generated at compile time. packages/jetbrains-plugin/src/main/resources/build.properties /**/video -/**/.DS_Store \ No newline at end of file +/**/.DS_Store + +FAKE_BROWSER_OUTPUT \ No newline at end of file diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/FixtureExtensions.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/FixtureExtensions.kt index 930f03d7..1eef0b3c 100644 --- a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/FixtureExtensions.kt +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/FixtureExtensions.kt @@ -55,3 +55,27 @@ inline fun RemoteRobot.findVisible( find(T::class.java, locator) } + +/** + * Opens the IntelliJ settings modal at the specific section. The section is the name of the + * group in the left sidebar. So for example, if you want to open the MongoDB section, you + * would specify "MongoDB". + * + * @param section + */ +fun RemoteRobot.openSettingsAtSection(section: String) { + this.runJs( + """ + importClass(com.intellij.openapi.application.ApplicationManager) + const runAction = new Runnable({ + run: function() { + com.intellij.openapi.options.ShowSettingsUtil.getInstance().showSettingsDialog( + null, + "$section", + ) + } + }) + ApplicationManager.getApplication().invokeLater(runAction) + """.trimIndent(), + ) +} diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/components/BrowserSettingsFixture.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/components/BrowserSettingsFixture.kt new file mode 100644 index 00000000..1077680a --- /dev/null +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/components/BrowserSettingsFixture.kt @@ -0,0 +1,71 @@ +/** + * Fixture that represents the browser settings page. It's used for tests that depend on opening a browser. + * + */ + +package com.mongodb.jbplugin.fixtures.components + +import com.intellij.remoterobot.RemoteRobot +import com.intellij.remoterobot.data.RemoteComponent +import com.intellij.remoterobot.fixtures.* +import com.intellij.remoterobot.search.locators.XpathLocator +import com.intellij.remoterobot.search.locators.byXpath +import com.intellij.remoterobot.utils.keyboard +import com.mongodb.jbplugin.fixtures.findVisible +import com.mongodb.jbplugin.fixtures.openSettingsAtSection +import java.nio.file.Files +import kotlin.io.path.Path + +/** + * Component that represents the settings page. + * + * @param remoteRobot + * @param remoteComponent + */ +@DefaultXpath(by = "hierarchy", xpath = "//div[@class='DialogPanel']//div[@class='JPanel']") +@FixtureName("BrowserSettingsFixture") +class BrowserSettingsFixture(remoteRobot: RemoteRobot, remoteComponent: RemoteComponent) : ContainerFixture( + remoteRobot, + remoteComponent, +) { + val ok by lazy { + remoteRobot.findAll().find { it.text == "OK" } ?: throw NoSuchElementException() + } + fun useFakeBrowser() { + val selector = remoteRobot.find(byXpath( +"//div[@accessiblename='Default Browser:' and @class='ComboBox']" +)) + selector.selectItem("Custom path") + + val commandInput = remoteRobot.find(XpathLocator("type", + "//div[@class='TextFieldWithBrowseButton']")) + commandInput.click() + + remoteRobot.keyboard { + selectAll() + enterText(Path("src", "test", "resources", "fake-browser.sh").toAbsolutePath().toString(), 5) + } + } + + fun lastBrowserUrl(): String { + val pathToOutput = Path("src", "test", "resources", "FAKE_BROWSER_OUTPUT").toAbsolutePath() + return Files.readString(pathToOutput).trim() + } + + fun useSystemBrowser() { + val selector = remoteRobot.find(byXpath( +"//div[@accessiblename='Default Browser:' and @class='ComboBox']" +)) + selector.selectItem("System default") + } +} + +/** + * Opens the settings dialog and returns a fixture, so it can be interacted. + * + * @return + */ +fun RemoteRobot.openBrowserSettings(): BrowserSettingsFixture { + openSettingsAtSection("Web Browsers and Preview") + return findVisible() +} diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/components/MongoDbSettingsFixture.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/components/MongoDbSettingsFixture.kt index 0d2fed00..bf25b4c5 100644 --- a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/components/MongoDbSettingsFixture.kt +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/fixtures/components/MongoDbSettingsFixture.kt @@ -12,6 +12,7 @@ import com.intellij.remoterobot.RemoteRobot import com.intellij.remoterobot.data.RemoteComponent import com.intellij.remoterobot.fixtures.* import com.mongodb.jbplugin.fixtures.findVisible +import com.mongodb.jbplugin.fixtures.openSettingsAtSection /** * Component that represents the settings page. @@ -21,11 +22,16 @@ import com.mongodb.jbplugin.fixtures.findVisible */ @DefaultXpath(by = "accessible name", xpath = "//div[@accessiblename='MongoDB Settings']") @FixtureName("MongoDBSettings") -class MongoDbSettingsFixture(remoteRobot: RemoteRobot, remoteComponent: RemoteComponent) : ContainerFixture(remoteRobot, - remoteComponent) { +class MongoDbSettingsFixture(remoteRobot: RemoteRobot, remoteComponent: RemoteComponent) : ContainerFixture( + remoteRobot, + remoteComponent, +) { val enableTelemetry by lazy { findAll().find { it.text == "Enable telemetry" } ?: throw NoSuchElementException() } + val privacyPolicyButton by lazy { + findAll().find { it.text == "View Privacy Policy" } ?: throw NoSuchElementException() + } val ok by lazy { remoteRobot.findAll().find { it.text == "OK" } ?: throw NoSuchElementException() } @@ -37,21 +43,7 @@ class MongoDbSettingsFixture(remoteRobot: RemoteRobot, remoteComponent: RemoteCo * @return */ fun RemoteRobot.openSettings(): MongoDbSettingsFixture { - this.runJs( - """ - importClass(com.intellij.openapi.application.ApplicationManager) - const runAction = new Runnable({ - run: function() { - com.intellij.openapi.options.ShowSettingsUtil.getInstance().showSettingsDialog( - null, - "MongoDB", - ) - } - }) - ApplicationManager.getApplication().invokeLater(runAction) - """.trimIndent(), - ) - + openSettingsAtSection("MongoDB") return findVisible() } @@ -63,7 +55,8 @@ fun RemoteRobot.openSettings(): MongoDbSettingsFixture { * @param name * @return */ -inline fun RemoteRobot.useSetting(name: String): T = callJs( +inline fun RemoteRobot.useSetting(name: String): T = + callJs( """ global.get('loadPluginService')( 'com.mongodb.jbplugin.settings.PluginSettingsStateComponent' diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/settings/SettingsUiTest.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/settings/SettingsUiTest.kt index 555a06ff..c5c30f0c 100644 --- a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/settings/SettingsUiTest.kt +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/settings/SettingsUiTest.kt @@ -3,8 +3,10 @@ package com.mongodb.jbplugin.settings import com.intellij.remoterobot.RemoteRobot import com.mongodb.jbplugin.fixtures.RequiresProject import com.mongodb.jbplugin.fixtures.UiTest +import com.mongodb.jbplugin.fixtures.components.openBrowserSettings import com.mongodb.jbplugin.fixtures.components.openSettings import com.mongodb.jbplugin.fixtures.components.useSetting +import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNotEquals import org.junit.jupiter.api.Test @@ -22,4 +24,26 @@ class SettingsUiTest { val telemetryAfterTest = remoteRobot.useSetting("isTelemetryEnabled") assertNotEquals(telemetryBeforeTest, telemetryAfterTest) } + + @Test + @RequiresProject("basic-java-project-with-mongodb") + fun `allows opening the privacy policy in a browser`(remoteRobot: RemoteRobot) { + remoteRobot.openBrowserSettings().run { + useFakeBrowser() + ok.click() + } + + val settings = remoteRobot.openSettings() + settings.privacyPolicyButton.click() + settings.ok.click() + + val lastBrowserUrl = + remoteRobot.openBrowserSettings().run { + useSystemBrowser() + ok.click() + lastBrowserUrl() + } + + assertEquals("https://www.mongodb.com/legal/privacy/privacy-policy", lastBrowserUrl) + } } diff --git a/packages/jetbrains-plugin/src/test/resources/fake-browser.sh b/packages/jetbrains-plugin/src/test/resources/fake-browser.sh new file mode 100755 index 00000000..7d80143b --- /dev/null +++ b/packages/jetbrains-plugin/src/test/resources/fake-browser.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +FAKE_BROWSER_OUTPUT="${SCRIPT_DIR}/FAKE_BROWSER_OUTPUT" + +echo $FAKE_BROWSER_OUTPUT + +rm -f "$FAKE_BROWSER_OUTPUT" +echo "$@" > "$FAKE_BROWSER_OUTPUT" \ No newline at end of file From 26dda9d6c1f4b09683a5fb39c04ca2b99adce42e Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Wed, 12 Jun 2024 16:11:10 +0200 Subject: [PATCH 10/12] chore: ensure jacocoTestReport does not rerun tests --- .github/workflows/quality-check.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/quality-check.yaml b/.github/workflows/quality-check.yaml index cca38767..dfed3297 100644 --- a/.github/workflows/quality-check.yaml +++ b/.github/workflows/quality-check.yaml @@ -191,7 +191,7 @@ jobs: report_paths: '**/build/test-results/test/TEST-*.xml' - name: Generate Coverage Report run: | - ./gradlew --quiet --console=plain "jacocoTestReport" + ./gradlew "jacocoTestReport" $(./gradlew "jacocoTestReport" --dry-run | awk '/^:/ { print "-x" $1 }' | sed '$ d') - uses: actions/upload-artifact@v4 name: Upload Functional Test Coverage with: From 7008ca566cb8691d0bcd611dfb487b0ea86b344d Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Wed, 12 Jun 2024 16:26:12 +0200 Subject: [PATCH 11/12] chore: add integration tests for i18n --- .../com/mongodb/jbplugin/i18n/SettingsMessages.kt | 6 ------ .../com/mongodb/jbplugin/i18n/TelemetryMessages.kt | 6 ------ .../mongodb/jbplugin/i18n/SettingsMessagesTest.kt | 12 ++++++++++++ .../mongodb/jbplugin/i18n/TelemetryMessagesTest.kt | 12 ++++++++++++ 4 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/i18n/SettingsMessagesTest.kt create mode 100644 packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/i18n/TelemetryMessagesTest.kt diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/SettingsMessages.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/SettingsMessages.kt index 513c1457..47052c71 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/SettingsMessages.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/SettingsMessages.kt @@ -4,7 +4,6 @@ import com.intellij.DynamicBundle import org.jetbrains.annotations.Nls import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.PropertyKey -import java.util.function.Supplier object SettingsMessages { @NonNls @@ -17,9 +16,4 @@ object SettingsMessages { String, vararg params: Any, ): @Nls String = instance.getMessage(key, *params) - - fun lazyMessage( - @PropertyKey(resourceBundle = BUNDLE) key: String, - vararg params: Any, - ): Supplier<@Nls String> = instance.getLazyMessage(key, *params) } diff --git a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/TelemetryMessages.kt b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/TelemetryMessages.kt index 6a77e389..79dba4fa 100644 --- a/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/TelemetryMessages.kt +++ b/packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/i18n/TelemetryMessages.kt @@ -4,7 +4,6 @@ import com.intellij.DynamicBundle import org.jetbrains.annotations.Nls import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.PropertyKey -import java.util.function.Supplier object TelemetryMessages { @NonNls @@ -17,9 +16,4 @@ object TelemetryMessages { String, vararg params: Any, ): @Nls String = instance.getMessage(key, *params) - - fun lazyMessage( - @PropertyKey(resourceBundle = BUNDLE) key: String, - vararg params: Any, - ): Supplier<@Nls String> = instance.getLazyMessage(key, *params) } diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/i18n/SettingsMessagesTest.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/i18n/SettingsMessagesTest.kt new file mode 100644 index 00000000..36f1b3bd --- /dev/null +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/i18n/SettingsMessagesTest.kt @@ -0,0 +1,12 @@ +package com.mongodb.jbplugin.i18n + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class SettingsMessagesTest { + @Test + fun `loads messages from the resource bundle`() { + val messages = SettingsMessages.message("settings.display-name") + assertEquals("MongoDB", messages) + } +} \ No newline at end of file diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/i18n/TelemetryMessagesTest.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/i18n/TelemetryMessagesTest.kt new file mode 100644 index 00000000..109460a0 --- /dev/null +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/i18n/TelemetryMessagesTest.kt @@ -0,0 +1,12 @@ +package com.mongodb.jbplugin.i18n + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class TelemetryMessagesTest { + @Test + fun `loads messages from the resource bundle`() { + val messages = TelemetryMessages.message("notification.group.name") + assertEquals("MongoDB telemetry", messages) + } +} \ No newline at end of file From 93892ad33b12f4865238112cbadfc914e7030be1 Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Wed, 12 Jun 2024 16:32:21 +0200 Subject: [PATCH 12/12] chore: fix typo Co-authored-by: Anna Henningsen --- .../com/mongodb/jbplugin/observability/TelemetryServiceTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt index ce14d681..720585ef 100644 --- a/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt +++ b/packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/observability/TelemetryServiceTest.kt @@ -96,7 +96,7 @@ internal class TelemetryServiceTest { } @Test - fun `does not flushes events, but shutdowns, when telemetry is disabled`( + fun `does not flush events, but shuts down, when telemetry is disabled`( application: Application, settings: PluginSettings, ) {