diff --git a/tests/pom.xml b/tests/pom.xml index 18dbd13a..911f90c0 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -6,8 +6,8 @@ jar AdvancedBillingTests - 1.8 - 1.8 + 17 + 17 UTF-8 diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerCreateTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerCreateTest.java similarity index 98% rename from tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerCreateTest.java rename to tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerCreateTest.java index 4fb45095..98e5015e 100644 --- a/tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerCreateTest.java +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerCreateTest.java @@ -1,6 +1,7 @@ -package com.maxio.advancedbilling.controllers; +package com.maxio.advancedbilling.controllers.customers; import com.maxio.advancedbilling.TestClient; +import com.maxio.advancedbilling.controllers.CustomersController; import com.maxio.advancedbilling.exceptions.ApiException; import com.maxio.advancedbilling.exceptions.CustomerErrorResponseException; import com.maxio.advancedbilling.models.CreateCustomer; diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerDeleteTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerDeleteTest.java similarity index 92% rename from tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerDeleteTest.java rename to tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerDeleteTest.java index 8747f3b1..14e385e0 100644 --- a/tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerDeleteTest.java +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerDeleteTest.java @@ -1,6 +1,7 @@ -package com.maxio.advancedbilling.controllers; +package com.maxio.advancedbilling.controllers.customers; import com.maxio.advancedbilling.TestClient; +import com.maxio.advancedbilling.controllers.CustomersController; import com.maxio.advancedbilling.exceptions.ApiException; import com.maxio.advancedbilling.models.CreateCustomer; import com.maxio.advancedbilling.models.CreateCustomerRequest; diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerListOrFindTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerListOrFindTest.java similarity index 99% rename from tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerListOrFindTest.java rename to tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerListOrFindTest.java index 2f0bbbd2..94ca9765 100644 --- a/tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerListOrFindTest.java +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerListOrFindTest.java @@ -1,6 +1,7 @@ -package com.maxio.advancedbilling.controllers; +package com.maxio.advancedbilling.controllers.customers; import com.maxio.advancedbilling.TestClient; +import com.maxio.advancedbilling.controllers.CustomersController; import com.maxio.advancedbilling.exceptions.ApiException; import com.maxio.advancedbilling.models.BasicDateField; import com.maxio.advancedbilling.models.CreateCustomer; diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerListSubscriptionsTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerListSubscriptionsTest.java similarity index 94% rename from tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerListSubscriptionsTest.java rename to tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerListSubscriptionsTest.java index 234dca96..3f55dcf0 100644 --- a/tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerListSubscriptionsTest.java +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerListSubscriptionsTest.java @@ -1,7 +1,12 @@ -package com.maxio.advancedbilling.controllers; +package com.maxio.advancedbilling.controllers.customers; import com.maxio.advancedbilling.AdvancedBillingClient; import com.maxio.advancedbilling.TestClient; +import com.maxio.advancedbilling.controllers.CustomersController; +import com.maxio.advancedbilling.controllers.PaymentProfilesController; +import com.maxio.advancedbilling.controllers.ProductFamiliesController; +import com.maxio.advancedbilling.controllers.ProductsController; +import com.maxio.advancedbilling.controllers.SubscriptionsController; import com.maxio.advancedbilling.exceptions.ApiException; import com.maxio.advancedbilling.models.CreateCustomer; import com.maxio.advancedbilling.models.CreateCustomerRequest; diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerReadTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerReadTest.java similarity index 97% rename from tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerReadTest.java rename to tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerReadTest.java index 2deadf6a..9ab5a62e 100644 --- a/tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerReadTest.java +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerReadTest.java @@ -1,6 +1,7 @@ -package com.maxio.advancedbilling.controllers; +package com.maxio.advancedbilling.controllers.customers; import com.maxio.advancedbilling.TestClient; +import com.maxio.advancedbilling.controllers.CustomersController; import com.maxio.advancedbilling.exceptions.ApiException; import com.maxio.advancedbilling.models.CreateCustomer; import com.maxio.advancedbilling.models.CreateCustomerRequest; diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerUpdateTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerUpdateTest.java similarity index 98% rename from tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerUpdateTest.java rename to tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerUpdateTest.java index 41fba753..ab54296a 100644 --- a/tests/src/test/java/com/maxio/advancedbilling/controllers/CustomersControllerUpdateTest.java +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/customers/CustomersControllerUpdateTest.java @@ -1,6 +1,7 @@ -package com.maxio.advancedbilling.controllers; +package com.maxio.advancedbilling.controllers.customers; import com.maxio.advancedbilling.TestClient; +import com.maxio.advancedbilling.controllers.CustomersController; import com.maxio.advancedbilling.exceptions.ApiException; import com.maxio.advancedbilling.exceptions.CustomerErrorResponseException; import com.maxio.advancedbilling.models.CreateCustomer; diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/ProductPricePointsControllerListTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/productpricepoints/ProductPricePointsControllerListTest.java similarity index 97% rename from tests/src/test/java/com/maxio/advancedbilling/controllers/ProductPricePointsControllerListTest.java rename to tests/src/test/java/com/maxio/advancedbilling/controllers/productpricepoints/ProductPricePointsControllerListTest.java index fa7ba271..cfa63a40 100644 --- a/tests/src/test/java/com/maxio/advancedbilling/controllers/ProductPricePointsControllerListTest.java +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/productpricepoints/ProductPricePointsControllerListTest.java @@ -1,7 +1,10 @@ -package com.maxio.advancedbilling.controllers; +package com.maxio.advancedbilling.controllers.productpricepoints; import com.maxio.advancedbilling.AdvancedBillingClient; import com.maxio.advancedbilling.TestClient; +import com.maxio.advancedbilling.controllers.ProductFamiliesController; +import com.maxio.advancedbilling.controllers.ProductPricePointsController; +import com.maxio.advancedbilling.controllers.ProductsController; import com.maxio.advancedbilling.exceptions.ApiException; import com.maxio.advancedbilling.models.CreateOrUpdateProduct; import com.maxio.advancedbilling.models.CreateOrUpdateProductRequest; diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerArchiveProductTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerArchiveProductTest.java new file mode 100644 index 00000000..11e2ebea --- /dev/null +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerArchiveProductTest.java @@ -0,0 +1,62 @@ +package com.maxio.advancedbilling.controllers.products; + +import com.maxio.advancedbilling.exceptions.ApiException; +import com.maxio.advancedbilling.exceptions.ErrorListResponseException; +import com.maxio.advancedbilling.models.Product; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.time.Instant; + +import static com.maxio.advancedbilling.utils.CommonAssertions.assertNotFound; +import static com.maxio.advancedbilling.utils.TimeUtils.parseStringTimestamp; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.junit.jupiter.api.Assertions.assertAll; + +public class ProductsControllerArchiveProductTest extends ProductsControllerTestBase { + + @Test + void shouldArchiveProduct() throws IOException, ApiException { + // given + Product product = createProduct(); + + // when + String timestamp = Instant.now().toString(); + productsController.archiveProduct(product.getId()); + + // then + Product archivedProduct = productsController.readProduct(product.getId()).getProduct(); + assertAll( + () -> assertThat(archivedProduct.getId()).isEqualTo(product.getId()), + () -> assertThat(archivedProduct.getArchivedAt()).isNotNull(), + () -> assertThat(parseStringTimestamp(archivedProduct.getArchivedAt())).isAfterOrEqualTo(timestamp) + ); + } + + @Test + void shouldNotArchiveSameProductTwice() throws IOException, ApiException { + // given + Product product = createProduct(); + + // when + productsController.archiveProduct(product.getId()); + + // then + assertThatExceptionOfType(ErrorListResponseException.class) + .isThrownBy(() -> productsController.archiveProduct(product.getId()) + ) + .withMessage("Unprocessable Entity (WebDAV)") + .satisfies(e -> { + assertThat(e.getResponseCode()).isEqualTo(422); + assertThat(e.getErrors()).containsExactlyInAnyOrder("Product cannot be archived."); + }); + } + + @Test + void shouldNotArchiveNotOwnedProduct() { + // when-then + assertNotFound(() -> productsController.archiveProduct(99999999)); + } + +} diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerCreateProductTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerCreateProductTest.java new file mode 100644 index 00000000..821d5a0b --- /dev/null +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerCreateProductTest.java @@ -0,0 +1,277 @@ +package com.maxio.advancedbilling.controllers.products; + +import com.maxio.advancedbilling.exceptions.ApiException; +import com.maxio.advancedbilling.exceptions.ErrorListResponseException; +import com.maxio.advancedbilling.models.CreateOrUpdateProduct; +import com.maxio.advancedbilling.models.CreateOrUpdateProductRequest; +import com.maxio.advancedbilling.models.IntervalUnit; +import com.maxio.advancedbilling.models.Product; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Collections; +import java.util.List; +import java.util.stream.Stream; + +import static com.maxio.advancedbilling.utils.TimeUtils.parseStringTimestamp; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.junit.jupiter.api.Assertions.assertAll; + +public class ProductsControllerCreateProductTest extends ProductsControllerTestBase { + + @Test + void shouldCreateProductWhenOnlyRequiredParametersAreProvided() throws IOException, ApiException { + // when + Instant timestamp = Instant.now().minus(5, ChronoUnit.SECONDS); + String handle = "washington-" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + Product product = productsController + .createProduct(productFamily.getId(), new CreateOrUpdateProductRequest( + new CreateOrUpdateProduct.Builder() + .name("Sample product") + .handle(handle) + .description("A sample product for testing") + .priceInCents(1000) + .interval(1) + .intervalUnit("month") + .requireCreditCard(true) + .build() + )) + .getProduct(); + + // then + assertAll( + () -> assertThat(product.getName()).isEqualTo("Sample product"), + () -> assertThat(product.getHandle()).isEqualTo(handle), + () -> assertThat(product.getDescription()).isEqualTo("A sample product for testing"), + () -> assertThat(product.getPriceInCents()).isEqualTo(1000), + () -> assertThat(product.getInterval()).isEqualTo(1), + () -> assertThat(product.getIntervalUnit().match(i -> i).value()).isEqualTo(IntervalUnit.MONTH.value()), + + () -> assertThat(product.getId()).isNotNull(), + () -> assertThat(parseStringTimestamp(product.getCreatedAt())).isAfterOrEqualTo(timestamp), + () -> assertThat(parseStringTimestamp(product.getUpdatedAt())).isAfterOrEqualTo(timestamp), + + () -> assertThat(product.getAccountingCode()).isNull(), + () -> assertThat(product.getRequestCreditCard()).isTrue(), + () -> assertThat(product.getExpirationInterval()).isNull(), + () -> assertThat(product.getExpirationIntervalUnit()).isNull(), + () -> assertThat(product.getInitialChargeInCents()).isNull(), + () -> assertThat(product.getTrialPriceInCents()).isNull(), + () -> assertThat(product.getTrialInterval()).isNull(), + () -> assertThat(product.getTrialIntervalUnit()).isNull(), + () -> assertThat(product.getArchivedAt()).isNull(), + () -> assertThat(product.getRequireCreditCard()).isTrue(), + () -> assertThat(product.getReturnParams()).isNull(), + () -> assertThat(product.getTaxable()).isFalse(), + () -> assertThat(product.getUpdateReturnUrl()).isNull(), + () -> assertThat(product.getInitialChargeAfterTrial()).isFalse(), + () -> assertThat(product.getVersionNumber()).isEqualTo(1), + () -> assertThat(product.getUpdateReturnParams()).isNull(), + () -> assertThat(product.getProductPricePointName()).isEqualTo("Original"), + () -> assertThat(product.getRequestBillingAddress()).isFalse(), + () -> assertThat(product.getRequireBillingAddress()).isFalse(), + () -> assertThat(product.getRequireShippingAddress()).isFalse(), + () -> assertThat(product.getTaxCode()).isNull(), + () -> assertThat(product.getDefaultProductPricePointId()).isPositive(), + () -> assertThat(product.getUseSiteExchangeRate()).isTrue(), + () -> assertThat(product.getItemCategory()).isNull(), + () -> assertThat(product.getProductPricePointId()).isPositive(), + () -> assertThat(product.getProductPricePointHandle()).isNotEmpty(), + + () -> assertThat(product.getProductFamily()).isNotNull(), + () -> assertThat(product.getProductFamily().getId()).isEqualTo(productFamily.getId()), + () -> assertThat(product.getProductFamily().getName()).isEqualTo(productFamily.getName()), + () -> assertThat(product.getProductFamily().getHandle()).isEqualTo(productFamily.getHandle()), + () -> assertThat(product.getProductFamily().getAccountingCode()).isEqualTo(productFamily.getAccountingCode()), + () -> assertThat(product.getProductFamily().getDescription()).isEqualTo(productFamily.getDescription()), + () -> assertThat(product.getProductFamily().getCreatedAt()).isEqualTo(productFamily.getCreatedAt()), + () -> assertThat(product.getProductFamily().getUpdatedAt()).isEqualTo(productFamily.getUpdatedAt()), + + () -> assertThat(product.getPublicSignupPages()).isEmpty() + ); + } + + @Test + void shouldCreateProductWhenAllParametersAreProvided() throws IOException, ApiException { + // when + Instant timestamp = Instant.now().minus(5, ChronoUnit.SECONDS); + String handle = "washington-" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + Product product = productsController + .createProduct(productFamily.getId(), new CreateOrUpdateProductRequest( + new CreateOrUpdateProduct.Builder() + .name("Sample product full") + .handle(handle) + .description("A sample product for testing") + .priceInCents(1000) + .interval(1) + .intervalUnit("month") + .requireCreditCard(true) + + .accountingCode("code") + .autoCreateSignupPage(true) + .taxCode("taxcode") + .build() + )) + .getProduct(); + // then + assertAll( + () -> assertThat(product.getName()).isEqualTo("Sample product full"), + () -> assertThat(product.getHandle()).isEqualTo(handle), + () -> assertThat(product.getDescription()).isEqualTo("A sample product for testing"), + () -> assertThat(product.getPriceInCents()).isEqualTo(1000), + () -> assertThat(product.getInterval()).isEqualTo(1), + () -> assertThat(product.getIntervalUnit().match(i -> i).value()).isEqualTo(IntervalUnit.MONTH.value()), + () -> assertThat(product.getTaxCode()).isEqualTo("taxcode"), + () -> assertThat(product.getAccountingCode()).isEqualTo("code"), + + () -> assertThat(product.getId()).isNotNull(), + () -> assertThat(parseStringTimestamp(product.getCreatedAt())).isAfterOrEqualTo(timestamp), + () -> assertThat(parseStringTimestamp(product.getUpdatedAt())).isAfterOrEqualTo(timestamp), + + () -> assertThat(product.getRequestCreditCard()).isTrue(), + () -> assertThat(product.getExpirationInterval()).isNull(), + () -> assertThat(product.getExpirationIntervalUnit()).isNull(), + () -> assertThat(product.getInitialChargeInCents()).isNull(), + () -> assertThat(product.getTrialPriceInCents()).isNull(), + () -> assertThat(product.getTrialInterval()).isNull(), + () -> assertThat(product.getTrialIntervalUnit()).isNull(), + () -> assertThat(product.getArchivedAt()).isNull(), + () -> assertThat(product.getRequireCreditCard()).isTrue(), + () -> assertThat(product.getReturnParams()).isNull(), + () -> assertThat(product.getTaxable()).isFalse(), + () -> assertThat(product.getUpdateReturnUrl()).isNull(), + () -> assertThat(product.getInitialChargeAfterTrial()).isFalse(), + () -> assertThat(product.getVersionNumber()).isEqualTo(1), + () -> assertThat(product.getUpdateReturnParams()).isNull(), + () -> assertThat(product.getProductPricePointName()).isEqualTo("Original"), + () -> assertThat(product.getRequestBillingAddress()).isFalse(), + () -> assertThat(product.getRequireBillingAddress()).isFalse(), + () -> assertThat(product.getRequireShippingAddress()).isFalse(), + () -> assertThat(product.getDefaultProductPricePointId()).isPositive(), + () -> assertThat(product.getUseSiteExchangeRate()).isTrue(), + () -> assertThat(product.getItemCategory()).isNull(), + () -> assertThat(product.getProductPricePointId()).isPositive(), + () -> assertThat(product.getProductPricePointHandle()).isNotEmpty(), + + () -> assertThat(product.getProductFamily()).isNotNull(), + () -> assertThat(product.getProductFamily().getId()).isEqualTo(productFamily.getId()), + () -> assertThat(product.getProductFamily().getName()).isEqualTo(productFamily.getName()), + () -> assertThat(product.getProductFamily().getHandle()).isEqualTo(productFamily.getHandle()), + () -> assertThat(product.getProductFamily().getAccountingCode()).isEqualTo(productFamily.getAccountingCode()), + () -> assertThat(product.getProductFamily().getDescription()).isEqualTo(productFamily.getDescription()), + () -> assertThat(product.getProductFamily().getCreatedAt()).isEqualTo(productFamily.getCreatedAt()), + () -> assertThat(product.getProductFamily().getUpdatedAt()).isEqualTo(productFamily.getUpdatedAt()), + + () -> assertThat(product.getPublicSignupPages().size()).isEqualTo(1), + () -> assertThat(product.getPublicSignupPages().get(0).getId()).isPositive(), + () -> assertThat(product.getPublicSignupPages().get(0).getReturnUrl()).isNull(), + () -> assertThat(product.getPublicSignupPages().get(0).getReturnParams()).isNull(), + () -> assertThat(product.getPublicSignupPages().get(0).getUrl()).isNotEmpty() + ); + } + + @Test + void shouldNotCreateProductWithExistingHandle() throws IOException, ApiException { + // when + String handle = "washington-" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + CreateOrUpdateProduct createOrUpdateProduct = new CreateOrUpdateProduct.Builder() + .name("Sample product full") + .handle(handle) + .priceInCents(1000) + .interval(1) + .intervalUnit("month") + .build(); + Product product = productsController + .createProduct(productFamily.getId(), new CreateOrUpdateProductRequest( + createOrUpdateProduct + )) + .getProduct(); + // then + String expectedErrorMessage = String.format( + "API Handle: must be unique - '%s' has been taken by another Product in this Site.", + handle); + assertThatExceptionOfType(ErrorListResponseException.class) + .isThrownBy(() -> productsController.createProduct( + productFamily.getId(), new CreateOrUpdateProductRequest(createOrUpdateProduct)) + ) + .withMessage("Unprocessable Entity (WebDAV)") + .satisfies(e -> { + assertThat(e.getResponseCode()).isEqualTo(422); + assertThat(e.getErrors()).containsExactlyInAnyOrder(expectedErrorMessage); + }); + } + + @ParameterizedTest + @MethodSource("argsForShouldNotCreateProductWhenBasicParametersAreBlank") + void shouldNotCreateProductWhenBasicParametersAreBlank(CreateOrUpdateProduct createProduct, List errorMessages) { + // when - then + assertThatExceptionOfType(ErrorListResponseException.class) + .isThrownBy(() -> productsController.createProduct( + productFamily.getId(), new CreateOrUpdateProductRequest(createProduct)) + ) + .withMessage("Unprocessable Entity (WebDAV)") + .satisfies(e -> { + assertThat(e.getResponseCode()).isEqualTo(422); + assertThat(e.getErrors()).hasSameElementsAs(errorMessages); + }); + } + + @Test + void shouldNotCreateProductForNotOwnedProductFamily() { + // when + String handle = "washington-" + RandomStringUtils.randomAlphanumeric(5).toLowerCase(); + CreateOrUpdateProduct createOrUpdateProduct = new CreateOrUpdateProduct.Builder() + .name("Sample product full") + .handle(handle) + .priceInCents(1000) + .interval(1) + .intervalUnit("month") + .build(); + + // then + assertThatExceptionOfType(ApiException.class) + .isThrownBy(() -> productsController + .createProduct(999999, new CreateOrUpdateProductRequest( + createOrUpdateProduct + )) + ) + .withMessage("HTTP Response Not OK") + .satisfies(e -> { + assertThat(e.getResponseCode()).isEqualTo(403); + assertThat(e.getHttpContext().getResponse().getBody()).isEqualTo("A valid product family id is required"); + }); + } + + private static Stream argsForShouldNotCreateProductWhenBasicParametersAreBlank() { + CreateOrUpdateProduct productTemplate = new CreateOrUpdateProduct.Builder().name("test-name").handle("product-handle-test") + .description("test description").priceInCents(11).interval(1).intervalUnit("month").build(); + return Stream.of( + Arguments.of( + productTemplate.toBuilder().name(null).build(), Collections.singletonList("Name: cannot be blank.") + ), + Arguments.of( + productTemplate.toBuilder().intervalUnit(null).build(), List.of("Interval unit: cannot be blank.", + "Interval unit: must be 'month' or 'day'.") + ), + Arguments.of( + productTemplate.toBuilder().handle("VERY INVALID HANDLE").build(), + List.of("API Handle: may only contain lowercase letters, numbers, underscores, and dashes") + ), + Arguments.of( + new CreateOrUpdateProduct(), + List.of("Name: cannot be blank.", + "Recurring Interval: must be greater than or equal to 1.", + "Interval unit: cannot be blank.", + "Interval unit: must be 'month' or 'day'.") + ) + ); + } + +} diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerListProductsTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerListProductsTest.java new file mode 100644 index 00000000..21cd210a --- /dev/null +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerListProductsTest.java @@ -0,0 +1,254 @@ +package com.maxio.advancedbilling.controllers.products; + +import com.maxio.advancedbilling.TestClient; +import com.maxio.advancedbilling.controllers.ProductPricePointsController; +import com.maxio.advancedbilling.exceptions.ApiException; +import com.maxio.advancedbilling.models.CreateProductPricePoint; +import com.maxio.advancedbilling.models.CreateProductPricePointRequest; +import com.maxio.advancedbilling.models.ListProductsInput; +import com.maxio.advancedbilling.models.Product; +import com.maxio.advancedbilling.models.ProductPricePoint; +import com.maxio.advancedbilling.models.ProductResponse; +import org.apache.commons.lang3.time.DateUtils; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import static com.maxio.advancedbilling.models.BasicDateField.CREATED_AT; +import static com.maxio.advancedbilling.utils.TimeUtils.parseStringTimestamp; +import static com.maxio.advancedbilling.utils.TimeUtils.toTimestamp; +import static com.maxio.advancedbilling.utils.TimeUtils.toTruncatedTimestamp; +import static org.assertj.core.api.Assertions.assertThat; + +public class ProductsControllerListProductsTest extends ProductsControllerTestBase { + + static List savedProducts = new ArrayList<>(); + + @BeforeAll + static void setupProducts() throws IOException, ApiException { + archiveAllSiteProducts(); + + for (int i=0; i < 4; i++) { + savedProducts.add(createProductWithHandle("list-products-" + i)); + } + + // setup new price point for one product in order to test filtering by use_site_exchange_rate + Product productWithChangedPricePoint = createProductWithHandle("list-products-5"); + ProductPricePointsController productPricePointsController = TestClient.createClient().getProductPricePointsController(); + CreateProductPricePointRequest createProductPricePointRequest = new CreateProductPricePointRequest( + new CreateProductPricePoint.Builder().useSiteExchangeRate(false).interval(1).intervalUnit("month") + .priceInCents(22).name("Price point to promote").build() + ); + ProductPricePoint pricePoint = productPricePointsController + .createProductPricePoint(productWithChangedPricePoint.getId(), createProductPricePointRequest) + .getPricePoint(); + productPricePointsController.setDefaultPricePointForProduct(productWithChangedPricePoint.getId(), pricePoint.getId()); + productWithChangedPricePoint = productsController.readProduct(productWithChangedPricePoint.getId()).getProduct(); + savedProducts.add(productWithChangedPricePoint); + } + + @Test + void shouldListProducts() throws IOException, ApiException { + // when + List productList = productsController.listProducts(new ListProductsInput()) + .stream().map(ProductResponse::getProduct).toList(); + + // then + assertThat(productList).usingRecursiveFieldByFieldElementComparatorIgnoringFields("updatedAt") + .isEqualTo(savedProducts); + } + + @Test + void shouldListProductsFilteringByStartDate() throws IOException, ApiException, ParseException { + // given + Date savedProductCreatedAt = parseStringTimestamp(savedProducts.get(0).getCreatedAt()); + String startDateFilterIncludeElements = toTruncatedTimestamp(savedProductCreatedAt); + String startDateFilterExcludeElements = toTruncatedTimestamp(DateUtils + .addDays(savedProductCreatedAt, 1)); + + // when + List productList1 = productsController.listProducts( + new ListProductsInput.Builder().dateField(CREATED_AT).startDate(startDateFilterIncludeElements).build() + ); + List productList2 = productsController.listProducts( + new ListProductsInput.Builder().dateField(CREATED_AT).startDate(startDateFilterExcludeElements).build() + ); + + // then + assertThat(productList1.stream().map(ProductResponse::getProduct).toList()) + .usingRecursiveFieldByFieldElementComparatorIgnoringFields("updatedAt").isEqualTo(savedProducts); + assertThat(productList2).isEmpty(); + } + + @Test + void shouldListProductsFilteringByEndDate() throws IOException, ApiException, ParseException { + // given + Date savedProductCreatedAt = parseStringTimestamp(savedProducts.get(0).getCreatedAt()); + String endDateFilterIncludeElements = toTruncatedTimestamp(savedProductCreatedAt); + String endDateFilterExcludeElements = toTruncatedTimestamp(DateUtils + .addDays(savedProductCreatedAt, -1)); + + // when + List productList1 = productsController.listProducts( + new ListProductsInput.Builder().dateField(CREATED_AT).endDate(endDateFilterIncludeElements).build() + ); + List productList2 = productsController.listProducts( + new ListProductsInput.Builder().dateField(CREATED_AT).endDate(endDateFilterExcludeElements).build() + ); + + // then + assertThat(productList1.stream().map(ProductResponse::getProduct).toList()) + .usingRecursiveFieldByFieldElementComparatorIgnoringFields("updatedAt").isEqualTo(savedProducts); + assertThat(productList2).isEmpty(); + + } + + @Test + void shouldListProductsFilteringByStartDateTime() throws IOException, ApiException, ParseException { + // given + String savedProductCreatedAt = savedProducts.get(0).getCreatedAt(); + String startDateTimeFilterExcludeElements = toTimestamp(DateUtils + .addMinutes(parseStringTimestamp(savedProductCreatedAt), 5)); + + // when + List productList1 = productsController.listProducts( + new ListProductsInput.Builder().dateField(CREATED_AT).startDatetime(savedProductCreatedAt).build() + ); + List productList2 = productsController.listProducts( + new ListProductsInput.Builder().dateField(CREATED_AT).startDatetime(startDateTimeFilterExcludeElements).build() + ); + + // then + assertThat(productList1.stream().map(ProductResponse::getProduct).toList()) + .usingRecursiveFieldByFieldElementComparatorIgnoringFields("updatedAt").isEqualTo(savedProducts); + assertThat(productList2).isEmpty(); + } + + @Test + void shouldListProductsFilteringByEndDateTime() throws IOException, ApiException, ParseException { + // given + Date savedProductCreatedAt = parseStringTimestamp(savedProducts.get(0).getCreatedAt()); + String endDateTimeFilterIncludeElements = toTimestamp(DateUtils.addMinutes(savedProductCreatedAt, 5)); + String endDateTimeFilterExcludeElements = toTimestamp(DateUtils.addMinutes(savedProductCreatedAt, -5)); + + // when + List productList1 = productsController.listProducts( + new ListProductsInput.Builder().dateField(CREATED_AT).endDatetime(endDateTimeFilterIncludeElements).build() + ); + List productList2 = productsController.listProducts( + new ListProductsInput.Builder().dateField(CREATED_AT).endDatetime(endDateTimeFilterExcludeElements).build() + ); + + // then + assertThat(productList1.stream().map(ProductResponse::getProduct).toList()) + .usingRecursiveFieldByFieldElementComparatorIgnoringFields("updatedAt").isEqualTo(savedProducts); + assertThat(productList2).isEmpty(); + } + + @Test + void shouldListProductsIncludingArchived() throws IOException, ApiException, InterruptedException { + // given + Thread.sleep(1000); + Product archivedProduct = createProductWithHandle("product-to-archive"); + Product productAfterArchive = productsController.archiveProduct(archivedProduct.getId()).getProduct(); + // when + // List products endpoint lists all products for site, so there is possibility that + // it will list some products created in other tests - that's why we're using additional + // date filter to narrow down to archived product created inside this test + List productListWithArchived = productsController.listProducts( + new ListProductsInput.Builder().dateField(CREATED_AT) + .startDatetime(archivedProduct.getCreatedAt()).includeArchived(true).build() + ); + List productListWithoutArchived = productsController.listProducts( + new ListProductsInput.Builder().dateField(CREATED_AT) + .startDatetime(archivedProduct.getCreatedAt()).includeArchived(false).build() + ); + + // then + assertThat(productListWithArchived).hasSize(1); + assertThat(productListWithArchived.get(0).getProduct()).usingRecursiveComparison() + .isEqualTo(productAfterArchive); + + assertThat(productListWithoutArchived).isEmpty(); + } + + @Test + void shouldListProductsFilteringByUseSiteExchangeRate() throws IOException, ApiException { + // given + Product productWithChangedPricePoint = savedProducts.get(4); + + // when + List productsWithUseSiteExchangeRateFalse = productsController.listProducts( + new ListProductsInput.Builder().filterUseSiteExchangeRate(false).build() + ); + List productsWithUseSiteExchangeRateTrue = productsController.listProducts( + new ListProductsInput.Builder().filterUseSiteExchangeRate(true).build() + ); + + // then + assertThat(productsWithUseSiteExchangeRateFalse).hasSize(1); + assertThat(productsWithUseSiteExchangeRateFalse.get(0).getProduct().getId()) + .isEqualTo(productWithChangedPricePoint.getId()); + assertThat(productsWithUseSiteExchangeRateFalse.get(0).getProduct().getUseSiteExchangeRate()) + .isFalse(); + + assertThat(productsWithUseSiteExchangeRateTrue).hasSize(4); + assertThat(productsWithUseSiteExchangeRateTrue.stream().map(ProductResponse::getProduct).toList()) + .usingRecursiveFieldByFieldElementComparatorIgnoringFields("updatedAt").containsExactlyInAnyOrderElementsOf(savedProducts.subList(0,4)); + } + + @Test + void shouldListProductsUsingPagination() throws IOException, ApiException { + // when + List listProductsPage1 = productsController + .listProducts(new ListProductsInput.Builder() + .page(1) + .perPage(2) + .build() + ); + List listProductsPage2 = productsController + .listProducts(new ListProductsInput.Builder() + .page(2) + .perPage(2) + .build() + ); + List listProductsPage3 = productsController + .listProducts(new ListProductsInput.Builder() + .page(3) + .perPage(2) + .build() + ); + List listProductsPage4 = productsController + .listProducts(new ListProductsInput.Builder() + .page(4) + .perPage(2) + .build() + ); + + // then + assertThat(listProductsPage1).hasSize(2); + assertThat(listProductsPage2).hasSize(2); + assertThat(listProductsPage3).hasSize(1); + assertThat(listProductsPage4).isEmpty(); + } + + private static void archiveAllSiteProducts() throws IOException, ApiException { + List productResponses = productsController.listProducts( + new ListProductsInput.Builder().perPage(200).build() + ); + while (productResponses.size() > 0) { + for (ProductResponse p: productResponses) { + productsController.archiveProduct(p.getProduct().getId()); + } + productResponses = productsController.listProducts( + new ListProductsInput.Builder().perPage(200).build() + ); + } + } + +} diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerReadProductByHandleTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerReadProductByHandleTest.java new file mode 100644 index 00000000..051e561a --- /dev/null +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerReadProductByHandleTest.java @@ -0,0 +1,33 @@ +package com.maxio.advancedbilling.controllers.products; + +import com.maxio.advancedbilling.exceptions.ApiException; +import com.maxio.advancedbilling.models.IntervalUnit; +import com.maxio.advancedbilling.models.Product; +import org.junit.jupiter.api.Test; + +import java.io.IOException; + +import static com.maxio.advancedbilling.utils.CommonAssertions.assertNotFound; +import static org.assertj.core.api.Assertions.assertThat; + +public class ProductsControllerReadProductByHandleTest extends ProductsControllerTestBase { + + @Test + void shouldReadProduct() throws IOException, ApiException { + // given + Product product = createProduct(); + + // when + Product readProduct = productsController.readProductByHandle(product.getHandle()).getProduct(); + + // then + assertThat(readProduct).usingRecursiveComparison().isEqualTo(product); + } + + @Test + void shouldNotReadNotOwnedProduct() { + // when-then + assertNotFound(() -> productsController.readProductByHandle("abc")); + } + +} diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerReadProductTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerReadProductTest.java new file mode 100644 index 00000000..7ab035f1 --- /dev/null +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerReadProductTest.java @@ -0,0 +1,32 @@ +package com.maxio.advancedbilling.controllers.products; + +import com.maxio.advancedbilling.exceptions.ApiException; +import com.maxio.advancedbilling.models.Product; +import org.junit.jupiter.api.Test; + +import java.io.IOException; + +import static com.maxio.advancedbilling.utils.CommonAssertions.assertNotFound; +import static org.assertj.core.api.Assertions.assertThat; + +public class ProductsControllerReadProductTest extends ProductsControllerTestBase { + + @Test + void shouldReadProduct() throws IOException, ApiException { + // given + Product product = createProduct(); + + // when + Product readProduct = productsController.readProduct(product.getId()).getProduct(); + + // then + assertThat(readProduct).usingRecursiveComparison().isEqualTo(product); + } + + @Test + void shouldNotArchiveNotOwnedProduct() { + // when-then + assertNotFound(() -> productsController.readProduct(99999999)); + } + +} diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerTestBase.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerTestBase.java new file mode 100644 index 00000000..91325627 --- /dev/null +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerTestBase.java @@ -0,0 +1,53 @@ +package com.maxio.advancedbilling.controllers.products; + +import com.maxio.advancedbilling.TestClient; +import com.maxio.advancedbilling.controllers.ProductFamiliesController; +import com.maxio.advancedbilling.controllers.ProductsController; +import com.maxio.advancedbilling.exceptions.ApiException; +import com.maxio.advancedbilling.models.CreateOrUpdateProduct; +import com.maxio.advancedbilling.models.CreateOrUpdateProductRequest; +import com.maxio.advancedbilling.models.CreateProductFamily; +import com.maxio.advancedbilling.models.CreateProductFamilyRequest; +import com.maxio.advancedbilling.models.Product; +import com.maxio.advancedbilling.models.ProductFamily; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.jupiter.api.BeforeAll; + +import java.io.IOException; + +abstract class ProductsControllerTestBase { + protected static final ProductsController productsController = TestClient.createClient().getProductsController(); + protected static ProductFamily productFamily; + + @BeforeAll + static void setup() throws IOException, ApiException { + ProductFamiliesController productFamiliesController = TestClient.createClient() + .getProductFamiliesController(); + + productFamily = productFamiliesController.createProductFamily(new CreateProductFamilyRequest( + new CreateProductFamily("Test Product Family " + + RandomStringUtils.randomAlphanumeric(5), null))) + .getProductFamily(); + } + + protected Product createProduct() throws IOException, ApiException { + return createProductWithHandle("initial_handle-" + RandomStringUtils.randomAlphanumeric(5).toLowerCase()); + } + + protected static Product createProductWithHandle(String handle) throws IOException, ApiException { + Product product = productsController + .createProduct(productFamily.getId(), new CreateOrUpdateProductRequest( + new CreateOrUpdateProduct.Builder() + .name("Initial Sample product-" + RandomStringUtils.randomAlphanumeric(5)) + .handle(handle) + .description("A sample product for testing") + .priceInCents(1000) + .interval(1) + .intervalUnit("month") + .build() + )) + .getProduct(); + return product; + } + +} diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerUpdateProductTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerUpdateProductTest.java new file mode 100644 index 00000000..485880d9 --- /dev/null +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/products/ProductsControllerUpdateProductTest.java @@ -0,0 +1,171 @@ +package com.maxio.advancedbilling.controllers.products; + +import com.maxio.advancedbilling.exceptions.ApiException; +import com.maxio.advancedbilling.exceptions.ErrorListResponseException; +import com.maxio.advancedbilling.models.CreateOrUpdateProduct; +import com.maxio.advancedbilling.models.CreateOrUpdateProductRequest; +import com.maxio.advancedbilling.models.IntervalUnit; +import com.maxio.advancedbilling.models.Product; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Collections; +import java.util.List; +import java.util.stream.Stream; + +import static com.maxio.advancedbilling.utils.CommonAssertions.assertNotFound; +import static com.maxio.advancedbilling.utils.TimeUtils.parseStringTimestamp; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.junit.jupiter.api.Assertions.assertAll; + +public class ProductsControllerUpdateProductTest extends ProductsControllerTestBase { + + @Test + void shouldUpdateProductWithAllParameters() throws IOException, ApiException { + // when + Instant timestamp = Instant.now().minus(5, ChronoUnit.SECONDS); + Product product = createProduct(); + + Product updatedProduct = productsController.updateProduct(product.getId(), new CreateOrUpdateProductRequest( + new CreateOrUpdateProduct.Builder() + .name("Updated Product") + .handle("updated_handle") + .description("Updated Description") + .priceInCents(2000) + .interval(2) + .intervalUnit(IntervalUnit.DAY.value()) + + .accountingCode("acccode") + .taxCode("taxcode") + .requireCreditCard(true) + .build() + )).getProduct(); + // then + assertAll( + () -> assertThat(updatedProduct.getId()).isEqualTo(product.getId()), + () -> assertThat(updatedProduct.getName()).isEqualTo("Updated Product"), + () -> assertThat(updatedProduct.getHandle()).isEqualTo("updated_handle"), + () -> assertThat(updatedProduct.getDescription()).isEqualTo("Updated Description"), + () -> assertThat(updatedProduct.getPriceInCents()).isEqualTo(2000), + () -> assertThat(updatedProduct.getInterval()).isEqualTo(2), + () -> assertThat(updatedProduct.getIntervalUnit().match(i -> i).value()).isEqualTo(IntervalUnit.DAY.value()), + () -> assertThat(parseStringTimestamp(updatedProduct.getCreatedAt())).isAfterOrEqualTo(timestamp), + () -> assertThat(parseStringTimestamp(updatedProduct.getUpdatedAt())).isAfterOrEqualTo(timestamp), + () -> assertThat(updatedProduct.getAccountingCode()).isEqualTo("acccode"), + () -> assertThat(updatedProduct.getRequestCreditCard()).isTrue(), + () -> assertThat(updatedProduct.getTaxCode()).isEqualTo("taxcode"), + + () -> assertThat(updatedProduct.getExpirationInterval()).isNull(), + () -> assertThat(updatedProduct.getExpirationIntervalUnit()).isNull(), + () -> assertThat(updatedProduct.getInitialChargeInCents()).isNull(), + () -> assertThat(updatedProduct.getTrialPriceInCents()).isNull(), + () -> assertThat(updatedProduct.getTrialInterval()).isNull(), + () -> assertThat(updatedProduct.getTrialIntervalUnit()).isNull(), + () -> assertThat(updatedProduct.getArchivedAt()).isNull(), + () -> assertThat(updatedProduct.getRequireCreditCard()).isTrue(), + () -> assertThat(updatedProduct.getReturnParams()).isNull(), + () -> assertThat(updatedProduct.getTaxable()).isFalse(), + () -> assertThat(updatedProduct.getUpdateReturnUrl()).isNull(), + () -> assertThat(updatedProduct.getInitialChargeAfterTrial()).isFalse(), + () -> assertThat(updatedProduct.getVersionNumber()).isEqualTo(1), + () -> assertThat(updatedProduct.getUpdateReturnParams()).isNull(), + () -> assertThat(updatedProduct.getProductPricePointName()).isEqualTo("Default"), + () -> assertThat(updatedProduct.getRequestBillingAddress()).isFalse(), + () -> assertThat(updatedProduct.getRequireBillingAddress()).isFalse(), + () -> assertThat(updatedProduct.getRequireShippingAddress()).isFalse(), + () -> assertThat(updatedProduct.getDefaultProductPricePointId()).isPositive(), + () -> assertThat(updatedProduct.getUseSiteExchangeRate()).isTrue(), + () -> assertThat(updatedProduct.getItemCategory()).isNull(), + () -> assertThat(updatedProduct.getProductPricePointId()).isPositive(), + () -> assertThat(updatedProduct.getProductPricePointHandle()).isNotEmpty(), + + () -> assertThat(updatedProduct.getProductFamily()).isNotNull(), + () -> assertThat(updatedProduct.getProductFamily().getId()).isEqualTo(productFamily.getId()), + () -> assertThat(updatedProduct.getProductFamily().getName()).isEqualTo(productFamily.getName()), + () -> assertThat(updatedProduct.getProductFamily().getHandle()).isEqualTo(productFamily.getHandle()), + () -> assertThat(updatedProduct.getProductFamily().getAccountingCode()).isEqualTo(productFamily.getAccountingCode()), + () -> assertThat(updatedProduct.getProductFamily().getDescription()).isEqualTo(productFamily.getDescription()), + () -> assertThat(updatedProduct.getProductFamily().getCreatedAt()).isEqualTo(productFamily.getCreatedAt()), + () -> assertThat(updatedProduct.getProductFamily().getUpdatedAt()).isEqualTo(productFamily.getUpdatedAt()) + ); + } + + @Test + void shouldNotUpdateProductHandleToHandleOfExistingProduct() throws IOException, ApiException { + // when + Product product1 = createProduct(); + Product product2 = createProduct(); + + // then + String expectedErrorMessage = String.format( + "API Handle: must be unique - '%s' has been taken by another Product in this Site.", + product1.getHandle()); + assertThatExceptionOfType(ErrorListResponseException.class) + .isThrownBy(() -> productsController.updateProduct( + product2.getId(), new CreateOrUpdateProductRequest( + new CreateOrUpdateProduct.Builder() + .name("Updated Product") + .handle(product1.getHandle()) + .description("Updated Description") + .priceInCents(2000) + .interval(2) + .intervalUnit(IntervalUnit.DAY.value()) + .build() + )) + ) + .withMessage("Unprocessable Entity (WebDAV)") + .satisfies(e -> { + assertThat(e.getResponseCode()).isEqualTo(422); + assertThat(e.getErrors()).containsExactlyInAnyOrder(expectedErrorMessage); + + }); + } + + @ParameterizedTest + @MethodSource("argsForShouldNotUpdateProductWithBlankBasicParameters") + void shouldNotUpdateProductWithBlankBasicParameters(CreateOrUpdateProduct updateProduct, + List errorMessages) throws IOException, ApiException { + // when - then + Product product = createProduct(); + assertThatExceptionOfType(ErrorListResponseException.class) + .isThrownBy(() -> productsController.updateProduct( + product.getId(), new CreateOrUpdateProductRequest(updateProduct)) + ) + .withMessage("Unprocessable Entity (WebDAV)") + .satisfies(e -> { + assertThat(e.getResponseCode()).isEqualTo(422); + assertThat(e.getErrors()).hasSameElementsAs(errorMessages); + }); + } + + @Test + void shouldNotUpdateNotOwnedProduct() { + // when-then + assertNotFound(() -> productsController.updateProduct(999999, new CreateOrUpdateProductRequest())); + } + + private static Stream argsForShouldNotUpdateProductWithBlankBasicParameters() { + CreateOrUpdateProduct productTemplate = new CreateOrUpdateProduct.Builder().name("test-name").handle("product-handle-test") + .description("test description").priceInCents(11).interval(1).intervalUnit("month").build(); + return Stream.of( + Arguments.of( + productTemplate.toBuilder().name(null).build(), Collections.singletonList("Name: cannot be blank.") + ), + Arguments.of( + productTemplate.toBuilder().intervalUnit(null).build(), List.of("Interval unit: cannot be blank.", + "Interval unit: must be 'month' or 'day'.") + ), + Arguments.of( + productTemplate.toBuilder().handle("VERY INVALID HANDLE").build(), + List.of("API Handle: may only contain lowercase letters, numbers, underscores, and dashes") + ) + ); + } + +} diff --git a/tests/src/test/java/com/maxio/advancedbilling/controllers/SitesControllerTest.java b/tests/src/test/java/com/maxio/advancedbilling/controllers/sites/SitesControllerTest.java similarity index 96% rename from tests/src/test/java/com/maxio/advancedbilling/controllers/SitesControllerTest.java rename to tests/src/test/java/com/maxio/advancedbilling/controllers/sites/SitesControllerTest.java index 608a2453..affae00b 100644 --- a/tests/src/test/java/com/maxio/advancedbilling/controllers/SitesControllerTest.java +++ b/tests/src/test/java/com/maxio/advancedbilling/controllers/sites/SitesControllerTest.java @@ -1,6 +1,7 @@ -package com.maxio.advancedbilling.controllers; +package com.maxio.advancedbilling.controllers.sites; import com.maxio.advancedbilling.TestClient; +import com.maxio.advancedbilling.controllers.SitesController; import com.maxio.advancedbilling.models.AllocationSettings; import com.maxio.advancedbilling.models.NetTerms; import com.maxio.advancedbilling.models.OrganizationAddress; diff --git a/tests/src/test/java/com/maxio/advancedbilling/utils/TimeUtils.java b/tests/src/test/java/com/maxio/advancedbilling/utils/TimeUtils.java new file mode 100644 index 00000000..530bc0fa --- /dev/null +++ b/tests/src/test/java/com/maxio/advancedbilling/utils/TimeUtils.java @@ -0,0 +1,26 @@ +package com.maxio.advancedbilling.utils; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class TimeUtils { + + private static final SimpleDateFormat AB_DATE_FORMAT = + new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); + private static final SimpleDateFormat TRUNCATED_DATE_FORMAT = + new SimpleDateFormat("yyyy-MM-dd"); + + public static Date parseStringTimestamp(String source) throws ParseException { + return AB_DATE_FORMAT.parse(source); + } + + public static String toTimestamp(Date source) { + return AB_DATE_FORMAT.format(source); + } + + public static String toTruncatedTimestamp(Date source) { + return TRUNCATED_DATE_FORMAT.format(source); + } + +}