mirror of
https://github.com/bitwarden/clients.git
synced 2026-07-04 21:05:54 +08:00
[PM-34685][Defect] Subscription status for organizations not updating with feature flag enabled (#20018)
This commit is contained in:
parent
ca0e443592
commit
9180d75244
@ -331,9 +331,12 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
|
||||
}
|
||||
|
||||
get subscriptionMarkedForCancel() {
|
||||
return (
|
||||
this.subscription != null && !this.subscription.cancelled && this.subscription.cancelAtEndDate
|
||||
);
|
||||
if (!this.subscription || this.subscription.cancelled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { status, cancelAtEndDate, cancelledDate } = this.subscription;
|
||||
return cancelAtEndDate || (status === "active" && !!cancelledDate);
|
||||
}
|
||||
|
||||
cancelSubscription = async () => {
|
||||
|
||||
@ -0,0 +1,114 @@
|
||||
import { DatePipe } from "@angular/common";
|
||||
import { TestBed } from "@angular/core/testing";
|
||||
import { mock } from "jest-mock-extended";
|
||||
|
||||
import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response";
|
||||
import { BillingSubscriptionResponse } from "@bitwarden/common/billing/models/response/subscription.response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import { SubscriptionStatusComponent } from "./subscription-status.component";
|
||||
|
||||
function makeSubscription(
|
||||
overrides: Partial<BillingSubscriptionResponse> = {},
|
||||
): BillingSubscriptionResponse {
|
||||
return {
|
||||
status: "active",
|
||||
cancelAtEndDate: false,
|
||||
cancelledDate: null,
|
||||
cancelled: false,
|
||||
items: [],
|
||||
...overrides,
|
||||
} as BillingSubscriptionResponse;
|
||||
}
|
||||
|
||||
function makeOrgResponse(
|
||||
subscription: BillingSubscriptionResponse | null,
|
||||
): OrganizationSubscriptionResponse {
|
||||
return { subscription } as OrganizationSubscriptionResponse;
|
||||
}
|
||||
|
||||
describe("SubscriptionStatusComponent", () => {
|
||||
let component: SubscriptionStatusComponent;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
SubscriptionStatusComponent,
|
||||
{ provide: I18nService, useValue: mock<I18nService>() },
|
||||
{ provide: DatePipe, useValue: mock<DatePipe>() },
|
||||
],
|
||||
});
|
||||
|
||||
component = TestBed.inject(SubscriptionStatusComponent);
|
||||
});
|
||||
|
||||
describe("status getter", () => {
|
||||
it("returns 'free' when there is no subscription", () => {
|
||||
component.organizationSubscriptionResponse = makeOrgResponse(null);
|
||||
expect(component.status).toBe("free");
|
||||
});
|
||||
|
||||
it("returns the subscription status when no cancellation is pending", () => {
|
||||
component.organizationSubscriptionResponse = makeOrgResponse(
|
||||
makeSubscription({ status: "active" }),
|
||||
);
|
||||
expect(component.status).toBe("active");
|
||||
});
|
||||
|
||||
it("returns 'pending_cancellation' when cancelAtEndDate is true", () => {
|
||||
component.organizationSubscriptionResponse = makeOrgResponse(
|
||||
makeSubscription({ cancelAtEndDate: true }),
|
||||
);
|
||||
expect(component.status).toBe("pending_cancellation");
|
||||
});
|
||||
|
||||
it("returns 'pending_cancellation' when cancelledDate is set (phase-based cancellation)", () => {
|
||||
component.organizationSubscriptionResponse = makeOrgResponse(
|
||||
makeSubscription({ cancelledDate: "2026-05-01" }),
|
||||
);
|
||||
expect(component.status).toBe("pending_cancellation");
|
||||
});
|
||||
|
||||
it("returns 'canceled' even when cancelAtEndDate is true", () => {
|
||||
component.organizationSubscriptionResponse = makeOrgResponse(
|
||||
makeSubscription({ status: "canceled", cancelAtEndDate: true }),
|
||||
);
|
||||
expect(component.status).toBe("canceled");
|
||||
});
|
||||
|
||||
it("returns 'canceled' even when cancelledDate is set", () => {
|
||||
component.organizationSubscriptionResponse = makeOrgResponse(
|
||||
makeSubscription({ status: "canceled", cancelledDate: "2026-05-01" }),
|
||||
);
|
||||
expect(component.status).toBe("canceled");
|
||||
});
|
||||
|
||||
it("returns 'trialing' when status is trialing", () => {
|
||||
component.organizationSubscriptionResponse = makeOrgResponse(
|
||||
makeSubscription({ status: "trialing" }),
|
||||
);
|
||||
expect(component.status).toBe("trialing");
|
||||
});
|
||||
|
||||
it("returns 'past_due' when status is past_due", () => {
|
||||
component.organizationSubscriptionResponse = makeOrgResponse(
|
||||
makeSubscription({ status: "past_due" }),
|
||||
);
|
||||
expect(component.status).toBe("past_due");
|
||||
});
|
||||
|
||||
it("returns 'unpaid' when status is unpaid", () => {
|
||||
component.organizationSubscriptionResponse = makeOrgResponse(
|
||||
makeSubscription({ status: "unpaid" }),
|
||||
);
|
||||
expect(component.status).toBe("unpaid");
|
||||
});
|
||||
|
||||
it("returns 'incomplete_expired' when status is incomplete_expired", () => {
|
||||
component.organizationSubscriptionResponse = makeOrgResponse(
|
||||
makeSubscription({ status: "incomplete_expired" }),
|
||||
);
|
||||
expect(component.status).toBe("incomplete_expired");
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -53,11 +53,18 @@ export class SubscriptionStatusComponent {
|
||||
}
|
||||
|
||||
get status(): string {
|
||||
return this.subscription
|
||||
? this.subscription.status != "canceled" && this.subscription.cancelAtEndDate
|
||||
? "pending_cancellation"
|
||||
: this.subscription.status
|
||||
: "free";
|
||||
if (!this.subscription) {
|
||||
return "free";
|
||||
}
|
||||
|
||||
const { status, cancelAtEndDate, cancelledDate } = this.subscription;
|
||||
const pendingCancellation = cancelAtEndDate || (status === "active" && !!cancelledDate);
|
||||
|
||||
if (status !== "canceled" && pendingCancellation) {
|
||||
return "pending_cancellation";
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
get subscription() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user