-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[DE-117] DE-629 - Java test CRUD for Invoices endpoints part 1 (Issue…
… Invoice)
- Loading branch information
1 parent
9d10400
commit 8dc8c72
Showing
1 changed file
with
317 additions
and
0 deletions.
There are no files selected for viewing
317 changes: 317 additions & 0 deletions
317
...test/java/com/maxio/advancedbilling/controllers/invoices/InvoicesControllerIssueTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,317 @@ | ||
package com.maxio.advancedbilling.controllers.invoices; | ||
|
||
import com.maxio.advancedbilling.AdvancedBillingClient; | ||
import com.maxio.advancedbilling.TestClient; | ||
import com.maxio.advancedbilling.controllers.InvoicesController; | ||
import com.maxio.advancedbilling.exceptions.ApiException; | ||
import com.maxio.advancedbilling.models.Component; | ||
import com.maxio.advancedbilling.models.CreateAllocation; | ||
import com.maxio.advancedbilling.models.CreateAllocationRequest; | ||
import com.maxio.advancedbilling.models.CreateInvoiceCoupon; | ||
import com.maxio.advancedbilling.models.CreateInvoiceItem; | ||
import com.maxio.advancedbilling.models.CreateInvoiceStatus; | ||
import com.maxio.advancedbilling.models.Customer; | ||
import com.maxio.advancedbilling.models.FailedPaymentAction; | ||
import com.maxio.advancedbilling.models.Invoice; | ||
import com.maxio.advancedbilling.models.InvoiceAddress; | ||
import com.maxio.advancedbilling.models.InvoiceBalanceItem; | ||
import com.maxio.advancedbilling.models.InvoiceConsolidationLevel; | ||
import com.maxio.advancedbilling.models.InvoiceCustomer; | ||
import com.maxio.advancedbilling.models.InvoiceLineItem; | ||
import com.maxio.advancedbilling.models.InvoicePayment; | ||
import com.maxio.advancedbilling.models.InvoicePaymentMethod; | ||
import com.maxio.advancedbilling.models.InvoicePreviousBalance; | ||
import com.maxio.advancedbilling.models.InvoiceSeller; | ||
import com.maxio.advancedbilling.models.InvoiceStatus; | ||
import com.maxio.advancedbilling.models.IssueInvoiceRequest; | ||
import com.maxio.advancedbilling.models.ListInvoicesInput; | ||
import com.maxio.advancedbilling.models.Product; | ||
import com.maxio.advancedbilling.models.ProductFamily; | ||
import com.maxio.advancedbilling.models.Subscription; | ||
import com.maxio.advancedbilling.models.containers.CreateInvoiceCouponAmount; | ||
import com.maxio.advancedbilling.models.containers.CreateInvoiceItemProductId; | ||
import com.maxio.advancedbilling.models.containers.CreateInvoiceItemQuantity; | ||
import com.maxio.advancedbilling.utils.TestSetup; | ||
import com.maxio.advancedbilling.utils.TestTeardown; | ||
import com.maxio.advancedbilling.utils.assertions.CommonAssertions; | ||
import org.junit.jupiter.api.AfterAll; | ||
import org.junit.jupiter.api.BeforeAll; | ||
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.LocalDate; | ||
import java.util.List; | ||
import java.util.stream.Stream; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.junit.jupiter.api.Assertions.assertAll; | ||
|
||
class InvoicesControllerIssueTest { | ||
private static final TestSetup TEST_SETUP = new TestSetup(); | ||
private static final AdvancedBillingClient CLIENT = TestClient.createClient(); | ||
private static final InvoicesController INVOICES_CONTROLLER = CLIENT.getInvoicesController(); | ||
|
||
private static Product product; | ||
private static Component quantityBasedComponent; | ||
private static Subscription subscription; | ||
private static Customer customer; | ||
private static Invoice openInvoice; | ||
private static Invoice paidInvoice; | ||
|
||
@BeforeAll | ||
static void setUp() throws IOException, ApiException { | ||
ProductFamily productFamily = TEST_SETUP.createProductFamily(); | ||
product = TEST_SETUP.createProduct(productFamily, b -> b.priceInCents(1250)); | ||
customer = TEST_SETUP.createCustomer(); | ||
quantityBasedComponent = TEST_SETUP.createQuantityBasedComponent( | ||
productFamily.getId(), | ||
b -> b.allowFractionalQuantities(true) | ||
); | ||
subscription = TEST_SETUP.createSubscription(customer, product); | ||
paidInvoice = INVOICES_CONTROLLER | ||
.listInvoices(new ListInvoicesInput.Builder().subscriptionId(subscription.getId()).build()) | ||
.getInvoices() | ||
.get(0); | ||
openInvoice = TEST_SETUP.createInvoice( | ||
subscription.getId(), | ||
b -> b | ||
.status(CreateInvoiceStatus.OPEN) | ||
.lineItems(List.of( | ||
new CreateInvoiceItem.Builder() | ||
.productId(CreateInvoiceItemProductId.fromNumber(product.getId())) | ||
.quantity(CreateInvoiceItemQuantity.fromString("1")) | ||
.build() | ||
)) | ||
.coupons(List.of( | ||
new CreateInvoiceCoupon.Builder() | ||
.code("MY_CUSTOM_CODE") | ||
.amount(CreateInvoiceCouponAmount.fromString("8.5")) | ||
.description("Super coupon with 8.5 amount.") | ||
.build() | ||
)) | ||
.build() | ||
); | ||
} | ||
|
||
@AfterAll | ||
static void teardown() throws IOException, ApiException { | ||
new TestTeardown().deleteCustomer(customer); | ||
} | ||
|
||
@SuppressWarnings("DataFlowIssue") | ||
@Test | ||
void shouldIssuePendingInvoice() throws IOException, ApiException { | ||
// given | ||
CreateAllocation createAllocation = new CreateAllocation.Builder() | ||
.quantity(5.4) | ||
.memo("Recoding component purchase") | ||
.build(); | ||
|
||
// this creates an invoice in the "PENDING" status | ||
CLIENT.getSubscriptionComponentsController().allocateComponent( | ||
subscription.getId(), | ||
quantityBasedComponent.getId(), | ||
new CreateAllocationRequest(createAllocation) | ||
); | ||
|
||
Invoice pendingInvoice = INVOICES_CONTROLLER | ||
.listInvoices(new ListInvoicesInput.Builder().status(InvoiceStatus.PENDING).build()) | ||
.getInvoices() | ||
.get(0); | ||
|
||
// when | ||
Invoice issuedInvoice = INVOICES_CONTROLLER.issueInvoice( | ||
pendingInvoice.getUid(), | ||
new IssueInvoiceRequest(FailedPaymentAction.LEAVE_OPEN_INVOICE) | ||
); | ||
|
||
// then | ||
assertThat(issuedInvoice.getUid()).isEqualTo(pendingInvoice.getUid()); | ||
assertThat(issuedInvoice.getSiteId()).isNotNull(); | ||
assertThat(issuedInvoice.getCustomerId()).isEqualTo(customer.getId()); | ||
assertThat(issuedInvoice.getSubscriptionId()).isEqualTo(subscription.getId()); | ||
assertThat(issuedInvoice.getNumber()).isNotNull(); | ||
assertThat(issuedInvoice.getSequenceNumber()).isNotNull(); | ||
assertThat(issuedInvoice.getCreatedAt()).isNotNull(); | ||
assertThat(issuedInvoice.getUpdatedAt()).isNotNull(); | ||
assertThat(issuedInvoice.getIssueDate()).isEqualTo(LocalDate.now()); | ||
assertThat(issuedInvoice.getDueDate()).isNotNull(); | ||
assertThat(issuedInvoice.getPaidDate()).isEqualTo(LocalDate.now()); | ||
assertThat(issuedInvoice.getStatus()).isEqualTo(InvoiceStatus.PAID); | ||
assertThat(issuedInvoice.getCollectionMethod()).isEqualTo("automatic"); | ||
assertThat(issuedInvoice.getPaymentInstructions()).isBlank(); | ||
assertThat(issuedInvoice.getCurrency()).isEqualTo("USD"); | ||
assertThat(issuedInvoice.getConsolidationLevel()).isEqualTo(InvoiceConsolidationLevel.NONE); | ||
assertThat(issuedInvoice.getParentInvoiceId()).isNull(); | ||
assertThat(issuedInvoice.getParentInvoiceNumber()).isNull(); | ||
assertThat(issuedInvoice.getGroupPrimarySubscriptionId()).isNull(); | ||
assertThat(issuedInvoice.getProductName()).isEqualTo(product.getName()); | ||
assertThat(issuedInvoice.getProductFamilyName()).isEqualTo(product.getProductFamily().getName()); | ||
assertThat(issuedInvoice.getRole()).isEqualTo("renewal"); | ||
|
||
InvoiceSeller invoiceSeller = issuedInvoice.getSeller(); | ||
InvoiceAddress sellerAddress = invoiceSeller.getAddress(); | ||
assertAll( | ||
() -> assertThat(invoiceSeller).isNotNull(), | ||
() -> assertThat(invoiceSeller.getName()).isEqualTo("Developer Experience"), | ||
() -> assertThat(sellerAddress).isNotNull(), | ||
() -> assertThat(sellerAddress.getStreet()).isEqualTo("Asdf Street"), | ||
() -> assertThat(sellerAddress.getLine2()).isEqualTo("123/444"), | ||
() -> assertThat(sellerAddress.getCity()).isEqualTo("San Antonio"), | ||
() -> assertThat(sellerAddress.getState()).isEqualTo("TX"), | ||
() -> assertThat(sellerAddress.getZip()).isEqualTo("78015"), | ||
() -> assertThat(sellerAddress.getCountry()).isEqualTo("US"), | ||
() -> assertThat(invoiceSeller.getPhone()).isEqualTo("555 111 222") | ||
); | ||
|
||
InvoiceCustomer invoiceCustomer = issuedInvoice.getCustomer(); | ||
assertAll( | ||
() -> assertThat(invoiceCustomer).isNotNull(), | ||
() -> assertThat(invoiceCustomer.getChargifyId()).isEqualTo(customer.getId()), | ||
() -> assertThat(invoiceCustomer.getFirstName()).isEqualTo(customer.getFirstName()), | ||
() -> assertThat(invoiceCustomer.getLastName()).isEqualTo(customer.getLastName()), | ||
() -> assertThat(invoiceCustomer.getOrganization()).isEqualTo(customer.getOrganization()), | ||
() -> assertThat(invoiceCustomer.getEmail()).isEqualTo(customer.getEmail()), | ||
() -> assertThat(invoiceCustomer.getVatNumber()).isNull(), | ||
() -> assertThat(invoiceCustomer.getReference()).isEqualTo(customer.getReference()) | ||
); | ||
|
||
assertThat(issuedInvoice.getMemo()).isBlank(); | ||
|
||
InvoiceAddress invoiceBillingAddress = issuedInvoice.getBillingAddress(); | ||
assertAll( | ||
() -> assertThat(invoiceBillingAddress).isNotNull(), | ||
() -> assertThat(invoiceBillingAddress.getStreet()).isEqualTo("My Billing Address"), | ||
() -> assertThat(invoiceBillingAddress.getLine2()).isNull(), | ||
() -> assertThat(invoiceBillingAddress.getCity()).isEqualTo("New York"), | ||
() -> assertThat(invoiceBillingAddress.getState()).isEqualTo("NY"), | ||
() -> assertThat(invoiceBillingAddress.getZip()).isEqualTo("10001"), | ||
() -> assertThat(invoiceBillingAddress.getCountry()).isEqualTo("USA") | ||
); | ||
|
||
InvoiceAddress invoiceShippingAddress = issuedInvoice.getShippingAddress(); | ||
assertAll( | ||
() -> assertThat(invoiceShippingAddress).isNotNull(), | ||
() -> assertThat(invoiceShippingAddress.getStreet()).isEqualTo(customer.getAddress()), | ||
() -> assertThat(invoiceShippingAddress.getLine2()).isEqualTo(customer.getAddress2()), | ||
() -> assertThat(invoiceShippingAddress.getCity()).isEqualTo("New York"), | ||
() -> assertThat(invoiceShippingAddress.getState()).isEqualTo("NY"), | ||
() -> assertThat(invoiceShippingAddress.getZip()).isEqualTo("111-11"), | ||
() -> assertThat(invoiceShippingAddress.getCountry()).isEqualTo("USA") | ||
); | ||
|
||
assertThat(issuedInvoice.getSubtotalAmount()).isEqualTo("5.4"); | ||
assertThat(issuedInvoice.getDiscountAmount()).isEqualTo("0.0"); | ||
assertThat(issuedInvoice.getTaxAmount()).isEqualTo("0.0"); | ||
assertThat(issuedInvoice.getTotalAmount()).isEqualTo("5.4"); | ||
assertThat(issuedInvoice.getCreditAmount()).isEqualTo("0.0"); | ||
assertThat(issuedInvoice.getRefundAmount()).isEqualTo("0.0"); | ||
assertThat(issuedInvoice.getPaidAmount()).isEqualTo("5.4"); | ||
assertThat(issuedInvoice.getDueAmount()).isEqualTo("0.0"); | ||
|
||
assertThat(issuedInvoice.getLineItems()) | ||
.hasSize(1) | ||
.usingRecursiveFieldByFieldElementComparatorIgnoringFields("uid", "description") | ||
.containsExactly( | ||
new InvoiceLineItem.Builder() | ||
.title("%s: 0.0 to 5.4 units".formatted(quantityBasedComponent.getName())) | ||
.quantity("5.4") | ||
.unitPrice("1.0") | ||
.subtotalAmount("5.4") | ||
.discountAmount("0.0") | ||
.taxAmount("0.0") | ||
.totalAmount("5.4") | ||
.tieredUnitPrice(false) | ||
.periodRangeStart(LocalDate.now().toString()) | ||
.periodRangeEnd(LocalDate.now().plusMonths(1).toString()) | ||
.productId(product.getId()) | ||
.productVersion(1) | ||
.productPricePointId(product.getProductPricePointId()) | ||
.componentId(quantityBasedComponent.getId()) | ||
.pricePointId(quantityBasedComponent.getDefaultPricePointId()) | ||
.customItem(false) | ||
.build() | ||
); | ||
|
||
assertThat(issuedInvoice.getDiscounts()).isNotNull().isEmpty(); | ||
assertThat(issuedInvoice.getTaxes()).isNotNull().isEmpty(); | ||
assertThat(issuedInvoice.getCredits()).isNotNull().isEmpty(); | ||
|
||
assertThat(issuedInvoice.getPayments()) | ||
.hasSize(1) | ||
.usingRecursiveFieldByFieldElementComparatorIgnoringFields("uid", "transactionTime", "transactionId", "gatewayTransactionId") | ||
.containsExactly(new InvoicePayment.Builder() | ||
.memo("%s %s - %s: Renewal payment".formatted(customer.getFirstName(), customer.getLastName(), product.getName())) | ||
.originalAmount("5.4") | ||
.appliedAmount("5.4") | ||
.paymentMethod(new InvoicePaymentMethod.Builder() | ||
.cardBrand("visa") | ||
.cardExpiration("05/2050") | ||
.lastFour(null) | ||
.maskedCardNumber("XXXX-XXXX-XXXX-1111") | ||
.type("credit_card") | ||
.build() | ||
) | ||
.prepayment(false) | ||
.gatewayUsed("bogus") | ||
.gatewayHandle(null) | ||
.build() | ||
); | ||
|
||
assertThat(issuedInvoice.getRefunds()).isNotNull().isEmpty(); | ||
assertThat(issuedInvoice.getCustomFields()).isNotNull().isEmpty(); | ||
|
||
InvoicePreviousBalance previousBalanceData = issuedInvoice.getPreviousBalanceData(); | ||
assertThat(previousBalanceData).isNotNull(); | ||
assertThat(previousBalanceData.getCapturedAt()).isNotNull(); | ||
assertThat(previousBalanceData.getInvoices()) | ||
.hasSize(1) | ||
.usingRecursiveFieldByFieldElementComparator() | ||
.containsExactly(new InvoiceBalanceItem.Builder() | ||
.uid(openInvoice.getUid()) | ||
.number(openInvoice.getNumber()) | ||
.outstandingAmount(openInvoice.getDueAmount()) | ||
.build() | ||
); | ||
|
||
assertThat(issuedInvoice.getPublicUrl()).isNotNull().isNotBlank(); | ||
} | ||
|
||
@ParameterizedTest | ||
@MethodSource("argsForShouldReturn422WhenIssuingInvoiceWithIncorrectStatus") | ||
void shouldReturn422WhenIssuingInvoiceWithIncorrectStatus(String invoiceUid) { | ||
// when - then | ||
CommonAssertions | ||
.assertThatErrorListResponse(() -> INVOICES_CONTROLLER.issueInvoice(invoiceUid, new IssueInvoiceRequest())) | ||
.isUnprocessableEntity() | ||
.hasErrors("Invoice must have 'pending' status"); | ||
} | ||
|
||
private static Stream<Arguments> argsForShouldReturn422WhenIssuingInvoiceWithIncorrectStatus() { | ||
return Stream.of( | ||
Arguments.arguments(paidInvoice.getUid()), | ||
Arguments.arguments(openInvoice.getUid()) | ||
); | ||
} | ||
|
||
@Test | ||
void shouldReturn404WhenIssuingNotExistentInvoice() { | ||
// when - then | ||
CommonAssertions.assertNotFound( | ||
() -> INVOICES_CONTROLLER.issueInvoice("123", new IssueInvoiceRequest(FailedPaymentAction.LEAVE_OPEN_INVOICE)), | ||
"Not Found" | ||
); | ||
} | ||
|
||
@Test | ||
void shouldReturn401WhenProvidingInvalidCredentials() { | ||
// when - then | ||
CommonAssertions.assertUnauthorized( | ||
() -> TestClient.createInvalidCredentialsClient().getInvoicesController().issueInvoice("123", null), | ||
"Unauthorized" | ||
); | ||
} | ||
} |