diff --git a/src/main/java/com/redhat/devtools/intellij/telemetry/core/IMessageBroker.java b/src/main/java/com/redhat/devtools/intellij/telemetry/core/IMessageBroker.java index f16ebd44..6d3523fb 100644 --- a/src/main/java/com/redhat/devtools/intellij/telemetry/core/IMessageBroker.java +++ b/src/main/java/com/redhat/devtools/intellij/telemetry/core/IMessageBroker.java @@ -15,4 +15,8 @@ public interface IMessageBroker { void send(Event event); void dispose(); + + interface IMessageBrokerFactory { + IMessageBroker create(boolean isDebug, ClassLoader classLoader); + } } diff --git a/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/Environment.java b/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/Environment.java index 1a065f8c..2e797e90 100644 --- a/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/Environment.java +++ b/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/Environment.java @@ -117,7 +117,7 @@ private void ensureCountry() { } } - class Buildable { + public class Buildable { public Environment build() { ensureIDE(); ensurePlatform(); diff --git a/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackEvent.java b/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackEvent.java deleted file mode 100644 index 00d15b87..00000000 --- a/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackEvent.java +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 Red Hat, Inc. - * Distributed under license by Red Hat, Inc. All rights reserved. - * This program is made available under the terms of the - * Eclipse Public License v2.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v20.html - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - ******************************************************************************/ -package com.redhat.devtools.intellij.telemetry.core.service; - -import java.util.HashMap; -import java.util.Map; - -public class FeedbackEvent extends Event { - - public FeedbackEvent(String name) { - this(name, new HashMap<>()); - } - - public FeedbackEvent(String name, Map properties) { - super(Type.ACTION, name, properties); - } -} diff --git a/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackMessageBuilder.java b/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackMessageBuilder.java deleted file mode 100644 index 5fdc251d..00000000 --- a/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackMessageBuilder.java +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 Red Hat, Inc. - * Distributed under license by Red Hat, Inc. All rights reserved. - * This program is made available under the terms of the - * Eclipse Public License v2.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v20.html - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - ******************************************************************************/ -package com.redhat.devtools.intellij.telemetry.core.service; - -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; -import com.redhat.devtools.intellij.telemetry.core.IService; -import com.redhat.devtools.intellij.telemetry.core.util.Lazy; - -import java.util.function.Supplier; - -import static com.redhat.devtools.intellij.telemetry.core.service.Event.Type.ACTION; - -public class FeedbackMessageBuilder { - - private static final Logger LOGGER = Logger.getInstance(FeedbackMessageBuilder.class); - - private final IService serviceFacade; - - public FeedbackMessageBuilder(ClassLoader classLoader) { - this(new FeedbackServiceFacade(classLoader)); - } - - FeedbackMessageBuilder(IService serviceFacade) { - this.serviceFacade = serviceFacade; - } - - static class FeedbackServiceFacade extends Lazy implements IService { - - protected FeedbackServiceFacade(final ClassLoader classLoader) { - this(() -> ApplicationManager.getApplication().getService(FeedbackServiceFactory.class).create(classLoader)); - } - - protected FeedbackServiceFacade(final Supplier supplier) { - super(supplier); - } - - @Override - public void send(Event event) { - get().send(event); - } - } - - public FeedbackMessage feedback(String name) { - return new FeedbackMessage(name, serviceFacade); - } - - public static class FeedbackMessage extends Message{ - - private FeedbackMessage(String name, IService service) { - super(ACTION, name, service); - } - } -} diff --git a/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackServiceFactory.java b/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackServiceFactory.java index 5a02f0e0..b040e1af 100644 --- a/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackServiceFactory.java +++ b/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackServiceFactory.java @@ -19,19 +19,7 @@ public class FeedbackServiceFactory implements DumbAware { - public IService create(ClassLoader classLoader) { - TelemetryConfiguration configuration = TelemetryConfiguration.getInstance(); - IMessageBroker broker = createSegmentBroker(configuration.isDebug(), classLoader); + public IService create(IMessageBroker broker) { return new FeedbackService(broker); } - - private IMessageBroker createSegmentBroker(boolean isDebug, ClassLoader classLoader) { - SegmentConfiguration brokerConfiguration = new SegmentConfiguration(classLoader); - return new SegmentBroker( - isDebug, - UserId.INSTANCE.get(), - null, - brokerConfiguration); - } - } diff --git a/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryMessageBuilder.java b/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryMessageBuilder.java index a819d51e..b0068eff 100644 --- a/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryMessageBuilder.java +++ b/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryMessageBuilder.java @@ -14,8 +14,11 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.messages.MessageBusConnection; +import com.redhat.devtools.intellij.telemetry.core.IMessageBroker; import com.redhat.devtools.intellij.telemetry.core.IService; +import com.redhat.devtools.intellij.telemetry.core.configuration.TelemetryConfiguration; import com.redhat.devtools.intellij.telemetry.core.service.Event.Type; +import com.redhat.devtools.intellij.telemetry.core.service.segment.SegmentBrokerFactory; import com.redhat.devtools.intellij.telemetry.core.util.Lazy; import com.redhat.devtools.intellij.telemetry.core.util.TimeUtils; @@ -33,18 +36,31 @@ public class TelemetryMessageBuilder { private static final Logger LOGGER = Logger.getInstance(TelemetryMessageBuilder.class); - private final TelemetryServiceFacade service; + private final IService telemetryFacade; + private final IService feedbackFacade; - public TelemetryMessageBuilder(ClassLoader classLoader) { - this(new TelemetryServiceFacade(classLoader)); + TelemetryMessageBuilder(ClassLoader classLoader) { + this(new SegmentBrokerFactory().create(TelemetryConfiguration.getInstance().isDebug(), classLoader)); } - TelemetryMessageBuilder(TelemetryServiceFacade serviceFacade) { - this.service = serviceFacade; + TelemetryMessageBuilder(IMessageBroker messageBroker) { + this( + new TelemetryServiceFacade(TelemetryConfiguration.getInstance(), messageBroker), + new FeedbackServiceFacade(messageBroker) + ); + } + + TelemetryMessageBuilder(IService telemetryFacade, IService feedbackFacade) { + this.telemetryFacade = telemetryFacade; + this.feedbackFacade = feedbackFacade; } public ActionMessage action(String name) { - return new ActionMessage(name, service); + return new ActionMessage(name, telemetryFacade); + } + + public FeedbackMessage feedback(String name) { + return new FeedbackMessage(name, feedbackFacade); } static class StartupMessage extends TelemetryMessage { @@ -194,8 +210,8 @@ protected TelemetryMessage(Type type, String name, IService service) { static class TelemetryServiceFacade extends Lazy implements IService { - protected TelemetryServiceFacade(final ClassLoader classLoader) { - this(() -> ApplicationManager.getApplication().getService(TelemetryServiceFactory.class).create(classLoader)); + protected TelemetryServiceFacade(final TelemetryConfiguration configuration, IMessageBroker broker) { + this(() -> ApplicationManager.getApplication().getService(TelemetryServiceFactory.class).create(configuration, broker)); } protected TelemetryServiceFacade(final Supplier supplier) { @@ -235,4 +251,28 @@ public void send(Event event) { get().send(event); } } + + static class FeedbackServiceFacade extends Lazy implements IService { + + protected FeedbackServiceFacade(final IMessageBroker broker) { + this(() -> ApplicationManager.getApplication().getService(FeedbackServiceFactory.class).create(broker)); + } + + protected FeedbackServiceFacade(final Supplier supplier) { + super(supplier); + } + + @Override + public void send(Event event) { + get().send(event); + } + } + + public static class FeedbackMessage extends Message{ + + FeedbackMessage(String name, IService service) { + super(ACTION, name, service); + } + } + } diff --git a/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryServiceFactory.java b/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryServiceFactory.java index 7754245c..cc22e0fe 100644 --- a/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryServiceFactory.java +++ b/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryServiceFactory.java @@ -13,32 +13,10 @@ import com.intellij.openapi.project.DumbAware; import com.redhat.devtools.intellij.telemetry.core.IMessageBroker; import com.redhat.devtools.intellij.telemetry.core.configuration.TelemetryConfiguration; -import com.redhat.devtools.intellij.telemetry.core.service.segment.SegmentBroker; -import com.redhat.devtools.intellij.telemetry.core.service.segment.SegmentConfiguration; public class TelemetryServiceFactory implements DumbAware { - private final IDE ide = new IDE.Factory() - .create() - .setJavaVersion(); - - public TelemetryService create(ClassLoader classLoader) { - Environment environment = new Environment.Builder() - .ide(ide) - .plugin(classLoader) - .build(); - TelemetryConfiguration configuration = TelemetryConfiguration.getInstance(); - IMessageBroker broker = createSegmentBroker(configuration.isDebug(), classLoader, environment); + public TelemetryService create(TelemetryConfiguration configuration, IMessageBroker broker) { return new TelemetryService(configuration, broker); } - - private IMessageBroker createSegmentBroker(boolean isDebug, ClassLoader classLoader, Environment environment) { - SegmentConfiguration brokerConfiguration = new SegmentConfiguration(classLoader); - return new SegmentBroker( - isDebug, - UserId.INSTANCE.get(), - environment, - brokerConfiguration); - } - } diff --git a/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/segment/SegmentBrokerFactory.java b/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/segment/SegmentBrokerFactory.java new file mode 100644 index 00000000..137c1adb --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/telemetry/core/service/segment/SegmentBrokerFactory.java @@ -0,0 +1,32 @@ +package com.redhat.devtools.intellij.telemetry.core.service.segment; + +import com.redhat.devtools.intellij.telemetry.core.IMessageBroker; +import com.redhat.devtools.intellij.telemetry.core.service.Environment; +import com.redhat.devtools.intellij.telemetry.core.service.IDE; +import com.redhat.devtools.intellij.telemetry.core.service.UserId; + +import static com.redhat.devtools.intellij.telemetry.core.IMessageBroker.*; + +public class SegmentBrokerFactory implements IMessageBrokerFactory { + + @Override + public IMessageBroker create(boolean isDebug, ClassLoader classLoader) { + Environment environment = createEnvironment(classLoader); + SegmentConfiguration configuration = new SegmentConfiguration(classLoader); + return new SegmentBroker( + isDebug, + UserId.INSTANCE.get(), + environment, + configuration); + } + + private static Environment createEnvironment(ClassLoader classLoader) { + IDE ide = new IDE.Factory() + .create() + .setJavaVersion(); + return new Environment.Builder() + .ide(ide) + .plugin(classLoader) + .build(); + } +} \ No newline at end of file diff --git a/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/Fakes.java b/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/Fakes.java index 7dbd21db..4cb1c1e5 100644 --- a/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/Fakes.java +++ b/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/Fakes.java @@ -58,4 +58,16 @@ public static ISegmentConfiguration segmentConfiguration(String normalWriteKey, }); return configuration; } + + public static TelemetryConfiguration telemetryConfiguration(TelemetryConfiguration.Mode mode) { + TelemetryConfiguration configuration = mock(TelemetryConfiguration.class); + when(configuration.isEnabled()) + .thenReturn(mode != TelemetryConfiguration.Mode.DISABLED); + when(configuration.isConfigured()) + .thenReturn(true); + when(configuration.getMode()) + .thenReturn(mode); + return configuration; + } + } diff --git a/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackMessageBuilderIntegrationTest.java b/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackMessageBuilderIntegrationTest.java deleted file mode 100644 index a789b385..00000000 --- a/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackMessageBuilderIntegrationTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2021 Red Hat, Inc. - * Distributed under license by Red Hat, Inc. All rights reserved. - * This program is made available under the terms of the - * Eclipse Public License v2.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v20.html - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - ******************************************************************************/ -package com.redhat.devtools.intellij.telemetry.core.service; - -import com.jakewharton.retrofit.Ok3Client; -import com.redhat.devtools.intellij.telemetry.core.IService; -import com.redhat.devtools.intellij.telemetry.core.service.segment.ISegmentConfiguration; -import com.redhat.devtools.intellij.telemetry.core.service.segment.IdentifyTraitsPersistence; -import com.redhat.devtools.intellij.telemetry.core.service.segment.SegmentBroker; -import com.redhat.devtools.intellij.telemetry.util.BlockingFlush; -import com.redhat.devtools.intellij.telemetry.util.StdOutLogging; -import com.segment.analytics.Analytics; -import okhttp3.OkHttpClient; -import org.junit.Ignore; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import retrofit.client.Client; - -import java.util.concurrent.TimeUnit; - -import static com.redhat.devtools.intellij.telemetry.core.service.Fakes.segmentConfiguration; -import static com.redhat.devtools.intellij.telemetry.core.service.FeedbackMessageBuilder.*; -import static org.mockito.Mockito.mock; - -@Ignore("For manual testing purposes only") -class FeedbackMessageBuilderIntegrationTest { - - public static final String SEGMENT_WRITE_KEY = "ySk3bh8S8hDIGVKX9FQ1BMGOdFxbsufn"; - - private BlockingFlush blockingFlush; - private Analytics analytics; - private FeedbackMessage message; - - @BeforeEach - void before() { - this.blockingFlush = BlockingFlush.create(); - this.analytics = createAnalytics(blockingFlush, createClient()); - ISegmentConfiguration configuration = segmentConfiguration(SEGMENT_WRITE_KEY, ""); - SegmentBroker broker = new SegmentBroker( - false, - UserId.INSTANCE.get(), - IdentifyTraitsPersistence.INSTANCE, - null, - configuration, - key -> analytics); - IService service = new FeedbackService(broker); - this.message = new FeedbackMessageBuilder(service) - .feedback("Testing Feedback"); - } - - @AfterEach - void after() { - shutdownAnalytics(); - } - - @Test - void should_send_track_event() { - // given - message.property("jedi", "yoda") - .property("use", "the force"); - // when - message.send(); - // then - } - - private Analytics createAnalytics(BlockingFlush blockingFlush, Client client) { - return Analytics.builder(SEGMENT_WRITE_KEY) - .plugin(new StdOutLogging()) - .plugin(blockingFlush.plugin()) - .client(client) - .build(); - } - - private Client createClient() { - return new Ok3Client( - new OkHttpClient.Builder() - .connectTimeout(5, TimeUnit.SECONDS) - .readTimeout(5, TimeUnit.SECONDS) - .writeTimeout(5, TimeUnit.SECONDS) - .build()); - } - - private void shutdownAnalytics() { - analytics.flush(); - blockingFlush.block(); - analytics.shutdown(); - } - -} diff --git a/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackMessageBuilderTest.java b/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackMessageBuilderTest.java deleted file mode 100644 index 2b7106c9..00000000 --- a/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/FeedbackMessageBuilderTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 Red Hat, Inc. - * Distributed under license by Red Hat, Inc. All rights reserved. - * This program is made available under the terms of the - * Eclipse Public License v2.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v20.html - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - ******************************************************************************/ -package com.redhat.devtools.intellij.telemetry.core.service; - -import com.redhat.devtools.intellij.telemetry.core.IService; -import com.redhat.devtools.intellij.telemetry.core.service.FeedbackMessageBuilder.FeedbackMessage; -import com.redhat.devtools.intellij.telemetry.core.service.FeedbackMessageBuilder.FeedbackServiceFacade; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; - -import static com.redhat.devtools.intellij.telemetry.core.service.Event.Type.ACTION; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -class FeedbackMessageBuilderTest { - - private final IService serviceFacadeMock = mock(IService.class); - private final FeedbackMessageBuilder builder = new FeedbackMessageBuilder(serviceFacadeMock); - private final IService service = mock(IService.class); - private final TestableFeedbackServiceFacade serviceFacade = spy(new TestableFeedbackServiceFacade(service)); - private final Event event = mock(Event.class); - - @Test - void action_should_create_message_with_action_type() { - // given - // when - FeedbackMessage message = builder.feedback("azrael"); - // then - assertThat(message.getType()).isEqualTo(ACTION); - } - - @Test - void action_should_create_message_with_given_name() { - // given - String name = "papa smurf"; - // when - FeedbackMessage message = builder.feedback(name); - // then - assertThat(message.getName()).isEqualTo(name); - } - - @Test - void property_should_add_property_with_given_key_and_name() { - // given - String key = "likes"; - String value = "papa smurf"; - // when - FeedbackMessage message = builder.feedback("smurfette").property(key, value); - // then - assertThat(message.getProperty(key)).isEqualTo(value); - } - - @Test - void property_should_ignore_property_with_null_key() { - // given - FeedbackMessage message = builder.feedback("smurfette"); - int beforeAdding = message.properties().size(); - // when - message.property(null, "papa smurf"); - // then - assertThat(message.properties()).hasSize(beforeAdding); - } - - @Test - void property_should_ignore_property_with_null_value() { - // given - FeedbackMessage message = builder.feedback("smurfette"); - int beforeAdding = message.properties().size(); - // when - message.property("likes", null); - // then - assertThat(message.properties()).hasSize(beforeAdding); - } - - @Test - void send_should_send_message_via_service_facade() { - // given - FeedbackMessage message = builder.feedback("gargamel"); - // when - message.send(); - // then - verify(serviceFacadeMock).send(any(Event.class)); - } - - @Test - void send_should_send_event_with_given_type_name_and_properties() { - // given - String name = "gargamel"; - String key1 = "the lovliest"; - String value1 = "smurfette"; - String key2 = "the smallest"; - String value2 = "baby smurf"; - FeedbackMessage message = builder.feedback(name) - .property(key1, value1) - .property(key2, value2); - ArgumentCaptor eventArgument = ArgumentCaptor.forClass(Event.class); - // when - message.send(); - // then - verify(serviceFacadeMock).send(eventArgument.capture()); - Event event = eventArgument.getValue(); - assertThat(event.getType()).isEqualTo(ACTION); - assertThat(event.getName()).isEqualTo(name); - assertThat(event.getProperties()) - .containsEntry(key1, value1) - .containsEntry(key2,value2); - } - - @Test - void send_should_send_to_same_facade_instance() { - // given - FeedbackMessage message1 = builder.feedback("gargamel"); - FeedbackMessage message2 = builder.feedback("azrael"); - FeedbackMessage message3 = builder.feedback("papa smurf"); - // when - message1.send(); - message2.send(); - message3.send(); - // then - verify(serviceFacadeMock, times(3)).send(any(Event.class)); - } - - @Test - void serviceFacade_send_should_create_service_once_only() { - // given - // when - serviceFacade.send(event); - serviceFacade.send(event); - serviceFacade.send(event); - // then - verify(serviceFacade, times(1)).onCreated(any()); - } - - private static class TestableFeedbackServiceFacade extends FeedbackServiceFacade { - - protected TestableFeedbackServiceFacade(IService service) { - super(() -> service); - } - - /* public for testing purposes */ - @Override - public void onCreated(IService value) { - super.onCreated(value); - } - } - -} diff --git a/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryMessageBuilderTest.java b/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryMessageBuilderTest.java index 241582de..432f60a3 100644 --- a/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryMessageBuilderTest.java +++ b/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryMessageBuilderTest.java @@ -13,6 +13,7 @@ import com.intellij.ide.AppLifecycleListener; import com.intellij.util.messages.MessageBusConnection; import com.redhat.devtools.intellij.telemetry.core.IService; +import com.redhat.devtools.intellij.telemetry.core.service.TelemetryMessageBuilder.FeedbackServiceFacade; import com.redhat.devtools.intellij.telemetry.core.util.AnonymizeUtils; import com.redhat.devtools.intellij.telemetry.core.util.TimeUtils; import org.junit.jupiter.api.Test; @@ -29,6 +30,7 @@ import static com.redhat.devtools.intellij.telemetry.core.service.TelemetryMessageBuilder.ActionMessage; import static com.redhat.devtools.intellij.telemetry.core.service.TelemetryMessageBuilder.ActionMessage.PROP_DURATION; import static com.redhat.devtools.intellij.telemetry.core.service.TelemetryMessageBuilder.ActionMessage.PROP_RESULT; +import static com.redhat.devtools.intellij.telemetry.core.service.TelemetryMessageBuilder.FeedbackMessage; import static com.redhat.devtools.intellij.telemetry.core.service.TelemetryMessageBuilder.ShutdownMessage; import static com.redhat.devtools.intellij.telemetry.core.service.TelemetryMessageBuilder.TelemetryServiceFacade; import static org.assertj.core.api.Assertions.assertThat; @@ -41,8 +43,9 @@ class TelemetryMessageBuilderTest { - private final TelemetryServiceFacade serviceFacadeMock = mock(TelemetryServiceFacade.class); - private final TelemetryMessageBuilder builder = new TelemetryMessageBuilder(serviceFacadeMock); + private final IService telemetryServiceFacade = mock(TelemetryServiceFacade.class); + private final IService feedbackServiceFacade = mock(FeedbackServiceFacade.class); + private final TelemetryMessageBuilder builder = new TelemetryMessageBuilder(telemetryServiceFacade, feedbackServiceFacade); private final IService service = mock(IService.class); private final MessageBusConnection bus = mock(MessageBusConnection.class); private final TestableTelemetryServiceFacade serviceFacade = spy(new TestableTelemetryServiceFacade(service, bus)); @@ -107,7 +110,7 @@ void send_should_send_message_via_service_facade() { // when message.send(); // then - verify(serviceFacadeMock).send(any(Event.class)); + verify(telemetryServiceFacade).send(any(Event.class)); } @Test @@ -125,7 +128,7 @@ void send_should_send_event_with_given_type_name_and_properties() { // when message.send(); // then - verify(serviceFacadeMock).send(eventArgument.capture()); + verify(telemetryServiceFacade).send(eventArgument.capture()); Event event = eventArgument.getValue(); assertThat(event.getType()).isEqualTo(ACTION); assertThat(event.getName()).isEqualTo(name); @@ -204,7 +207,7 @@ void send_should_send_to_same_facade_instance() { message2.send(); message3.send(); // then - verify(serviceFacadeMock, times(3)).send(any(Event.class)); + verify(telemetryServiceFacade, times(3)).send(any(Event.class)); } @Test @@ -422,11 +425,123 @@ void shutdownMessage_should_report_session_duration() { LocalDateTime shutdown = LocalDateTime.of(LocalDate.now().plusDays(1), LocalTime.of(4, 2)); Duration duration = Duration.between(startup, shutdown); // when - ShutdownMessage message = new ShutdownMessage(startup, shutdown, serviceFacadeMock); + ShutdownMessage message = new ShutdownMessage(startup, shutdown, telemetryServiceFacade); // then assertThat(message.getSessionDuration()).isEqualTo(TimeUtils.toString(duration)); } + @Test + void feedback_should_create_message_with_action_type() { + // given + // when + FeedbackMessage message = builder.feedback("azrael"); + // then + assertThat(message.getType()).isEqualTo(ACTION); + } + + @Test + void feedback_should_create_message_with_given_name() { + // given + String name = "papa smurf"; + // when + FeedbackMessage message = builder.feedback(name); + // then + assertThat(message.getName()).isEqualTo(name); + } + + @Test + void feedback_property_should_add_property_with_given_key_and_name() { + // given + String key = "likes"; + String value = "papa smurf"; + // when + FeedbackMessage message = builder.feedback("smurfette").property(key, value); + // then + assertThat(message.getProperty(key)).isEqualTo(value); + } + + @Test + void feedback_property_should_ignore_property_with_null_key() { + // given + FeedbackMessage message = builder.feedback("smurfette"); + int beforeAdding = message.properties().size(); + // when + message.property(null, "papa smurf"); + // then + assertThat(message.properties()).hasSize(beforeAdding); + } + + @Test + void feedback_property_should_ignore_property_with_null_value() { + // given + FeedbackMessage message = builder.feedback("smurfette"); + int beforeAdding = message.properties().size(); + // when + message.property("likes", null); + // then + assertThat(message.properties()).hasSize(beforeAdding); + } + + @Test + void feedback_send_should_send_message_via_service_facade() { + // given + FeedbackMessage message = builder.feedback("gargamel"); + // when + message.send(); + // then + verify(feedbackServiceFacade).send(any(Event.class)); + } + + @Test + void feedback_send_should_send_event_with_given_type_name_and_properties() { + // given + String name = "gargamel"; + String key1 = "the lovliest"; + String value1 = "smurfette"; + String key2 = "the smallest"; + String value2 = "baby smurf"; + FeedbackMessage message = builder.feedback(name) + .property(key1, value1) + .property(key2, value2); + ArgumentCaptor eventArgument = ArgumentCaptor.forClass(Event.class); + // when + message.send(); + // then + verify(feedbackServiceFacade).send(eventArgument.capture()); + Event event = eventArgument.getValue(); + assertThat(event.getType()).isEqualTo(ACTION); + assertThat(event.getName()).isEqualTo(name); + assertThat(event.getProperties()) + .containsEntry(key1, value1) + .containsEntry(key2,value2); + } + + @Test + void feedback_send_should_send_to_same_facade_instance() { + // given + FeedbackMessage message1 = builder.feedback("gargamel"); + FeedbackMessage message2 = builder.feedback("azrael"); + FeedbackMessage message3 = builder.feedback("papa smurf"); + // when + message1.send(); + message2.send(); + message3.send(); + // then + verify(feedbackServiceFacade, times(3)).send(any(Event.class)); + } + + @Test + void feedback_send_should_create_service_once_only() { + // given + TestableFeedbackServiceFacade facade = spy(new TestableFeedbackServiceFacade(mock(IService.class))); + // when + facade.send(event); + facade.send(event); + facade.send(event); + // then + verify(facade, times(1)).onCreated(any()); + } + private static class TestableTelemetryServiceFacade extends TelemetryServiceFacade { private final MessageBusConnection bus; @@ -444,4 +559,16 @@ protected MessageBusConnection createMessageBusConnection() { public void sendShutdown() {} } + private static class TestableFeedbackServiceFacade extends FeedbackServiceFacade { + + protected TestableFeedbackServiceFacade(IService service) { + super(() -> service); + } + + /** public for testing purposes **/ + @Override + protected void onCreated(IService value) { + super.onCreated(value); + } + } } diff --git a/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryServiceIntegrationTest.java b/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryServiceIntegrationTest.java index 33bdf799..dda98889 100644 --- a/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryServiceIntegrationTest.java +++ b/src/test/java/com/redhat/devtools/intellij/telemetry/core/service/TelemetryServiceIntegrationTest.java @@ -22,9 +22,9 @@ import com.redhat.devtools.intellij.telemetry.util.StdOutLogging; import com.segment.analytics.Analytics; import okhttp3.OkHttpClient; -import org.junit.Ignore; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import retrofit.client.Client; @@ -32,14 +32,16 @@ import static com.redhat.devtools.intellij.telemetry.core.service.Fakes.environment; import static com.redhat.devtools.intellij.telemetry.core.service.Fakes.segmentConfiguration; -import static com.redhat.devtools.intellij.telemetry.core.service.Event.Type.ACTION; +import static com.redhat.devtools.intellij.telemetry.core.service.Fakes.telemetryConfiguration; +import static com.redhat.devtools.intellij.telemetry.core.service.TelemetryMessageBuilder.FeedbackServiceFacade; +import static com.redhat.devtools.intellij.telemetry.core.service.TelemetryMessageBuilder.TelemetryServiceFacade; import static org.mockito.Mockito.mock; -@Ignore("For manual testing purposes only") +@Disabled("For manual testing purposes only") class TelemetryServiceIntegrationTest { private static final String EXTENSION_NAME = "com.redhat.devtools.intellij.telemetry"; - private static final String EXTENSION_VERSION = "0.0.1"; + private static final String EXTENSION_VERSION = "1.0.0.44"; private static final String APPLICATION_VERSION = "1.0.0"; private static final String APPLICATION_NAME = TelemetryServiceIntegrationTest.class.getSimpleName(); private static final String PLATFORM_NAME = "smurfOS"; @@ -48,18 +50,18 @@ class TelemetryServiceIntegrationTest { private static final String LOCALE = "de_CH"; private static final String TIMEZONE = "Europe/Bern"; private static final String COUNTRY = "Switzerland"; - public static final String SEGMENT_WRITE_KEY = "HYuMCHlIpTvukCKZA42OubI1cvGIAap6"; + public static final String SEGMENT_WRITE_KEY = "--HYuMCHlIpTvukCKZA42OubI1cvGIAap6"; + public static final String SEGMENT_DEBUG_WRITE_KEY = "--ySk3bh8S8hDIGVKX9FQ1BMGOdFxbsufn"; private BlockingFlush blockingFlush; private Analytics analytics; - private IService service; - private Event event; + private TelemetryMessageBuilder messageBuilder; @BeforeEach void before() { this.blockingFlush = BlockingFlush.create(); this.analytics = createAnalytics(blockingFlush, createClient()); - ISegmentConfiguration configuration = segmentConfiguration(SEGMENT_WRITE_KEY, ""); + ISegmentConfiguration segmentConfiguration = segmentConfiguration(SEGMENT_WRITE_KEY, SEGMENT_DEBUG_WRITE_KEY); Environment environment = environment( APPLICATION_NAME, APPLICATION_VERSION, @@ -76,14 +78,23 @@ void before() { UserId.INSTANCE.get(), IdentifyTraitsPersistence.INSTANCE, environment, - configuration, + segmentConfiguration, key -> analytics); - this.service = new TelemetryService( - TelemetryConfiguration.getInstance(), + TelemetryConfiguration telemetryConfiguration = telemetryConfiguration(TelemetryConfiguration.Mode.DEBUG); + TelemetryService telemetryService = new TelemetryService( + telemetryConfiguration, broker, mock(MessageBusConnection.class), mock(TelemetryNotifications.class)); - this.event = new Event(ACTION, "Testing Telemetry"); + IService telemetryServiceFacade = new TelemetryServiceFacade(() -> telemetryService) { + @Override + protected MessageBusConnection createMessageBusConnection() { + return mock(MessageBusConnection.class); + } + }; + FeedbackService feedbackService = new FeedbackService(broker); + IService feedbackServiceFacade = new FeedbackServiceFacade(() -> feedbackService); + this.messageBuilder = new TelemetryMessageBuilder(telemetryServiceFacade, feedbackServiceFacade); } @AfterEach @@ -92,10 +103,25 @@ void after() { } @Test - void should_send_track_event() { + void should_send_telemetry() { // given // when - service.send(event); + messageBuilder.action("testing-telemetry") + .property("Smurf", "Smurfette") + .property("Sorcerer", "Gargamel") + .success() + .send(); + // then + } + + @Test + void should_send_feedback() { + // given + // when + messageBuilder.feedback("testing-feedback") + .property("Jedi", "Luke Skywalker") + .property("Sith", "Darth Vader") + .send(); // then }