mirror of
https://github.com/cloudflare/vinext.git
synced 2026-09-14 19:04:59 +08:00
137 lines
4.3 KiB
TypeScript
137 lines
4.3 KiB
TypeScript
import { describe, expect, it } from "vite-plus/test";
|
|
import type { CachedRouteValue } from "../packages/vinext/src/shims/cache.js";
|
|
import {
|
|
applyRouteHandlerMiddlewareContext,
|
|
applyRouteHandlerRevalidateHeader,
|
|
buildAppRouteCacheValue,
|
|
buildRouteHandlerCachedResponse,
|
|
finalizeRouteHandlerResponse,
|
|
markRouteHandlerCacheMiss,
|
|
} from "../packages/vinext/src/server/app-route-handler-response.js";
|
|
|
|
function buildCachedRouteValue(
|
|
body: string,
|
|
headers: Record<string, string> = {},
|
|
): CachedRouteValue {
|
|
return {
|
|
kind: "APP_ROUTE",
|
|
body: new TextEncoder().encode(body).buffer,
|
|
status: 200,
|
|
headers,
|
|
};
|
|
}
|
|
|
|
describe("app route handler response helpers", () => {
|
|
it("returns the original response when no middleware context exists", () => {
|
|
const response = new Response("hello");
|
|
|
|
expect(
|
|
applyRouteHandlerMiddlewareContext(response, {
|
|
headers: null,
|
|
status: null,
|
|
}),
|
|
).toBe(response);
|
|
});
|
|
|
|
it("applies middleware headers and status overrides to route handler responses", async () => {
|
|
const response = new Response("hello", {
|
|
status: 200,
|
|
headers: {
|
|
"content-type": "text/plain",
|
|
"x-response": "app",
|
|
},
|
|
});
|
|
|
|
const result = applyRouteHandlerMiddlewareContext(response, {
|
|
headers: new Headers([
|
|
["x-middleware", "mw"],
|
|
["x-response", "middleware-copy"],
|
|
]),
|
|
status: 202,
|
|
});
|
|
|
|
expect(result.status).toBe(202);
|
|
expect(result.headers.get("content-type")).toBe("text/plain");
|
|
expect(result.headers.get("x-response")).toBe("app, middleware-copy");
|
|
expect(result.headers.get("x-middleware")).toBe("mw");
|
|
await expect(result.text()).resolves.toBe("hello");
|
|
});
|
|
|
|
it("builds cached HIT and STALE route handler responses", async () => {
|
|
const cachedValue = buildCachedRouteValue("from-cache", {
|
|
"content-type": "text/plain",
|
|
});
|
|
|
|
const hit = buildRouteHandlerCachedResponse(cachedValue, {
|
|
cacheState: "HIT",
|
|
isHead: false,
|
|
revalidateSeconds: 60,
|
|
});
|
|
expect(hit.headers.get("x-vinext-cache")).toBe("HIT");
|
|
expect(hit.headers.get("cache-control")).toBe("s-maxage=60, stale-while-revalidate");
|
|
await expect(hit.text()).resolves.toBe("from-cache");
|
|
|
|
const staleHead = buildRouteHandlerCachedResponse(cachedValue, {
|
|
cacheState: "STALE",
|
|
isHead: true,
|
|
revalidateSeconds: 60,
|
|
});
|
|
expect(staleHead.headers.get("x-vinext-cache")).toBe("STALE");
|
|
expect(staleHead.headers.get("cache-control")).toBe("s-maxage=0, stale-while-revalidate");
|
|
await expect(staleHead.text()).resolves.toBe("");
|
|
});
|
|
|
|
it("serializes APP_ROUTE cache values without cache bookkeeping headers", async () => {
|
|
const response = new Response("cache me", {
|
|
status: 201,
|
|
headers: {
|
|
"content-type": "text/plain",
|
|
"cache-control": "s-maxage=60, stale-while-revalidate",
|
|
"x-vinext-cache": "MISS",
|
|
"x-extra": "kept",
|
|
},
|
|
});
|
|
|
|
const value = await buildAppRouteCacheValue(response);
|
|
|
|
expect(value.kind).toBe("APP_ROUTE");
|
|
expect(value.status).toBe(201);
|
|
expect(value.headers).toEqual({
|
|
"content-type": "text/plain",
|
|
"x-extra": "kept",
|
|
});
|
|
expect(new TextDecoder().decode(value.body)).toBe("cache me");
|
|
});
|
|
|
|
it("finalizes route handler responses with cookies and auto-head semantics", async () => {
|
|
const response = new Response("body", {
|
|
status: 202,
|
|
statusText: "Accepted",
|
|
headers: {
|
|
"content-type": "text/plain",
|
|
},
|
|
});
|
|
|
|
const result = finalizeRouteHandlerResponse(response, {
|
|
pendingCookies: ["a=1; Path=/"],
|
|
draftCookie: "draft=1; Path=/",
|
|
isHead: true,
|
|
});
|
|
|
|
expect(result.status).toBe(202);
|
|
expect(result.statusText).toBe("Accepted");
|
|
expect(result.headers.getSetCookie?.()).toEqual(["a=1; Path=/", "draft=1; Path=/"]);
|
|
await expect(result.text()).resolves.toBe("");
|
|
});
|
|
|
|
it("applies revalidate and MISS headers separately", () => {
|
|
const response = new Response("hello");
|
|
|
|
applyRouteHandlerRevalidateHeader(response, 30);
|
|
markRouteHandlerCacheMiss(response);
|
|
|
|
expect(response.headers.get("cache-control")).toBe("s-maxage=30, stale-while-revalidate");
|
|
expect(response.headers.get("x-vinext-cache")).toBe("MISS");
|
|
});
|
|
});
|