Initial PHP rebuild of the app
This commit is contained in:
690 files changed
+33944
-12046
No files matched your search
@@ -0,0 +1,27 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { NextRequest } from "next/server";
|
||||
|
||||
// The Manager must not load the business Auth.js module even if a stale
|
||||
// client requests `/api/auth/session`.
|
||||
vi.mock("@/auth", () => {
|
||||
throw new Error("Business Auth.js must not load in Manager mode.");
|
||||
});
|
||||
|
||||
import { GET } from "@/app/api/auth/[...nextauth]/route";
|
||||
|
||||
describe("Manager business-auth boundary", () => {
|
||||
const originalManagerMode = process.env.MANAGER_MODE;
|
||||
|
||||
afterEach(() => {
|
||||
if (originalManagerMode === undefined) delete process.env.MANAGER_MODE;
|
||||
else process.env.MANAGER_MODE = originalManagerMode;
|
||||
});
|
||||
|
||||
it("returns 404 without importing business Auth.js", async () => {
|
||||
process.env.MANAGER_MODE = "true";
|
||||
|
||||
const response = await GET(new NextRequest("https://manager.example.com/api/auth/session"));
|
||||
|
||||
expect(response.status).toBe(404);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
vi.mock("@/lib/db/prisma", () => {
|
||||
throw new Error("Business Prisma must not load in Manager framework routes.");
|
||||
});
|
||||
|
||||
vi.mock("@/lib/business/branding", () => {
|
||||
throw new Error("Business branding must not load in Manager framework routes.");
|
||||
});
|
||||
|
||||
import { GET as health } from "@/app/api/health/route";
|
||||
import manifest from "@/app/manifest";
|
||||
|
||||
describe("Manager framework routes", () => {
|
||||
const originalManagerMode = process.env.MANAGER_MODE;
|
||||
|
||||
afterEach(() => {
|
||||
if (originalManagerMode === undefined) delete process.env.MANAGER_MODE;
|
||||
else process.env.MANAGER_MODE = originalManagerMode;
|
||||
});
|
||||
|
||||
it("serves health without Prisma", async () => {
|
||||
process.env.MANAGER_MODE = "true";
|
||||
|
||||
const response = await health();
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(await response.json()).toMatchObject({ status: "healthy", deployment: "manager" });
|
||||
});
|
||||
|
||||
it("serves Manager manifest without business branding", async () => {
|
||||
process.env.MANAGER_MODE = "true";
|
||||
|
||||
const result = await manifest();
|
||||
|
||||
expect(result.name).toBe("NextChair Manager");
|
||||
expect(result.start_url).toBe("/manager");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { NextRequest } from "next/server";
|
||||
|
||||
const isInstalledForRequest = vi.fn();
|
||||
// Keep the Auth.js wrapper observable. Manager requests must not construct or
|
||||
// invoke it; business requests still must use it for req.auth handling.
|
||||
const { nextAuth, handleProxyRequestForTest } = vi.hoisted(() => {
|
||||
const handleProxyRequestForTest = vi.fn(async (_request: NextRequest) => new Response(null, { status: 200 }));
|
||||
const nextAuth = vi.fn(() => ({
|
||||
auth: (request: NextRequest) => handleProxyRequestForTest(request),
|
||||
}));
|
||||
|
||||
return { nextAuth, handleProxyRequestForTest };
|
||||
});
|
||||
|
||||
// If proxy.ts or its Manager request path statically imports Prisma, this
|
||||
// mock throws while the test module is loading. Manager mode must not reach it.
|
||||
vi.mock("@/lib/db/prisma", () => {
|
||||
throw new Error("Prisma must not be imported by the Manager proxy path.");
|
||||
});
|
||||
|
||||
vi.mock("@/lib/installation/installation-state", () => ({ isInstalledForRequest }));
|
||||
|
||||
vi.mock("next-auth", () => ({ default: nextAuth }));
|
||||
|
||||
import proxy, { handleProxyRequest } from "@/proxy";
|
||||
|
||||
function request(pathname: string) {
|
||||
return new NextRequest(`https://manager.example.com${pathname}`);
|
||||
}
|
||||
|
||||
describe("proxy deployment separation", () => {
|
||||
const originalManagerMode = process.env.MANAGER_MODE;
|
||||
|
||||
afterEach(() => {
|
||||
if (originalManagerMode === undefined) delete process.env.MANAGER_MODE;
|
||||
else process.env.MANAGER_MODE = originalManagerMode;
|
||||
isInstalledForRequest.mockReset();
|
||||
nextAuth.mockClear();
|
||||
handleProxyRequestForTest.mockClear();
|
||||
});
|
||||
|
||||
it("routes the Manager root before loading or checking business installation state", async () => {
|
||||
process.env.MANAGER_MODE = "true";
|
||||
|
||||
const response = await proxy(request("/"));
|
||||
|
||||
expect(response.status).toBe(307);
|
||||
expect(response.headers.get("location")).toBe("https://manager.example.com/manager");
|
||||
expect(response.headers.get("content-security-policy")).toContain("default-src 'self'");
|
||||
expect(isInstalledForRequest).not.toHaveBeenCalled();
|
||||
expect(nextAuth).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("serves Manager routes without business installation state", async () => {
|
||||
process.env.MANAGER_MODE = "true";
|
||||
|
||||
const response = await proxy(request("/manager"));
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(isInstalledForRequest).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("checks installation state for a normal business request", async () => {
|
||||
process.env.MANAGER_MODE = "false";
|
||||
isInstalledForRequest.mockResolvedValue(false);
|
||||
|
||||
const response = await handleProxyRequest(request("/"));
|
||||
|
||||
expect(response.status).toBe(307);
|
||||
expect(response.headers.get("location")).toBe("https://manager.example.com/install");
|
||||
expect(isInstalledForRequest).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("uses Auth.js for normal business requests", async () => {
|
||||
process.env.MANAGER_MODE = "false";
|
||||
|
||||
await proxy(request("/"));
|
||||
|
||||
expect(nextAuth).toHaveBeenCalledOnce();
|
||||
expect(handleProxyRequestForTest).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("preserves protected business route redirects after installation", async () => {
|
||||
process.env.MANAGER_MODE = "false";
|
||||
isInstalledForRequest.mockResolvedValue(true);
|
||||
|
||||
const response = await handleProxyRequest(request("/owner"));
|
||||
|
||||
expect(response.status).toBe(307);
|
||||
expect(response.headers.get("location")).toContain("/sign-in?callbackUrl=%2Fowner");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
vi.mock("next/navigation", () => ({
|
||||
redirect: (location: string) => {
|
||||
throw new Error(`redirect:${location}`);
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/db/prisma", () => {
|
||||
throw new Error("Business Prisma must not load while importing the Manager root.");
|
||||
});
|
||||
|
||||
vi.mock("@/features/welcome/pages/business-welcome-page", () => {
|
||||
throw new Error("Business welcome page must not load while importing the Manager root.");
|
||||
});
|
||||
|
||||
import RootPage from "@/app/page";
|
||||
|
||||
describe("root deployment entry point", () => {
|
||||
const originalManagerMode = process.env.MANAGER_MODE;
|
||||
|
||||
afterEach(() => {
|
||||
if (originalManagerMode === undefined) delete process.env.MANAGER_MODE;
|
||||
else process.env.MANAGER_MODE = originalManagerMode;
|
||||
});
|
||||
|
||||
it("redirects Manager root without evaluating business page or Prisma", async () => {
|
||||
process.env.MANAGER_MODE = "true";
|
||||
|
||||
await expect(RootPage()).rejects.toThrow("redirect:/manager");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user