Skip to content

Commit dd3b420

Browse files
committed
fix: revalidate premium before deletion
1 parent 8d496ec commit dd3b420

12 files changed

Lines changed: 944 additions & 89 deletions

app/account/tabs/__tests__/delete-tab-premium.test.tsx

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
waitFor,
1919
} from "@testing-library/react-native";
2020
import React from "react";
21+
import { Alert } from "react-native";
2122

2223
import { useCydAccount } from "@/contexts/CydAccountProvider";
2324

@@ -241,6 +242,7 @@ describe("DeleteTab Premium Integration", () => {
241242

242243
beforeEach(() => {
243244
jest.clearAllMocks();
245+
mockCheckPremiumAccess.mockResolvedValue({ status: "signed_out" });
244246
mockWithBlueskyController.mockImplementation(
245247
async (_accountId, _accountUUID, fn) => {
246248
return fn({
@@ -370,6 +372,7 @@ describe("DeleteTab Premium Integration", () => {
370372
});
371373

372374
it("should show PremiumRequiredModal when signed in without premium", async () => {
375+
mockCheckPremiumAccess.mockResolvedValue({ status: "not_premium" });
373376
mockUseCydAccount.mockReturnValue({
374377
state: {
375378
isSignedIn: true,
@@ -476,6 +479,7 @@ describe("DeleteTab Premium Integration", () => {
476479
});
477480

478481
// Confirm premium
482+
mockCheckPremiumAccess.mockResolvedValue({ status: "premium" });
479483
await act(async () => {
480484
fireEvent.press(screen.getByTestId("premium-modal-confirm"));
481485
});
@@ -490,6 +494,7 @@ describe("DeleteTab Premium Integration", () => {
490494

491495
describe("Delete My Data button - with premium", () => {
492496
beforeEach(() => {
497+
mockCheckPremiumAccess.mockResolvedValue({ status: "premium" });
493498
mockUseCydAccount.mockReturnValue({
494499
state: {
495500
isSignedIn: true,
@@ -561,6 +566,25 @@ describe("DeleteTab Premium Integration", () => {
561566

562567
expect(screen.queryByTestId("premium-required-modal")).toBeNull();
563568
});
569+
570+
it("blocks deletion when cached Premium access has expired", async () => {
571+
mockCheckPremiumAccess.mockResolvedValue({ status: "not_premium" });
572+
render(<DeleteTab {...defaultProps} />);
573+
574+
await waitFor(() => {
575+
expect(screen.getByText("Continue to Review")).toBeTruthy();
576+
});
577+
fireEvent.press(screen.getByText("Continue to Review"));
578+
await waitFor(() => expect(screen.getByText("Delete My Data")).toBeTruthy());
579+
580+
fireEvent.press(screen.getByText("Delete My Data"));
581+
582+
await waitFor(() => {
583+
expect(mockCheckPremiumAccess).toHaveBeenCalledTimes(1);
584+
expect(screen.getByTestId("premium-required-modal")).toBeTruthy();
585+
});
586+
expect(screen.queryByTestId("delete-automation-modal")).toBeNull();
587+
});
564588
});
565589

566590
describe("Continue to Review button", () => {
@@ -585,7 +609,12 @@ describe("DeleteTab Premium Integration", () => {
585609
});
586610

587611
describe("premium check error handling", () => {
588-
it("should show PremiumRequiredModal when premium check fails with error", async () => {
612+
it("should show a retryable error when premium verification fails", async () => {
613+
const alertSpy = jest.spyOn(Alert, "alert").mockImplementation();
614+
mockCheckPremiumAccess.mockResolvedValue({
615+
status: "error",
616+
message: "Server error",
617+
});
589618
mockUseCydAccount.mockReturnValue({
590619
state: {
591620
isSignedIn: true,
@@ -618,13 +647,19 @@ describe("DeleteTab Premium Integration", () => {
618647
fireEvent.press(screen.getByText("Delete My Data"));
619648
});
620649

621-
// Should show premium modal (since hasPremiumAccess is false)
622650
await waitFor(() => {
623-
expect(screen.getByTestId("premium-required-modal")).toBeTruthy();
651+
expect(alertSpy).toHaveBeenCalledWith(
652+
"Couldn’t verify Premium",
653+
"Check your connection and try again.",
654+
expect.any(Array),
655+
);
624656
});
657+
expect(screen.queryByTestId("premium-required-modal")).toBeNull();
625658
});
626659

627-
it("should show PremiumRequiredModal when premium check throws", async () => {
660+
it("fails closed when the premium check throws", async () => {
661+
const alertSpy = jest.spyOn(Alert, "alert").mockImplementation();
662+
mockCheckPremiumAccess.mockRejectedValue(new Error("Network error"));
628663
mockUseCydAccount.mockReturnValue({
629664
state: {
630665
isSignedIn: true,
@@ -657,10 +692,10 @@ describe("DeleteTab Premium Integration", () => {
657692
fireEvent.press(screen.getByText("Delete My Data"));
658693
});
659694

660-
// Should show premium modal (since hasPremiumAccess is false)
661695
await waitFor(() => {
662-
expect(screen.getByTestId("premium-required-modal")).toBeTruthy();
696+
expect(alertSpy).toHaveBeenCalled();
663697
});
698+
expect(screen.queryByTestId("delete-automation-modal")).toBeNull();
664699
});
665700
});
666701
});

0 commit comments

Comments
 (0)