104 lines
2.8 KiB
TypeScript
104 lines
2.8 KiB
TypeScript
import { api } from "@/lib/api";
|
|
import {
|
|
fetchOrganizationBillingState,
|
|
hasOrganizationBillingAccess,
|
|
isOrganizationBillingQueryEnabled,
|
|
shouldShowInAppBillingPaywall,
|
|
type OrganizationBillingState,
|
|
} from "@/hooks/organization";
|
|
|
|
jest.mock("@/lib/api", () => ({
|
|
api: {
|
|
get: jest.fn(),
|
|
},
|
|
}));
|
|
|
|
jest.mock("@/stores/auth", () => ({
|
|
useAuthStore: jest.fn(),
|
|
}));
|
|
|
|
const mockedApi = api as jest.Mocked<typeof api>;
|
|
|
|
const baseOrganizationState: OrganizationBillingState = {
|
|
active_subscription_plan: null,
|
|
active_subscription_quantity: 0,
|
|
invites_sent: [],
|
|
is_billing_owner: true,
|
|
is_trial_expired: true,
|
|
members: [],
|
|
organization: {
|
|
id: 1,
|
|
logo_url: null,
|
|
member_count: 1,
|
|
name: "XTablo",
|
|
plan: "solo",
|
|
tablo_count: 0,
|
|
},
|
|
required_plan: "solo",
|
|
required_team_quantity: 1,
|
|
trial_ends_at: "2026-05-16T00:00:00.000Z",
|
|
trial_starts_at: "2026-05-02T00:00:00.000Z",
|
|
};
|
|
|
|
describe("organization billing hook helpers", () => {
|
|
beforeEach(() => {
|
|
mockedApi.get.mockReset();
|
|
});
|
|
|
|
it("fetches the organization billing payload with the current bearer token", async () => {
|
|
mockedApi.get.mockResolvedValue({ data: baseOrganizationState });
|
|
|
|
const result = await fetchOrganizationBillingState("session-token");
|
|
|
|
expect(mockedApi.get).toHaveBeenCalledWith("/api/v1/users/organization", {
|
|
headers: {
|
|
Authorization: "Bearer session-token",
|
|
},
|
|
});
|
|
expect(result).toEqual(baseOrganizationState);
|
|
});
|
|
|
|
it("enables the query only when an access token is present", () => {
|
|
expect(isOrganizationBillingQueryEnabled(null)).toBe(false);
|
|
expect(isOrganizationBillingQueryEnabled(undefined)).toBe(false);
|
|
expect(isOrganizationBillingQueryEnabled("token")).toBe(true);
|
|
});
|
|
|
|
it("treats active subscriptions and active trials as organization access", () => {
|
|
expect(hasOrganizationBillingAccess(baseOrganizationState)).toBe(false);
|
|
expect(
|
|
hasOrganizationBillingAccess({
|
|
...baseOrganizationState,
|
|
active_subscription_plan: "annual",
|
|
})
|
|
).toBe(true);
|
|
expect(
|
|
hasOrganizationBillingAccess({
|
|
...baseOrganizationState,
|
|
is_trial_expired: false,
|
|
})
|
|
).toBe(true);
|
|
});
|
|
|
|
it("shows the iOS paywall only to unpaid billing owners after the trial expires", () => {
|
|
expect(shouldShowInAppBillingPaywall(baseOrganizationState)).toBe(true);
|
|
expect(
|
|
shouldShowInAppBillingPaywall({
|
|
...baseOrganizationState,
|
|
is_billing_owner: false,
|
|
})
|
|
).toBe(false);
|
|
expect(
|
|
shouldShowInAppBillingPaywall({
|
|
...baseOrganizationState,
|
|
active_subscription_plan: "solo",
|
|
})
|
|
).toBe(false);
|
|
expect(
|
|
shouldShowInAppBillingPaywall({
|
|
...baseOrganizationState,
|
|
is_trial_expired: false,
|
|
})
|
|
).toBe(false);
|
|
});
|
|
});
|