예제 #1
0
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")
						})
					})
				})
			})
		})
	})
}
예제 #2
0
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)
						})
					})
				})
			})
		})
	})
}
예제 #3
0
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)
			})
		})
	})
}
예제 #4
0
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")
		})
	})
}
예제 #5
0
// 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")
				})
			})
		})
	})
}
예제 #6
0
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)
}
예제 #7
0
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)
				})
			})
		})
	})
}
예제 #8
0
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)
			})
		})
	})
}
예제 #9
0
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)
}
예제 #10
0
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)
}
예제 #11
0
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)
								})
							})
						})
					})
				})
			})
		})
	})
}
예제 #12
0
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)
								})
							})
						})
					})
				})
			})
		})
	})
}
예제 #13
0
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)
}
예제 #14
0
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)
							})
						})
					})
				})
			})
		})
	})
}
예제 #15
0
// 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)
					})
				})
			})
		})
	})
}
예제 #16
0
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)
			})
		})
	})
}
예제 #17
0
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)
						})
					})
				})
			})
		})
	})
}
예제 #18
0
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)
									})
								})
							})
						})
					})
				})
			})
		})
	})
}
예제 #19
0
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")
			})
		})
	})
}
예제 #20
0
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)
						})
					})
				})
			})
		})
	})
}
예제 #21
0
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)
					})
				})
			})
		})
	})
}
예제 #22
0
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)
							})
						})
					})
				})
			})
		})
	})
}
예제 #23
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'
									})
								})
							})
						})
					})
				})
			})
		})
	})
}
예제 #24
0
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")
						})
					})
				})
			})
		})
	})
}
예제 #25
0
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")
						})
					})
				})
			})
		})
	})
}
예제 #26
0
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)
							})
						})
					})
				})
			})
		})
	})
}
예제 #27
0
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)
							})
						})
					})
				})
			})
		})
	})
}
예제 #28
0
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)
								})
							})
						})
					})
				})
			})
		})
	})
}
예제 #29
0
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)
											})
										})
									})
								})
							})
						})
					})
				})
			})
		})
	})
}
예제 #30
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)
										})
									})
								})
							})
						})
					})
				})
			})
		})
	})
}