Files
formbricks/apps/web/modules/entitlements/lib/checks.test.ts
T

198 lines
7.2 KiB
TypeScript

import { beforeEach, describe, expect, test, vi } from "vitest";
import {
getOrganizationEntitlementLimits,
hasOrganizationEntitlement,
hasOrganizationEntitlementWithLicenseGuard,
} from "./checks";
import { getOrganizationEntitlementsContext } from "./provider";
import type { TOrganizationEntitlementsContext } from "./types";
vi.mock("server-only", () => ({}));
vi.mock("./provider", () => ({
getOrganizationEntitlementsContext: vi.fn(),
}));
vi.mock("./types", async (importOriginal) => {
const actual = await importOriginal<typeof import("./types")>();
return {
...actual,
isEntitlementFeature: actual.isEntitlementFeature,
};
});
const mockGetContext = vi.mocked(getOrganizationEntitlementsContext);
const baseContext: TOrganizationEntitlementsContext = {
organizationId: "org1",
source: "cloud_stripe",
features: ["rbac", "spam-protection"],
limits: { projects: 3, monthlyResponses: 500 },
licenseStatus: "no-license",
licenseFeatures: null,
stripeCustomerId: "cus_1",
subscriptionStatus: null,
usageCycleAnchor: null,
};
beforeEach(() => {
vi.clearAllMocks();
});
describe("hasOrganizationEntitlement", () => {
test("returns true when feature is present", async () => {
mockGetContext.mockResolvedValue(baseContext);
expect(await hasOrganizationEntitlement("org1", "rbac")).toBe(true);
});
test("returns false when feature is absent", async () => {
mockGetContext.mockResolvedValue(baseContext);
expect(await hasOrganizationEntitlement("org1", "hide-branding")).toBe(false);
});
test("returns false for unknown feature key", async () => {
mockGetContext.mockResolvedValue(baseContext);
expect(await hasOrganizationEntitlement("org1", "not-a-feature")).toBe(false);
});
});
describe("hasOrganizationEntitlementWithLicenseGuard", () => {
test("returns true when no license and feature present", async () => {
mockGetContext.mockResolvedValue(baseContext);
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "rbac")).toBe(true);
});
test("returns false for trial-restricted follow-ups while trialing", async () => {
mockGetContext.mockResolvedValue({
...baseContext,
features: ["follow-ups"],
subscriptionStatus: "trialing",
});
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "follow-ups")).toBe(false);
});
test("returns false for trial-restricted custom links while trialing", async () => {
mockGetContext.mockResolvedValue({
...baseContext,
features: ["custom-links-in-surveys"],
subscriptionStatus: "trialing",
});
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "custom-links-in-surveys")).toBe(false);
});
test("returns false for trial-restricted custom redirect while trialing", async () => {
mockGetContext.mockResolvedValue({
...baseContext,
features: ["custom-redirect-url"],
subscriptionStatus: "trialing",
});
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "custom-redirect-url")).toBe(false);
});
test("returns false when feature not present", async () => {
mockGetContext.mockResolvedValue(baseContext);
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "hide-branding")).toBe(false);
});
test("returns false for unknown feature key", async () => {
mockGetContext.mockResolvedValue(baseContext);
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "not-a-feature")).toBe(false);
});
test("returns false when license is inactive", async () => {
mockGetContext.mockResolvedValue({
...baseContext,
licenseStatus: "expired",
});
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "rbac")).toBe(false);
});
test("returns true when license active and mapped feature enabled", async () => {
mockGetContext.mockResolvedValue({
...baseContext,
licenseStatus: "active",
licenseFeatures: { accessControl: true } as TOrganizationEntitlementsContext["licenseFeatures"],
});
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "rbac")).toBe(true);
});
test("returns false when license active but mapped feature disabled", async () => {
mockGetContext.mockResolvedValue({
...baseContext,
licenseStatus: "active",
licenseFeatures: { accessControl: false } as TOrganizationEntitlementsContext["licenseFeatures"],
});
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "rbac")).toBe(false);
});
test("returns true when license active and ai-smart-tools mapped feature enabled", async () => {
mockGetContext.mockResolvedValue({
...baseContext,
features: ["ai-smart-tools"],
licenseStatus: "active",
licenseFeatures: { aiSmartTools: true } as TOrganizationEntitlementsContext["licenseFeatures"],
});
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "ai-smart-tools")).toBe(true);
});
test("returns false when license active but ai-smart-tools mapped feature disabled", async () => {
mockGetContext.mockResolvedValue({
...baseContext,
features: ["ai-smart-tools"],
licenseStatus: "active",
licenseFeatures: { aiSmartTools: false } as TOrganizationEntitlementsContext["licenseFeatures"],
});
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "ai-smart-tools")).toBe(false);
});
test("returns true when license active and ai-data-analysis mapped feature enabled", async () => {
mockGetContext.mockResolvedValue({
...baseContext,
features: ["ai-data-analysis"],
licenseStatus: "active",
licenseFeatures: { aiDataAnalysis: true } as TOrganizationEntitlementsContext["licenseFeatures"],
});
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "ai-data-analysis")).toBe(true);
});
test("returns false when license active but ai-data-analysis mapped feature disabled", async () => {
mockGetContext.mockResolvedValue({
...baseContext,
features: ["ai-data-analysis"],
licenseStatus: "active",
licenseFeatures: { aiDataAnalysis: false } as TOrganizationEntitlementsContext["licenseFeatures"],
});
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "ai-data-analysis")).toBe(false);
});
test("returns true when license active and feature has no license mapping", async () => {
mockGetContext.mockResolvedValue({
...baseContext,
features: ["custom-redirect-url"],
licenseStatus: "active",
subscriptionStatus: "active",
licenseFeatures: {} as TOrganizationEntitlementsContext["licenseFeatures"],
});
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "custom-redirect-url")).toBe(true);
});
test("does not affect unrelated features while trialing", async () => {
mockGetContext.mockResolvedValue({
...baseContext,
features: ["rbac"],
subscriptionStatus: "trialing",
});
expect(await hasOrganizationEntitlementWithLicenseGuard("org1", "rbac")).toBe(true);
});
});
describe("getOrganizationEntitlementLimits", () => {
test("returns limits from context", async () => {
mockGetContext.mockResolvedValue(baseContext);
expect(await getOrganizationEntitlementLimits("org1")).toEqual({
projects: 3,
monthlyResponses: 500,
});
});
});