diff --git a/vtex/__tests__/client-segment-cookie.test.ts b/vtex/__tests__/client-segment-cookie.test.ts index f165d20..f0de476 100644 --- a/vtex/__tests__/client-segment-cookie.test.ts +++ b/vtex/__tests__/client-segment-cookie.test.ts @@ -18,12 +18,45 @@ function mockResponse(body: unknown = {}, status = 200): Response { } as Response; } -/** Run `fn` inside a fake request context with the given cookie header. */ +/** + * Run `fn` inside a fake request context with the given cookie header. + * + * Two problems prevented a naive `RequestContext.run(new Request(...))` + * approach from working: + * + * 1. Under the Fetch spec a Request's headers are in the "request" + * guard mode, which silently drops forbidden request headers — + * including `cookie` — at construction time. Node 22 / undici + * enforces this strictly, so the cookie never reaches + * `request.headers.get("cookie")`. + * 2. `@decocms/start`'s `RequestContext` is backed by a + * `RequestStore` that defaults to a NOOP implementation. The + * ALS-backed store is installed by site code at worker boot, not + * in unit tests. So `RequestContext.run(req, fn)` calls + * `fn()` without any propagation, and `RequestContext.current` + * inside `fn` still returns `null` — production code under test + * never sees the test's cookie. + * + * Fix: build a fresh `Headers` object (which uses the "none" guard, + * so `set("cookie", ...)` works), wrap it in a minimal `Ctx`-shaped + * object, and override the `RequestContext.current` getter via + * `vi.spyOn`. The spy is restored after `fn` resolves to keep tests + * isolated. Nothing here depends on undici or ALS internals. + */ function withRequest(cookieHeader: string | null, fn: () => Promise): Promise { - const request = new Request("http://localhost/", { - headers: cookieHeader ? { cookie: cookieHeader } : {}, - }); - return RequestContext.run(request, fn); + const headers = new Headers(); + if (cookieHeader) headers.set("cookie", cookieHeader); + const fakeCtx = { + request: { headers } as unknown as Request, + signal: new AbortController().signal, + responseHeaders: new Headers(), + bag: new Map(), + startedAt: Date.now(), + }; + const spy = vi + .spyOn(RequestContext, "current", "get") + .mockReturnValue(fakeCtx as unknown as ReturnType); + return fn().finally(() => spy.mockRestore()); } describe("vtexFetchResponse — vtex_segment cookie forwarding", () => {