Skip to content

Commit

Permalink
[DE-572] Tests for listing Product(s) Price Points
Browse files Browse the repository at this point in the history
  • Loading branch information
patryk-grudzien-keen committed Nov 30, 2023
1 parent 1d756b3 commit 4b02033
Show file tree
Hide file tree
Showing 3 changed files with 422 additions and 87 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package com.maxio.advancedbilling.controllers.productpricepoints;

import com.maxio.advancedbilling.AdvancedBillingClient;
import com.maxio.advancedbilling.TestClient;
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;
import com.maxio.advancedbilling.models.CreateProductFamily;
import com.maxio.advancedbilling.models.CreateProductFamilyRequest;
import com.maxio.advancedbilling.models.CreateProductPricePoint;
import com.maxio.advancedbilling.models.CreateProductPricePointRequest;
import com.maxio.advancedbilling.models.IntervalUnit;
import com.maxio.advancedbilling.models.ListAllProductPricePointsInput;
import com.maxio.advancedbilling.models.ListProductsInput;
import com.maxio.advancedbilling.models.PricePointType;
import com.maxio.advancedbilling.models.Product;
import com.maxio.advancedbilling.models.ProductFamily;
import com.maxio.advancedbilling.models.ProductPricePoint;
import com.maxio.advancedbilling.models.ProductPricePointResponse;
import com.maxio.advancedbilling.models.ProductResponse;
import org.junit.jupiter.api.BeforeAll;

import java.io.IOException;
import java.util.EnumSet;
import java.util.List;

import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
import static org.junit.jupiter.api.Assertions.fail;

abstract class ProductPricePointsBaseTest {

protected static final AdvancedBillingClient ADVANCED_BILLING_CLIENT = TestClient.createClient();
protected static final ProductsController PRODUCTS_CONTROLLER = ADVANCED_BILLING_CLIENT.getProductsController();
protected static final ProductPricePointsController PRODUCT_PRICE_POINTS_CONTROLLER = ADVANCED_BILLING_CLIENT.getProductPricePointsController();

protected static ProductFamily productFamily;

@BeforeAll
static void setupProductFamily() throws IOException, ApiException {
productFamily = ADVANCED_BILLING_CLIENT
.getProductFamiliesController()
.createProductFamily(new CreateProductFamilyRequest.Builder(
new CreateProductFamily.Builder()
.name("Test Product Family %s".formatted(randomAlphabetic(5)))
.build()
).build()
)
.getProductFamily();
}

protected static Product createProduct() throws IOException, ApiException {
return PRODUCTS_CONTROLLER
.createProduct(
productFamily.getId(),
new CreateOrUpdateProductRequest(new CreateOrUpdateProduct.Builder()
.name("product-name-%s".formatted(randomNumeric(5)))
.handle("product-handle-%s".formatted(randomNumeric(5)))
.intervalUnit(IntervalUnit.MONTH)
.interval(2)
.build()
)
)
.getProduct();
}

protected static ProductPricePointResponse createProductPricePoint(int productId, CreateProductPricePoint createProductPricePoint)
throws IOException, ApiException {
return createProductPricePointWithDelay(0, productId, createProductPricePoint);
}

protected static ProductPricePointResponse createProductPricePointWithDelay(long delayInMillis, int productId,
CreateProductPricePoint createProductPricePoint)
throws IOException, ApiException {
try {
Thread.sleep(delayInMillis);
} catch (InterruptedException e) {
fail(e.getMessage(), e);
}

return PRODUCT_PRICE_POINTS_CONTROLLER
.createProductPricePoint(productId, new CreateProductPricePointRequest(createProductPricePoint));
}

protected static CreateProductPricePoint.Builder defaultBuilder() {
return new CreateProductPricePoint.Builder()
.priceInCents(100L)
.interval(2)
.intervalUnit(IntervalUnit.MONTH)
.trialPriceInCents(4900L)
.trialInterval(1)
.trialIntervalUnit(IntervalUnit.MONTH)
.trialType("payment_expected")
.initialChargeInCents(120000L)
.initialChargeAfterTrial(false)
.expirationInterval(12)
.expirationIntervalUnit(IntervalUnit.MONTH);
}

// when archiving default price point, {"errors":["Cannot archive the default price point."]} is returned
protected static void archiveAllSitePricePointsExcludingDefault() throws IOException, ApiException {
List<ProductPricePoint> sitePricePointsExcludingDefault = listAllSitePricePointsPerPage200ExcludingDefault();
while (!sitePricePointsExcludingDefault.isEmpty()) {
for (ProductPricePoint pricePoint : sitePricePointsExcludingDefault) {
PRODUCT_PRICE_POINTS_CONTROLLER.archiveProductPricePoint(
pricePoint.getProductId(),
pricePoint.getId()
);
}
sitePricePointsExcludingDefault = listAllSitePricePointsPerPage200ExcludingDefault();
}
}

protected static void archiveAllSiteProducts() throws IOException, ApiException {
List<ProductResponse> productResponses = listAllSiteProductsPerPage200();
while (!productResponses.isEmpty()) {
for (ProductResponse p : productResponses) {
PRODUCTS_CONTROLLER.archiveProduct(p.getProduct().getId());
}
productResponses = listAllSiteProductsPerPage200();
}
}

protected static List<PricePointType> pricePointTypesExcludingDefault() {
return EnumSet.complementOf(EnumSet.of(PricePointType.ENUM_DEFAULT)).stream().toList();
}

private static List<ProductResponse> listAllSiteProductsPerPage200() throws IOException, ApiException {
return PRODUCTS_CONTROLLER.listProducts(
new ListProductsInput.Builder().perPage(200).build()
);
}

private static List<ProductPricePoint> listAllSitePricePointsPerPage200ExcludingDefault() throws IOException, ApiException {
return PRODUCT_PRICE_POINTS_CONTROLLER
.listAllProductPricePoints(new ListAllProductPricePointsInput.Builder()
.filterType(pricePointTypesExcludingDefault())
.perPage(200)
.build()
)
.getPricePoints();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
package com.maxio.advancedbilling.controllers.productpricepoints;

import com.maxio.advancedbilling.exceptions.ApiException;
import com.maxio.advancedbilling.models.BasicDateField;
import com.maxio.advancedbilling.models.IncludeNotNull;
import com.maxio.advancedbilling.models.IntervalUnit;
import com.maxio.advancedbilling.models.ListAllProductPricePointsInput;
import com.maxio.advancedbilling.models.PricePointType;
import com.maxio.advancedbilling.models.Product;
import com.maxio.advancedbilling.models.ProductPricePoint;
import com.maxio.advancedbilling.models.SortingDirection;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;

import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;

class ProductPricePointsControllerListAllTest extends ProductPricePointsBaseTest {

private static Product product;
private static ProductPricePoint archivedProductPricePoint;

private static final LinkedList<ProductPricePoint> PRODUCT_PRICE_POINTS_OF_TYPE_CATALOG = new LinkedList<>();

@BeforeAll
static void beforeAll() throws IOException, ApiException {
archiveAllSiteProducts();
archiveAllSitePricePointsExcludingDefault();

product = createProduct(); // this creates a default price point
for (int i = 0; i < 3; i++) {
PRODUCT_PRICE_POINTS_OF_TYPE_CATALOG.add(createProductPricePointWithDelay(
1000,
product.getId(),
defaultBuilder().name("test-price-point-%s".formatted(randomAlphabetic(5))).build()
).getPricePoint()
);
}

archivedProductPricePoint = PRODUCT_PRICE_POINTS_CONTROLLER.archiveProductPricePoint(
product.getId(),
createProductPricePoint(product.getId(), defaultBuilder().name("archived-test-price-point-%s".formatted(randomAlphabetic(5))).build()).getPricePoint().getId()
)
.getPricePoint();
}

@Test
void shouldReturnListWithOriginalPricePointUsingFilterOfTypeDefault() throws IOException, ApiException {
// when
List<ProductPricePoint> productPricePoints = PRODUCT_PRICE_POINTS_CONTROLLER
.listAllProductPricePoints(
filterByStartDatetimeOfProductCreation(builder -> builder.filterType(List.of(PricePointType.ENUM_DEFAULT)))
)
.getPricePoints();

// then
assertThat(productPricePoints).hasSize(1);
ProductPricePoint defaultPricePoint = productPricePoints.get(0);
assertAll(
() -> assertThat(defaultPricePoint.getId()).isNotNull(),
() -> assertThat(defaultPricePoint.getName()).isEqualTo("Original"),
() -> assertThat(defaultPricePoint.getHandle()).isNotNull(),
() -> assertThat(defaultPricePoint.getPriceInCents()).isEqualTo(0),
() -> assertThat(defaultPricePoint.getInterval()).isEqualTo(2),
() -> assertThat(defaultPricePoint.getIntervalUnit()).isEqualTo(IntervalUnit.MONTH),
() -> assertThat(defaultPricePoint.getTrialPriceInCents()).isNull(),
() -> assertThat(defaultPricePoint.getTrialInterval()).isNull(),
() -> assertThat(defaultPricePoint.getTrialIntervalUnit()).isNull(),
() -> assertThat(defaultPricePoint.getTrialType()).isEqualTo("payment_expected"),
() -> assertThat(defaultPricePoint.getIntroductoryOffer()).isNull(),
() -> assertThat(defaultPricePoint.getInitialChargeInCents()).isNull(),
() -> assertThat(defaultPricePoint.getInitialChargeAfterTrial()).isFalse(),
() -> assertThat(defaultPricePoint.getExpirationInterval()).isNull(),
() -> assertThat(defaultPricePoint.getExpirationIntervalUnit()).isNull(),
() -> assertThat(defaultPricePoint.getExpirationIntervalUnit()).isNull(),
() -> assertThat(defaultPricePoint.getProductId()).isEqualTo(product.getId()),
() -> assertThat(defaultPricePoint.getArchivedAt()).isNull(),
() -> assertThat(defaultPricePoint.getCreatedAt()).isNotNull(),
() -> assertThat(defaultPricePoint.getUpdatedAt()).isNotNull(),
() -> assertThat(defaultPricePoint.getUseSiteExchangeRate()).isTrue(),
() -> assertThat(defaultPricePoint.getType()).isEqualTo(PricePointType.ENUM_DEFAULT),
() -> assertThat(defaultPricePoint.getTaxIncluded()).isFalse(),
() -> assertThat(defaultPricePoint.getSubscriptionId()).isNull()
);
}

@Test
void shouldReturnListWithAllPricePointsSortedByCreatedAtDesc() throws IOException, ApiException {
// when
List<ProductPricePoint> productPricePoints = PRODUCT_PRICE_POINTS_CONTROLLER
.listAllProductPricePoints(
filterByStartDatetimeOfProductCreation(builder -> builder.direction(SortingDirection.DESC))
)
.getPricePoints();

// then
assertThat(productPricePoints).hasSize(4);
assertThat(productPricePoints.get(0).getCreatedAt()).isAfter(productPricePoints.get(1).getCreatedAt());
}

@Test
void shouldReturnListOfArchivedPricePoints() throws IOException, ApiException {
// when
List<ProductPricePoint> archivedPricePoints = PRODUCT_PRICE_POINTS_CONTROLLER
.listAllProductPricePoints(
filterByStartDatetimeOfProductCreation(builder -> builder.filterArchivedAt(IncludeNotNull.NOT_NULL))
)
.getPricePoints();

// then
assertThat(archivedPricePoints)
.hasSize(1)
.singleElement()
.usingRecursiveComparison()
.isEqualTo(archivedProductPricePoint);
}

@Test
void shouldReturnEmptyListWhenEndDateFilterDoesNotMatchCreatedAtTimeframe() throws IOException, ApiException {
// when
List<ProductPricePoint> productPricePoints = PRODUCT_PRICE_POINTS_CONTROLLER
.listAllProductPricePoints(new ListAllProductPricePointsInput.Builder()
.filterDateField(BasicDateField.CREATED_AT)
.filterEndDate(LocalDate.parse("2020-01-01"))
.build()
)
.getPricePoints();

// then
assertThat(productPricePoints).isEmpty();
}

@Test
void shouldReturnEmptyListWhenEndDateTimeFilterDoesNotMatchCreatedAtTimeframe() throws IOException, ApiException {
// when
List<ProductPricePoint> productPricePoints = PRODUCT_PRICE_POINTS_CONTROLLER
.listAllProductPricePoints(new ListAllProductPricePointsInput.Builder()
.filterDateField(BasicDateField.CREATED_AT)
.filterEndDatetime(ZonedDateTime.parse("2020-01-01T00:00:00Z"))
.build()
)
.getPricePoints();

// then
assertThat(productPricePoints).isEmpty();
}

@Test
void shouldReturnEmptyListWhenIdsFilterContainsIncorrectValues() throws IOException, ApiException {
// when
List<ProductPricePoint> productPricePoints = PRODUCT_PRICE_POINTS_CONTROLLER
.listAllProductPricePoints(
filterByStartDatetimeOfProductCreation(builder -> builder.filterIds(List.of(1, 2, 3, 4, 5)))
)
.getPricePoints();

// then
assertThat(productPricePoints).isEmpty();
}

@Test
void shouldReturnEmptyListWhenStartDateFilterDoesNotMatchCreatedAtTimeframe() throws IOException, ApiException {
// when
List<ProductPricePoint> productPricePoints = PRODUCT_PRICE_POINTS_CONTROLLER
.listAllProductPricePoints(new ListAllProductPricePointsInput.Builder()
.filterDateField(BasicDateField.CREATED_AT)
.filterStartDate(LocalDate.parse("2030-01-01"))
.build()
)
.getPricePoints();

// then
assertThat(productPricePoints).isEmpty();
}

@Test
void shouldReturnEmptyListWhenStartDateTimeFilterDoesNotMatchCreatedAtTimeframe() throws IOException, ApiException {
// when
List<ProductPricePoint> productPricePoints = PRODUCT_PRICE_POINTS_CONTROLLER
.listAllProductPricePoints(new ListAllProductPricePointsInput.Builder()
.filterDateField(BasicDateField.CREATED_AT)
.filterStartDatetime(ZonedDateTime.parse("2030-01-01T00:00:00Z"))
.build()
)
.getPricePoints();

// then
assertThat(productPricePoints).isEmpty();
}

@Test
void shouldReturnListWithPricePointOfTypeCatalog() throws IOException, ApiException {
// when
List<ProductPricePoint> customPricePoints = PRODUCT_PRICE_POINTS_CONTROLLER
.listAllProductPricePoints(
filterByStartDatetimeOfProductCreation(builder -> builder.filterType(List.of(PricePointType.CATALOG)))
)
.getPricePoints();

// then
assertThat(customPricePoints)
.hasSize(3)
.usingRecursiveFieldByFieldElementComparator()
.isEqualTo(PRODUCT_PRICE_POINTS_OF_TYPE_CATALOG);
}

@Test
void shouldReturnListWithPagedPricePoints() throws IOException, ApiException {
// when
List<ProductPricePoint> page1 = PRODUCT_PRICE_POINTS_CONTROLLER
.listAllProductPricePoints(
filterByStartDatetimeOfProductCreation(builder -> builder.page(1).perPage(2))
)
.getPricePoints();
List<ProductPricePoint> page2 = PRODUCT_PRICE_POINTS_CONTROLLER
.listAllProductPricePoints(
filterByStartDatetimeOfProductCreation(builder -> builder.page(2).perPage(2))
)
.getPricePoints();
List<ProductPricePoint> page3 = PRODUCT_PRICE_POINTS_CONTROLLER
.listAllProductPricePoints(
filterByStartDatetimeOfProductCreation(builder -> builder.page(3).perPage(2))
)
.getPricePoints();

// then
assertThat(page1).hasSize(2);
assertThat(page2).hasSize(2);
assertThat(page3).hasSize(0);
}

private ListAllProductPricePointsInput filterByStartDatetimeOfProductCreation(Consumer<ListAllProductPricePointsInput.Builder> customizer) {
ListAllProductPricePointsInput.Builder builder = new ListAllProductPricePointsInput.Builder()
// filtering by product's createdAt to skip potential leftovers from other tests
.filterDateField(BasicDateField.CREATED_AT)
.filterStartDatetime(product.getCreatedAt());
customizer.accept(builder);
return builder.build();
}
}
Loading

0 comments on commit 4b02033

Please sign in to comment.