Initial Commit
This commit is contained in:
137
packages/api-stack/api/api-tenant/src/storage/storage.test.ts
Normal file
137
packages/api-stack/api/api-tenant/src/storage/storage.test.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { afterEach, describe, expect, it } from "@suaveplan/testing/runner";
|
||||
import { Hono } from "hono";
|
||||
import { createTenantMiddleware } from "../middleware/middleware.js";
|
||||
import { headerResolver } from "../resolver/resolver.js";
|
||||
import type { Tenant } from "../types/tenant.js";
|
||||
import {
|
||||
getCurrentTenant,
|
||||
getCurrentTenantId,
|
||||
isTenantStorageEnabled,
|
||||
runWithTenant,
|
||||
tenantStorageMiddleware,
|
||||
withTenantStorage,
|
||||
} from "./storage.js";
|
||||
|
||||
function makeTenant(id = "t_1"): Tenant {
|
||||
return {
|
||||
id,
|
||||
name: "Acme",
|
||||
slug: id,
|
||||
status: "active",
|
||||
settings: {},
|
||||
enabledPlugins: [],
|
||||
domains: [],
|
||||
createdAt: new Date(0),
|
||||
updatedAt: new Date(0),
|
||||
};
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
withTenantStorage(false);
|
||||
});
|
||||
|
||||
describe("withTenantStorage toggle", () => {
|
||||
it("defaults to off", { timeout: 5000 }, () => {
|
||||
expect(isTenantStorageEnabled()).toBe(false);
|
||||
});
|
||||
|
||||
it("toggles on/off", { timeout: 5000 }, () => {
|
||||
withTenantStorage(true);
|
||||
expect(isTenantStorageEnabled()).toBe(true);
|
||||
withTenantStorage(false);
|
||||
expect(isTenantStorageEnabled()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("AsyncLocalStorage thread", () => {
|
||||
it("ALS off keeps getCurrentTenant undefined", {
|
||||
timeout: 5000,
|
||||
}, async () => {
|
||||
const app = new Hono();
|
||||
let seen: Tenant | undefined;
|
||||
app.use(
|
||||
"*",
|
||||
createTenantMiddleware({
|
||||
resolver: headerResolver("x-tenant-id", async () =>
|
||||
makeTenant()
|
||||
),
|
||||
})
|
||||
);
|
||||
app.use("*", tenantStorageMiddleware());
|
||||
app.get("/", async (c) => {
|
||||
await new Promise<void>((r) => setImmediate(r));
|
||||
seen = getCurrentTenant();
|
||||
return c.text("ok");
|
||||
});
|
||||
await app.request("/", { headers: { "x-tenant-id": "acme" } });
|
||||
expect(seen).toBeUndefined();
|
||||
});
|
||||
|
||||
it("ALS on threads tenant through async stack", {
|
||||
timeout: 5000,
|
||||
}, async () => {
|
||||
withTenantStorage(true);
|
||||
const app = new Hono();
|
||||
let seenId: string | undefined;
|
||||
app.use(
|
||||
"*",
|
||||
createTenantMiddleware({
|
||||
resolver: headerResolver("x-tenant-id", async () =>
|
||||
makeTenant("acme-deep")
|
||||
),
|
||||
})
|
||||
);
|
||||
app.use("*", tenantStorageMiddleware());
|
||||
app.get("/", async (c) => {
|
||||
// Cross several async boundaries before reading.
|
||||
await new Promise<void>((r) => setImmediate(r));
|
||||
await new Promise<void>((r) => setTimeout(r, 1));
|
||||
seenId = getCurrentTenantId();
|
||||
return c.text("ok");
|
||||
});
|
||||
await app.request("/", { headers: { "x-tenant-id": "acme" } });
|
||||
expect(seenId).toBe("acme-deep");
|
||||
});
|
||||
|
||||
it("middleware is no-op when tenant unresolved (ALS on)", {
|
||||
timeout: 5000,
|
||||
}, async () => {
|
||||
withTenantStorage(true);
|
||||
const app = new Hono();
|
||||
app.use("*", tenantStorageMiddleware());
|
||||
app.get("/", (c) => {
|
||||
expect(getCurrentTenant()).toBeUndefined();
|
||||
return c.text("ok");
|
||||
});
|
||||
const res = await app.request("/");
|
||||
expect(res.status).toBe(200);
|
||||
});
|
||||
|
||||
it("runWithTenant runs inside ALS scope", {
|
||||
timeout: 5000,
|
||||
}, async () => {
|
||||
withTenantStorage(true);
|
||||
const t = makeTenant("explicit");
|
||||
const id = runWithTenant(t, () => getCurrentTenantId());
|
||||
expect(id).toBe("explicit");
|
||||
});
|
||||
|
||||
it("runWithTenant runs fn directly when ALS off", {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
const t = makeTenant();
|
||||
const id = runWithTenant(t, () => getCurrentTenantId());
|
||||
expect(id).toBeUndefined();
|
||||
});
|
||||
|
||||
it("middleware bypasses ALS when toggle is off", {
|
||||
timeout: 5000,
|
||||
}, async () => {
|
||||
const app = new Hono();
|
||||
app.use("*", tenantStorageMiddleware());
|
||||
app.get("/", (c) => c.text("ok"));
|
||||
const res = await app.request("/");
|
||||
expect(res.status).toBe(200);
|
||||
expect(isTenantStorageEnabled()).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user