143 lines
4.8 KiB
TypeScript
143 lines
4.8 KiB
TypeScript
import { describe, expect, it } from "@suaveplan/testing/runner";
|
|
import type { Tenant } from "../types/tenant.js";
|
|
import { createTenantContext, NullTenantContext } from "./context.js";
|
|
|
|
function makeTenant(over: Partial<Tenant> = {}): Tenant {
|
|
return {
|
|
id: "t_1",
|
|
name: "Acme",
|
|
slug: "acme",
|
|
status: "active",
|
|
settings: {},
|
|
enabledPlugins: ["payment"],
|
|
domains: [],
|
|
createdAt: new Date(0),
|
|
updatedAt: new Date(0),
|
|
...over,
|
|
};
|
|
}
|
|
|
|
describe("createTenantContext", () => {
|
|
it("exposes tenant and tenantId", { timeout: 5000 }, () => {
|
|
const ctx = createTenantContext(makeTenant());
|
|
expect(ctx.tenant.slug).toBe("acme");
|
|
expect(ctx.tenantId).toBe("t_1");
|
|
});
|
|
|
|
it("isPluginEnabled honours enabledPlugins", { timeout: 5000 }, () => {
|
|
const ctx = createTenantContext(makeTenant());
|
|
expect(ctx.isPluginEnabled("payment")).toBe(true);
|
|
expect(ctx.isPluginEnabled("ghost")).toBe(false);
|
|
});
|
|
|
|
it("getSetting walks dot-paths and returns default", {
|
|
timeout: 5000,
|
|
}, () => {
|
|
const ctx = createTenantContext(
|
|
makeTenant({
|
|
settings: {
|
|
custom: { nested: { value: 42 } },
|
|
timezone: "UTC",
|
|
},
|
|
})
|
|
);
|
|
expect(ctx.getSetting<number>("custom.nested.value")).toBe(42);
|
|
expect(ctx.getSetting<string>("timezone")).toBe("UTC");
|
|
expect(ctx.getSetting<number>("missing.path", 7)).toBe(7);
|
|
expect(ctx.getSetting<number>("missing.path")).toBeUndefined();
|
|
});
|
|
|
|
it("getSetting returns default when leaf is nullish", {
|
|
timeout: 5000,
|
|
}, () => {
|
|
const ctx = createTenantContext(
|
|
makeTenant({
|
|
settings: {
|
|
custom: {
|
|
explicitNull: null,
|
|
zero: 0,
|
|
} as Record<string, unknown>,
|
|
},
|
|
})
|
|
);
|
|
expect(ctx.getSetting<number>("custom.explicitNull", 42)).toBe(42);
|
|
// Leaf 0 is non-nullish; default ignored.
|
|
expect(ctx.getSetting<number>("custom.zero", 9)).toBe(0);
|
|
});
|
|
|
|
it("getSetting returns default when intermediate is null", {
|
|
timeout: 5000,
|
|
}, () => {
|
|
const ctx = createTenantContext(
|
|
makeTenant({
|
|
settings: {
|
|
custom: { nullSlot: null } as Record<string, unknown>,
|
|
},
|
|
})
|
|
);
|
|
expect(ctx.getSetting<number>("custom.nullSlot.x", 9)).toBe(9);
|
|
});
|
|
|
|
it("isFeatureEnabled reads features boolean", { timeout: 5000 }, () => {
|
|
const ctx = createTenantContext(
|
|
makeTenant({ settings: { features: { x: true, y: false } } })
|
|
);
|
|
expect(ctx.isFeatureEnabled("x")).toBe(true);
|
|
expect(ctx.isFeatureEnabled("y")).toBe(false);
|
|
expect(ctx.isFeatureEnabled("missing")).toBe(false);
|
|
});
|
|
|
|
it("isFeatureEnabled is false when no features map", {
|
|
timeout: 5000,
|
|
}, () => {
|
|
const ctx = createTenantContext(makeTenant());
|
|
expect(ctx.isFeatureEnabled("x")).toBe(false);
|
|
});
|
|
|
|
it("getLimit reads limits map", { timeout: 5000 }, () => {
|
|
const ctx = createTenantContext(
|
|
makeTenant({
|
|
settings: { limits: { maxUsers: 10, maxApiCalls: 1000 } },
|
|
})
|
|
);
|
|
expect(ctx.getLimit("maxUsers")).toBe(10);
|
|
expect(ctx.getLimit("maxApiCalls")).toBe(1000);
|
|
expect(ctx.getLimit("unknownKey")).toBeUndefined();
|
|
});
|
|
|
|
it("getLimit returns undefined when no limits", { timeout: 5000 }, () => {
|
|
const ctx = createTenantContext(makeTenant());
|
|
expect(ctx.getLimit("maxUsers")).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe("NullTenantContext", () => {
|
|
it("NullTenantContext fail-closes plugin check", { timeout: 5000 }, () => {
|
|
expect(NullTenantContext.isPluginEnabled("payment")).toBe(false);
|
|
expect(NullTenantContext.isPluginEnabled("anything")).toBe(false);
|
|
});
|
|
|
|
it("NullTenantContext fail-closes feature check", {
|
|
timeout: 5000,
|
|
}, () => {
|
|
expect(NullTenantContext.isFeatureEnabled("x")).toBe(false);
|
|
});
|
|
|
|
it("getSetting returns supplied default", { timeout: 5000 }, () => {
|
|
expect(NullTenantContext.getSetting<number>("any.key", 7)).toBe(7);
|
|
expect(NullTenantContext.getSetting<number>("any.key")).toBeUndefined();
|
|
});
|
|
|
|
it("getLimit returns undefined", { timeout: 5000 }, () => {
|
|
expect(NullTenantContext.getLimit("maxUsers")).toBeUndefined();
|
|
});
|
|
|
|
it("tenantId is empty string", { timeout: 5000 }, () => {
|
|
expect(NullTenantContext.tenantId).toBe("");
|
|
});
|
|
|
|
it("is frozen", { timeout: 5000 }, () => {
|
|
expect(Object.isFrozen(NullTenantContext)).toBe(true);
|
|
});
|
|
});
|