78 lines
4.6 KiB
TypeScript
78 lines
4.6 KiB
TypeScript
import "@testing-library/jest-dom";
|
|
import { render, screen } from "@testing-library/react";
|
|
import { MemoryRouter } from "react-router";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
import PageFeatureDisabled from "./PageFeatureDisabled";
|
|
import PagePlanRequired from "./PagePlanRequired";
|
|
|
|
vi.mock("~/components/brand/Logo", () => ({ default: () => <div data-testid="logo">Logo</div> }));
|
|
vi.mock("~/components/public/PublicFooter", () => ({ default: () => <footer data-testid="public-footer">Footer</footer> }));
|
|
vi.mock("react-i18next", () => ({
|
|
useTranslation: () => ({
|
|
t: (key: string, options?: Record<string, unknown>) => {
|
|
const messages: Record<string, string> = {
|
|
"access.planRequired.eyebrow": "Plan required",
|
|
"access.planRequired.title": "Upgrade your plan to continue.",
|
|
"access.planRequired.namedDescription": "This feature requires a higher subscription plan for {{tenant}}. Review your subscription to restore access.",
|
|
"access.planRequired.description": "This feature requires a higher subscription plan. Review your subscription to restore access.",
|
|
"access.planRequired.manageSubscription": "Manage subscription",
|
|
"access.featureDisabled.eyebrow": "Feature disabled",
|
|
"access.featureDisabled.title": "Feature unavailable.",
|
|
"access.featureDisabled.namedDescription": "{{feature}} is currently disabled.",
|
|
"access.featureDisabled.description": "This feature is currently disabled.",
|
|
"access.featureDisabled.fullDescription": "{{featureCopy}} Contact your administrator if you need access.",
|
|
"access.featureDisabled.backToDashboard": "Back to dashboard",
|
|
};
|
|
let value = typeof options?.defaultValue === "string" ? options.defaultValue : messages[key] ?? key;
|
|
for (const [name, replacement] of Object.entries(options ?? {})) {
|
|
value = value.replaceAll(`{{${name}}}`, String(replacement));
|
|
}
|
|
return value;
|
|
},
|
|
}),
|
|
}));
|
|
|
|
function renderAccessPage(page: React.ReactNode) {
|
|
return render(<MemoryRouter>{page}</MemoryRouter>);
|
|
}
|
|
|
|
describe("access-state pages", () => {
|
|
it("renders the plan-required page with shared 403 shell and subscription action", () => {
|
|
renderAccessPage(<PagePlanRequired tenantSlug="acme" subscriptionPath="/settings/subscription" />);
|
|
|
|
expect(screen.getByTestId("error-page")).toHaveAttribute("data-error-status", "403");
|
|
expect(screen.getByText("Plan required")).toBeInTheDocument();
|
|
expect(screen.getByRole("heading", { name: "Upgrade your plan to continue." })).toBeInTheDocument();
|
|
expect(screen.getByText("This feature requires a higher subscription plan for acme. Review your subscription to restore access.")).toBeInTheDocument();
|
|
expect(screen.getByRole("link", { name: "Manage subscription" })).toHaveAttribute("href", "/settings/subscription");
|
|
});
|
|
|
|
it("renders stable plan-required copy without optional tenant or action props", () => {
|
|
renderAccessPage(<PagePlanRequired />);
|
|
|
|
expect(screen.getByTestId("error-page")).toHaveAttribute("data-error-status", "403");
|
|
expect(screen.getByText("This feature requires a higher subscription plan. Review your subscription to restore access.")).toBeInTheDocument();
|
|
expect(screen.queryByRole("link", { name: "Manage subscription" })).not.toBeInTheDocument();
|
|
expect(screen.queryByText(/secret/i)).not.toBeInTheDocument();
|
|
});
|
|
|
|
it("renders the feature-disabled page with a safe dashboard action", () => {
|
|
renderAccessPage(<PageFeatureDisabled featureLabel="Advanced reports" dashboardPath="/teams/acme/dashboard" />);
|
|
|
|
expect(screen.getByTestId("error-page")).toHaveAttribute("data-error-status", "403");
|
|
expect(screen.getByText("Feature disabled")).toBeInTheDocument();
|
|
expect(screen.getByRole("heading", { name: "Feature unavailable." })).toBeInTheDocument();
|
|
expect(screen.getByText("Advanced reports is currently disabled. Contact your administrator if you need access.")).toBeInTheDocument();
|
|
expect(screen.getByRole("link", { name: "Back to dashboard" })).toHaveAttribute("href", "/teams/acme/dashboard");
|
|
});
|
|
|
|
it("renders stable feature-disabled copy without raw feature keys or custom paths", () => {
|
|
renderAccessPage(<PageFeatureDisabled />);
|
|
|
|
expect(screen.getByTestId("error-page")).toHaveAttribute("data-error-status", "403");
|
|
expect(screen.getByText("This feature is currently disabled. Contact your administrator if you need access.")).toBeInTheDocument();
|
|
expect(screen.getByRole("link", { name: "Back to dashboard" })).toHaveAttribute("href", "/dashboard");
|
|
expect(screen.queryByText("billing.enterprise.secret_feature")).not.toBeInTheDocument();
|
|
});
|
|
});
|