Skip to content

Commit d39aff7

Browse files
authored
Merge pull request #18892 from mozilla/FXA-11683
feat(payments-cart): Updates amount in metadata to unit amount
2 parents 078a2da + 2d00577 commit d39aff7

5 files changed

Lines changed: 166 additions & 95 deletions

File tree

libs/payments/cart/src/lib/checkout.service.spec.ts

Lines changed: 118 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
PaymentIntentManager,
3838
PaymentMethodManager,
3939
PriceManager,
40+
PricingForCurrencyFactory,
4041
ProductManager,
4142
PromotionCodeManager,
4243
STRIPE_SUBSCRIPTION_METADATA,
@@ -125,6 +126,7 @@ describe('CheckoutService', () => {
125126
let paymentIntentManager: PaymentIntentManager;
126127
let paypalBillingAgreementManager: PaypalBillingAgreementManager;
127128
let paypalCustomerManager: PaypalCustomerManager;
129+
let priceManager: PriceManager;
128130
let privateMethod: any;
129131
let productConfigurationManager: ProductConfigurationManager;
130132
let profileClient: ProfileClient;
@@ -207,6 +209,7 @@ describe('CheckoutService', () => {
207209
PaypalBillingAgreementManager
208210
);
209211
paypalCustomerManager = moduleRef.get(PaypalCustomerManager);
212+
priceManager = moduleRef.get(PriceManager);
210213
privateMethod = jest
211214
.spyOn(checkoutService as any, 'customerChanged')
212215
.mockResolvedValue({});
@@ -584,11 +587,15 @@ describe('CheckoutService', () => {
584587
price: mockPrice,
585588
eligibility: mockEligibilityResult,
586589
});
590+
const mockPricingForCurrency = PricingForCurrencyFactory();
587591

588592
beforeEach(async () => {
589593
jest
590594
.spyOn(checkoutService, 'prePaySteps')
591595
.mockResolvedValue(mockPrePayStepsResult);
596+
jest
597+
.spyOn(priceManager, 'retrievePricingForCurrency')
598+
.mockResolvedValue(mockPricingForCurrency);
592599
jest
593600
.spyOn(subscriptionManager, 'create')
594601
.mockResolvedValue(mockSubscription);
@@ -640,7 +647,7 @@ describe('CheckoutService', () => {
640647
payment_behavior: 'default_incomplete',
641648
currency: mockCart.currency,
642649
metadata: {
643-
amount: mockCart.amount,
650+
amount: mockPricingForCurrency.unitAmountForCurrency,
644651
currency: mockCart.currency,
645652
},
646653
},
@@ -696,11 +703,15 @@ describe('CheckoutService', () => {
696703
version: mockCart.version + 1,
697704
eligibility: mockEligibilityResult,
698705
});
706+
const mockPricingForCurrency = PricingForCurrencyFactory();
699707

700708
beforeEach(async () => {
701709
jest
702710
.spyOn(checkoutService, 'prePaySteps')
703711
.mockResolvedValue(PrePayStepsResultFactory(mockPrePayStepsResult));
712+
jest
713+
.spyOn(priceManager, 'retrievePricingForCurrency')
714+
.mockResolvedValue(mockPricingForCurrency);
704715
jest
705716
.spyOn(checkoutService, 'upgradeSubscription')
706717
.mockResolvedValue(mockSubscription);
@@ -766,10 +777,16 @@ describe('CheckoutService', () => {
766777
price: mockPrice,
767778
eligibility: mockEligibilityResult,
768779
});
780+
const mockPricingForCurrency = PricingForCurrencyFactory({
781+
unitAmountForCurrency: 1000,
782+
});
769783

770784
jest
771785
.spyOn(checkoutService, 'prePaySteps')
772786
.mockResolvedValue(mockPrePayStepsResult);
787+
jest
788+
.spyOn(priceManager, 'retrievePricingForCurrency')
789+
.mockResolvedValue(mockPricingForCurrency);
773790
jest
774791
.spyOn(subscriptionManager, 'create')
775792
.mockResolvedValue(mockSubscription);
@@ -831,6 +848,7 @@ describe('CheckoutService', () => {
831848
version: mockCart.version + 1,
832849
eligibility: mockEligibilityResult,
833850
});
851+
const mockPricingForCurrency = PricingForCurrencyFactory();
834852

835853
beforeEach(async () => {
836854
jest
@@ -842,6 +860,9 @@ describe('CheckoutService', () => {
842860
jest
843861
.spyOn(paypalBillingAgreementManager, 'retrieveOrCreateId')
844862
.mockResolvedValue(mockBillingAgreementId);
863+
jest
864+
.spyOn(priceManager, 'retrievePricingForCurrency')
865+
.mockResolvedValue(mockPricingForCurrency);
845866
jest.spyOn(statsd, 'increment');
846867
jest
847868
.spyOn(subscriptionManager, 'create')
@@ -913,7 +934,7 @@ describe('CheckoutService', () => {
913934
],
914935
currency: mockCart.currency,
915936
metadata: {
916-
amount: mockCart.amount,
937+
amount: mockPricingForCurrency.unitAmountForCurrency,
917938
currency: mockCart.currency,
918939
},
919940
},
@@ -980,11 +1001,15 @@ describe('CheckoutService', () => {
9801001
version: mockCart.version + 1,
9811002
eligibility: mockEligibilityResult,
9821003
});
1004+
const mockPricingForCurrency = PricingForCurrencyFactory();
9831005

9841006
beforeEach(async () => {
9851007
jest
9861008
.spyOn(checkoutService, 'prePaySteps')
9871009
.mockResolvedValue(PrePayStepsResultFactory(mockPrePayStepsResult));
1010+
jest
1011+
.spyOn(priceManager, 'retrievePricingForCurrency')
1012+
.mockResolvedValue(mockPricingForCurrency);
9881013
jest
9891014
.spyOn(checkoutService, 'upgradeSubscription')
9901015
.mockResolvedValue(mockSubscription);
@@ -1081,106 +1106,111 @@ describe('CheckoutService', () => {
10811106
});
10821107
});
10831108
});
1109+
});
10841110

1085-
describe('upgradeSubscription', () => {
1086-
const customerId = 'cus_123';
1087-
const toPriceId = 'price_123';
1088-
const fromPriceId = 'price_321';
1089-
const cart = ResultCartFactory();
1090-
const redundantOverlaps = [
1091-
SubscriptionEligibilityUpgradeDowngradeResultFactory(),
1092-
];
1093-
const subscription = StripeSubscriptionFactory();
1094-
const redundantSubscription = StripeResponseFactory(
1095-
StripeSubscriptionFactory()
1096-
);
1111+
describe('upgradeSubscription', () => {
1112+
const customerId = 'cus_123';
1113+
const toPriceId = 'price_123';
1114+
const fromPriceId = 'price_321';
1115+
const cart = ResultCartFactory();
1116+
const redundantOverlaps = [
1117+
SubscriptionEligibilityUpgradeDowngradeResultFactory(),
1118+
];
1119+
const subscription = StripeSubscriptionFactory();
1120+
const redundantSubscription = StripeResponseFactory(
1121+
StripeSubscriptionFactory()
1122+
);
1123+
const mockPricingForCurrency = PricingForCurrencyFactory();
10971124

1098-
beforeEach(() => {
1099-
jest
1100-
.spyOn(subscriptionManager, 'update')
1101-
.mockResolvedValueOnce(StripeResponseFactory(subscription))
1102-
.mockResolvedValueOnce(StripeResponseFactory(redundantSubscription));
1103-
jest
1104-
.spyOn(subscriptionManager, 'cancel')
1105-
.mockResolvedValue(StripeResponseFactory(subscription));
1106-
});
1125+
beforeEach(() => {
1126+
jest
1127+
.spyOn(priceManager, 'retrievePricingForCurrency')
1128+
.mockResolvedValueOnce(mockPricingForCurrency);
1129+
jest
1130+
.spyOn(subscriptionManager, 'update')
1131+
.mockResolvedValueOnce(StripeResponseFactory(subscription))
1132+
.mockResolvedValueOnce(StripeResponseFactory(redundantSubscription));
1133+
jest
1134+
.spyOn(subscriptionManager, 'cancel')
1135+
.mockResolvedValue(StripeResponseFactory(subscription));
1136+
});
11071137

1108-
it('successfully calls subscription update', async () => {
1109-
jest
1110-
.spyOn(subscriptionManager, 'retrieveForCustomerAndPrice')
1111-
.mockResolvedValueOnce(subscription)
1112-
.mockResolvedValueOnce(redundantSubscription);
1138+
it('successfully calls subscription update', async () => {
1139+
jest
1140+
.spyOn(subscriptionManager, 'retrieveForCustomerAndPrice')
1141+
.mockResolvedValueOnce(subscription)
1142+
.mockResolvedValueOnce(redundantSubscription);
1143+
1144+
await checkoutService.upgradeSubscription(
1145+
customerId,
1146+
toPriceId,
1147+
fromPriceId,
1148+
cart,
1149+
[]
1150+
);
1151+
expect(priceManager.retrievePricingForCurrency).toHaveBeenCalled();
1152+
expect(subscriptionManager.update).toHaveBeenCalledTimes(1);
1153+
});
11131154

1114-
await checkoutService.upgradeSubscription(
1155+
it('successfully updates and cancels redundant subscriptions when present', async () => {
1156+
jest
1157+
.spyOn(subscriptionManager, 'retrieveForCustomerAndPrice')
1158+
.mockResolvedValueOnce(subscription)
1159+
.mockResolvedValueOnce(redundantSubscription);
1160+
1161+
await checkoutService.upgradeSubscription(
1162+
customerId,
1163+
toPriceId,
1164+
fromPriceId,
1165+
cart,
1166+
redundantOverlaps
1167+
);
1168+
expect(subscriptionManager.update).toHaveBeenCalledTimes(2);
1169+
expect(subscriptionManager.update).toHaveBeenNthCalledWith(
1170+
2,
1171+
redundantSubscription.id,
1172+
{
1173+
metadata: {
1174+
redundantCancellation: 'true',
1175+
autoCancelledRedundantFor: subscription.id,
1176+
cancelled_for_customer_at: expect.anything(),
1177+
},
1178+
}
1179+
);
1180+
expect(subscriptionManager.cancel).toHaveBeenCalledWith(
1181+
redundantSubscription.id,
1182+
{ prorate: true }
1183+
);
1184+
});
1185+
1186+
it('throws an error upgrade subscription could not be found', async () => {
1187+
jest
1188+
.spyOn(subscriptionManager, 'retrieveForCustomerAndPrice')
1189+
.mockResolvedValue(undefined);
1190+
await expect(
1191+
checkoutService.upgradeSubscription(
11151192
customerId,
11161193
toPriceId,
11171194
fromPriceId,
11181195
cart,
1119-
[]
1120-
);
1121-
expect(subscriptionManager.update).toHaveBeenCalledTimes(1);
1122-
});
1123-
1124-
it('successfully updates and cancels redundant subscriptions when present', async () => {
1125-
jest
1126-
.spyOn(subscriptionManager, 'retrieveForCustomerAndPrice')
1127-
.mockResolvedValueOnce(subscription)
1128-
.mockResolvedValueOnce(redundantSubscription);
1196+
redundantOverlaps
1197+
)
1198+
).rejects.toBeInstanceOf(CheckoutUpgradeError);
1199+
});
11291200

1130-
await checkoutService.upgradeSubscription(
1201+
it('throws unhandled error', async () => {
1202+
jest
1203+
.spyOn(subscriptionManager, 'retrieveForCustomerAndPrice')
1204+
.mockRejectedValue(new Error('unhandled error'));
1205+
await expect(
1206+
checkoutService.upgradeSubscription(
11311207
customerId,
11321208
toPriceId,
11331209
fromPriceId,
11341210
cart,
11351211
redundantOverlaps
1136-
);
1137-
expect(subscriptionManager.update).toHaveBeenCalledTimes(2);
1138-
expect(subscriptionManager.update).toHaveBeenNthCalledWith(
1139-
2,
1140-
redundantSubscription.id,
1141-
{
1142-
metadata: {
1143-
redundantCancellation: 'true',
1144-
autoCancelledRedundantFor: subscription.id,
1145-
cancelled_for_customer_at: expect.anything(),
1146-
},
1147-
}
1148-
);
1149-
expect(subscriptionManager.cancel).toHaveBeenCalledWith(
1150-
redundantSubscription.id,
1151-
{ prorate: true }
1152-
);
1153-
});
1154-
1155-
it('throws an error upgrade subscription could not be found', async () => {
1156-
jest
1157-
.spyOn(subscriptionManager, 'retrieveForCustomerAndPrice')
1158-
.mockResolvedValue(undefined);
1159-
await expect(
1160-
checkoutService.upgradeSubscription(
1161-
customerId,
1162-
toPriceId,
1163-
fromPriceId,
1164-
cart,
1165-
redundantOverlaps
1166-
)
1167-
).rejects.toBeInstanceOf(CheckoutUpgradeError);
1168-
});
1169-
1170-
it('throws unhandled error', async () => {
1171-
jest
1172-
.spyOn(subscriptionManager, 'retrieveForCustomerAndPrice')
1173-
.mockRejectedValue(new Error('unhandled error'));
1174-
await expect(
1175-
checkoutService.upgradeSubscription(
1176-
customerId,
1177-
toPriceId,
1178-
fromPriceId,
1179-
cart,
1180-
redundantOverlaps
1181-
)
1182-
).rejects.toBeInstanceOf(Error);
1183-
});
1212+
)
1213+
).rejects.toBeInstanceOf(Error);
11841214
});
11851215
});
11861216
});

0 commit comments

Comments
 (0)