mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-21 03:03:25 -05:00
198 lines
7.2 KiB
TypeScript
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,
|
|
});
|
|
});
|
|
});
|