mirror of
https://github.com/SrIzan10/next-auth.git
synced 2026-05-01 10:55:20 +00:00
* fix(core): preserve `set-cookie` by the user * add test * improve req/res mocking * refactor * fix comment typo
180 lines
5.1 KiB
TypeScript
180 lines
5.1 KiB
TypeScript
import { mockReqRes, nextHandler } from "./utils"
|
|
|
|
it("Missing req.url throws in dev", async () => {
|
|
await expect(nextHandler).rejects.toThrow(new Error("Missing url"))
|
|
})
|
|
|
|
const configErrorMessage =
|
|
"There is a problem with the server configuration. Check the server logs for more information."
|
|
|
|
it("Missing req.url returns config error in prod", async () => {
|
|
// @ts-expect-error
|
|
process.env.NODE_ENV = "production"
|
|
const { res, logger } = await nextHandler()
|
|
|
|
expect(logger.error).toBeCalledTimes(1)
|
|
const error = new Error("Missing url")
|
|
expect(logger.error).toBeCalledWith("INVALID_URL", error)
|
|
|
|
expect(res.status).toBeCalledWith(400)
|
|
expect(res.json).toBeCalledWith({ message: configErrorMessage })
|
|
|
|
// @ts-expect-error
|
|
process.env.NODE_ENV = "test"
|
|
})
|
|
|
|
it("Missing host throws in dev", async () => {
|
|
await expect(
|
|
async () =>
|
|
await nextHandler({
|
|
req: { query: { nextauth: ["session"] } },
|
|
})
|
|
).rejects.toThrow(Error)
|
|
})
|
|
|
|
it("Missing host config error in prod", async () => {
|
|
// @ts-expect-error
|
|
process.env.NODE_ENV = "production"
|
|
const { res, logger } = await nextHandler({
|
|
req: { query: { nextauth: ["session"] } },
|
|
})
|
|
expect(res.status).toBeCalledWith(400)
|
|
expect(res.json).toBeCalledWith({ message: configErrorMessage })
|
|
|
|
expect(logger.error).toBeCalledWith("INVALID_URL", new Error("Missing url"))
|
|
// @ts-expect-error
|
|
process.env.NODE_ENV = "test"
|
|
})
|
|
|
|
it("Defined host throws 400 in production if not trusted", async () => {
|
|
// @ts-expect-error
|
|
process.env.NODE_ENV = "production"
|
|
const { res } = await nextHandler({
|
|
req: { headers: { host: "http://localhost" } },
|
|
})
|
|
expect(res.status).toBeCalledWith(400)
|
|
// @ts-expect-error
|
|
process.env.NODE_ENV = "test"
|
|
})
|
|
|
|
it("Defined host throws 400 in production if trusted but invalid URL", async () => {
|
|
// @ts-expect-error
|
|
process.env.NODE_ENV = "production"
|
|
const { res } = await nextHandler({
|
|
req: { headers: { host: "localhost" } },
|
|
options: { trustHost: true },
|
|
})
|
|
expect(res.status).toBeCalledWith(400)
|
|
// @ts-expect-error
|
|
process.env.NODE_ENV = "test"
|
|
})
|
|
|
|
it("Defined host does not throw in production if trusted and valid URL", async () => {
|
|
// @ts-expect-error
|
|
process.env.NODE_ENV = "production"
|
|
const { res } = await nextHandler({
|
|
req: {
|
|
url: "/api/auth/session",
|
|
headers: { host: "http://localhost" },
|
|
},
|
|
options: { trustHost: true },
|
|
})
|
|
expect(res.status).toBeCalledWith(200)
|
|
// @ts-expect-error
|
|
expect(JSON.parse(res.send.mock.calls[0][0])).toEqual({})
|
|
// @ts-expect-error
|
|
process.env.NODE_ENV = "test"
|
|
})
|
|
|
|
it("Use process.env.NEXTAUTH_URL for host if present", async () => {
|
|
process.env.NEXTAUTH_URL = "http://localhost"
|
|
const { res } = await nextHandler({
|
|
req: { url: "/api/auth/session" },
|
|
})
|
|
expect(res.status).toBeCalledWith(200)
|
|
// @ts-expect-error
|
|
expect(JSON.parse(res.send.mock.calls[0][0])).toEqual({})
|
|
})
|
|
|
|
it("Redirects if necessary", async () => {
|
|
process.env.NEXTAUTH_URL = "http://localhost"
|
|
const { res } = await nextHandler({
|
|
req: {
|
|
method: "post",
|
|
url: "/api/auth/signin/github",
|
|
},
|
|
})
|
|
expect(res.status).toBeCalledWith(302)
|
|
expect(res.getHeaders()).toEqual({
|
|
location: "http://localhost/api/auth/signin?csrf=true",
|
|
"set-cookie": [
|
|
expect.stringMatching(
|
|
/next-auth.csrf-token=.*; Path=\/; HttpOnly; SameSite=Lax/
|
|
),
|
|
`next-auth.callback-url=${encodeURIComponent(
|
|
process.env.NEXTAUTH_URL
|
|
)}; Path=/; HttpOnly; SameSite=Lax`,
|
|
],
|
|
})
|
|
|
|
expect(res.send).toBeCalledWith("")
|
|
})
|
|
|
|
it("Returns redirect if `X-Auth-Return-Redirect` header is present", async () => {
|
|
process.env.NEXTAUTH_URL = "http://localhost"
|
|
const { res } = await nextHandler({
|
|
req: {
|
|
method: "post",
|
|
url: "/api/auth/signin/github",
|
|
headers: { "X-Auth-Return-Redirect": "1" },
|
|
},
|
|
})
|
|
|
|
expect(res.status).toBeCalledWith(200)
|
|
|
|
expect(res.getHeaders()).toEqual({
|
|
"content-type": "application/json",
|
|
"set-cookie": [
|
|
expect.stringMatching(
|
|
/next-auth.csrf-token=.*; Path=\/; HttpOnly; SameSite=Lax/
|
|
),
|
|
`next-auth.callback-url=${encodeURIComponent(
|
|
process.env.NEXTAUTH_URL
|
|
)}; Path=/; HttpOnly; SameSite=Lax`,
|
|
],
|
|
})
|
|
|
|
expect(res.send).toBeCalledWith(
|
|
JSON.stringify({ url: "http://localhost/api/auth/signin?csrf=true" })
|
|
)
|
|
})
|
|
|
|
it("Should preserve user's `set-cookie` headers", async () => {
|
|
const { req, res } = mockReqRes({
|
|
method: "post",
|
|
url: "/api/auth/signin/credentials",
|
|
headers: { host: "localhost", "X-Auth-Return-Redirect": "1" },
|
|
})
|
|
res.setHeader("set-cookie", ["foo=bar", "bar=baz"])
|
|
|
|
await nextHandler({ req, res })
|
|
|
|
expect(res.getHeaders()).toEqual({
|
|
"content-type": "application/json",
|
|
"set-cookie": [
|
|
"foo=bar",
|
|
"bar=baz",
|
|
expect.stringMatching(
|
|
/next-auth.csrf-token=.*; Path=\/; HttpOnly; SameSite=Lax/
|
|
),
|
|
`next-auth.callback-url=${encodeURIComponent(
|
|
"http://localhost"
|
|
)}; Path=/; HttpOnly; SameSite=Lax`,
|
|
],
|
|
})
|
|
|
|
expect(res.send).toBeCalledWith(
|
|
JSON.stringify({ url: "http://localhost/api/auth/signin?csrf=true" })
|
|
)
|
|
})
|