xtablo-source/xtablo-expo/components/__tests__/organization-hook.test.ts
2026-05-03 09:28:46 +02:00

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);
});
});