mirror of
https://github.com/bitwarden/browser
synced 2026-02-20 03:13:55 +00:00
[PM-30908]Correct Premium subscription status handling (#18475)
* Implement the required changes * Fix the family plan creation for expired sub * Resolve the pr comments * resolve the resubscribe issue * Removed redirectOnCompletion: true from the resubscribe * Display the Change payment method dialog on the subscription page * adjust the page reload time * revert payment method open in subscription page * Enable cancel premium see the subscription page * Revert the removal of hasPremiumPersonally * remove extra space * Add can view subscription * Use the canViewSubscription * Resolve the tab default to premium * use the subscription Instead of hasPremium * Revert the changes on user-subscription * Use the flag to redirect to subscription page * revert the canViewSubscription change * resolve the route issue with premium * Change the path to * Revert the previous iteration changes * Fix the build error
This commit is contained in:
committed by
jaasen-livefront
parent
b801f1c710
commit
a377312759
@@ -78,6 +78,7 @@ type SubscriptionCardAction =
|
||||
| "contact-support"
|
||||
| "manage-invoices"
|
||||
| "reinstate-subscription"
|
||||
| "resubscribe"
|
||||
| "update-payment"
|
||||
| "upgrade-plan";
|
||||
```
|
||||
@@ -279,7 +280,7 @@ Payment issue expired, subscription has been suspended:
|
||||
</billing-subscription-card>
|
||||
```
|
||||
|
||||
**Actions available:** Contact Support
|
||||
**Actions available:** Resubscribe
|
||||
|
||||
### Past Due
|
||||
|
||||
@@ -370,7 +371,7 @@ Subscription that has been canceled:
|
||||
</billing-subscription-card>
|
||||
```
|
||||
|
||||
**Note:** Canceled subscriptions display no callout or actions.
|
||||
**Actions available:** Resubscribe
|
||||
|
||||
### Enterprise
|
||||
|
||||
|
||||
@@ -44,9 +44,11 @@ describe("SubscriptionCardComponent", () => {
|
||||
unpaid: "Unpaid",
|
||||
weCouldNotProcessYourPayment: "We could not process your payment",
|
||||
contactSupportShort: "Contact support",
|
||||
yourSubscriptionHasExpired: "Your subscription has expired",
|
||||
yourSubscriptionIsExpired: "Your subscription is expired",
|
||||
yourSubscriptionIsCanceled: "Your subscription is canceled",
|
||||
yourSubscriptionIsScheduledToCancel: `Your subscription is scheduled to cancel on ${params[0]}`,
|
||||
reinstateSubscription: "Reinstate subscription",
|
||||
resubscribe: "Resubscribe",
|
||||
upgradeYourPlan: "Upgrade your plan",
|
||||
premiumShareEvenMore: "Premium share even more",
|
||||
upgradeNow: "Upgrade now",
|
||||
@@ -253,7 +255,7 @@ describe("SubscriptionCardComponent", () => {
|
||||
expect(buttons[1].nativeElement.textContent.trim()).toBe("Contact support");
|
||||
});
|
||||
|
||||
it("should display incomplete_expired callout with contact support action", () => {
|
||||
it("should display incomplete_expired callout with resubscribe action", () => {
|
||||
setupComponent({
|
||||
...baseSubscription,
|
||||
status: "incomplete_expired",
|
||||
@@ -265,18 +267,18 @@ describe("SubscriptionCardComponent", () => {
|
||||
expect(calloutData).toBeTruthy();
|
||||
expect(calloutData!.type).toBe("danger");
|
||||
expect(calloutData!.title).toBe("Expired");
|
||||
expect(calloutData!.description).toContain("Your subscription has expired");
|
||||
expect(calloutData!.description).toContain("Your subscription is expired");
|
||||
expect(calloutData!.callsToAction?.length).toBe(1);
|
||||
|
||||
const callout = fixture.debugElement.query(By.css("bit-callout"));
|
||||
expect(callout).toBeTruthy();
|
||||
|
||||
const description = callout.query(By.css("p"));
|
||||
expect(description.nativeElement.textContent).toContain("Your subscription has expired");
|
||||
expect(description.nativeElement.textContent).toContain("Your subscription is expired");
|
||||
|
||||
const buttons = callout.queryAll(By.css("button"));
|
||||
expect(buttons.length).toBe(1);
|
||||
expect(buttons[0].nativeElement.textContent.trim()).toBe("Contact support");
|
||||
expect(buttons[0].nativeElement.textContent.trim()).toBe("Resubscribe");
|
||||
});
|
||||
|
||||
it("should display pending cancellation callout for active status with cancelAt", () => {
|
||||
@@ -364,15 +366,29 @@ describe("SubscriptionCardComponent", () => {
|
||||
expect(buttons[0].nativeElement.textContent.trim()).toBe("Manage invoices");
|
||||
});
|
||||
|
||||
it("should not display callout for canceled status", () => {
|
||||
it("should display canceled callout with resubscribe action", () => {
|
||||
setupComponent({
|
||||
...baseSubscription,
|
||||
status: "canceled",
|
||||
canceled: new Date("2025-01-15"),
|
||||
});
|
||||
|
||||
const calloutData = component.callout();
|
||||
expect(calloutData).toBeTruthy();
|
||||
expect(calloutData!.type).toBe("danger");
|
||||
expect(calloutData!.title).toBe("Canceled");
|
||||
expect(calloutData!.description).toContain("Your subscription is canceled");
|
||||
expect(calloutData!.callsToAction?.length).toBe(1);
|
||||
|
||||
const callout = fixture.debugElement.query(By.css("bit-callout"));
|
||||
expect(callout).toBeFalsy();
|
||||
expect(callout).toBeTruthy();
|
||||
|
||||
const description = callout.query(By.css("p"));
|
||||
expect(description.nativeElement.textContent).toContain("Your subscription is canceled");
|
||||
|
||||
const buttons = callout.queryAll(By.css("button"));
|
||||
expect(buttons.length).toBe(1);
|
||||
expect(buttons[0].nativeElement.textContent.trim()).toBe("Resubscribe");
|
||||
});
|
||||
|
||||
it("should display unpaid callout with manage invoices action", () => {
|
||||
@@ -489,6 +505,39 @@ describe("SubscriptionCardComponent", () => {
|
||||
|
||||
expect(emitSpy).toHaveBeenCalledWith("manage-invoices");
|
||||
});
|
||||
|
||||
it("should emit resubscribe action when button is clicked for incomplete_expired status", () => {
|
||||
setupComponent({
|
||||
...baseSubscription,
|
||||
status: "incomplete_expired",
|
||||
suspension: new Date("2025-01-15"),
|
||||
gracePeriod: 7,
|
||||
});
|
||||
|
||||
const emitSpy = jest.spyOn(component.callToActionClicked, "emit");
|
||||
|
||||
const button = fixture.debugElement.query(By.css("bit-callout button"));
|
||||
button.triggerEventHandler("click", { button: 0 });
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(emitSpy).toHaveBeenCalledWith("resubscribe");
|
||||
});
|
||||
|
||||
it("should emit resubscribe action when button is clicked for canceled status", () => {
|
||||
setupComponent({
|
||||
...baseSubscription,
|
||||
status: "canceled",
|
||||
canceled: new Date("2025-01-15"),
|
||||
});
|
||||
|
||||
const emitSpy = jest.spyOn(component.callToActionClicked, "emit");
|
||||
|
||||
const button = fixture.debugElement.query(By.css("bit-callout button"));
|
||||
button.triggerEventHandler("click", { button: 0 });
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(emitSpy).toHaveBeenCalledWith("resubscribe");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Cart summary header content", () => {
|
||||
|
||||
@@ -51,10 +51,13 @@ export default {
|
||||
weCouldNotProcessYourPayment:
|
||||
"We could not process your payment. Please update your payment method or contact the support team for assistance.",
|
||||
contactSupportShort: "Contact Support",
|
||||
yourSubscriptionHasExpired:
|
||||
"Your subscription has expired. Please contact the support team for assistance.",
|
||||
yourSubscriptionIsExpired:
|
||||
"Your subscription is expired. Please resubscribe to continue using premium features.",
|
||||
yourSubscriptionIsCanceled:
|
||||
"Your subscription is canceled. Please resubscribe to continue using premium features.",
|
||||
yourSubscriptionIsScheduledToCancel: `Your subscription is scheduled to cancel on ${args[0]}. You can reinstate it anytime before then.`,
|
||||
reinstateSubscription: "Reinstate subscription",
|
||||
resubscribe: "Resubscribe",
|
||||
upgradeYourPlan: "Upgrade your plan",
|
||||
premiumShareEvenMore:
|
||||
"Share even more with Families, or get powerful, trusted password security with Teams or Enterprise.",
|
||||
|
||||
@@ -20,6 +20,7 @@ export const SubscriptionCardActions = {
|
||||
ContactSupport: "contact-support",
|
||||
ManageInvoices: "manage-invoices",
|
||||
ReinstateSubscription: "reinstate-subscription",
|
||||
Resubscribe: "resubscribe",
|
||||
UpdatePayment: "update-payment",
|
||||
UpgradePlan: "upgrade-plan",
|
||||
} as const;
|
||||
@@ -154,12 +155,12 @@ export class SubscriptionCardComponent {
|
||||
return {
|
||||
title: this.i18nService.t("expired"),
|
||||
type: "danger",
|
||||
description: this.i18nService.t("yourSubscriptionHasExpired"),
|
||||
description: this.i18nService.t("yourSubscriptionIsExpired"),
|
||||
callsToAction: [
|
||||
{
|
||||
text: this.i18nService.t("contactSupportShort"),
|
||||
text: this.i18nService.t("resubscribe"),
|
||||
buttonType: "unstyled",
|
||||
action: SubscriptionCardActions.ContactSupport,
|
||||
action: SubscriptionCardActions.Resubscribe,
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -218,7 +219,18 @@ export class SubscriptionCardComponent {
|
||||
};
|
||||
}
|
||||
case SubscriptionStatuses.Canceled: {
|
||||
return null;
|
||||
return {
|
||||
title: this.i18nService.t("canceled"),
|
||||
type: "danger",
|
||||
description: this.i18nService.t("yourSubscriptionIsCanceled"),
|
||||
callsToAction: [
|
||||
{
|
||||
text: this.i18nService.t("resubscribe"),
|
||||
buttonType: "unstyled",
|
||||
action: SubscriptionCardActions.Resubscribe,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
case SubscriptionStatuses.Unpaid: {
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user