60 lines
3.3 KiB
TypeScript
60 lines
3.3 KiB
TypeScript
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
|
import { createElement, Suspense } from "react"
|
|
import { renderToString } from "react-dom/server"
|
|
import { describe, expect, it, vi } from "vitest"
|
|
|
|
const loaders = vi.hoisted(() => ({ project: vi.fn(), workspace: vi.fn(), other: vi.fn(), broken: vi.fn() }))
|
|
vi.mock("@app/modules/pages", () => ({
|
|
modulePages: { notes: loaders.project, other: loaders.other, broken: loaders.broken },
|
|
workspacePages: { notes: loaders.workspace },
|
|
}))
|
|
const { createPageViews, prepareInitialModuleViews, projectPageViews } = await import("../apps/web/src/ui/page-views")
|
|
|
|
describe("initial module view hydration", () => {
|
|
it("lets the router mount after a failed warmup and preserves the error for its route", async () => {
|
|
const failure = new Error("module chunk unavailable")
|
|
loaders.broken.mockRejectedValue(failure)
|
|
await expect(
|
|
prepareInitialModuleViews([
|
|
{ routeId: "/$org/$workspace/$project/$module/$", status: "success", loaderData: { module: "broken" } },
|
|
]),
|
|
).resolves.toBeUndefined()
|
|
await expect(projectPageViews.prepare("broken")).rejects.toBe(failure)
|
|
expect(loaders.broken).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it("renders prepared server markup synchronously and loads no other module", async () => {
|
|
const selected = vi.fn(async () => ({ View: () => createElement("a", { href: "/ready" }, "Ready") }))
|
|
const other = vi.fn(async () => ({ View: () => createElement("div", {}, "Other") }))
|
|
const views = createPageViews({ selected, other })
|
|
await Promise.all([views.prepare("selected"), views.prepare("selected")])
|
|
const html = renderToString(
|
|
createElement(Suspense, { fallback: "loading fallback" }, createElement(views.viewOf("selected"))),
|
|
)
|
|
expect(html).toContain('<a href="/ready">Ready</a>')
|
|
expect(html).not.toContain("loading fallback")
|
|
expect(selected).toHaveBeenCalledTimes(1)
|
|
expect(other).not.toHaveBeenCalled()
|
|
expect(views.viewOf("selected")).toBe(views.viewOf("selected"))
|
|
expect(views.has("toString")).toBe(false)
|
|
expect(() => views.viewOf("unregistered")).toThrow("no page for module")
|
|
})
|
|
|
|
it("prepares only successful matched project and workspace page data", async () => {
|
|
loaders.project.mockResolvedValue({ View: () => createElement("div") })
|
|
loaders.workspace.mockResolvedValue({ View: () => createElement("div") })
|
|
await prepareInitialModuleViews([
|
|
{ routeId: "/$org/$workspace/$project/$module/$", status: "success", loaderData: { module: "notes" } },
|
|
{ routeId: "/$org/$workspace/modules/$module/$", status: "success", loaderData: { module: "notes" } },
|
|
{ routeId: "/$org", status: "success", loaderData: { module: "other" } },
|
|
{ routeId: "/$org/$workspace/$project/$module/$", status: "error", loaderData: { module: "other" } },
|
|
{ routeId: "/$org/$workspace/modules/$module/$", status: "notFound", loaderData: { module: "notes" } },
|
|
{ routeId: "/$org/$workspace/modules/$module/$", status: "redirected" },
|
|
{ routeId: "/$org/$workspace/modules/$module/$", status: "success", loaderData: { module: "unknown" } },
|
|
])
|
|
expect(loaders.project).toHaveBeenCalledTimes(1)
|
|
expect(loaders.workspace).toHaveBeenCalledTimes(1)
|
|
expect(loaders.other).not.toHaveBeenCalled()
|
|
})
|
|
})
|