From 50cdc9941fdc8afacd832760a7d7a5f76ed1708b Mon Sep 17 00:00:00 2001 From: kmigielek Date: Tue, 23 Jan 2024 21:02:07 +0100 Subject: [PATCH] invoice tests --- .github/workflows/build.yml | 2 - test/api_test.go | 42 ++++++++++- test/helpers_test.go | 8 +- test/invoice_test.go | 146 ++++++++++++++++++++++++++++++++++++ 4 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 test/invoice_test.go diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 658f3b52..69b64d4b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,8 +5,6 @@ on: branches: - "main" pull_request: - branches: - - "main" env: TEST_API_KEY: ${{secrets.TEST_API_KEY}} diff --git a/test/api_test.go b/test/api_test.go index 21000c9e..db8501d1 100644 --- a/test/api_test.go +++ b/test/api_test.go @@ -1,11 +1,14 @@ package test import ( + "math/rand" "testing" + "time" "github.com/caarlos0/env/v10" "github.com/jaswdr/faker" advancedbilling "github.com/maxio-com/ab-golang-sdk" + "github.com/maxio-com/ab-golang-sdk/models" "github.com/stretchr/testify/suite" ) @@ -22,14 +25,33 @@ type APISuite struct { client advancedbilling.ClientInterface unauthorizedClient advancedbilling.ClientInterface + baseBillingAddress baseBillingAddress } -func TestAPITestSuite(t *testing.T) { +type baseBillingAddress struct { + firstName string + lastName string + phone string + address string + city string + state string + country string + zip string + card card +} + +type card struct { + expirationMonth int + expirationYear int + cardType models.CardType +} + +func TestAPISuite(t *testing.T) { suite.Run(t, new(APISuite)) } func (s *APISuite) SetupTest() { - s.fkr = faker.New() + s.fkr = faker.NewWithSeed(rand.NewSource(time.Now().Unix())) cfg := Config{} if err := env.Parse(&cfg); err != nil { @@ -50,4 +72,20 @@ func (s *APISuite) SetupTest() { s.client = advancedbilling.NewClient(config) s.unauthorizedClient = advancedbilling.NewClient(configUnauthorized) + + s.baseBillingAddress = baseBillingAddress{ + firstName: "Joe", + lastName: "Smith", + phone: "4111111111111111", + card: card{ + expirationMonth: int(time.Now().Month()), + expirationYear: time.Now().Year() + 1, + cardType: models.CardType_VISA, + }, + city: "Boston", + state: "MA", + address: "123 Mass Ave.", + country: "US", + zip: "02120", + } } diff --git a/test/helpers_test.go b/test/helpers_test.go index f3cbee24..a0751f68 100644 --- a/test/helpers_test.go +++ b/test/helpers_test.go @@ -37,7 +37,7 @@ func (s *APISuite) createCustomer(ctx context.Context) models.Customer { func (s *APISuite) createProductFamily(ctx context.Context) models.ProductFamily { resp, err := s.client.ProductFamiliesController().CreateProductFamily(ctx, &models.CreateProductFamilyRequest{ ProductFamily: models.CreateProductFamily{ - Name: strPtr(s.fkr.Company().Name()), + Name: strPtr(s.fkr.RandomStringWithLength(20)), }, }) @@ -50,7 +50,7 @@ func (s *APISuite) createProductFamily(ctx context.Context) models.ProductFamily func (s *APISuite) createProduct(ctx context.Context, productFamilyID int) models.Product { resp, err := s.client.ProductsController().CreateProduct(ctx, productFamilyID, &models.CreateOrUpdateProductRequest{ Product: models.CreateOrUpdateProduct{ - Name: s.fkr.RandomStringWithLength(30), + Name: s.fkr.RandomStringWithLength(20), Description: "Testable product", PriceInCents: 50, Interval: 1, @@ -158,6 +158,10 @@ func newDate() string { return fmt.Sprintf("%d-%d-%d", t.Year(), t.Month(), t.Day()) } +func dateFromTime(t time.Time) string { + return fmt.Sprintf("%d-%d-%d", t.Year(), t.Month(), t.Day()) +} + func timePtr(v time.Time) *time.Time { return &v } diff --git a/test/invoice_test.go b/test/invoice_test.go new file mode 100644 index 00000000..ea3989c4 --- /dev/null +++ b/test/invoice_test.go @@ -0,0 +1,146 @@ +package test + +import ( + "context" + "net/http" + "testing" + "time" + + "github.com/maxio-com/ab-golang-sdk/models" +) + +func (s *APISuite) TestInvoice() { + ctx := context.Background() + + customer := s.createCustomer(ctx) + productFamily := s.createProductFamily(ctx) + product := s.createProduct(ctx, *productFamily.Id) + coupon := s.createCoupon(ctx, *productFamily.Id) + + subscription := s.newSubscription(customer, product, "", []models.CreateSubscriptionComponent{}) + + sub, err := s.client.SubscriptionsController().CreateSubscription(ctx, &models.CreateSubscriptionRequest{Subscription: subscription}) + s.NoError(err) + s.Equal(http.StatusCreated, sub.Response.StatusCode) + + cases := []struct { + name string + assert func(t *testing.T, resp models.ApiResponse[models.InvoiceResponse], invoice models.CreateInvoice, err error) + invoice models.CreateInvoice + }{ + { + name: "valid", + invoice: models.CreateInvoice{ + Coupons: []models.CreateInvoiceCoupon{ + { + Code: coupon.Code, + }, + }, + LineItems: []models.CreateInvoiceItem{ + { + Title: strPtr("A product"), + Quantity: interfacePtr(12), + UnitPrice: interfacePtr("150"), + }, + }, + IssueDate: timePtr(time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)), + BillingAddress: &models.CreateInvoiceAddress{ + FirstName: &s.baseBillingAddress.firstName, + LastName: &s.baseBillingAddress.lastName, + Phone: &s.baseBillingAddress.phone, + Address: &s.baseBillingAddress.address, + Country: &s.baseBillingAddress.country, + Zip: &s.baseBillingAddress.zip, + City: &s.baseBillingAddress.city, + }, + }, + assert: func(t *testing.T, resp models.ApiResponse[models.InvoiceResponse], invoice models.CreateInvoice, err error) { + s.NoError(err) + s.Equal(http.StatusCreated, resp.Response.StatusCode) + + inv := resp.Data.Invoice + + s.Equal(s.baseBillingAddress.address, *inv.BillingAddress.Street.Value()) + s.Equal(s.baseBillingAddress.city, *inv.BillingAddress.City.Value()) + s.Equal(s.baseBillingAddress.country, *inv.BillingAddress.Country.Value()) + + s.Equal(customer.Id, inv.CustomerId) + s.Equal(customer.Email, inv.Customer.Email) + s.Equal(customer.FirstName, inv.Customer.FirstName) + s.Equal(customer.LastName, inv.Customer.LastName) + + s.Len(inv.Discounts, 1) + s.Equal(inv.Discounts[0].Code, coupon.Code) + + s.Len(inv.LineItems, 1) + + void, err := s.client.InvoicesController().VoidInvoice(ctx, *resp.Data.Invoice.Uid, &models.VoidInvoiceRequest{ + Void: models.VoidInvoice{Reason: "Duplicate invoice"}, + }) + + s.NoError(err) + s.Equal(http.StatusCreated, void.Response.StatusCode) + + events, err := s.client.InvoicesController().ListInvoiceEvents( + ctx, + nil, + nil, + nil, + nil, + resp.Data.Invoice.Uid, + nil, + nil, // cant pass event types here. Server throws 500 + ) + + s.NoError(err) + s.Equal(http.StatusOK, events.Response.StatusCode) + }, + }, + { + name: "invalid invoice", + invoice: models.CreateInvoice{ + Coupons: []models.CreateInvoiceCoupon{ + { + Code: coupon.Code, + }, + }, + LineItems: []models.CreateInvoiceItem{ + { + Title: strPtr("A product"), + Quantity: interfacePtr(12), + UnitPrice: interfacePtr("150"), + PeriodRangeStart: strPtr(dateFromTime(time.Now())), + PeriodRangeEnd: strPtr(dateFromTime(time.Now().AddDate(-1, 0, 0))), + }, + }, + IssueDate: timePtr(time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)), + BillingAddress: &models.CreateInvoiceAddress{ + FirstName: &s.baseBillingAddress.firstName, + LastName: &s.baseBillingAddress.lastName, + Phone: &s.baseBillingAddress.phone, + Address: &s.baseBillingAddress.address, + Country: &s.baseBillingAddress.country, + Zip: &s.baseBillingAddress.zip, + City: &s.baseBillingAddress.city, + }, + }, + assert: func(t *testing.T, resp models.ApiResponse[models.InvoiceResponse], invoice models.CreateInvoice, err error) { + // s.Equal(err.Error(), errors.NewNestedErrorResponse(422, "Unprocessable Entity (WebDAV)").Error()) // not able to reat nested error messages here + s.Equal(http.StatusUnprocessableEntity, resp.Response.StatusCode) + }, + }, + } + + for _, c := range cases { + s.T().Run(c.name, func(t *testing.T) { + resp, err := s.client.InvoicesController().CreateInvoice( + ctx, + *sub.Data.Subscription.Id, + &models.CreateInvoiceRequest{ + Invoice: c.invoice, + }) + + c.assert(t, resp, c.invoice, err) + }) + } +}