diff --git a/pom.xml b/pom.xml index 39822db..96863c2 100644 --- a/pom.xml +++ b/pom.xml @@ -92,6 +92,7 @@ true com.abacatepay.AbacatePay + true diff --git a/src/main/java/com/abacatepay/AbacatePay.java b/src/main/java/com/abacatepay/AbacatePay.java index 9925d76..a77bc6e 100644 --- a/src/main/java/com/abacatepay/AbacatePay.java +++ b/src/main/java/com/abacatepay/AbacatePay.java @@ -1,37 +1,38 @@ package com.abacatepay; -import com.abacatepay.clients.AbacatePayClient; import com.abacatepay.clients.factories.AbacatePayClientFactory; +import com.abacatepay.model.AbacatePayBilling; import com.abacatepay.model.IAbacatePay; import com.abacatepay.model.IAbacatePayBilling; -import com.abacatepay.model.billing.CreateBillingData; -import com.abacatepay.model.billing.CreateBillingResponse; -import com.abacatepay.model.billing.ListBillingResponse; -import feign.FeignException; import feign.RequestInterceptor; public class AbacatePay implements IAbacatePay { private static final String API_BASE_URL = "https://api.abacatepay.com/v1"; + private static final String SDK_NAME = "abacatepay-java-sdk"; + private static final String SDK_VERSION = resolveVersion(); - private final AbacatePayClient client; private final String apiKey; private final String userAgent; + private final IAbacatePayBilling billing; public AbacatePay(String apiKey) { - this.apiKey = apiKey; - this.client = AbacatePayClientFactory.create(API_BASE_URL, requestInterceptor()); + if (apiKey == null || apiKey.isBlank()) { + throw new IllegalArgumentException("API key not provided"); + } - //TODO: Pegar a versão do SDK dinamicamente - this.userAgent = "Java SDK (1.0.0)"; + this.apiKey = apiKey; + this.userAgent = buildUserAgent(); + this.billing = new AbacatePayBilling( + AbacatePayClientFactory.create( + API_BASE_URL, + requestInterceptor() + ) + ); } private RequestInterceptor requestInterceptor() { return template -> { - if (apiKey == null || apiKey.isEmpty()) { - throw new IllegalArgumentException("API key not provided"); - } - template.header("Authorization", "Bearer " + apiKey); template.header("Content-Type", "application/json"); template.header("User-Agent", userAgent); @@ -40,28 +41,32 @@ private RequestInterceptor requestInterceptor() { @Override public IAbacatePayBilling billing() { + return billing; + } - class AbacatePayBilling implements IAbacatePayBilling { + private static String resolveVersion() { + Package pkg = AbacatePay.class.getPackage(); + String version = null; - @Override - public CreateBillingResponse create(CreateBillingData data) { - try { - return client.create(data); - } catch (IllegalArgumentException | FeignException e) { - return new CreateBillingResponse(e.getMessage()); - } - } + if (pkg != null) { + version = pkg.getImplementationVersion(); + } - @Override - public ListBillingResponse list() { - try { - return client.list(); - } catch (IllegalArgumentException | FeignException e) { - return new ListBillingResponse(e.getMessage()); - } - } + if (version == null || version.isBlank()) { + version = "dev"; } - return new AbacatePayBilling(); + return version; + } + + private static String buildUserAgent() { + return String.format( + "%s/%s Java/%s (%s %s)", + SDK_NAME, + SDK_VERSION, + System.getProperty("java.version"), + System.getProperty("os.name"), + System.getProperty("os.version") + ); } } diff --git a/src/main/java/com/abacatepay/model/AbacatePayBilling.java b/src/main/java/com/abacatepay/model/AbacatePayBilling.java new file mode 100644 index 0000000..d77aa8f --- /dev/null +++ b/src/main/java/com/abacatepay/model/AbacatePayBilling.java @@ -0,0 +1,34 @@ +package com.abacatepay.model; + +import com.abacatepay.clients.AbacatePayClient; +import com.abacatepay.model.billing.CreateBillingData; +import com.abacatepay.model.billing.CreateBillingResponse; +import com.abacatepay.model.billing.ListBillingResponse; +import feign.FeignException; + +public class AbacatePayBilling implements IAbacatePayBilling { + + private final AbacatePayClient client; + + public AbacatePayBilling(AbacatePayClient client) { + this.client = client; + } + + @Override + public CreateBillingResponse create(CreateBillingData data) { + try { + return client.create(data); + } catch (IllegalArgumentException | FeignException e) { + return new CreateBillingResponse(e.getMessage()); + } + } + + @Override + public ListBillingResponse list() { + try { + return client.list(); + } catch (IllegalArgumentException | FeignException e) { + return new ListBillingResponse(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/test/java/com/abacatepay/AbacatePayTest.java b/src/test/java/com/abacatepay/AbacatePayTest.java index 9db2cde..138e128 100644 --- a/src/test/java/com/abacatepay/AbacatePayTest.java +++ b/src/test/java/com/abacatepay/AbacatePayTest.java @@ -1,40 +1,44 @@ package com.abacatepay; import com.abacatepay.clients.AbacatePayClient; +import com.abacatepay.model.AbacatePayBilling; +import com.abacatepay.model.IAbacatePayBilling; import com.abacatepay.model.billing.CreateBillingData; import com.abacatepay.model.billing.CreateBillingResponse; import com.abacatepay.model.billing.ListBillingResponse; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.lang.reflect.Field; +import java.lang.reflect.Method; import static org.mockito.Mockito.*; class AbacatePayTest { @Mock - private AbacatePayClient abacatePayClient; + private AbacatePayClient mockClient; - @InjectMocks private AbacatePay abacatePay; @BeforeEach - public void setUp() throws Exception { + void setUp() throws Exception { MockitoAnnotations.openMocks(this); abacatePay = new AbacatePay("apiKey"); - setClientMock(abacatePay, abacatePayClient); + + IAbacatePayBilling realBilling = new AbacatePayBilling(mockClient); + + setClientMock(abacatePay, realBilling); } - private void setClientMock(AbacatePay abacatePay, AbacatePayClient mockClient) throws Exception { - Field clientField = AbacatePay.class.getDeclaredField("client"); + private void setClientMock(AbacatePay abacatePay, IAbacatePayBilling realBilling) throws Exception { + Field clientField = AbacatePay.class.getDeclaredField("billing"); clientField.setAccessible(true); - clientField.set(abacatePay, mockClient); + clientField.set(abacatePay, realBilling); } @Test @@ -42,44 +46,85 @@ void shouldReturnCreateBillingResponseOnSuccess() { CreateBillingData data = CreateBillingData.builder().build(); CreateBillingResponse expectedResponse = new CreateBillingResponse(); - when(abacatePayClient.create(data)).thenReturn(expectedResponse); + when(mockClient.create(data)).thenReturn(expectedResponse); CreateBillingResponse result = abacatePay.billing().create(data); - verify(abacatePayClient, atMostOnce()).create(data); + + verify(mockClient, atMostOnce()).create(data); Assertions.assertEquals(expectedResponse, result, "Should return the expected response"); } @Test - void shouldCreateBillingThrowsAnException() { + void shouldCreateBillingReturnErrorResponseWhenClientFails() { CreateBillingData data = CreateBillingData.builder().build(); - CreateBillingResponse expectedResponse = new CreateBillingResponse("API key not provided"); + String errorMessage = "Internal Server Error"; - when(abacatePayClient.create(data)).thenThrow(new IllegalArgumentException("API key not provided")); + when(mockClient.create(data)).thenThrow(new IllegalArgumentException(errorMessage)); CreateBillingResponse result = abacatePay.billing().create(data); - verify(abacatePayClient, atMostOnce()).create(data); - Assertions.assertEquals(expectedResponse, result, "Should return the expected response"); + + verify(mockClient, atMostOnce()).create(data); + Assertions.assertNotNull(result, "Should not return null"); + Assertions.assertEquals(errorMessage, result.getError()); } @Test void shouldReturnBillingListResponseOnSucess() { ListBillingResponse expectedResponse = new ListBillingResponse(); - when(abacatePayClient.list()).thenReturn(expectedResponse); + when(mockClient.list()).thenReturn(expectedResponse); ListBillingResponse result = abacatePay.billing().list(); - verify(abacatePayClient, atMostOnce()).list(); + verify(mockClient, atMostOnce()).list(); Assertions.assertEquals(expectedResponse, result, "Should return the expected response"); } @Test - void shouldListBillingThrowsAnException() { - ListBillingResponse expectedResponse = new ListBillingResponse("API key not provided"); + void shouldListBillingReturnErrorResponseWhenClientFails() { + String errorMessage = "Internal Server Error"; - when(abacatePayClient.list()).thenThrow(new IllegalArgumentException("API key not provided")); + when(mockClient.list()).thenThrow(new IllegalArgumentException(errorMessage)); ListBillingResponse result = abacatePay.billing().list(); - verify(abacatePayClient, atMostOnce()).list(); - Assertions.assertEquals(expectedResponse, result, "Should return the expected response"); + + verify(mockClient, atMostOnce()).list(); + Assertions.assertNotNull(result, "Should not return null"); + Assertions.assertEquals(errorMessage, result.getError()); + } + + @Test + void shouldThrowExceptionWhenApiKeyIsMissing() { + IllegalArgumentException exception = Assertions.assertThrows(IllegalArgumentException.class, () -> { + new AbacatePay(""); + }); + + Assertions.assertEquals("API key not provided", exception.getMessage()); + } + + @Test + void testResolveVersionDirectly() throws Exception { + Method method = AbacatePay.class.getDeclaredMethod("resolveVersion"); + method.setAccessible(true); + + String version = (String) method.invoke(null); + + Assertions.assertNotNull(version); + Assertions.assertEquals("dev", version, "local environment should return 'dev' as version"); + } + + @Test + void testBuildUserAgentDirectly() throws Exception { + Method method = AbacatePay.class.getDeclaredMethod("buildUserAgent"); + method.setAccessible(true); + + String userAgent = (String) method.invoke(null); + + String currentJava = System.getProperty("java.version"); + String currentOs = System.getProperty("os.name"); + + Assertions.assertNotNull(userAgent); + Assertions.assertTrue(userAgent.startsWith("abacatepay-java-sdk/"), "Should start with the SDK name"); + Assertions.assertTrue(userAgent.contains("Java/" + currentJava), "Should contain the Java tag version"); + Assertions.assertTrue(userAgent.contains(currentOs), "Should contain the OS name"); } } diff --git a/src/test/java/com/abacatepay/model/AbacatePayBillingTest.java b/src/test/java/com/abacatepay/model/AbacatePayBillingTest.java new file mode 100644 index 0000000..82ee39d --- /dev/null +++ b/src/test/java/com/abacatepay/model/AbacatePayBillingTest.java @@ -0,0 +1,109 @@ +package com.abacatepay.model; + +import com.abacatepay.clients.AbacatePayClient; +import com.abacatepay.model.billing.CreateBillingData; +import com.abacatepay.model.billing.CreateBillingResponse; +import com.abacatepay.model.billing.ListBillingResponse; +import feign.FeignException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.mockito.Mockito.*; + +class AbacatePayBillingTest { + + @Mock + private AbacatePayClient mockClient; + + private AbacatePayBilling abacatePayBilling; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + + this.abacatePayBilling = new AbacatePayBilling(mockClient); + } + + @Test + void shouldReturnCreateBillingResponseOnSuccess() { + CreateBillingData data = CreateBillingData.builder().build(); + CreateBillingResponse expectedResponse = new CreateBillingResponse(); + + when(mockClient.create(data)).thenReturn(expectedResponse); + + CreateBillingResponse result = abacatePayBilling.create(data); + + verify(mockClient, atMostOnce()).create(data); + Assertions.assertEquals(expectedResponse, result, "Should return the expected response"); + } + + @Test + void shouldReturnErrorResponseWhenCreateThrowsIllegalArgumentException() { + CreateBillingData data = CreateBillingData.builder().build(); + String errorMessage = "Internal Server Error"; + + when(mockClient.create(data)).thenThrow(new IllegalArgumentException(errorMessage)); + + CreateBillingResponse result = abacatePayBilling.create(data); + + verify(mockClient, atMostOnce()).create(data); + Assertions.assertNotNull(result); + Assertions.assertEquals(errorMessage, result.getError(), "Should return the expected response"); + } + + @Test + void shouldReturnErrorResponseWhenCreateThrowsFeignException() { + CreateBillingData data = CreateBillingData.builder().build(); + + FeignException mockFeignException = mock(FeignException.class); + when(mockFeignException.getMessage()).thenReturn("HTTP 401 Unauthorized"); + + when(mockClient.create(data)).thenThrow(mockFeignException); + + CreateBillingResponse result = abacatePayBilling.create(data); + + verify(mockClient, atMostOnce()).create(data); + Assertions.assertNotNull(result); + Assertions.assertEquals("HTTP 401 Unauthorized", result.getError()); + } + + @Test + void shouldReturnListBillingResponseOnSuccess() { + ListBillingResponse expectedResponse = new ListBillingResponse(); + when(mockClient.list()).thenReturn(expectedResponse); + + ListBillingResponse result = abacatePayBilling.list(); + + verify(mockClient, atMostOnce()).list(); + Assertions.assertEquals(expectedResponse, result, "Should return the expected response"); + } + + @Test + void shouldReturnErrorResponseWhenListThrowsIllegalArgumentException() { + String errorMessage = "Internal Server Error"; + when(mockClient.list()).thenThrow(new IllegalArgumentException(errorMessage)); + + ListBillingResponse result = abacatePayBilling.list(); + + verify(mockClient, atMostOnce()).list(); + Assertions.assertNotNull(result); + Assertions.assertEquals(errorMessage, result.getError()); + } + + @Test + void shouldReturnErrorResponseWhenListThrowsFeignException() { + FeignException mockFeignException = mock(FeignException.class); + when(mockFeignException.getMessage()).thenReturn("HTTP 500 Internal Server Error"); + + when(mockClient.list()).thenThrow(mockFeignException); + + ListBillingResponse result = abacatePayBilling.list(); + + verify(mockClient, atMostOnce()).list(); + Assertions.assertNotNull(result); + Assertions.assertEquals("HTTP 500 Internal Server Error", result.getError()); + } +}