diff --git a/src/main/java/com/schematic/api/EventBuffer.java b/src/main/java/com/schematic/api/EventBuffer.java index 41a731e..35fa5af 100644 --- a/src/main/java/com/schematic/api/EventBuffer.java +++ b/src/main/java/com/schematic/api/EventBuffer.java @@ -4,7 +4,6 @@ import com.schematic.api.resources.events.EventsClient; import com.schematic.api.resources.events.requests.CreateEventBatchRequestBody; import com.schematic.api.types.CreateEventRequestBody; - import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -42,10 +41,7 @@ public class EventBuffer implements AutoCloseable { * @param maxBatchSize Maximum number of events to include in a single batch * @param flushInterval How often to automatically flush the buffer */ - public EventBuffer(EventsClient eventsClient, - SchematicLogger logger, - int maxBatchSize, - Duration flushInterval) { + public EventBuffer(EventsClient eventsClient, SchematicLogger logger, int maxBatchSize, Duration flushInterval) { this.events = new ConcurrentLinkedQueue<>(); this.maxBatchSize = maxBatchSize > 0 ? maxBatchSize : DEFAULT_MAX_BATCH_SIZE; this.flushInterval = flushInterval != null ? flushInterval : DEFAULT_FLUSH_INTERVAL; @@ -120,9 +116,8 @@ public void flush() { private void sendBatchWithRetry(List batch, int retryCount) { try { - CreateEventBatchRequestBody requestBody = CreateEventBatchRequestBody.builder() - .events(batch) - .build(); + CreateEventBatchRequestBody requestBody = + CreateEventBatchRequestBody.builder().events(batch).build(); eventsClient.createEventBatch(requestBody); processedEvents.addAndGet(batch.size()); @@ -130,14 +125,11 @@ private void sendBatchWithRetry(List batch, int retryCou } catch (Exception e) { if (retryCount < MAX_RETRY_ATTEMPTS) { long delayMillis = RETRY_INITIAL_DELAY.toMillis() * (1L << retryCount); - logger.warn("Failed to send event batch, attempting retry %d of %d in %d ms", - retryCount + 1, MAX_RETRY_ATTEMPTS, delayMillis); - - scheduler.schedule( - () -> sendBatchWithRetry(batch, retryCount + 1), - delayMillis, - TimeUnit.MILLISECONDS - ); + logger.warn( + "Failed to send event batch, attempting retry %d of %d in %d ms", + retryCount + 1, MAX_RETRY_ATTEMPTS, delayMillis); + + scheduler.schedule(() -> sendBatchWithRetry(batch, retryCount + 1), delayMillis, TimeUnit.MILLISECONDS); } else { failedEvents.addAndGet(batch.size()); logger.error("Failed to flush events: " + e.getMessage()); @@ -147,17 +139,16 @@ private void sendBatchWithRetry(List batch, int retryCou private void startPeriodicFlush() { scheduler.scheduleAtFixedRate( - () -> { - try { - flush(); - } catch (Exception e) { - logger.error("Error during periodic flush: %s", e.getMessage()); - } - }, - flushInterval.toMillis(), - flushInterval.toMillis(), - TimeUnit.MILLISECONDS - ); + () -> { + try { + flush(); + } catch (Exception e) { + logger.error("Error during periodic flush: %s", e.getMessage()); + } + }, + flushInterval.toMillis(), + flushInterval.toMillis(), + TimeUnit.MILLISECONDS); } /** @@ -195,12 +186,8 @@ public void close() { */ public String getMetrics() { return String.format( - "EventBuffer Metrics - Processed: %d, Dropped: %d, Failed: %d, Current Queue Size: %d", - processedEvents.get(), - droppedEvents.get(), - failedEvents.get(), - events.size() - ); + "EventBuffer Metrics - Processed: %d, Dropped: %d, Failed: %d, Current Queue Size: %d", + processedEvents.get(), droppedEvents.get(), failedEvents.get(), events.size()); } /** diff --git a/src/main/java/com/schematic/api/Schematic.java b/src/main/java/com/schematic/api/Schematic.java index ce051fb..283ae44 100644 --- a/src/main/java/com/schematic/api/Schematic.java +++ b/src/main/java/com/schematic/api/Schematic.java @@ -38,30 +38,29 @@ private Schematic(Builder builder) { super(buildClientOptions(builder.apiKey, builder)); this.apiKey = builder.apiKey; - this.eventBufferInterval = builder.eventBufferInterval != null ? - builder.eventBufferInterval : - Duration.ofMillis(5000); + this.eventBufferInterval = + builder.eventBufferInterval != null ? builder.eventBufferInterval : Duration.ofMillis(5000); this.logger = builder.logger != null ? builder.logger : new ConsoleLogger(); this.flagDefaults = builder.flagDefaults != null ? builder.flagDefaults : new HashMap<>(); this.offline = builder.offline; - this.flagCheckCacheProviders = builder.cacheProviders != null ? - builder.cacheProviders : - Collections.singletonList(new LocalCache<>()); + this.flagCheckCacheProviders = + builder.cacheProviders != null ? builder.cacheProviders : Collections.singletonList(new LocalCache<>()); this.eventBuffer = new EventBuffer( - super.events(), - this.logger, - builder.eventBufferMaxSize, - builder.eventBufferInterval != null ? builder.eventBufferInterval : Duration.ofMillis(5000) - ); - - this.shutdownHook = new Thread(() -> { - try { - this.eventBuffer.close(); - } catch (Exception e) { - logger.error("Error during Schematic shutdown: " + e.getMessage()); - } - }, "SchematicShutdownHook"); + super.events(), + this.logger, + builder.eventBufferMaxSize, + builder.eventBufferInterval != null ? builder.eventBufferInterval : Duration.ofMillis(5000)); + + this.shutdownHook = new Thread( + () -> { + try { + this.eventBuffer.close(); + } catch (Exception e) { + logger.error("Error during Schematic shutdown: " + e.getMessage()); + } + }, + "SchematicShutdownHook"); Runtime.getRuntime().addShutdownHook(this.shutdownHook); } @@ -137,10 +136,10 @@ public Schematic build() { private static ClientOptions buildClientOptions(String apiKey, Builder builder) { String basePath = builder.basePath != null ? builder.basePath : "https://api.schematichq.com"; return ClientOptions.builder() - .environment(Environment.custom(basePath)) - .addHeader("Authorization", "Bearer " + apiKey) - .addHeader("Content-Type", "application/json") - .build(); + .environment(Environment.custom(basePath)) + .addHeader("Authorization", "Bearer " + apiKey) + .addHeader("Content-Type", "application/json") + .build(); } public List> getFlagCheckCacheProviders() { @@ -176,10 +175,8 @@ public boolean checkFlag(String flagKey, Map company, Map company, Map keys, EventBodyIdentifyCompany company, String name, Map traits) { + public void identify( + Map keys, EventBodyIdentifyCompany company, String name, Map traits) { if (offline) return; try { EventBodyIdentify body = EventBodyIdentify.builder() - .keys(keys) - .company(company) - .name(name) - .traits(objectMapToJsonNode(traits)) - .build(); + .keys(keys) + .company(company) + .name(name) + .traits(objectMapToJsonNode(traits)) + .build(); CreateEventRequestBody event = CreateEventRequestBody.builder() - .eventType(CreateEventRequestBodyEventType.IDENTIFY) - .body(EventBody.of(body)) - .sentAt(OffsetDateTime.now()) - .build(); + .eventType(CreateEventRequestBodyEventType.IDENTIFY) + .body(EventBody.of(body)) + .sentAt(OffsetDateTime.now()) + .build(); eventBuffer.push(event); } catch (Exception e) { @@ -219,22 +217,23 @@ public void identify(Map keys, EventBodyIdentifyCompany company, } } - public void track(String eventName, Map company, Map user, Map traits) { + public void track( + String eventName, Map company, Map user, Map traits) { if (offline) return; try { EventBodyTrack body = EventBodyTrack.builder() - .event(eventName) - .company(company) - .user(user) - .traits(objectMapToJsonNode(traits)) - .build(); + .event(eventName) + .company(company) + .user(user) + .traits(objectMapToJsonNode(traits)) + .build(); CreateEventRequestBody event = CreateEventRequestBody.builder() - .eventType(CreateEventRequestBodyEventType.TRACK) - .body(EventBody.of(body)) - .sentAt(OffsetDateTime.now()) - .build(); + .eventType(CreateEventRequestBodyEventType.TRACK) + .body(EventBody.of(body)) + .sentAt(OffsetDateTime.now()) + .build(); eventBuffer.push(event); } catch (Exception e) { @@ -286,8 +285,8 @@ private Map objectMapToJsonNode(Map map) { private String serializeMap(Map map) { return map.entrySet().stream() - .sorted(Map.Entry.comparingByKey()) - .map(e -> e.getKey() + "=" + e.getValue()) - .collect(Collectors.joining(";")); + .sorted(Map.Entry.comparingByKey()) + .map(e -> e.getKey() + "=" + e.getValue()) + .collect(Collectors.joining(";")); } } diff --git a/src/main/java/com/schematic/api/cache/CacheProvider.java b/src/main/java/com/schematic/api/cache/CacheProvider.java index b4aa953..93a8dcf 100644 --- a/src/main/java/com/schematic/api/cache/CacheProvider.java +++ b/src/main/java/com/schematic/api/cache/CacheProvider.java @@ -4,6 +4,8 @@ public interface CacheProvider { T get(String key); + void set(String key, T val, Duration ttlOverride); + void set(String key, T val); -} \ No newline at end of file +} diff --git a/src/main/java/com/schematic/api/cache/CachedItem.java b/src/main/java/com/schematic/api/cache/CachedItem.java index f7ee05c..3af3d42 100644 --- a/src/main/java/com/schematic/api/cache/CachedItem.java +++ b/src/main/java/com/schematic/api/cache/CachedItem.java @@ -32,4 +32,4 @@ public void setExpiration(Instant expiration) { public String getKey() { return key; } -} \ No newline at end of file +} diff --git a/src/main/java/com/schematic/api/cache/LocalCache.java b/src/main/java/com/schematic/api/cache/LocalCache.java index 03c1ca7..ac80ee5 100644 --- a/src/main/java/com/schematic/api/cache/LocalCache.java +++ b/src/main/java/com/schematic/api/cache/LocalCache.java @@ -2,8 +2,8 @@ import java.time.Duration; import java.time.Instant; -import java.util.concurrent.ConcurrentHashMap; import java.util.LinkedList; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; public class LocalCache implements CacheProvider { @@ -103,4 +103,4 @@ private void remove(String key) { } } } -} \ No newline at end of file +} diff --git a/src/main/java/com/schematic/api/logger/ConsoleLogger.java b/src/main/java/com/schematic/api/logger/ConsoleLogger.java index 5d6eb7b..e569538 100644 --- a/src/main/java/com/schematic/api/logger/ConsoleLogger.java +++ b/src/main/java/com/schematic/api/logger/ConsoleLogger.java @@ -20,4 +20,4 @@ public void info(String message, Object... args) { public void debug(String message, Object... args) { System.out.println("[DEBUG] " + String.format(message, args)); } -} \ No newline at end of file +} diff --git a/src/main/java/com/schematic/api/logger/SchematicLogger.java b/src/main/java/com/schematic/api/logger/SchematicLogger.java index 921ccfc..5de5adf 100644 --- a/src/main/java/com/schematic/api/logger/SchematicLogger.java +++ b/src/main/java/com/schematic/api/logger/SchematicLogger.java @@ -2,7 +2,10 @@ public interface SchematicLogger { void error(String message, Object... args); + void warn(String message, Object... args); + void info(String message, Object... args); + void debug(String message, Object... args); -} \ No newline at end of file +} diff --git a/src/main/java/com/schematic/api/resources/accounts/AccountsClient.java b/src/main/java/com/schematic/api/resources/accounts/AccountsClient.java index c64f7ec..50c6f8d 100644 --- a/src/main/java/com/schematic/api/resources/accounts/AccountsClient.java +++ b/src/main/java/com/schematic/api/resources/accounts/AccountsClient.java @@ -67,8 +67,7 @@ public ListApiKeysResponse listApiKeys(ListApiKeysRequest request, RequestOption httpUrl.addQueryParameter( "environment_id", request.getEnvironmentId().get()); } - httpUrl.addQueryParameter( - "require_environment", Boolean.toString(request.getRequireEnvironment())); + httpUrl.addQueryParameter("require_environment", Boolean.toString(request.getRequireEnvironment())); if (request.getLimit().isPresent()) { httpUrl.addQueryParameter("limit", request.getLimit().get().toString()); } @@ -363,8 +362,7 @@ public CountApiKeysResponse countApiKeys(CountApiKeysRequest request, RequestOpt httpUrl.addQueryParameter( "environment_id", request.getEnvironmentId().get()); } - httpUrl.addQueryParameter( - "require_environment", Boolean.toString(request.getRequireEnvironment())); + httpUrl.addQueryParameter("require_environment", Boolean.toString(request.getRequireEnvironment())); if (request.getLimit().isPresent()) { httpUrl.addQueryParameter("limit", request.getLimit().get().toString()); } diff --git a/src/test/java/com/schematic/api/TestCache.java b/src/test/java/com/schematic/api/TestCache.java index 449c898..bcb3326 100644 --- a/src/test/java/com/schematic/api/TestCache.java +++ b/src/test/java/com/schematic/api/TestCache.java @@ -1,8 +1,9 @@ package com.schematic.api; -import com.schematic.api.cache.LocalCache; +import static org.junit.jupiter.api.Assertions.*; + import com.schematic.api.cache.CacheProvider; -import org.junit.jupiter.api.Test; +import com.schematic.api.cache.LocalCache; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -10,7 +11,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; class LocalCacheTest { @@ -53,10 +54,7 @@ void testDefaultTTL() throws InterruptedException { @Test void testDefaultCapacity() { - LocalCache cacheProvider = new LocalCache<>( - LocalCache.DEFAULT_CACHE_CAPACITY, - Duration.ofMinutes(10) - ); + LocalCache cacheProvider = new LocalCache<>(LocalCache.DEFAULT_CACHE_CAPACITY, Duration.ofMinutes(10)); String key = "test_key"; cacheProvider.set(key, -1); @@ -116,10 +114,7 @@ void testConcurrentAccess() throws InterruptedException { } assertEquals(cacheCapacity, cacheHits.size()); - assertNotEquals( - cacheCapacity, - cacheHits.get(cacheHits.size() - 1) - cacheHits.get(0) + 1 - ); + assertNotEquals(cacheCapacity, cacheHits.get(cacheHits.size() - 1) - cacheHits.get(0) + 1); } @Test diff --git a/src/test/java/com/schematic/api/TestEventBuffer.java b/src/test/java/com/schematic/api/TestEventBuffer.java index 30ebca4..1cf6c63 100644 --- a/src/test/java/com/schematic/api/TestEventBuffer.java +++ b/src/test/java/com/schematic/api/TestEventBuffer.java @@ -1,9 +1,16 @@ package com.schematic.api; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + import com.schematic.api.logger.SchematicLogger; import com.schematic.api.resources.events.EventsClient; import com.schematic.api.resources.events.requests.CreateEventBatchRequestBody; import com.schematic.api.types.CreateEventRequestBody; +import java.time.Duration; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -12,21 +19,14 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.time.Duration; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class EventBufferTest { @Mock private EventsClient eventsClient; + @Mock private SchematicLogger logger; + private EventBuffer eventBuffer; @BeforeEach @@ -139,17 +139,18 @@ void concurrentPushes_ShouldHandleCorrectly() throws InterruptedException { for (int i = 0; i < threadCount; i++) { new Thread(() -> { - try { - startLatch.await(); - for (int j = 0; j < 10; j++) { - eventBuffer.push(mock(CreateEventRequestBody.class)); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } finally { - doneLatch.countDown(); - } - }).start(); + try { + startLatch.await(); + for (int j = 0; j < 10; j++) { + eventBuffer.push(mock(CreateEventRequestBody.class)); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + doneLatch.countDown(); + } + }) + .start(); } startLatch.countDown(); @@ -163,8 +164,8 @@ void concurrentPushes_ShouldHandleCorrectly() throws InterruptedException { verify(eventsClient, atLeastOnce()).createEventBatch(captor.capture()); int totalEvents = captor.getAllValues().stream() - .mapToInt(batch -> batch.getEvents().size()) - .sum(); + .mapToInt(batch -> batch.getEvents().size()) + .sum(); assertEquals(100, totalEvents); } } diff --git a/src/test/java/com/schematic/api/TestLogger.java b/src/test/java/com/schematic/api/TestLogger.java index 019ba78..f8dcb23 100644 --- a/src/test/java/com/schematic/api/TestLogger.java +++ b/src/test/java/com/schematic/api/TestLogger.java @@ -1,12 +1,13 @@ package com.schematic.api; +import static org.junit.jupiter.api.Assertions.*; + import com.schematic.api.logger.ConsoleLogger; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import static org.junit.jupiter.api.Assertions.*; class LoggerTest { private ByteArrayOutputStream outputStream; diff --git a/src/test/java/com/schematic/api/TestReadme.java b/src/test/java/com/schematic/api/TestReadme.java index 81d64bd..3015413 100644 --- a/src/test/java/com/schematic/api/TestReadme.java +++ b/src/test/java/com/schematic/api/TestReadme.java @@ -1,5 +1,9 @@ package com.schematic.api; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + import com.fasterxml.jackson.databind.JsonNode; import com.schematic.api.cache.LocalCache; import com.schematic.api.core.ObjectMappers; @@ -17,9 +21,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; // Testing code examples used in README @ExtendWith(MockitoExtension.class) @@ -31,9 +32,7 @@ class SchematicReadmeTest { void testCompanyUpsert() { // Test the company upsert example from README CompaniesClient companiesClient = mock(CompaniesClient.class); - Schematic spySchematic = spy(Schematic.builder() - .apiKey("test_api_key") - .build()); + Schematic spySchematic = spy(Schematic.builder().apiKey("test_api_key").build()); when(spySchematic.companies()).thenReturn(companiesClient); Map keys = new HashMap<>(); @@ -45,24 +44,23 @@ void testCompanyUpsert() { traits.put("is_active", ObjectMappers.JSON_MAPPER.valueToTree(true)); UpsertCompanyRequestBody request = UpsertCompanyRequestBody.builder() - .keys(keys) - .name("Acme Widgets, Inc.") - .traits(traits) - .build(); + .keys(keys) + .name("Acme Widgets, Inc.") + .traits(traits) + .build(); OffsetDateTime now = OffsetDateTime.now(); CompanyDetailResponseData responseData = CompanyDetailResponseData.builder() - .createdAt(now) - .environmentId("test-env") - .id("test-id") - .name("Acme Widgets, Inc.") - .updatedAt(now) - .userCount(1) - .build(); - - UpsertCompanyResponse response = UpsertCompanyResponse.builder() - .data(responseData) - .build(); + .createdAt(now) + .environmentId("test-env") + .id("test-id") + .name("Acme Widgets, Inc.") + .updatedAt(now) + .userCount(1) + .build(); + + UpsertCompanyResponse response = + UpsertCompanyResponse.builder().data(responseData).build(); when(companiesClient.upsertCompany(any())).thenReturn(response); @@ -74,9 +72,7 @@ void testCompanyUpsert() { @Test void testClientBasicInitialization() { // Test basic client initialization from README - Schematic schematic = Schematic.builder() - .apiKey("test_api_key") - .build(); + Schematic schematic = Schematic.builder().apiKey("test_api_key").build(); assertNotNull(schematic); assertEquals("test_api_key", schematic.getApiKey()); @@ -86,9 +82,9 @@ void testClientBasicInitialization() { void testClientWithLocalCache() { // Test client with local cache configuration Schematic schematic = Schematic.builder() - .apiKey("test_api_key") - .cacheProviders(Collections.singletonList(new LocalCache<>())) - .build(); + .apiKey("test_api_key") + .cacheProviders(Collections.singletonList(new LocalCache<>())) + .build(); assertNotNull(schematic.getFlagCheckCacheProviders()); assertEquals(1, schematic.getFlagCheckCacheProviders().size()); @@ -99,9 +95,9 @@ void testClientWithLocalCache() { void testClientWithDisabledCache() { // Test client with disabled caching Schematic schematic = Schematic.builder() - .apiKey("test_api_key") - .cacheProviders(Collections.emptyList()) - .build(); + .apiKey("test_api_key") + .cacheProviders(Collections.emptyList()) + .build(); assertTrue(schematic.getFlagCheckCacheProviders().isEmpty()); } @@ -111,9 +107,9 @@ void testClientWithCustomEventBuffer() { // Test client with custom event buffer interval Duration customInterval = Duration.ofSeconds(5); Schematic schematic = Schematic.builder() - .apiKey("test_api_key") - .eventBufferInterval(customInterval) - .build(); + .apiKey("test_api_key") + .eventBufferInterval(customInterval) + .build(); assertEquals(customInterval, schematic.getEventBufferInterval()); } @@ -125,10 +121,10 @@ void testClientWithOfflineModeAndDefaults() { flagDefaults.put("some-flag-key", true); Schematic schematic = Schematic.builder() - .apiKey("test_api_key") - .offline(true) - .flagDefaults(flagDefaults) - .build(); + .apiKey("test_api_key") + .offline(true) + .flagDefaults(flagDefaults) + .build(); assertTrue(schematic.isOffline()); assertTrue(schematic.checkFlag("some-flag-key", null, null)); diff --git a/src/test/java/com/schematic/api/TestSchematic.java b/src/test/java/com/schematic/api/TestSchematic.java index f5d2643..72acccc 100644 --- a/src/test/java/com/schematic/api/TestSchematic.java +++ b/src/test/java/com/schematic/api/TestSchematic.java @@ -1,5 +1,11 @@ package com.schematic.api; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.contains; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + import com.schematic.api.cache.CacheProvider; import com.schematic.api.cache.LocalCache; import com.schematic.api.logger.SchematicLogger; @@ -7,28 +13,21 @@ import com.schematic.api.resources.features.types.CheckFlagResponse; import com.schematic.api.types.CheckFlagResponseData; import com.schematic.api.types.EventBodyIdentifyCompany; +import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.time.Duration; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.contains; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class SchematicTest { @Mock private SchematicLogger logger; - + private Schematic schematic; private static final Duration DEFAULT_BUFFER_PERIOD = Duration.ofSeconds(3); @@ -47,13 +46,13 @@ void checkFlag_HandlesNullData() { FeaturesClient featuresClient = mock(FeaturesClient.class); Schematic spySchematic = spy(schematic); when(spySchematic.features()).thenReturn(featuresClient); - + CheckFlagResponse response = mock(CheckFlagResponse.class); when(response.getData()).thenReturn(null); when(featuresClient.checkFlag(any(), any())).thenReturn(response); - + boolean result = spySchematic.checkFlag("test_flag", null, null); - + assertFalse(result); verify(logger).error(contains("Error checking flag")); } @@ -65,14 +64,14 @@ void checkFlag_CachesResultIfNotCached() { when(spySchematic.features()).thenReturn(featuresClient); CheckFlagResponse response = CheckFlagResponse.builder() - .data(CheckFlagResponseData.builder() - .reason("test_reason") - .value(true) - .build()) - .build(); - + .data(CheckFlagResponseData.builder() + .reason("test_reason") + .value(true) + .build()) + .build(); + when(featuresClient.checkFlag(eq("test_flag"), any())).thenReturn(response); - + boolean result = spySchematic.checkFlag("test_flag", null, null); assertTrue(result); @@ -129,9 +128,8 @@ void checkFlag_ReturnsDefaultOnError() { @Test void identify_EnqueuesEventNonBlocking() throws InterruptedException { Map keys = Collections.singletonMap("user_id", "12345"); - EventBodyIdentifyCompany company = EventBodyIdentifyCompany.builder() - .name("test_company") - .build(); + EventBodyIdentifyCompany company = + EventBodyIdentifyCompany.builder().name("test_company").build(); Map traits = new HashMap<>(); schematic.identify(keys, company, "John Doe", traits); @@ -157,7 +155,7 @@ void track_OfflineMode() { Map company = Collections.singletonMap("company_id", "67890"); Map user = Collections.singletonMap("user_id", "12345"); Map traits = new HashMap<>(); - + Schematic.builder() .apiKey("test_api_key") .offline(true) @@ -171,10 +169,9 @@ void track_OfflineMode() { @Test void identify_OfflineMode() { Map keys = Collections.singletonMap("user_id", "12345"); - EventBodyIdentifyCompany company = EventBodyIdentifyCompany.builder() - .name("test_company") - .build(); - + EventBodyIdentifyCompany company = + EventBodyIdentifyCompany.builder().name("test_company").build(); + Schematic.builder() .apiKey("test_api_key") .offline(true) @@ -197,4 +194,4 @@ void checkFlag_OfflineModeReturnsDefault() { assertTrue(result); } -} \ No newline at end of file +}