func createSubItem(t *testing.T) (*stripe.Sub, *stripe.SubItem, func()) { customerParams := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Card: &stripe.CardParams{ Number: "378282246310005", Month: "06", Year: "20", }, }, } cust, err := customer.New(customerParams) if err != nil { t.Fatalf("customer creation: %s", err) } planID := fmt.Sprintf("test-%d", rand.Int63()) planParams := &stripe.PlanParams{ ID: planID, Name: "Test Plan", Amount: 99, Currency: currency.USD, Interval: plan.Month, } p, err := plan.New(planParams) if err != nil { t.Fatalf("plan creation: %s", err) } subParams := &stripe.SubParams{ Customer: cust.ID, Items: []*stripe.SubItemsParams{ { Plan: p.ID, Quantity: 1, }, }, } target, err := sub.New(subParams) if err != nil { t.Fatalf("subscription creation: %s", err) } if target.Items == nil { t.Fatalf("no items for sub %s", target.ID) } if len(target.Items.Values) != 1 { t.Fatalf("missing items: %#v", target) } return target, target.Items.Values[0], func() { sub.Cancel(target.ID, nil) plan.Del(p.ID) customer.Del(cust.ID) } }
func TestSubscriptionNew(t *testing.T) { customerParams := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Card: &stripe.CardParams{ Number: "378282246310005", Month: "06", Year: "20", }, }, } cust, _ := customer.New(customerParams) planParams := &stripe.PlanParams{ ID: "test", Name: "Test Plan", Amount: 99, Currency: currency.USD, Interval: plan.Month, } plan.New(planParams) subParams := &stripe.SubParams{ Customer: cust.ID, Plan: "test", Quantity: 10, TaxPercent: 20.0, BillingCycleAnchor: time.Now().AddDate(0, 0, 12).Unix(), } target, err := New(subParams) if err != nil { t.Error(err) } if target.Plan.ID != subParams.Plan { t.Errorf("Plan %v does not match expected plan %v\n", target.Plan, subParams.Plan) } if target.Quantity != subParams.Quantity { t.Errorf("Quantity %v does not match expected quantity %v\n", target.Quantity, subParams.Quantity) } if target.TaxPercent != subParams.TaxPercent { t.Errorf("TaxPercent %f does not match expected TaxPercent %f\n", target.TaxPercent, subParams.TaxPercent) } if target.PeriodEnd != subParams.BillingCycleAnchor { t.Errorf("PeriodEnd %v does not match expected BillingCycleAnchor %v\n", target.PeriodEnd, subParams.BillingCycleAnchor) } customer.Del(cust.ID) plan.Del("test") }
func TestSubscriptionUpdate(t *testing.T) { customerParams := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Card: &stripe.CardParams{ Number: "378282246310005", Month: "06", Year: "20", }, }, } cust, _ := customer.New(customerParams) planParams := &stripe.PlanParams{ ID: "test", Name: "Test Plan", Amount: 99, Currency: currency.USD, Interval: plan.Month, } plan.New(planParams) subParams := &stripe.SubParams{ Customer: cust.ID, Plan: "test", Quantity: 10, TrialEndNow: true, } subscription, _ := New(subParams) updatedSub := &stripe.SubParams{ Customer: cust.ID, NoProrate: true, Quantity: 13, TaxPercent: 20.0, } target, err := Update(subscription.ID, updatedSub) if err != nil { t.Error(err) } if target.Quantity != updatedSub.Quantity { t.Errorf("Quantity %v does not match expected quantity %v\n", target.Quantity, updatedSub.Quantity) } if target.TaxPercent != updatedSub.TaxPercent { t.Errorf("TaxPercent %f does not match expected tax_percent %f\n", target.TaxPercent, updatedSub.TaxPercent) } customer.Del(cust.ID) plan.Del("test") }
func TestSubscriptionCancel(t *testing.T) { customerParams := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Card: &stripe.CardParams{ Number: "378282246310005", Month: "06", Year: "20", }, }, } cust, _ := customer.New(customerParams) planParams := &stripe.PlanParams{ ID: "test", Name: "Test Plan", Amount: 99, Currency: currency.USD, Interval: plan.Month, } plan.New(planParams) subParams := &stripe.SubParams{ Customer: cust.ID, Plan: "test", Quantity: 10, } subscription, _ := New(subParams) s, err := Cancel(subscription.ID, nil) if err != nil { t.Error(err) } if s.Canceled == 0 { t.Errorf("Subscription.Canceled %v expected to be non 0\n", s.Canceled) } subscription, _ = New(subParams) s, err = Cancel(subscription.ID, &stripe.SubParams{Customer: cust.ID}) if err != nil { t.Error(err) } if s.Canceled == 0 { t.Errorf("Subscription.Canceled %v expected to be non 0\n", s.Canceled) } customer.Del(cust.ID) plan.Del("test") }
// make sure we can subscribe to 7 days-free plan with more trial period func TestSubscribingToPaidPlanWithWithDifferentTrialPeriodThanDefault(t *testing.T) { Convey("Given stub data", t, func() { withTestServer(t, func(endpoint string) { withStubData(endpoint, func(username, groupName, sessionID string) { pp := &stripe.PlanParams{ Amount: 12345, Interval: stripeplan.Month, IntervalCount: 1, TrialPeriod: 1, // trial for one day Name: fmt.Sprintf("plan for %s", username), Currency: currency.USD, ID: fmt.Sprintf("plan_for_%s", username), Statement: "NAN-FREE", } plan, err := stripeplan.New(pp) So(err, ShouldBeNil) addCreditCardToUserWithChecks(endpoint, sessionID) createURL := endpoint + EndpointSubscriptionCreate deleteURL := endpoint + EndpointSubscriptionCancel group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) req, err := json.Marshal(&stripe.SubParams{ Customer: group.Payment.Customer.ID, Plan: plan.ID, TrialEnd: time.Now().Add(time.Hour * 48).Unix(), }) tests.ResultedWithNoErrorCheck(req, err) sub, err := rest.DoRequestWithAuth("POST", createURL, req, sessionID) tests.ResultedWithNoErrorCheck(sub, err) v := &stripe.Sub{} err = json.Unmarshal(sub, v) So(err, ShouldBeNil) So(v.TrialEnd, ShouldBeGreaterThan, time.Now().Add(time.Hour*24*time.Duration(pp.TrialPeriod)).Unix()) Convey("We should be able to cancel the subscription", func() { res, err := rest.DoRequestWithAuth("DELETE", deleteURL, req, sessionID) tests.ResultedWithNoErrorCheck(res, err) v := &stripe.Sub{} err = json.Unmarshal(res, v) So(err, ShouldBeNil) So(v.Status, ShouldEqual, "canceled") }) }) }) }) }
func TestSubscriptionGet(t *testing.T) { customerParams := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Card: &stripe.CardParams{ Number: "378282246310005", Month: "06", Year: "20", }, }, } cust, _ := customer.New(customerParams) planParams := &stripe.PlanParams{ ID: "test", Name: "Test Plan", Amount: 99, Currency: currency.USD, Interval: plan.Month, } plan.New(planParams) subParams := &stripe.SubParams{ Customer: cust.ID, Plan: "test", Quantity: 10, } subscription, _ := New(subParams) target, err := Get(subscription.ID, nil) if err != nil { t.Error(err) } if target.ID != subscription.ID { t.Errorf("Subscription id %q does not match expected id %q\n", target.ID, subscription.ID) } target, err = Get(subscription.ID, &stripe.SubParams{Customer: cust.ID}) if err != nil { t.Error(err) } if target.ID != subscription.ID { t.Errorf("Subscription id %q does not match expected id %q\n", target.ID, subscription.ID) } customer.Del(cust.ID) plan.Del("test") }
func TestSubscriptionZeroQuantity(t *testing.T) { customerParams := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Card: &stripe.CardParams{ Number: "378282246310005", Month: "06", Year: "20", }, }, } cust, _ := customer.New(customerParams) planParams := &stripe.PlanParams{ ID: "test", Name: "Test Plan", Amount: 99, Currency: currency.USD, Interval: plan.Month, } plan.New(planParams) subParams := &stripe.SubParams{ Customer: cust.ID, Plan: "test", QuantityZero: true, TaxPercentZero: true, } target, err := New(subParams) if err != nil { t.Error(err) } if target.Plan.ID != subParams.Plan { t.Errorf("Plan %v does not match expected plan %v\n", target.Plan, subParams.Plan) } if target.Quantity != 0 { t.Errorf("Quantity %v does not match expected quantity %v\n", target.Quantity, 0) } if target.TaxPercent != 0 { t.Errorf("Tax percent %v does not match expected tax percent %v\n", target.TaxPercent, 0) } customer.Del(cust.ID) plan.Del("test") }
func TestSubscriptionList(t *testing.T) { customerParams := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Card: &stripe.CardParams{ Number: "378282246310005", Month: "06", Year: "20", }, }, } cust, _ := customer.New(customerParams) planParams := &stripe.PlanParams{ ID: "test", Name: "Test Plan", Amount: 99, Currency: currency.USD, Interval: plan.Month, } plan.New(planParams) subParams := &stripe.SubParams{ Customer: cust.ID, Plan: "test", Quantity: 10, } for i := 0; i < 5; i++ { New(subParams) } i := List(&stripe.SubListParams{Customer: cust.ID}) for i.Next() { if i.Sub() == nil { t.Error("No nil values expected") } if i.Meta() == nil { t.Error("No metadata returned") } } if err := i.Err(); err != nil { t.Error(err) } customer.Del(cust.ID) plan.Del("test") }
// EnsurePlan makes sure plan is in stripe func EnsurePlan(planParams *stripe.PlanParams) error { p, err := stripeplan.Get(planParams.ID, nil) if err == nil && p != nil && p.ID == planParams.ID { return nil } stripeErr, ok := err.(*stripe.Error) if !ok { return err } if stripeErr.Type != stripe.ErrorTypeInvalidRequest { return err } _, err = stripeplan.New(planParams) return err }
func withTrialTestPlan(f func(planID string)) { pp := &stripe.PlanParams{ Amount: 10, Interval: plan.Month, IntervalCount: 1, TrialPeriod: 1, Name: "Trailing 10", Currency: currency.USD, ID: fmt.Sprintf("p_%s", bson.NewObjectId().Hex()), Statement: "Trailing 10", } _, err := plan.New(pp) So(err, ShouldBeNil) f(pp.ID) _, err = plan.Del(pp.ID) So(err, ShouldBeNil) }
func withNonFreeTestPlan(f func(planID string)) { pp := &stripe.PlanParams{ Amount: 12345, Interval: plan.Month, IntervalCount: 1, TrialPeriod: 0, Name: "If only that much free", Currency: currency.USD, ID: "p_" + bson.NewObjectId().Hex(), Statement: "NAN-FREE", } _, err := plan.New(pp) So(err, ShouldBeNil) f(pp.ID) _, err = plan.Del(pp.ID) So(err, ShouldBeNil) }
func TestListItems(t *testing.T) { sub, _, cleanup := createSubItem(t) defer cleanup() // Create a new plan planID := fmt.Sprintf("test-%d", rand.Int63()) planParams := &stripe.PlanParams{ ID: planID, Name: "Expensive plan", Amount: 1000, Currency: currency.USD, Interval: plan.Month, } p, err := plan.New(planParams) if err != nil { t.Fatal(err) } defer plan.Del(p.ID) item, err := New(&stripe.SubItemParams{ Sub: sub.ID, Plan: p.ID, Quantity: 2, }) if err != nil { t.Errorf("new err: %s", err) } if item.Quantity != 2 { t.Errorf("quantity should be 2 after update, not %d", item.Quantity) } if item.ID != "" { item, err := Del(item.ID, nil) if err != nil { t.Errorf("del err: %s", err) } if !item.Deleted { t.Errorf("item should be deleted %#v", item) } } }
func TestCustomerNewWithPlan(t *testing.T) { planParams := &stripe.PlanParams{ ID: "test", Name: "Test Plan", Amount: 99, Currency: currency.USD, Interval: plan.Month, } _, err := plan.New(planParams) if err != nil { t.Error(err) } customerParams := &stripe.CustomerParams{ Plan: planParams.ID, TaxPercent: 10.0, } customerParams.SetSource(&stripe.CardParams{ Name: "Test Card", Number: "378282246310005", Month: "06", Year: "20", }) target, err := New(customerParams) if err != nil { t.Error(err) } _, err = Del(target.ID) if err != nil { t.Error(err) } _, err = plan.Del(planParams.ID) if err != nil { t.Error(err) } }
func TestInvoiceCreatedHandlerDowngradePlan(t *testing.T) { testData := ` { "id": "in_00000000000000", "object": "invoice", "amount_due": 0, "application_fee": null, "attempt_count": 0, "attempted": false, "charge": null, "closed": false, "currency": "usd", "customer": "%s", "date": 1471348722, "description": null, "discount": null, "ending_balance": 0, "forgiven": false, "livemode": false, "metadata": {}, "next_payment_attempt": null, "paid": false, "period_end": 1471348722, "period_start": 1471348722, "receipt_number": null, "starting_balance": 0, "statement_descriptor": null, "subscription": "%s", "subtotal": %d, "tax": null, "tax_percent": null, "total": %d, "webhooks_delivered_at": 1471348722 }` tests.WithConfiguration(t, func(c *config.Config) { stripe.Key = c.Stripe.SecretToken Convey("Given stub data", t, func() { withStubData(func(username, groupName, sessionID string) { group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) withTestCreditCardToken(func(token string) { // attach payment source cp := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Token: token, }, } c, err := UpdateCustomerForGroup(username, groupName, cp) tests.ResultedWithNoErrorCheck(c, err) const totalMembers = 9 generateAndAddMembersToGroup(group.Slug, totalMembers) // create test plan id := "p_" + bson.NewObjectId().Hex() pp := &stripe.PlanParams{ Amount: Plans[UpTo50Users].Amount, Interval: plan.Month, IntervalCount: 1, TrialPeriod: 0, Name: id, Currency: currency.USD, ID: id, } p, err := plan.New(pp) So(err, ShouldBeNil) // subscribe to test plan with more than actual number, simulating having 11 members previous month var extraneousCount uint64 = uint64(totalMembers) + 2 params := &stripe.SubParams{ Customer: group.Payment.Customer.ID, Plan: p.ID, Quantity: extraneousCount, } sub, err := EnsureSubscriptionForGroup(group.Slug, params) tests.ResultedWithNoErrorCheck(sub, err) // check if group has correct sub id groupAfterSub, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(groupAfterSub, err) So(sub.ID, ShouldEqual, groupAfterSub.Payment.Subscription.ID) Convey("When invoice.created is triggered with previous plan's amount", func() { raw := []byte(fmt.Sprintf( testData, group.Payment.Customer.ID, sub.ID, Plans[UpTo10Users].Amount*extraneousCount, Plans[UpTo10Users].Amount*extraneousCount, )) So(invoiceCreatedHandler(raw), ShouldBeNil) Convey("subscription id should not stay same", func() { groupAfterHook, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(groupAfterHook, err) // group should have correct sub id So(sub.ID, ShouldNotEqual, groupAfterHook.Payment.Subscription.ID) sub, err := GetSubscriptionForGroup(groupName) tests.ResultedWithNoErrorCheck(sub, err) So(sub.Plan.ID, ShouldEqual, UpTo10Users) count, err := (&models.PresenceDaily{}).CountDistinctByGroupName(group.Slug) So(err, ShouldBeNil) So(count, ShouldEqual, 0) Convey("we should clean up successfully", func() { sub, err := DeleteSubscriptionForGroup(group.Slug) tests.ResultedWithNoErrorCheck(sub, err) _, err = plan.Del(pp.ID) So(err, ShouldBeNil) }) }) }) }) }) }) }) }
func TestAtTheEndOfTrialPeriodSubscriptionStatusIsStillTrialing(t *testing.T) { Convey("Given stub data", t, func() { withTestServer(t, func(endpoint string) { withStubData(endpoint, func(username, groupName, sessionID string) { withTestCreditCardToken(func(token string) { req, err := json.Marshal(&stripe.CustomerParams{ Source: &stripe.SourceParams{ Token: token, }, }) tests.ResultedWithNoErrorCheck(req, err) res, err := rest.DoRequestWithAuth( "POST", endpoint+EndpointCustomerUpdate, req, sessionID, ) tests.ResultedWithNoErrorCheck(res, err) createURL := endpoint + EndpointSubscriptionCreate group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) pp := &stripe.PlanParams{ Amount: 12345, Interval: stripeplan.Month, IntervalCount: 1, TrialPeriod: 1, // trial for one day Name: fmt.Sprintf("plan for %s", username), Currency: currency.USD, ID: fmt.Sprintf("plan_for_%s", username), Statement: "NAN-FREE", } plan, err := stripeplan.New(pp) So(err, ShouldBeNil) defer stripeplan.Del(plan.ID) req, err = json.Marshal(&stripe.SubParams{ Customer: group.Payment.Customer.ID, Plan: plan.ID, }) tests.ResultedWithNoErrorCheck(req, err) res, err = rest.DoRequestWithAuth("POST", createURL, req, sessionID) tests.ResultedWithNoErrorCheck(res, err) sub := &stripe.Sub{} err = json.Unmarshal(res, sub) So(err, ShouldBeNil) subParams := &stripe.SubParams{ Customer: group.Payment.Customer.ID, Plan: plan.ID, TrialEnd: time.Now().UTC().Add(time.Second * 60 * 5).Unix(), } sub, err = stripesub.Update(sub.ID, subParams) tests.ResultedWithNoErrorCheck(sub, err) sub, err = stripesub.Get(sub.ID, nil) tests.ResultedWithNoErrorCheck(sub, err) So(sub.Status, ShouldEqual, "trialing") }) }) }) }) }
// Invoices are somewhat painful to test since you need // to first have some items, so test everything together to // avoid unnecessary duplication func TestAllInvoicesScenarios(t *testing.T) { customerParams := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Card: &stripe.CardParams{ Number: "378282246310005", Month: "06", Year: "20", }, }, } cust, _ := customer.New(customerParams) item := &stripe.InvoiceItemParams{ Customer: cust.ID, Amount: 100, Currency: currency.USD, Desc: "Test Item", } targetItem, err := invoiceitem.New(item) if err != nil { t.Error(err) } if targetItem.Customer.ID != item.Customer { t.Errorf("Item customer %q does not match expected customer %q\n", targetItem.Customer.ID, item.Customer) } if targetItem.Desc != item.Desc { t.Errorf("Item description %q does not match expected description %q\n", targetItem.Desc, item.Desc) } if targetItem.Amount != item.Amount { t.Errorf("Item amount %v does not match expected amount %v\n", targetItem.Amount, item.Amount) } if targetItem.Currency != item.Currency { t.Errorf("Item currency %q does not match expected currency %q\n", targetItem.Currency, item.Currency) } if targetItem.Date == 0 { t.Errorf("Item date is not set\n") } invoiceParams := &stripe.InvoiceParams{ Customer: cust.ID, Desc: "Desc", Statement: "Statement", TaxPercent: 20.0, } targetInvoice, err := New(invoiceParams) if err != nil { t.Error(err) } if targetInvoice.Customer.ID != invoiceParams.Customer { t.Errorf("Invoice customer %q does not match expected customer %q\n", targetInvoice.Customer.ID, invoiceParams.Customer) } if targetInvoice.TaxPercent != invoiceParams.TaxPercent { t.Errorf("Invoice tax percent %f does not match expected tax percent %f\n", targetInvoice.TaxPercent, invoiceParams.TaxPercent) } if targetInvoice.Tax != 20 { t.Errorf("Invoice tax %v does not match expected tax 20\n", targetInvoice.Tax) } if targetInvoice.Amount != targetItem.Amount+targetInvoice.Tax { t.Errorf("Invoice amount %v does not match expected amount %v + tax %v\n", targetInvoice.Amount, targetItem.Amount, targetInvoice.Tax) } if targetInvoice.Currency != targetItem.Currency { t.Errorf("Invoice currency %q does not match expected currency %q\n", targetInvoice.Currency, targetItem.Currency) } if targetInvoice.Date == 0 { t.Errorf("Invoice date is not set\n") } if targetInvoice.Start == 0 { t.Errorf("Invoice start is not set\n") } if targetInvoice.End == 0 { t.Errorf("Invoice end is not set\n") } if targetInvoice.Total != targetInvoice.Amount || targetInvoice.Subtotal != targetInvoice.Amount-targetInvoice.Tax { t.Errorf("Invoice total %v and subtotal %v do not match expected amount %v\n", targetInvoice.Total, targetInvoice.Subtotal, targetInvoice.Amount) } if targetInvoice.Desc != invoiceParams.Desc { t.Errorf("Invoice description %q does not match expected description %q\n", targetInvoice.Desc, invoiceParams.Desc) } if targetInvoice.Statement != invoiceParams.Statement { t.Errorf("Invoice statement %q does not match expected statement %q\n", targetInvoice.Statement, invoiceParams.Statement) } if targetInvoice.Lines == nil { t.Errorf("Invoice lines not found\n") } if targetInvoice.Lines.Count != 1 { t.Errorf("Invoice lines count %v does not match expected value\n", targetInvoice.Lines.Count) } if targetInvoice.Lines.Values == nil { t.Errorf("Invoice lines values not found\n") } if targetInvoice.Lines.Values[0].Amount != targetItem.Amount { t.Errorf("Invoice line amount %v does not match expected amount %v\n", targetInvoice.Lines.Values[0].Amount, targetItem.Amount) } if targetInvoice.Lines.Values[0].Currency != targetItem.Currency { t.Errorf("Invoice line currency %q does not match expected currency %q\n", targetInvoice.Lines.Values[0].Currency, targetItem.Currency) } if targetInvoice.Lines.Values[0].Desc != targetItem.Desc { t.Errorf("Invoice line description %q does not match expected description %q\n", targetInvoice.Lines.Values[0].Desc, targetItem.Desc) } if targetInvoice.Lines.Values[0].Type != TypeInvoiceItem { t.Errorf("Invoice line type %q does not match expected type\n", targetInvoice.Lines.Values[0].Type) } if targetInvoice.Lines.Values[0].Period == nil { t.Errorf("Invoice line period not found\n") } if targetInvoice.Lines.Values[0].Period.Start == 0 { t.Errorf("Invoice line period start is not set\n") } if targetInvoice.Lines.Values[0].Period.End == 0 { t.Errorf("Invoice line period end is not set\n") } updatedItem := &stripe.InvoiceItemParams{ Amount: 99, Desc: "Updated Desc", Discountable: true, } targetItemUpdated, err := invoiceitem.Update(targetItem.ID, updatedItem) if err != nil { t.Error(err) } if targetItemUpdated.Desc != updatedItem.Desc { t.Errorf("Updated item description %q does not match expected description %q\n", targetItemUpdated.Desc, updatedItem.Desc) } if targetItemUpdated.Amount != updatedItem.Amount { t.Errorf("Updated item amount %v does not match expected amount %v\n", targetItemUpdated.Amount, updatedItem.Amount) } if !targetItemUpdated.Discountable { t.Errorf("Updated item is not discountable") } updatedInvoice := &stripe.InvoiceParams{ Desc: "Updated Desc", Statement: "Updated", } targetInvoiceUpdated, err := Update(targetInvoice.ID, updatedInvoice) if err != nil { t.Error(err) } if targetInvoiceUpdated.Desc != updatedInvoice.Desc { t.Errorf("Updated invoice description %q does not match expected description %q\n", targetInvoiceUpdated.Desc, updatedInvoice.Desc) } if targetInvoiceUpdated.Statement != updatedInvoice.Statement { t.Errorf("Updated invoice statement %q does not match expected statement %q\n", targetInvoiceUpdated.Statement, updatedInvoice.Statement) } _, err = invoiceitem.Get(targetItem.ID, nil) if err != nil { t.Error(err) } ii := invoiceitem.List(&stripe.InvoiceItemListParams{Customer: cust.ID}) for ii.Next() { if ii.InvoiceItem() == nil { t.Error("No nil values expected") } if ii.Meta() == nil { t.Error("No metadata returned") } } if err := ii.Err(); err != nil { t.Error(err) } i := List(&stripe.InvoiceListParams{Customer: cust.ID}) for i.Next() { if i.Invoice() == nil { t.Error("No nil values expected") } if i.Meta() == nil { t.Error("No metadata returned") } } if err := i.Err(); err != nil { t.Error(err) } il := ListLines(&stripe.InvoiceLineListParams{ID: targetInvoice.ID, Customer: cust.ID}) for il.Next() { if il.InvoiceLine() == nil { t.Error("No nil values expected") } if il.Meta() == nil { t.Error("No metadata returned") } } if err := il.Err(); err != nil { t.Error(err) } iiDel, err := invoiceitem.Del(targetItem.ID) if err != nil { t.Error(err) } if !iiDel.Deleted { t.Errorf("Invoice Item id %q expected to be marked as deleted on the returned resource\n", iiDel.ID) } _, err = Get(targetInvoice.ID, nil) if err != nil { t.Error(err) } planParams := &stripe.PlanParams{ ID: "test", Name: "Test Plan", Amount: 99, Currency: currency.USD, Interval: plan.Month, } _, err = plan.New(planParams) if err != nil { t.Error(err) } subParams := &stripe.SubParams{ Customer: cust.ID, Plan: planParams.ID, Quantity: 10, TrialEndNow: true, } subscription, err := sub.New(subParams) if err != nil { t.Error(err) } nextParams := &stripe.InvoiceParams{ Customer: cust.ID, Sub: subscription.ID, SubPlan: planParams.ID, SubNoProrate: false, SubProrationDate: time.Now().AddDate(0, 0, 12).Unix(), SubQuantity: 1, SubTrialEnd: time.Now().AddDate(0, 0, 12).Unix(), } nextInvoice, err := GetNext(nextParams) if err != nil { t.Error(err) } if nextInvoice.Customer.ID != cust.ID { t.Errorf("Invoice customer %v does not match expected customer%v\n", nextInvoice.Customer.ID, cust.ID) } if nextInvoice.Sub != subscription.ID { t.Errorf("Invoice subscription %v does not match expected subscription%v\n", nextInvoice.Sub, subscription.ID) } closeInvoice := &stripe.InvoiceParams{ Closed: true, } targetInvoiceClosed, err := Update(targetInvoice.ID, closeInvoice) if err != nil { t.Error(err) } if targetInvoiceClosed.Closed != closeInvoice.Closed { t.Errorf("Invoice was not closed as expected and its value is %v", targetInvoiceClosed.Closed) } openInvoice := &stripe.InvoiceParams{ NoClosed: true, } targetInvoiceOpened, err := Update(targetInvoice.ID, openInvoice) if err != nil { t.Error(err) } if targetInvoiceOpened.Closed != false { t.Errorf("Invoice was not reponed as expected and its value is %v", targetInvoiceOpened.Closed) } _, err = plan.Del(planParams.ID) if err != nil { t.Error(err) } customer.Del(cust.ID) }
func TestSubscriptionDiscount(t *testing.T) { couponParams := &stripe.CouponParams{ Duration: coupon.Forever, ID: "sub_coupon", Percent: 99, } coupon.New(couponParams) customerParams := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Card: &stripe.CardParams{ Number: "378282246310005", Month: "06", Year: "20", }, }, } cust, _ := customer.New(customerParams) planParams := &stripe.PlanParams{ ID: "test", Name: "Test Plan", Amount: 99, Currency: currency.USD, Interval: plan.Month, } plan.New(planParams) subParams := &stripe.SubParams{ Customer: cust.ID, Plan: "test", Quantity: 10, Coupon: "sub_coupon", } target, err := New(subParams) if err != nil { t.Error(err) } if target.Discount == nil { t.Errorf("Discount not found, but one was expected\n") } if target.Discount.Coupon == nil { t.Errorf("Coupon not found, but one was expected\n") } if target.Discount.Coupon.ID != subParams.Coupon { t.Errorf("Coupon id %q does not match expected id %q\n", target.Discount.Coupon.ID, subParams.Coupon) } _, err = discount.DelSub(target.ID) if err != nil { t.Error(err) } target, err = Get(target.ID, nil) if err != nil { t.Error(err) } if target.Discount != nil { t.Errorf("A discount %v was found, but was expected to have been deleted\n", target.Discount) } customer.Del(cust.ID) plan.Del("test") coupon.Del("sub_coupon") }
func TestInvoiceCreatedHandlerCustomPlan(t *testing.T) { testData := ` { "closed": false, "paid": false, "customer": "%s" }` tests.WithConfiguration(t, func(c *config.Config) { stripe.Key = c.Stripe.SecretToken Convey("Given stub data", t, func() { withStubData(func(username, groupName, sessionID string) { group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) // create custom test plan id := "p_c_" + bson.NewObjectId().Hex() pp := &stripe.PlanParams{ Amount: Plans[UpTo10Users].Amount, Interval: plan.Month, IntervalCount: 1, TrialPeriod: 1, Name: id, Currency: currency.USD, ID: id, } p, err := plan.New(pp) So(err, ShouldBeNil) const totalMembers = 9 // subscribe to test plan params := &stripe.SubParams{ Customer: group.Payment.Customer.ID, Plan: p.ID, Quantity: totalMembers, } Convey("Even if we process customer with a custom plan we should require CC", func() { _, err := EnsureSubscriptionForGroup(group.Slug, params) So(err, ShouldEqual, ErrCustomerSourceNotExists) Convey("When custom plan holder has CC", func() { withTestCreditCardToken(func(token string) { // attach payment source cp := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Token: token, }, } c, err := UpdateCustomerForGroup(username, groupName, cp) tests.ResultedWithNoErrorCheck(c, err) Convey("We should be able to create subscription", func() { sub, err := EnsureSubscriptionForGroup(group.Slug, params) tests.ResultedWithNoErrorCheck(sub, err) // check if group has correct sub id groupAfterSub, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(groupAfterSub, err) So(sub.ID, ShouldEqual, groupAfterSub.Payment.Subscription.ID) Convey("When invoice.created is triggered with custom plan", func() { raw := []byte(fmt.Sprintf( testData, group.Payment.Customer.ID, )) err := invoiceCreatedHandler(raw) So(err, ShouldBeNil) Convey("subscription id should stay same", func() { groupAfterHook, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(groupAfterHook, err) // group should have correct sub id So(sub.ID, ShouldEqual, groupAfterHook.Payment.Subscription.ID) count, err := (&models.PresenceDaily{}).CountDistinctByGroupName(group.Slug) So(err, ShouldBeNil) So(count, ShouldEqual, 0) Convey("we should clean up successfully", func() { sub, err := DeleteSubscriptionForGroup(group.Slug) tests.ResultedWithNoErrorCheck(sub, err) _, err = plan.Del(pp.ID) So(err, ShouldBeNil) }) }) }) }) }) }) }) }) }) }) }
func TestInvoiceCreatedHandlerWithCouponAndAccountBalance(t *testing.T) { testData := ` { "id": "in_00000000000000", "object": "invoice", "amount_due": 0, "charge": null, "closed": false, "currency": "usd", "customer": "%s", "discount":{ "object": "discount", "coupon": { "id": "QtadvP4t", "object": "coupon", "amount_off": %d, "created": 1473113335, "currency": "usd", "duration": "once", "valid": true }, "customer": "cus_98mqDLgCNhwhIo", "end": null, "start": 1473113336, "subscription": null }, "date": 1471348722, "ending_balance": 0, "forgiven": false, "livemode": false, "metadata": {}, "next_payment_attempt": null, "paid": false, "period_end": 1471348722, "period_start": 1471348722, "receipt_number": null, "starting_balance": %d, "statement_descriptor": null, "subscription": "%s", "subtotal": %d, "tax": null, "tax_percent": null, "total": %d, "webhooks_delivered_at": 1471348722 }` tests.WithConfiguration(t, func(c *config.Config) { stripe.Key = c.Stripe.SecretToken Convey("Given stub data", t, func() { withStubData(func(username, groupName, sessionID string) { group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) // add credit card to the user withTestCreditCardToken(func(token string) { var offAmount uint64 = 100 var offBalance int64 = 200 withTestCoupon(offAmount, func(couponCode string) { // attach payment source cp := &stripe.CustomerParams{ // add our coupon Coupon: couponCode, // add some credit to user Balance: -offBalance, // add the CC Source: &stripe.SourceParams{ Token: token, }, } c, err := UpdateCustomerForGroup(username, groupName, cp) tests.ResultedWithNoErrorCheck(c, err) const totalMembers = 9 // generate 9 members with a total of 1 deleted user (also there is an admin) generateAndAddMembersToGroup(group.Slug, totalMembers) // create test plan id := "p_" + bson.NewObjectId().Hex() pp := &stripe.PlanParams{ Amount: Plans[UpTo10Users].Amount, Interval: plan.Month, IntervalCount: 1, TrialPeriod: 0, Name: id, Currency: currency.USD, ID: id, } p, err := plan.New(pp) So(err, ShouldBeNil) // subscribe to test plan params := &stripe.SubParams{ Customer: group.Payment.Customer.ID, Plan: p.ID, Quantity: totalMembers, } sub, err := EnsureSubscriptionForGroup(group.Slug, params) tests.ResultedWithNoErrorCheck(sub, err) // check if group has correct sub id groupAfterSub, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(groupAfterSub, err) So(sub.ID, ShouldEqual, groupAfterSub.Payment.Subscription.ID) Convey("When invoice.created is triggered with right amount of total fee", func() { totalDiscount := uint64(offBalance) + offAmount raw := []byte(fmt.Sprintf( testData, group.Payment.Customer.ID, offAmount, -offBalance, sub.ID, Plans[UpTo10Users].Amount*totalMembers, (Plans[UpTo10Users].Amount*totalMembers)-(totalDiscount), )) var capturedMails []*emailsender.Mail realMailSender := mailSender mailSender = func(m *emailsender.Mail) error { capturedMails = append(capturedMails, m) return nil } So(invoiceCreatedHandler(raw), ShouldBeNil) mailSender = realMailSender // this means we didnt change the subscription. So(len(capturedMails), ShouldEqual, 0) Convey("subscription id should stay same", func() { groupAfterHook, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(groupAfterHook, err) // group should have correct sub id So(sub.ID, ShouldEqual, groupAfterHook.Payment.Subscription.ID) count, err := (&models.PresenceDaily{}).CountDistinctByGroupName(group.Slug) So(err, ShouldBeNil) So(count, ShouldEqual, 0) Convey("we should clean up successfully", func() { sub, err := DeleteSubscriptionForGroup(group.Slug) tests.ResultedWithNoErrorCheck(sub, err) _, err = plan.Del(pp.ID) So(err, ShouldBeNil) }) }) }) }) }) }) }) }) }
func TestInvoiceCreatedHandlerUpgradePlan(t *testing.T) { testData := ` { "id": "in_00000000000000", "object": "invoice", "amount_due": 0, "application_fee": null, "attempt_count": 0, "attempted": false, "charge": null, "closed": false, "currency": "usd", "customer": "%s", "date": 1471348722, "description": null, "discount": null, "ending_balance": 0, "forgiven": false, "livemode": false, "metadata": {}, "next_payment_attempt": null, "paid": false, "period_end": 1471348722, "period_start": 1471348722, "receipt_number": null, "starting_balance": 0, "statement_descriptor": null, "subscription": "%s", "subtotal": %d, "tax": null, "tax_percent": null, "total": %d, "webhooks_delivered_at": 1471348722 }` tests.WithConfiguration(t, func(c *config.Config) { stripe.Key = c.Stripe.SecretToken Convey("Given stub data", t, func() { withStubData(func(username, groupName, sessionID string) { group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) withTestCreditCardToken(func(token string) { // attach payment source cp := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Token: token, }, } c, err := UpdateCustomerForGroup(username, groupName, cp) tests.ResultedWithNoErrorCheck(c, err) const totalMembers = 9 generateAndAddMembersToGroup(group.Slug, totalMembers) // create test plan id := "p_" + bson.NewObjectId().Hex() pp := &stripe.PlanParams{ Amount: Plans[UpTo10Users].Amount, Interval: plan.Month, IntervalCount: 1, TrialPeriod: 0, Name: id, Currency: currency.USD, ID: id, } p, err := plan.New(pp) So(err, ShouldBeNil) // subscribe to test plan params := &stripe.SubParams{ Customer: group.Payment.Customer.ID, Plan: p.ID, Quantity: totalMembers, } sub, err := EnsureSubscriptionForGroup(group.Slug, params) tests.ResultedWithNoErrorCheck(sub, err) // check if group has correct sub id groupAfterSub, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(groupAfterSub, err) So(sub.ID, ShouldEqual, groupAfterSub.Payment.Subscription.ID) // add 1 more user to force plan upgrade generateAndAddMembersToGroup(group.Slug, 1) Convey("When invoice.created is triggered with previous plan's amount", func() { raw := []byte(fmt.Sprintf( testData, group.Payment.Customer.ID, sub.ID, Plans[UpTo10Users].Amount*totalMembers, Plans[UpTo10Users].Amount*totalMembers, )) var capturedMails []*emailsender.Mail realMailSender := mailSender mailSender = func(m *emailsender.Mail) error { capturedMails = append(capturedMails, m) return nil } So(invoiceCreatedHandler(raw), ShouldBeNil) mailSender = realMailSender // check we are sending events on subscription change. So(len(capturedMails), ShouldEqual, 1) So(capturedMails[0].Subject, ShouldEqual, eventNameJoinedNewPricingTier) So(len(capturedMails[0].Properties.Options), ShouldBeGreaterThan, 1) oldPlanID := capturedMails[0].Properties.Options["oldPlanID"] newPlanID := capturedMails[0].Properties.Options["newPlanID"] So(oldPlanID, ShouldNotBeBlank) So(newPlanID, ShouldNotBeBlank) So(newPlanID, ShouldNotEqual, oldPlanID) Convey("subscription id should not stay same", func() { groupAfterHook, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(groupAfterHook, err) // group should have correct sub id So(sub.ID, ShouldNotEqual, groupAfterHook.Payment.Subscription.ID) sub, err := GetSubscriptionForGroup(groupName) tests.ResultedWithNoErrorCheck(sub, err) So(sub.Plan.ID, ShouldEqual, UpTo50Users) count, err := (&models.PresenceDaily{}).CountDistinctByGroupName(group.Slug) So(err, ShouldBeNil) So(count, ShouldEqual, 0) Convey("we should clean up successfully", func() { sub, err := DeleteSubscriptionForGroup(group.Slug) tests.ResultedWithNoErrorCheck(sub, err) _, err = plan.Del(pp.ID) So(err, ShouldBeNil) }) }) }) }) }) }) }) }