Skip to content

Commit 0077f32

Browse files
authored
test(client): add tests for deferred domain resolution in standalone builds (#2609)
2 parents 6c4c7db + a946ee2 commit 0077f32

1 file changed

Lines changed: 62 additions & 2 deletions

File tree

src/server/client.test.ts

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
import { NextResponse } from "next/server.js";
1+
import { NextRequest, NextResponse } from "next/server.js";
22
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
33

4-
import { InvalidConfigurationError } from "../errors/index.js";
4+
import {
5+
DomainResolutionError,
6+
InvalidConfigurationError
7+
} from "../errors/index.js";
58
import { SessionData } from "../types/index.js";
69
import { Auth0Client } from "./client.js";
710

@@ -151,6 +154,63 @@ describe("Auth0Client", () => {
151154
"tokenRefreshBuffer must be a non-negative number of seconds."
152155
);
153156
});
157+
158+
describe("deferred domain resolution (standalone / runtime-injected env)", () => {
159+
it("should not throw during construction when AUTH0_DOMAIN is absent and domain is not passed", () => {
160+
// Simulate a Next.js standalone build where AUTH0_DOMAIN is only injected at runtime.
161+
// The Auth0Client constructor must not throw — domain validation is deferred to request time.
162+
delete process.env[ENV_VARS.DOMAIN];
163+
process.env[ENV_VARS.CLIENT_ID] = "client_123";
164+
process.env[ENV_VARS.CLIENT_SECRET] = "client_secret";
165+
process.env[ENV_VARS.APP_BASE_URL] = "https://app.example.com";
166+
process.env[ENV_VARS.SECRET] = "secret_value";
167+
168+
expect(() => new Auth0Client()).not.toThrow();
169+
});
170+
171+
it("should resolve domain at request time when AUTH0_DOMAIN is set after construction", async () => {
172+
// Domain is absent at construction, but present when the first request is made.
173+
delete process.env[ENV_VARS.DOMAIN];
174+
process.env[ENV_VARS.CLIENT_ID] = "client_123";
175+
process.env[ENV_VARS.CLIENT_SECRET] = "client_secret";
176+
process.env[ENV_VARS.APP_BASE_URL] = "https://app.example.com";
177+
process.env[ENV_VARS.SECRET] = "secret_value";
178+
179+
const client = new Auth0Client();
180+
181+
// Now inject the domain as if a container runtime has set it
182+
process.env[ENV_VARS.DOMAIN] = "runtime.auth0.com";
183+
184+
// Calling getSession with no active session should not throw an
185+
// InvalidConfigurationError — the domain is now resolvable.
186+
// getSession returns null when there is no session; it should NOT throw
187+
// because domain is now available via the deferred resolver.
188+
const req = new NextRequest("https://app.example.com/");
189+
await expect(client.getSession(req)).resolves.toBeNull();
190+
});
191+
192+
it("should throw InvalidConfigurationError at request time when AUTH0_DOMAIN is still absent", async () => {
193+
// Both build time and request time are missing AUTH0_DOMAIN — the deferred
194+
// resolver must throw with a clear message rather than a cryptic internal error.
195+
delete process.env[ENV_VARS.DOMAIN];
196+
process.env[ENV_VARS.CLIENT_ID] = "client_123";
197+
process.env[ENV_VARS.CLIENT_SECRET] = "client_secret";
198+
process.env[ENV_VARS.APP_BASE_URL] = "https://app.example.com";
199+
process.env[ENV_VARS.SECRET] = "secret_value";
200+
201+
const client = new Auth0Client();
202+
203+
// AUTH0_DOMAIN remains unset — should throw at request time.
204+
// The deferred resolver throws InvalidConfigurationError, which the
205+
// AuthClientProvider wraps in a DomainResolutionError. The original
206+
// message is accessible via .cause.
207+
const req = new NextRequest("https://app.example.com/");
208+
const err = await client.getSession(req).catch((e) => e);
209+
expect(err).toBeInstanceOf(DomainResolutionError);
210+
expect(err.cause).toBeInstanceOf(InvalidConfigurationError);
211+
expect(err.cause?.message).toContain("Missing: domain");
212+
});
213+
});
154214
});
155215

156216
// TODO: Re-implement DPoP handle management if needed

0 commit comments

Comments
 (0)