mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-30 10:19:51 -06:00
Co-authored-by: Harsh Bhat <90265455+harshsbhat@users.noreply.github.com> Co-authored-by: Johannes <johannes@formbricks.com> Co-authored-by: Piyush Gupta <56182734+gupta-piyush19@users.noreply.github.com> Co-authored-by: Aditya <162564995+Naidu-4444@users.noreply.github.com> Co-authored-by: Piyush Gupta <piyushguptaa2z123@gmail.com> Co-authored-by: pandeymangg <anshuman.pandey9999@gmail.com> Co-authored-by: Dhruwang Jariwala <67850763+Dhruwang@users.noreply.github.com> Co-authored-by: Johannes <72809645+jobenjada@users.noreply.github.com> Co-authored-by: Jakob Schott <154420406+jakobsitory@users.noreply.github.com> Co-authored-by: Suraj <surajsuthar0067@gmail.com> Co-authored-by: Kshitij Sharma <63995641+kshitij-codes@users.noreply.github.com> Co-authored-by: Dhruwang <dhruwangjariwala18@gmail.com> Co-authored-by: Matti Nannt <mail@matthiasnannt.com>
382 lines
13 KiB
TypeScript
382 lines
13 KiB
TypeScript
import { describe, expect, test } from "vitest";
|
|
import { createCacheKey, parseCacheKey, validateCacheKey } from "./cacheKeys";
|
|
|
|
describe("cacheKeys", () => {
|
|
describe("createCacheKey", () => {
|
|
describe("environment keys", () => {
|
|
test("should create environment state key", () => {
|
|
const key = createCacheKey.environment.state("env123");
|
|
expect(key).toBe("fb:env:env123:state");
|
|
});
|
|
|
|
test("should create environment surveys key", () => {
|
|
const key = createCacheKey.environment.surveys("env456");
|
|
expect(key).toBe("fb:env:env456:surveys");
|
|
});
|
|
|
|
test("should create environment actionClasses key", () => {
|
|
const key = createCacheKey.environment.actionClasses("env789");
|
|
expect(key).toBe("fb:env:env789:action_classes");
|
|
});
|
|
|
|
test("should create environment config key", () => {
|
|
const key = createCacheKey.environment.config("env101");
|
|
expect(key).toBe("fb:env:env101:config");
|
|
});
|
|
|
|
test("should create environment segments key", () => {
|
|
const key = createCacheKey.environment.segments("env202");
|
|
expect(key).toBe("fb:env:env202:segments");
|
|
});
|
|
});
|
|
|
|
describe("organization keys", () => {
|
|
test("should create organization billing key", () => {
|
|
const key = createCacheKey.organization.billing("org123");
|
|
expect(key).toBe("fb:org:org123:billing");
|
|
});
|
|
|
|
test("should create organization environments key", () => {
|
|
const key = createCacheKey.organization.environments("org456");
|
|
expect(key).toBe("fb:org:org456:environments");
|
|
});
|
|
|
|
test("should create organization config key", () => {
|
|
const key = createCacheKey.organization.config("org789");
|
|
expect(key).toBe("fb:org:org789:config");
|
|
});
|
|
|
|
test("should create organization limits key", () => {
|
|
const key = createCacheKey.organization.limits("org101");
|
|
expect(key).toBe("fb:org:org101:limits");
|
|
});
|
|
});
|
|
|
|
describe("license keys", () => {
|
|
test("should create license status key", () => {
|
|
const key = createCacheKey.license.status("org123");
|
|
expect(key).toBe("fb:license:org123:status");
|
|
});
|
|
|
|
test("should create license features key", () => {
|
|
const key = createCacheKey.license.features("org456");
|
|
expect(key).toBe("fb:license:org456:features");
|
|
});
|
|
|
|
test("should create license usage key", () => {
|
|
const key = createCacheKey.license.usage("org789");
|
|
expect(key).toBe("fb:license:org789:usage");
|
|
});
|
|
|
|
test("should create license check key", () => {
|
|
const key = createCacheKey.license.check("org123", "feature-x");
|
|
expect(key).toBe("fb:license:org123:check:feature-x");
|
|
});
|
|
|
|
test("should create license previous_result key", () => {
|
|
const key = createCacheKey.license.previous_result("org456");
|
|
expect(key).toBe("fb:license:org456:previous_result");
|
|
});
|
|
});
|
|
|
|
describe("user keys", () => {
|
|
test("should create user profile key", () => {
|
|
const key = createCacheKey.user.profile("user123");
|
|
expect(key).toBe("fb:user:user123:profile");
|
|
});
|
|
|
|
test("should create user preferences key", () => {
|
|
const key = createCacheKey.user.preferences("user456");
|
|
expect(key).toBe("fb:user:user456:preferences");
|
|
});
|
|
|
|
test("should create user organizations key", () => {
|
|
const key = createCacheKey.user.organizations("user789");
|
|
expect(key).toBe("fb:user:user789:organizations");
|
|
});
|
|
|
|
test("should create user permissions key", () => {
|
|
const key = createCacheKey.user.permissions("user123", "org456");
|
|
expect(key).toBe("fb:user:user123:org:org456:permissions");
|
|
});
|
|
});
|
|
|
|
describe("project keys", () => {
|
|
test("should create project config key", () => {
|
|
const key = createCacheKey.project.config("proj123");
|
|
expect(key).toBe("fb:project:proj123:config");
|
|
});
|
|
|
|
test("should create project environments key", () => {
|
|
const key = createCacheKey.project.environments("proj456");
|
|
expect(key).toBe("fb:project:proj456:environments");
|
|
});
|
|
|
|
test("should create project surveys key", () => {
|
|
const key = createCacheKey.project.surveys("proj789");
|
|
expect(key).toBe("fb:project:proj789:surveys");
|
|
});
|
|
});
|
|
|
|
describe("survey keys", () => {
|
|
test("should create survey metadata key", () => {
|
|
const key = createCacheKey.survey.metadata("survey123");
|
|
expect(key).toBe("fb:survey:survey123:metadata");
|
|
});
|
|
|
|
test("should create survey responses key", () => {
|
|
const key = createCacheKey.survey.responses("survey456");
|
|
expect(key).toBe("fb:survey:survey456:responses");
|
|
});
|
|
|
|
test("should create survey stats key", () => {
|
|
const key = createCacheKey.survey.stats("survey789");
|
|
expect(key).toBe("fb:survey:survey789:stats");
|
|
});
|
|
});
|
|
|
|
describe("session keys", () => {
|
|
test("should create session data key", () => {
|
|
const key = createCacheKey.session.data("session123");
|
|
expect(key).toBe("fb:session:session123:data");
|
|
});
|
|
|
|
test("should create session permissions key", () => {
|
|
const key = createCacheKey.session.permissions("session456");
|
|
expect(key).toBe("fb:session:session456:permissions");
|
|
});
|
|
});
|
|
|
|
describe("rate limit keys", () => {
|
|
test("should create rate limit api key", () => {
|
|
const key = createCacheKey.rateLimit.api("api-key-123", "endpoint-v1");
|
|
expect(key).toBe("fb:rate_limit:api:api-key-123:endpoint-v1");
|
|
});
|
|
|
|
test("should create rate limit login key", () => {
|
|
const key = createCacheKey.rateLimit.login("user-ip-hash");
|
|
expect(key).toBe("fb:rate_limit:login:user-ip-hash");
|
|
});
|
|
|
|
test("should create rate limit core key", () => {
|
|
const key = createCacheKey.rateLimit.core("auth:login", "user123", 1703174400);
|
|
expect(key).toBe("fb:rate_limit:auth:login:user123:1703174400");
|
|
});
|
|
});
|
|
|
|
describe("custom keys", () => {
|
|
test("should create custom key without subResource", () => {
|
|
const key = createCacheKey.custom("temp", "identifier123");
|
|
expect(key).toBe("fb:temp:identifier123");
|
|
});
|
|
|
|
test("should create custom key with subResource", () => {
|
|
const key = createCacheKey.custom("analytics", "user456", "daily-stats");
|
|
expect(key).toBe("fb:analytics:user456:daily-stats");
|
|
});
|
|
|
|
test("should work with all valid namespaces", () => {
|
|
const validNamespaces = ["temp", "analytics", "webhook", "integration", "backup"];
|
|
|
|
validNamespaces.forEach((namespace) => {
|
|
const key = createCacheKey.custom(namespace, "test-id");
|
|
expect(key).toBe(`fb:${namespace}:test-id`);
|
|
});
|
|
});
|
|
|
|
test("should throw error for invalid namespace", () => {
|
|
expect(() => createCacheKey.custom("invalid", "identifier")).toThrow(
|
|
"Invalid cache namespace: invalid. Use: temp, analytics, webhook, integration, backup"
|
|
);
|
|
});
|
|
|
|
test("should throw error for empty namespace", () => {
|
|
expect(() => createCacheKey.custom("", "identifier")).toThrow(
|
|
"Invalid cache namespace: . Use: temp, analytics, webhook, integration, backup"
|
|
);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("validateCacheKey", () => {
|
|
test("should validate correct cache keys", () => {
|
|
const validKeys = [
|
|
"fb:env:env123:state",
|
|
"fb:user:user456:profile",
|
|
"fb:org:org789:billing",
|
|
"fb:rate_limit:api:key123:endpoint",
|
|
"fb:custom:namespace:identifier:sub:resource",
|
|
];
|
|
|
|
validKeys.forEach((key) => {
|
|
expect(validateCacheKey(key)).toBe(true);
|
|
});
|
|
});
|
|
|
|
test("should reject keys without fb prefix", () => {
|
|
const invalidKeys = ["env:env123:state", "user:user456:profile", "redis:key:value", "cache:item:data"];
|
|
|
|
invalidKeys.forEach((key) => {
|
|
expect(validateCacheKey(key)).toBe(false);
|
|
});
|
|
});
|
|
|
|
test("should reject keys with insufficient parts", () => {
|
|
const invalidKeys = ["fb:", "fb:env", "fb:env:", "fb:user:user123:"];
|
|
|
|
invalidKeys.forEach((key) => {
|
|
expect(validateCacheKey(key)).toBe(false);
|
|
});
|
|
});
|
|
|
|
test("should reject keys with empty parts", () => {
|
|
const invalidKeys = ["fb::env123:state", "fb:env::state", "fb:env:env123:", "fb:user::profile"];
|
|
|
|
invalidKeys.forEach((key) => {
|
|
expect(validateCacheKey(key)).toBe(false);
|
|
});
|
|
});
|
|
|
|
test("should validate minimum valid key", () => {
|
|
expect(validateCacheKey("fb:a:b")).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("parseCacheKey", () => {
|
|
test("should parse basic cache key", () => {
|
|
const result = parseCacheKey("fb:env:env123:state");
|
|
|
|
expect(result).toEqual({
|
|
prefix: "fb",
|
|
resource: "env",
|
|
identifier: "env123",
|
|
subResource: "state",
|
|
full: "fb:env:env123:state",
|
|
});
|
|
});
|
|
|
|
test("should parse key without subResource", () => {
|
|
const result = parseCacheKey("fb:user:user123");
|
|
|
|
expect(result).toEqual({
|
|
prefix: "fb",
|
|
resource: "user",
|
|
identifier: "user123",
|
|
subResource: undefined,
|
|
full: "fb:user:user123",
|
|
});
|
|
});
|
|
|
|
test("should parse key with multiple subResource parts", () => {
|
|
const result = parseCacheKey("fb:user:user123:org:org456:permissions");
|
|
|
|
expect(result).toEqual({
|
|
prefix: "fb",
|
|
resource: "user",
|
|
identifier: "user123",
|
|
subResource: "org:org456:permissions",
|
|
full: "fb:user:user123:org:org456:permissions",
|
|
});
|
|
});
|
|
|
|
test("should parse rate limit key with timestamp", () => {
|
|
const result = parseCacheKey("fb:rate_limit:auth:login:user123:1703174400");
|
|
|
|
expect(result).toEqual({
|
|
prefix: "fb",
|
|
resource: "rate_limit",
|
|
identifier: "auth",
|
|
subResource: "login:user123:1703174400",
|
|
full: "fb:rate_limit:auth:login:user123:1703174400",
|
|
});
|
|
});
|
|
|
|
test("should throw error for invalid cache key", () => {
|
|
const invalidKeys = ["invalid:key:format", "fb:env", "fb::env123:state", "redis:user:profile"];
|
|
|
|
invalidKeys.forEach((key) => {
|
|
expect(() => parseCacheKey(key)).toThrow(`Invalid cache key format: ${key}`);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("cache key patterns and consistency", () => {
|
|
test("all environment keys should follow same pattern", () => {
|
|
const envId = "test-env-123";
|
|
const envKeys = [
|
|
createCacheKey.environment.state(envId),
|
|
createCacheKey.environment.surveys(envId),
|
|
createCacheKey.environment.actionClasses(envId),
|
|
createCacheKey.environment.config(envId),
|
|
createCacheKey.environment.segments(envId),
|
|
];
|
|
|
|
envKeys.forEach((key) => {
|
|
expect(key).toMatch(/^fb:env:test-env-123:.+$/);
|
|
expect(validateCacheKey(key)).toBe(true);
|
|
});
|
|
});
|
|
|
|
test("all organization keys should follow same pattern", () => {
|
|
const orgId = "test-org-456";
|
|
const orgKeys = [
|
|
createCacheKey.organization.billing(orgId),
|
|
createCacheKey.organization.environments(orgId),
|
|
createCacheKey.organization.config(orgId),
|
|
createCacheKey.organization.limits(orgId),
|
|
];
|
|
|
|
orgKeys.forEach((key) => {
|
|
expect(key).toMatch(/^fb:org:test-org-456:.+$/);
|
|
expect(validateCacheKey(key)).toBe(true);
|
|
});
|
|
});
|
|
|
|
test("all generated keys should be parseable", () => {
|
|
const testKeys = [
|
|
createCacheKey.environment.state("env123"),
|
|
createCacheKey.user.profile("user456"),
|
|
createCacheKey.organization.billing("org789"),
|
|
createCacheKey.survey.metadata("survey101"),
|
|
createCacheKey.session.data("session202"),
|
|
createCacheKey.rateLimit.core("auth:login", "user303", 1703174400),
|
|
createCacheKey.custom("temp", "temp404", "cleanup"),
|
|
];
|
|
|
|
testKeys.forEach((key) => {
|
|
expect(() => parseCacheKey(key)).not.toThrow();
|
|
|
|
const parsed = parseCacheKey(key);
|
|
expect(parsed.prefix).toBe("fb");
|
|
expect(parsed.full).toBe(key);
|
|
expect(parsed.resource).toBeTruthy();
|
|
expect(parsed.identifier).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
test("keys should be unique across different resources", () => {
|
|
const keys = [
|
|
createCacheKey.environment.state("same-id"),
|
|
createCacheKey.user.profile("same-id"),
|
|
createCacheKey.organization.billing("same-id"),
|
|
createCacheKey.project.config("same-id"),
|
|
createCacheKey.survey.metadata("same-id"),
|
|
];
|
|
|
|
const uniqueKeys = new Set(keys);
|
|
expect(uniqueKeys.size).toBe(keys.length);
|
|
});
|
|
|
|
test("namespace validation should prevent collisions", () => {
|
|
// These should not throw (valid namespaces)
|
|
expect(() => createCacheKey.custom("temp", "id")).not.toThrow();
|
|
expect(() => createCacheKey.custom("analytics", "id")).not.toThrow();
|
|
|
|
// These should throw (reserved/invalid namespaces)
|
|
expect(() => createCacheKey.custom("env", "id")).toThrow();
|
|
expect(() => createCacheKey.custom("user", "id")).toThrow();
|
|
expect(() => createCacheKey.custom("org", "id")).toThrow();
|
|
});
|
|
});
|
|
});
|