testsuite/ui: Add coupon tests

Add some testing around adding/replacing promotional coupons and what
the user sees in the UI depending on their coupon status.

Change-Id: Ice6c0a0644d05af0c30c87a93ba963c0bb09e32d
This commit is contained in:
Moby von Briesen 2021-10-18 17:06:31 -04:00
parent 8d18033a99
commit 9c8b6c3fc3
3 changed files with 157 additions and 14 deletions

View File

@ -41,7 +41,29 @@ var mocks = struct {
m: make(map[storj.NodeID]*mockStripeState),
}
const testPromoCode string = "testpromocode"
var (
testPromoCodes = map[string]*stripe.PromotionCode{
"promo1": {
ID: "p1",
Coupon: &stripe.Coupon{
AmountOff: 500,
Currency: stripe.CurrencyUSD,
Name: "Test Promo Code 1",
},
},
"promo2": {
ID: "p2",
Coupon: &stripe.Coupon{
PercentOff: 50,
Name: "Test Promo Code 2",
},
},
}
promoIDs = map[string]*stripe.PromotionCode{
"p1": testPromoCodes["promo1"],
"p2": testPromoCodes["promo2"],
}
)
// mockStripeState Stripe client mock.
type mockStripeState struct {
@ -80,9 +102,6 @@ func NewStripeMock(id storj.NodeID, customersDB CustomersDB, usersDB console.Use
state, ok := mocks.m[id]
if !ok {
promoCodes := make(map[string][]*stripe.PromotionCode)
promoCodes[testPromoCode] = []*stripe.PromotionCode{{}}
state = &mockStripeState{
customers: &mockCustomersState{},
paymentMethods: newMockPaymentMethods(),
@ -91,7 +110,7 @@ func NewStripeMock(id storj.NodeID, customersDB CustomersDB, usersDB console.Use
customerBalanceTransactions: newMockCustomerBalanceTransactions(),
charges: &mockCharges{},
promoCodes: &mockPromoCodes{
promoCodes: promoCodes,
promoCodes: testPromoCodes,
},
}
mocks.m[id] = state
@ -262,8 +281,8 @@ func (m *mockCustomers) Update(id string, params *stripe.CustomerParams) (*strip
if params.Metadata != nil {
customer.Metadata = params.Metadata
}
if params.PromotionCode != nil {
customer.Discount = &stripe.Discount{Coupon: &stripe.Coupon{}}
if params.PromotionCode != nil && promoIDs[*params.PromotionCode] != nil {
customer.Discount = &stripe.Discount{Coupon: promoIDs[*params.PromotionCode].Coupon}
}
// TODO update customer with more params as necessary
@ -471,7 +490,7 @@ func (m *mockCharges) List(listParams *stripe.ChargeListParams) *charge.Iter {
}
type mockPromoCodes struct {
promoCodes map[string][]*stripe.PromotionCode
promoCodes map[string]*stripe.PromotionCode
}
func (m *mockPromoCodes) List(params *stripe.PromotionCodeListParams) *promotioncode.Iter {
@ -479,15 +498,15 @@ func (m *mockPromoCodes) List(params *stripe.PromotionCodeListParams) *promotion
defer mocks.Unlock()
query := stripe.Query(func(p *stripe.Params, b *form.Values) ([]interface{}, stripe.ListContainer, error) {
promoCodes := m.promoCodes[*params.Code]
ret := make([]interface{}, len(promoCodes))
for i, v := range promoCodes {
ret[i] = v
promoCode := m.promoCodes[*params.Code]
if promoCode == nil {
return make([]interface{}, 0), &stripe.ListMeta{TotalCount: 0}, nil
}
ret := make([]interface{}, 1)
ret[0] = promoCode
listMeta := &stripe.ListMeta{
TotalCount: uint32(len(promoCodes)),
TotalCount: 1,
}
lc := newListContainer(listMeta)

View File

@ -0,0 +1,123 @@
// Copyright (C) 2021 Storj Labs, Inc.
// See LICENSE for copying information.
package satellite_test
import (
"testing"
"github.com/go-rod/rod"
"github.com/go-rod/rod/lib/input"
"github.com/stretchr/testify/require"
"storj.io/common/testcontext"
"storj.io/storj/private/testplanet"
"storj.io/storj/testsuite/ui/uitest"
)
func TestCouponCodes(t *testing.T) {
uitest.Run(t, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet, browser *rod.Browser) {
signupPageURL := planet.Satellites[0].ConsoleURL() + "/signup"
fullName := "John Doe"
emailAddress := "test@email.com"
password := "qazwsx123"
page := openPage(browser, signupPageURL)
// first time User signs up
page.MustElement("[aria-roledescription=name] input").MustInput(fullName)
page.MustElement("[aria-roledescription=email] input").MustInput(emailAddress)
page.MustElement("[aria-roledescription=password] input").MustInput(password)
page.MustElement("[aria-roledescription=retype-password] input").MustInput(password)
page.MustElement(".checkmark").MustClick()
page.Keyboard.MustPress(input.Enter)
waitVueTick(page)
confirmAccountEmailMessage := page.MustElement("[aria-roledescription=title]").MustText()
require.Contains(t, confirmAccountEmailMessage, "You're almost there!")
// first time user logs in
page.MustElement("[href=\"/login\"]").MustClick()
waitVueTick(page)
page.MustElement("[aria-roledescription=email] input").MustInput(emailAddress)
page.MustElement("[aria-roledescription=password] input").MustInput(password)
page.Keyboard.MustPress(input.Enter)
// waitVueTick(page)
// skip onboarding process
page.MustElement("[href=\"/project-dashboard\"]").MustClick()
dashboardTitle := page.MustElement("[aria-roledescription=title]").MustText()
require.Contains(t, dashboardTitle, "Dashboard")
// go to billing page
page.MustElement(".settings-selection").MustClick()
page.MustElementX("(//p[text()=\" Billing \"])").MustClick()
// waitVueTick(page)
couponText := page.MustElement(".coupon-area__container__text-container").MustText()
require.Contains(t, couponText, "Add a Coupon to Get Started")
require.Contains(t, couponText, "Your coupon will show up here.")
// Adding a valid promo code (promo1 and promo2 are defined in satellite/payments/stripecoinpayments/stripemock.go)
{
page.MustElementR("span", "Add Coupon Code").MustClick()
page.MustElement("input[placeholder=\"Enter Coupon Code\"]").MustInput("promo1")
page.MustElementR("span", "Apply Coupon Code").MustClick()
page.MustElementR("p", "Successfully applied coupon code")
page.MustElement(".add-coupon__close-icon").MustClick()
couponText := page.MustElement(".coupon-area__container__text-container").MustText()
require.Contains(t, couponText, "Test Promo Code 1")
require.Contains(t, couponText, "$5 off")
}
// Attempting replace with invalid promo code
{
page.MustElementR("span", "Add Coupon Code").MustClick()
page.MustElement("input[placeholder=\"Enter Coupon Code\"]").MustInput("notpromo1")
page.MustElementR("span", "Apply Coupon Code").MustClick()
page.MustElementR(".add-coupon__confirm-message", "Are you sure.*remove.*current coupon.*replace.*new coupon")
page.MustElementR("span", "Back").MustClick()
page.MustElement("input[placeholder=\"Enter Coupon Code\"]").MustInput("notpromo1")
page.MustElementR("span", "Apply Coupon Code").MustClick()
page.MustElementR(".add-coupon__confirm-message", "Are you sure.*remove.*current coupon.*replace.*new coupon")
page.MustElementR("span", "Yes").MustClick()
page.MustElementR("p", "Could not apply coupon code")
// old coupon should still be applied
page.MustElement(".add-coupon__close-icon").MustClick()
couponText := page.MustElement(".coupon-area__container__text-container").MustText()
require.Contains(t, couponText, "Test Promo Code 1")
require.Contains(t, couponText, "$5 off")
}
// Replacing with a valid promo code
{
page.MustElementR("span", "Add Coupon Code").MustClick()
page.MustElement("input[placeholder=\"Enter Coupon Code\"]").MustInput("promo2")
page.MustElementR("span", "Apply Coupon Code").MustClick()
page.MustElementR(".add-coupon__confirm-message", "Are you sure.*remove.*current coupon.*replace.*new coupon")
page.MustElementR("span", "Yes").MustClick()
page.MustElementR("p", "Successfully applied coupon code")
page.MustElement(".add-coupon__close-icon").MustClick()
couponText := page.MustElement(".coupon-area__container__text-container").MustText()
require.Contains(t, couponText, "Test Promo Code 2")
require.Contains(t, couponText, "50% off")
}
// Rate limit
{
page.MustElementR("span", "Add Coupon Code").MustClick()
for i := 0; i < 3; i++ {
page.MustElement("input[placeholder=\"Enter Coupon Code\"]").MustInput("promo1")
page.MustElementR("span", "Apply Coupon Code").MustClick()
page.MustElementR("span", "Yes").MustClick()
}
page.MustElementR("p", "You've exceeded limit of attempts")
}
})
}

View File

@ -40,6 +40,7 @@ func Run(t *testing.T, test Test) {
config.Console.StaticDir = dir
}
config.Console.NewOnboarding = true
config.Console.CouponCodeBillingUIEnabled = true
},
},
NonParallel: true,