Files
template-app/test/reserved-routes.test.ts
T
2026-11-14 09:56:45 +00:00

77 lines
3.4 KiB
TypeScript

// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
// The first path segment is an organization's slug (`src/routes/$org*`), so every other top-level route
// the web shell mounts must be a slug no organization can take: kit-tenancy refuses the slugs in
// RESERVED_SLUGS when an organization is created. A new top-level route that is not reserved would
// let an organization of that name shadow it, or the route shadow the organization (R8: `/members`).
// `server.mjs` serves the build's static files before any route, so a folder of those counts as well.
// The same holds one level down: the third segment is a project's slug, so a static route beside
// `$org.$workspace.$project` (`modules`, F10's pages above a project) is a slug no project can take.
import { existsSync, readdirSync } from "node:fs"
import { RESERVED_PROJECT_SLUGS, RESERVED_SLUGS } from "@conusai-kit/tenancy"
import { describe, expect, it } from "vitest"
const routesDir = new URL("../apps/web/src/routes/", import.meta.url)
const publicDir = new URL("../apps/web/public/", import.meta.url)
/** A route file's first URL segment: `_layout.` and `(group).` add none, so what follows them is the route. */
const firstSegment = (file: string): string | undefined =>
file
.replace(/\.tsx?$/, "")
.split(".")
.find((part) => !/^[_(]/.test(part))
/** The routes' top-level segments: not `$param`, `__root` or `index`. */
const startSegments = readdirSync(routesDir)
.map(firstSegment)
.filter((segment): segment is string => segment !== undefined && !segment.startsWith("$") && segment !== "index")
/** Folders `dist/client` holds: Vite's own (its default `assetsDir`) and whatever `public/` brings. */
const staticSegments = [
"assets",
...(existsSync(publicDir) ? readdirSync(publicDir, { withFileTypes: true }) : [])
.filter((entry) => entry.isDirectory())
.map((entry) => entry.name),
]
const routeSegments = [...new Set([...startSegments, ...staticSegments])]
/** The static segments beside a project: `$org.$workspace.<segment>...`, but not the workspace's own `index`. */
const workspaceSegments = [
...new Set(
readdirSync(routesDir)
.map((file) => /^\$org\.\$workspace\.([^$.][^.]*)\./.exec(file)?.[1])
.filter((segment): segment is string => segment !== undefined && segment !== "index"),
),
]
describe("top-level routes", () => {
it("finds the routes the shell mounts, or this suite proves nothing", () => {
// Each is a route R8's rule applies to; the list is what apps/web/ROUTES.md names at the top level.
expect(startSegments).toEqual(
expect.arrayContaining(["api", "auth", "invitations", "members", "onboarding", "settings"]),
)
})
it("reads a route behind a pathless layout as the route it is", () => {
expect(firstSegment("_public.pricing.tsx")).toBe("pricing")
expect(firstSegment("(marketing).pricing.tsx")).toBe("pricing")
expect(firstSegment("__root.tsx")).toBeUndefined()
})
it.each(routeSegments)("reserves /%s from organization slugs", (segment) => {
expect(RESERVED_SLUGS).toContain(segment)
})
})
describe("routes beside a project", () => {
it("finds the route of a module's pages above a project, or this suite proves nothing", () => {
expect(workspaceSegments).toContain("modules")
})
it.each(workspaceSegments)("reserves /<org>/<workspace>/%s from project slugs", (segment) => {
expect(RESERVED_PROJECT_SLUGS).toContain(segment)
})
})