func TestCreateSubscription(t *testing.T) { Convey("Given stub data", t, func() { withTestServer(t, func(endpoint string) { withStubData(endpoint, func(username, groupName, sessionID string) { withTestPlan(func(planID string) { withTestCreditCardToken(func(token string) { updateURL := endpoint + EndpointCustomerUpdate cp := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Token: token, }, } req, err := json.Marshal(cp) tests.ResultedWithNoErrorCheck(req, err) res, err := rest.DoRequestWithAuth("POST", updateURL, req, sessionID) tests.ResultedWithNoErrorCheck(res, err) withSubscription(endpoint, groupName, sessionID, planID, func(subscriptionID string) { So(subscriptionID, ShouldNotBeEmpty) getURL := endpoint + EndpointSubscriptionGet res, err := rest.DoRequestWithAuth("GET", getURL, nil, sessionID) tests.ResultedWithNoErrorCheck(res, err) v := &stripe.Sub{} err = json.Unmarshal(res, v) So(err, ShouldBeNil) So(v.Status, ShouldEqual, "active") }) }) }) }) }) }) }
func TestPing(t *testing.T) { Convey("Given testing user & group", t, func() { withTestServer(t, func(endpoint string) { withStubData(endpoint, func(username, groupName, sessionID string) { Convey("We should be able to send the ping request to", func() { externalURL := endpoint + presence.EndpointPresencePing privateURL := endpoint + presence.EndpointPresencePingPrivate acc := &models.Account{} err := acc.ByNick(username) tests.ResultedWithNoErrorCheck(acc, err) Convey("external endpoint", func() { _, err := rest.DoRequestWithAuth("GET", externalURL, nil, sessionID) So(err, ShouldBeNil) pp := &presence.PrivatePing{ GroupName: groupName, Username: username, } req, err := json.Marshal(pp) tests.ResultedWithNoErrorCheck(req, err) Convey("internal endpoint without auth", func() { _, err := rest.DoRequestWithAuth("POST", privateURL, req, "") So(err, ShouldBeNil) }) }) }) }) }) }) }
func TestCreditCardAuthRetryFail(t *testing.T) { Convey("When a non subscribed user request for Auth", t, func() { withTestServer(t, func(endpoint string) { withTestCreditCardToken(func(token string) { testUsername := "******" testGroupName := "guests" ses, err := modelhelper.CreateSessionForAccount(testUsername, testGroupName) tests.ResultedWithNoErrorCheck(ses, err) cp := &stripe.ChargeParams{ Source: &stripe.SourceParams{ Token: token, }, Email: "*****@*****.**", } req, err := json.Marshal(cp) tests.ResultedWithNoErrorCheck(req, err) res, err := rest.DoRequestWithAuth("POST", endpoint+EndpointCreditCardAuth, req, ses.ClientId) So(err, ShouldBeNil) res, err = rest.DoRequestWithAuth("POST", endpoint+EndpointCreditCardAuth, req, ses.ClientId) So(err, ShouldNotBeNil) So(res, ShouldBeNil) }) }) }) }
func withSubscription(endpoint, groupName, sessionID, planID string, f func(subscriptionID string)) { createURL := endpoint + EndpointSubscriptionCreate deleteURL := endpoint + EndpointSubscriptionCancel group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) Convey("We should be able to create a subscription", func() { req, err := json.Marshal(&stripe.SubParams{ Customer: group.Payment.Customer.ID, Plan: planID, }) tests.ResultedWithNoErrorCheck(req, err) res, err := rest.DoRequestWithAuth("POST", createURL, req, sessionID) tests.ResultedWithNoErrorCheck(res, err) v := &stripe.Sub{} err = json.Unmarshal(res, v) So(err, ShouldBeNil) f(v.ID) 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") }) }) }
// 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 withStubData(endpoint string, f func(username string, groupName string, sessionID string)) { acc, _, groupName := models.CreateRandomGroupDataWithChecks() group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) err = modelhelper.MakeAdmin(bson.ObjectIdHex(acc.OldId), group.Id) So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(acc.Nick, groupName) tests.ResultedWithNoErrorCheck(ses, err) f(acc.Nick, groupName, ses.ClientId) }
func TestCreditCardInfoNotSubscribingMember(t *testing.T) { Convey("When a non subscribed user request to get CC", t, func() { withTestServer(t, func(endpoint string) { withStubData(endpoint, func(username, groupName, sessionID string) { group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) err = modelhelper.UpdateGroupPartial( modelhelper.Selector{"_id": group.Id}, modelhelper.Selector{ "$unset": modelhelper.Selector{"payment.customer.id": ""}, }, ) So(err, ShouldBeNil) Convey("Endpoint should return error", func() { _, err := rest.DoRequestWithAuth("GET", endpoint+EndpointCreditCardHas, nil, sessionID) So(err, ShouldNotBeNil) // set the customer id back becase test data callback requires it. err = modelhelper.UpdateGroupPartial( modelhelper.Selector{"_id": group.Id}, modelhelper.Selector{ "$set": modelhelper.Selector{"payment.customer.id": group.Payment.Customer.ID}, }, ) So(err, ShouldBeNil) }) }) }) }) }
func TestCheckOwnership(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("accounts can own things", t, func() { account, groupChannel, groupName := models.CreateRandomGroupDataWithChecks() ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) tests.ResultedWithNoErrorCheck(ses, err) tedsAccount, err := models.CreateAccountInBothDbsWithNick("ted") tests.ResultedWithNoErrorCheck(tedsAccount, err) bobsPost, err := rest.CreatePost(groupChannel.Id, ses.ClientId) tests.ResultedWithNoErrorCheck(bobsPost, err) Convey("it should say when an account owns a post", func() { isOwner, err := rest.CheckPostOwnership(account, bobsPost) So(err, ShouldBeNil) So(isOwner, ShouldBeTrue) }) Convey("it should say when an account doesn't own a post", func() { isOwner, err := rest.CheckPostOwnership(tedsAccount, bobsPost) So(err, ShouldBeNil) So(isOwner, ShouldBeFalse) }) bobsChannel, err := rest.CreateChannelByGroupNameAndType(account.Id, groupName, models.Channel_TYPE_TOPIC, ses.ClientId) So(err, ShouldBeNil) Convey("it should say when an account owns a channel", func() { isOwner, err := rest.CheckChannelOwnership(account, bobsChannel) So(err, ShouldBeNil) So(isOwner, ShouldBeTrue) }) Convey("it should say when an account doesn't own a channel", func() { isOwner, err := rest.CheckChannelOwnership(tedsAccount, bobsChannel) So(err, ShouldBeNil) So(isOwner, ShouldBeFalse) }) }) }) }
func withStubData(f func(username string, groupName string, sessionID string)) { acc, _, groupName := models.CreateRandomGroupDataWithChecks() group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) err = modelhelper.MakeAdmin(bson.ObjectIdHex(acc.OldId), group.Id) So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(acc.Nick, groupName) tests.ResultedWithNoErrorCheck(ses, err) cus, err := EnsureCustomerForGroup(acc.Nick, groupName, &stripe.CustomerParams{}) tests.ResultedWithNoErrorCheck(cus, err) f(acc.Nick, groupName, ses.ClientId) err = DeleteCustomerForGroup(groupName) So(err, ShouldBeNil) }
func withTestCreditCardToken(f func(token string)) { t, err := token.New(&stripe.TokenParams{ Card: &stripe.CardParams{ Number: "4242424242424242", Month: "12", Year: "2020", CVC: "123", }, }) tests.ResultedWithNoErrorCheck(t, err) f(t.ID) }
func TestCheckCustomerHasSource(t *testing.T) { tests.WithConfiguration(t, func(c *config.Config) { stripe.Key = c.Stripe.SecretToken Convey("Given a customer", t, func() { withStubData(func(username, groupName, sessionID string) { group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) So(group.Payment.Customer.ID, ShouldNotBeBlank) Convey("When customer does not have card", func() { err := CheckCustomerHasSource(group.Payment.Customer.ID) Convey("CheckCustomerHasSource should return false", func() { So(err, ShouldEqual, ErrCustomerSourceNotExists) Convey("When customer does have card", func() { // add credit card to the user 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("CheckCustomerHasSource should return true", func() { err := CheckCustomerHasSource(group.Payment.Customer.ID) So(err, ShouldBeNil) }) }) }) }) }) }) }) }) }
func TestInvoiceList(t *testing.T) { Convey("Given stub data", t, func() { withTestServer(t, func(endpoint string) { withStubData(endpoint, func(username, groupName, sessionID string) { withTestPlan(func(planID string) { createURL := endpoint + EndpointSubscriptionCreate deleteURL := endpoint + EndpointSubscriptionCancel group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) addCreditCardToUserWithChecks(endpoint, sessionID) Convey("We should be able to create a subscription", func() { req, err := json.Marshal(&stripe.SubParams{ Customer: group.Payment.Customer.ID, Plan: planID, }) tests.ResultedWithNoErrorCheck(req, err) res, err := rest.DoRequestWithAuth("POST", createURL, req, sessionID) tests.ResultedWithNoErrorCheck(res, err) v := &stripe.Sub{} err = json.Unmarshal(res, v) So(err, ShouldBeNil) So(v.Status, ShouldEqual, "active") Convey("We should be able to list invoices", func() { listInvoicesURL := endpoint + EndpointInvoiceList res, err = rest.DoRequestWithAuth("GET", listInvoicesURL, nil, sessionID) tests.ResultedWithNoErrorCheck(res, err) var invoices []*stripe.Invoice err = json.Unmarshal(res, &invoices) So(err, ShouldBeNil) So(len(invoices), ShouldBeGreaterThan, 0) Convey("We should be able to list invoices with startingAfter query param", func() { listInvoicesURLWithQuery := fmt.Sprintf("%s%s?startingAfter=%s", endpoint, EndpointInvoiceList, invoices[0].ID) res, err = rest.DoRequestWithAuth("GET", listInvoicesURLWithQuery, nil, sessionID) tests.ResultedWithNoErrorCheck(res, err) var invoices []*stripe.Invoice err = json.Unmarshal(res, &invoices) So(err, ShouldBeNil) So(len(invoices), ShouldEqual, 0) // because we only have one invoice Convey("We should be able to cancel the subscription", func() { res, err = rest.DoRequestWithAuth("DELETE", deleteURL, req, sessionID) tests.ResultedWithNoErrorCheck(res, err) }) }) }) }) }) }) }) }) }
func withStubData(endpoint string, f func(username string, groupName string, sessionID string)) { createURL := endpoint + EndpointCustomerCreate acc, _, groupName := models.CreateRandomGroupDataWithChecks() group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) err = modelhelper.MakeAdmin(bson.ObjectIdHex(acc.OldId), group.Id) So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(acc.Nick, groupName) tests.ResultedWithNoErrorCheck(ses, err) req, err := json.Marshal(&stripe.CustomerParams{}) tests.ResultedWithNoErrorCheck(req, err) res, err := rest.DoRequestWithAuth("POST", createURL, req, ses.ClientId) tests.ResultedWithNoErrorCheck(res, err) f(acc.Nick, groupName, ses.ClientId) So(payment.DeleteCustomerForGroup(groupName), ShouldBeNil) }
func TestCustomer(t *testing.T) { Convey("Given a user", t, func() { withTestServer(t, func(endpoint string) { withStubData(endpoint, func(username, groupName, sessionID string) { Convey("Then Group should have customer id", func() { group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) So(group.Payment.Customer.ID, ShouldNotBeBlank) Convey("We should be able to get the customer", func() { getURL := endpoint + EndpointCustomerGet res, err := rest.DoRequestWithAuth("GET", getURL, nil, sessionID) So(err, ShouldBeNil) So(res, ShouldNotBeNil) v := &stripe.Customer{} err = json.Unmarshal(res, v) So(err, ShouldBeNil) So(v.Deleted, ShouldEqual, false) So(v.Desc, ShouldContainSubstring, groupName) So(len(v.Meta), ShouldBeGreaterThanOrEqualTo, 2) So(v.Meta["groupName"], ShouldEqual, groupName) So(v.Meta["username"], ShouldEqual, username) Convey("After adding credit card to the user", func() { addCreditCardToUserWithChecks(endpoint, sessionID) res, err = rest.DoRequestWithAuth("GET", getURL, nil, sessionID) So(err, ShouldBeNil) So(res, ShouldNotBeNil) Convey("Customer should have CC assigned", func() { v = &stripe.Customer{} err = json.Unmarshal(res, v) So(err, ShouldBeNil) So(v.DefaultSource, ShouldNotBeNil) So(v.DefaultSource.Deleted, ShouldBeFalse) So(v.DefaultSource.ID, ShouldNotBeEmpty) }) }) }) }) }) }) }) }
// make sure we can subscribe to a paid plan without a CC if it has trial period func TestSubscribingToPaidPlanWithWithTrialPeriodHavingNoCC(t *testing.T) { Convey("Given stub data", t, func() { withTestServer(t, func(endpoint string) { withStubData(endpoint, func(username, groupName, sessionID string) { withNonFreeTestPlan(func(planID string) { createURL := endpoint + EndpointSubscriptionCreate group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) Convey("We should not be able to create a subscription", func() { req, err := json.Marshal(&stripe.SubParams{ Customer: group.Payment.Customer.ID, Plan: planID, }) tests.ResultedWithNoErrorCheck(req, err) _, err = rest.DoRequestWithAuth("POST", createURL, req, sessionID) So(err, ShouldNotBeNil) }) }) }) }) }) }
func TestCreditCardDeleteNonAdmin(t *testing.T) { Convey("When a non admin user request comes", t, func() { withTestServer(t, func(endpoint string) { acc, _, groupName := models.CreateRandomGroupDataWithChecks() ses, err := modelhelper.CreateSessionForAccount(acc.Nick, groupName) tests.ResultedWithNoErrorCheck(ses, err) Convey("Endpoint should return error", func() { ccdeleteURL := endpoint + EndpointCreditCardDelete _, err := rest.DoRequestWithAuth("DELETE", ccdeleteURL, nil, ses.ClientId) So(err, ShouldNotBeNil) }) }) }) }
func TestInvoiceHandlers(t *testing.T) { testData := ` { "id": "in_00000000000000", "object": "invoice", "amount_due": 100, "currency": "usd", "customer": %q }` tests.WithConfiguration(t, func(c *config.Config) { stripe.Key = c.Stripe.SecretToken Convey("Given stub data", t, func() { withStubData(func(username, groupName, sessionID string) { Convey("Then Group should have customer id", func() { group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) Convey("When invoice handlers are triggered", func() { var invoice *stripe.Invoice raw := fmt.Sprintf(testData, group.Payment.Customer.ID) err := json.Unmarshal([]byte(raw), &invoice) So(err, ShouldBeNil) var capturedMails []*emailsender.Mail realMailSender := mailSender mailSender = func(m *emailsender.Mail) error { capturedMails = append(capturedMails, m) return nil } eventName := "test event name" err = sendInvoiceEvent(invoice, eventName) So(err, ShouldBeNil) mailSender = realMailSender Convey("properties of event should be set accordingly", func() { So(len(capturedMails), ShouldEqual, 1) So(capturedMails[0].Subject, ShouldEqual, eventName) }) }) }) }) }) }) }
func TestCreditCardInfo(t *testing.T) { Convey("Given a user", t, func() { withTestServer(t, func(endpoint string) { withStubData(endpoint, func(username, groupName, sessionID string) { Convey("When a credit card added", func() { c1 := addCreditCardToUserWithChecks(endpoint, sessionID) Convey("Group should have the credit card", func() { _, err := rest.DoRequestWithAuth("GET", endpoint+EndpointCreditCardHas, nil, sessionID) So(err, ShouldBeNil) Convey("After updating the credit card", func() { c2 := addCreditCardToUserWithChecks(endpoint, sessionID) Convey("Group should still have a card", func() { _, err := rest.DoRequestWithAuth("GET", endpoint+EndpointCreditCardHas, nil, sessionID) So(err, ShouldBeNil) // current and previous cc id should not be same So(c1.DefaultSource.ID, ShouldNotEqual, c2.DefaultSource.ID) Convey("After deleting the credit card", func() { ccdeleteURL := endpoint + EndpointCreditCardDelete res, err := rest.DoRequestWithAuth("DELETE", ccdeleteURL, nil, sessionID) tests.ResultedWithNoErrorCheck(res, err) Convey("Customer should not have the a credit card", func() { _, err := rest.DoRequestWithAuth("GET", endpoint+EndpointCreditCardHas, nil, sessionID) So(err, ShouldNotBeNil) }) }) }) }) }) }) }) }) }) }
func TestCreditCardAuthNoSession(t *testing.T) { Convey("When a non subscribed user request for Auth", t, func() { withTestServer(t, func(endpoint string) { withTestCreditCardToken(func(token string) { cp := &stripe.ChargeParams{ Source: &stripe.SourceParams{ Token: token, }, Email: "*****@*****.**", } req, err := json.Marshal(cp) tests.ResultedWithNoErrorCheck(req, err) res, err := rest.DoRequestWithAuth("POST", endpoint+EndpointCreditCardAuth, req, "") So(err, ShouldNotBeNil) So(res, ShouldBeNil) So(err.Error(), ShouldContainSubstring, "does not have session id") }) }) }) }
func TestInfoPlan(t *testing.T) { Convey("Given a user", t, func() { withTestServer(t, func(endpoint string) { withStubData(endpoint, func(username, groupName, sessionID string) { withTestPlan(func(planID string) { addCreditCardToUserWithChecks(endpoint, sessionID) withSubscription(endpoint, groupName, sessionID, planID, func(subscriptionID string) { Convey("We should be able to get info", func() { infoURL := endpoint + EndpointInfo res, err := rest.DoRequestWithAuth("GET", infoURL, nil, sessionID) tests.ResultedWithNoErrorCheck(res, err) v := &payment.Usage{} err = json.Unmarshal(res, v) So(err, ShouldBeNil) So(v.ExpectedPlan.ID, ShouldEqual, planID) }) }) }) }) }) }) }
func TestChannelParticipantOperations(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("while testing channel participants", t, func() { Convey("First Create Users and initiate conversation", func() { ownerAccount, groupChannel, groupName := models.CreateRandomGroupDataWithChecks() ownerSes, err := modelhelper.FetchOrCreateSession(ownerAccount.Nick, groupName) So(err, ShouldBeNil) So(ownerSes, ShouldNotBeNil) secondAccount, err := models.CreateAccountInBothDbs() tests.ResultedWithNoErrorCheck(secondAccount, err) _, err = groupChannel.AddParticipant(secondAccount.Id) So(err, ShouldBeNil) thirdAccount, err := models.CreateAccountInBothDbs() tests.ResultedWithNoErrorCheck(thirdAccount, err) _, err = groupChannel.AddParticipant(thirdAccount.Id) So(err, ShouldBeNil) forthAccount, err := models.CreateAccountInBothDbs() tests.ResultedWithNoErrorCheck(forthAccount, err) _, err = groupChannel.AddParticipant(forthAccount.Id) So(err, ShouldBeNil) devrim, err := models.CreateAccountInBothDbsWithNick("devrim") tests.ResultedWithNoErrorCheck(devrim, err) _, err = groupChannel.AddParticipant(devrim.Id) So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(ownerAccount.Nick, groupName) tests.ResultedWithNoErrorCheck(ses, err) secondSes, err := modelhelper.FetchOrCreateSession(secondAccount.Nick, groupName) tests.ResultedWithNoErrorCheck(secondSes, err) pmr := models.ChannelRequest{} pmr.AccountId = ownerAccount.Id pmr.Body = "new conversation" pmr.GroupName = groupName pmr.Recipients = []string{"devrim"} channelContainer, err := rest.SendPrivateChannelRequest(pmr, ownerSes.ClientId) So(err, ShouldBeNil) So(channelContainer, ShouldNotBeNil) Convey("First user should be able to add second and third users to conversation", func() { _, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id, thirdAccount.Id) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) // it is four because first user is "devrim" here So(len(participants), ShouldEqual, 4) Convey("First user should not be able to re-add second participant", func() { _, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 4) }) Convey("Second user should be able to leave conversation", func() { // token of account -> secondAccount _, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, secondSes.ClientId, secondAccount.Id) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 3) Convey("A user who is not participant of a conversation should not be able to add another user to the conversation", func() { _, err = rest.AddChannelParticipant(channelContainer.Channel.Id, secondSes.ClientId, forthAccount.Id) So(err, ShouldNotBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 3) }) }) Convey("Channel owner should be able to kick another conversation participant", func() { _, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 3) }) Convey("when a user is blocked", func() { _, err = rest.BlockChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id) So(err, ShouldBeNil) Convey("it should not be in channel participant list", func() { participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 3) }) Convey("should not be able to add it back", func() { _, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id) So(err, ShouldNotBeNil) }) Convey("should be able to unblock", func() { _, err = rest.UnblockChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id) So(err, ShouldBeNil) Convey("it should not be in channel participant list still", func() { participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 3) }) Convey("when we add the same user as participant", func() { _, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id, thirdAccount.Id) So(err, ShouldBeNil) Convey("it should be in channel participant list", func() { participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 4) }) }) }) }) Convey("Second user should not be able to kick another conversation participant", func() { _, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, secondSes.ClientId, thirdAccount.Id) So(err, ShouldNotBeNil) }) }) Convey("First user should be able to invite second user", func() { _, err = rest.InviteChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) // it is four because first user is "devrim" here So(len(participants), ShouldEqual, 2) Convey("Second user should be able to reject invitation", func() { ses, err := modelhelper.FetchOrCreateSession(secondAccount.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) err = rest.RejectInvitation(channelContainer.Channel.Id, ses.ClientId) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 2) }) Convey("Second user should be able to accept invitation", func() { ses, err := modelhelper.FetchOrCreateSession(secondAccount.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) err = rest.AcceptInvitation(channelContainer.Channel.Id, ses.ClientId) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 3) }) }) // TODO Until we find a better way for handling async stuff, this test is skipped. Instead of sleep, we should use some // timeouts for testing these kind of stuff. SkipConvey("All private messages must be deleted when all participant users leave the channel", func() { account := models.NewAccount() err = account.ByNick("devrim") So(err, ShouldBeNil) _, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, ses.ClientId, account.Id) So(err, ShouldBeNil) _, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, ownerAccount.Id) So(err, ShouldBeNil) time.Sleep(1 * time.Second) testChannel := models.NewChannel() err := testChannel.ById(channelContainer.Channel.Id) So(err, ShouldEqual, bongo.RecordNotFound) testChannelList := models.NewChannelMessageList() err = bongo.B.Unscoped().Where("channel_id = ?", channelContainer.Channel.Id).Find(testChannelList).Error So(err, ShouldEqual, bongo.RecordNotFound) testMessage := models.NewChannelMessage() err = bongo.B.Unscoped().Where("initial_channel_id = ?", channelContainer.Channel.Id).Find(testMessage).Error So(err, ShouldEqual, bongo.RecordNotFound) }) Convey("Users should not be able to add/remove users to/from bot channels", func() { ownerAccount, _, groupName := models.CreateRandomGroupDataWithChecks() participant := models.NewAccount() participant.OldId = AccountOldId.Hex() participant, err = rest.CreateAccount(participant) So(err, ShouldBeNil) So(participant, ShouldNotBeNil) ses, err := modelhelper.FetchOrCreateSession(ownerAccount.Nick, groupName) So(err, ShouldBeNil) ch, err := rest.CreateChannelByGroupNameAndType(ownerAccount.Id, groupName, models.Channel_TYPE_BOT, ses.ClientId) So(err, ShouldBeNil) So(ch, ShouldNotBeNil) // account is -> ownerAccount.Id _, err = rest.AddChannelParticipant(ch.Id, ses.ClientId, participant.Id) So(strings.Contains(err.Error(), "can not add participants for bot channel"), ShouldBeTrue) }) Convey("Users should be able to add/remove users to/from topic channels", func() { ownerAccount, _, groupName := models.CreateRandomGroupDataWithChecks() participant := models.NewAccount() participant.OldId = AccountOldId.Hex() participant, err = rest.CreateAccount(participant) So(err, ShouldBeNil) So(participant, ShouldNotBeNil) ses, err := modelhelper.FetchOrCreateSession(ownerAccount.Nick, groupName) So(err, ShouldBeNil) ch, err := rest.CreateChannelByGroupNameAndType(ownerAccount.Id, groupName, models.Channel_TYPE_TOPIC, ses.ClientId) So(err, ShouldBeNil) So(ch, ShouldNotBeNil) // account is -> ownerAccount.Id _, err = rest.AddChannelParticipant(ch.Id, ses.ClientId, participant.Id) So(err, ShouldBeNil) Convey("adding same user again should success", func() { _, err = rest.AddChannelParticipant(ch.Id, ses.ClientId, participant.Id) So(err, ShouldBeNil) }) _, err = rest.DeleteChannelParticipant(ch.Id, ses.ClientId, participant.Id) So(err, ShouldBeNil) Convey("removing same user again should success", func() { _, err = rest.DeleteChannelParticipant(ch.Id, ses.ClientId, participant.Id) So(err, ShouldBeNil) }) }) Convey("while removing users from group channels", func() { ownerAccount, _, groupName := models.CreateRandomGroupDataWithChecks() participant := models.NewAccount() participant.OldId = AccountOldId.Hex() participant, err = rest.CreateAccount(participant) So(err, ShouldBeNil) So(participant, ShouldNotBeNil) participant2 := models.NewAccount() participant2.OldId = AccountOldId.Hex() participant2, err = rest.CreateAccount(participant2) So(err, ShouldBeNil) So(participant2, ShouldNotBeNil) ownerSes, err := modelhelper.FetchOrCreateSession(ownerAccount.Nick, groupName) So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(participant.Nick, groupName) So(err, ShouldBeNil) ch, err := rest.CreateChannelByGroupNameAndType(ownerAccount.Id, groupName, models.Channel_TYPE_GROUP, ownerSes.ClientId) So(err, ShouldBeNil) So(ch, ShouldNotBeNil) // ownerSes session is admin's session data _, err = rest.AddChannelParticipant(ch.Id, ownerSes.ClientId, participant.Id) So(err, ShouldBeNil) _, err = rest.AddChannelParticipant(ch.Id, ownerSes.ClientId, participant2.Id) So(err, ShouldBeNil) Convey("owner should be able to remove user from group channel", func() { // ownerSes session is admin's session data _, err = rest.DeleteChannelParticipant(ch.Id, ownerSes.ClientId, participant2.Id) So(err, ShouldBeNil) }) Convey("nonOwner should not be able to remove user from group channel", func() { // ses session is participant's session data _, err = rest.DeleteChannelParticipant(ch.Id, ses.ClientId, participant2.Id) So(err, ShouldNotBeNil) }) }) }) }) }) }
func TestInvoiceCreatedHandlerWithZeroUser(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) { withNonFreeTestPlan(func(planID string) { withTestCreditCardToken(func(token string) { group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) // attach payment source cp := &stripe.CustomerParams{ Source: &stripe.SourceParams{Token: token}, } c, err := UpdateCustomerForGroup(username, groupName, cp) tests.ResultedWithNoErrorCheck(c, err) // this is just a random number const totalMembers = 4 // subscribe to test plan params := &stripe.SubParams{ Customer: group.Payment.Customer.ID, Plan: planID, 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) count, err := (&models.PresenceDaily{}).CountDistinctByGroupName(group.Slug) So(err, ShouldBeNil) So(count, ShouldEqual, 0) 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, )) 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, Free) count, err := (&models.PresenceDaily{}).CountDistinctByGroupName(group.Slug) So(err, ShouldBeNil) So(count, ShouldEqual, 0) }) }) }) }) }) }) }) }
// TestBalanceApply does not test anything on our end. And i am not trying to be // clever with testing stripe. This test is here only for making sure about the // logic of Amount, Subtotal And the Total. This is the third time i am // forgetting the logic and wanted to document it here with code. func TestBalanceApply(t *testing.T) { Convey("Given a user who subscribed to a paid plan", t, func() { withTestServer(t, func(endpoint string) { withStubData(endpoint, func(username, groupName, sessionID string) { withNonFreeTestPlan(func(planID string) { addCreditCardToUserWithChecks(endpoint, sessionID) withSubscription(endpoint, groupName, sessionID, planID, func(subscriptionID string) { withTestCoupon(func(couponID string) { Convey("After adding balance to the user", func() { group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) var subtotal int64 = 12345 // A negative amount represents a credit that // decreases the amount due on an invoice; a // positive amount increases the amount due on // an invoice. var balance int64 = -150 var coupon int64 = 100 expectedAmount := subtotal - coupon - (-balance) // negate the balance cp := &stripe.CustomerParams{ Balance: balance, Coupon: couponID, } c, err := customer.Update(group.Payment.Customer.ID, cp) tests.ResultedWithNoErrorCheck(c, err) Convey("Customer should have discount", func() { So(c, ShouldNotBeNil) So(c.Balance, ShouldEqual, balance) Convey("Invoice should the discount", func() { i, err := invoice.GetNext(&stripe.InvoiceParams{Customer: c.ID}) tests.ResultedWithNoErrorCheck(i, err) So(i.Subtotal, ShouldEqual, subtotal) So(i.Subtotal, ShouldBeGreaterThan, i.Total) So(i.Subtotal, ShouldEqual, i.Total+coupon) // dont forget to negate So(i.Total, ShouldEqual, subtotal-coupon) So(i.Total, ShouldBeGreaterThan, i.Amount) So(i.Total, ShouldEqual, i.Amount+(-balance)) So(i.Amount, ShouldEqual, i.Total-(-balance)) So(i.Amount, ShouldEqual, expectedAmount) // Subtotal = amount + coupon + balance // Total = amount + coupon // Amount = the final price that customer will pay. // Subtotal: 12345, // Total: 12245, // Amount: 12145, // Expected: '12245' // Actual: '12445' }) }) }) }) }) }) }) }) }) }
func TestCustomerSubscriptionCreatedHandler(t *testing.T) { testData := ` { "id": "sub_94xDGmeKJ35NhI", "object": "subscription", "application_fee_percent": null, "cancel_at_period_end": false, "canceled_at": 1472229377, "created": 1472229375, "current_period_end": 1472229675, "current_period_start": 1472229375, "customer": "%s", "discount": null, "ended_at": 1472229377, "livemode": false, "metadata": {}, "plan": { "id": "my_test_plan", "object": "plan", "amount": 12345, "created": 1472229375, "currency": "usd", "interval": "month", "interval_count": 1, "livemode": false, "metadata": {}, "name": "plan for 57c06ffc9bc22b9f5db651c6", "statement_descriptor": "NAN-FREE", "trial_period_days": 1 }, "quantity": 1, "start": 1472229376, "status": "trialing", "tax_percent": null, "trial_end": 1472834175, "trial_start": 1472229375 }` tests.WithConfiguration(t, func(c *config.Config) { stripe.Key = c.Stripe.SecretToken Convey("Given stub data", t, func() { withStubData(func(username, groupName, sessionID string) { Convey("Then Group should have customer id", func() { group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) So(group.Payment.Customer.ID, ShouldNotBeBlank) Convey("When subscription.created is triggered", func() { raw := []byte(fmt.Sprintf(testData, group.Payment.Customer.ID)) var capturedMails []*emailsender.Mail realMailSender := mailSender mailSender = func(m *emailsender.Mail) error { capturedMails = append(capturedMails, m) return nil } err := customerSubscriptionCreatedHandler(raw) So(err, ShouldBeNil) mailSender = realMailSender Convey("properties of event should be set accordingly", func() { So(len(capturedMails), ShouldEqual, 2) So(capturedMails[0].Subject, ShouldEqual, "subscribed to my_test_plan plan") So(capturedMails[1].Subject, ShouldEqual, "seven days trial started") }) }) }) }) }) }) }
func TestCustomerSourceCreatedHandler(t *testing.T) { testData := ` { "id": "card_00000000000000", "object": "card", "address_city": null, "address_country": null, "address_line1": null, "address_line1_check": null, "address_line2": null, "address_state": null, "address_zip": null, "address_zip_check": null, "brand": "Visa", "country": "US", "customer": "%s", "cvc_check": null, "dynamic_last4": null, "exp_month": 10, "exp_year": 2020, "funding": "credit", "last4": "4242", "metadata": {}, "name": null, "tokenization_method": null, "fingerprint": "VLZ7tf1OXmWI4TVF" }` tests.WithConfiguration(t, func(c *config.Config) { stripe.Key = c.Stripe.SecretToken Convey("Given stub data", t, func() { withStubData(func(username, groupName, sessionID string) { Convey("Then Group should have customer id", func() { group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) So(group.Payment.Customer.ID, ShouldNotBeBlank) Convey("When customer.source.created is triggered", func() { raw := []byte(fmt.Sprintf(testData, group.Payment.Customer.ID)) var capturedMails []*emailsender.Mail realMailSender := mailSender mailSender = func(m *emailsender.Mail) error { capturedMails = append(capturedMails, m) return nil } err := customerSourceCreatedHandler(raw) So(err, ShouldBeNil) mailSender = realMailSender Convey("properties of event should be set accordingly", func() { So(len(capturedMails), ShouldEqual, 1) So(capturedMails[0].Subject, ShouldEqual, "entered credit card") }) }) }) }) }) }) }
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 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) }) }) }) }) }) }) }) }
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 TestCreditCardDelete(t *testing.T) { Convey("Given a user", t, func() { withTestServer(t, func(endpoint string) { withStubData(endpoint, func(username, groupName, sessionID string) { Convey("When a credit card added", func() { withTestCreditCardToken(func(token string) { updateURL := endpoint + EndpointCustomerUpdate getURL := endpoint + EndpointCustomerGet cp := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Token: token, }, } req, err := json.Marshal(cp) tests.ResultedWithNoErrorCheck(req, err) res, err := rest.DoRequestWithAuth("POST", updateURL, req, sessionID) So(err, ShouldBeNil) So(res, ShouldNotBeNil) Convey("Customer should have the credit card", func() { c1 := &stripe.Customer{} err = json.Unmarshal(res, c1) So(err, ShouldBeNil) So(c1.DefaultSource, ShouldNotBeNil) So(c1.DefaultSource.Deleted, ShouldBeFalse) So(c1.DefaultSource.ID, ShouldNotBeEmpty) Convey("After updating the credit card", func() { withTestCreditCardToken(func(token string) { cp := &stripe.CustomerParams{ Source: &stripe.SourceParams{ Token: token, }, } req, err := json.Marshal(cp) tests.ResultedWithNoErrorCheck(req, err) res, err = rest.DoRequestWithAuth("POST", updateURL, req, sessionID) tests.ResultedWithNoErrorCheck(res, err) c2 := &stripe.Customer{} err = json.Unmarshal(res, c2) So(err, ShouldBeNil) Convey("Customer should have the new credit card", func() { So(c2.DefaultSource, ShouldNotBeNil) So(c2.DefaultSource.Deleted, ShouldBeFalse) So(c2.DefaultSource.ID, ShouldNotBeEmpty) // current and previous cc id should not be same So(c1.DefaultSource.ID, ShouldNotEqual, c2.DefaultSource.ID) Convey("After deleting the credit card", func() { ccdeleteURL := endpoint + EndpointCreditCardDelete _, err = rest.DoRequestWithAuth("DELETE", ccdeleteURL, nil, sessionID) tests.ResultedWithNoErrorCheck(res, err) res, err = rest.DoRequestWithAuth("GET", getURL, nil, sessionID) So(err, ShouldBeNil) So(res, ShouldNotBeNil) Convey("Customer should not have the a credit card", func() { c3 := &stripe.Customer{} err = json.Unmarshal(res, c3) So(err, ShouldBeNil) So(c3.DefaultSource, ShouldBeNil) So(len(c3.Sources.Values), ShouldEqual, 0) }) }) }) }) }) }) }) }) }) }) }) }
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) }) }) }) }) }) }) }) }) }) }) }