Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions vtex/__tests__/client-segment-cookie.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>(cookieHeader: string | null, fn: () => Promise<T>): Promise<T> {
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<typeof Reflect.get>);
return fn().finally(() => spy.mockRestore());
}

describe("vtexFetchResponse — vtex_segment cookie forwarding", () => {
Expand Down