Files
archived-next-auth/packages/next-auth/tests/state-handler.test.ts
Balázs Orbán 7e91d7df54 refactor(core): use standard Request and Response (#4769)
* WIP use `Request` and `Response` for core

* bump Next.js

* rename ts types

* refactor

* simplify

* upgrade Next.js

* implement body reader

* use `Request`/`Response` in `next-auth/next`

* make linter happy

* revert

* fix tests

* remove workaround for middleware return type

* return session in protected api route example

* don't export internal handler

* fall back host to localhost

* refactor `getBody`

* refactor `next-auth/next`

* chore: add `@edge-runtime/jest-environment`

* fix tests, using Node 18 as runtime

* fix test

* remove patch

* fix neo4j build

* remove new-line

* reduce file changes in the PR

* fix tests

* fix tests

* refactor

* refactor

* add host tests

* refactor tests

* fix body reading

* fix tests

* use 302

* fix test

* fix again

* fix tests

* handle when body is `Buffer`

* move comment
2022-12-03 13:39:08 +00:00

165 lines
4.5 KiB
TypeScript

import { mockLogger } from "./utils"
import type {
InternalOptions,
LoggerInstance,
InternalProvider,
CallbacksOptions,
Account,
Awaitable,
Profile,
Session,
User,
CookiesOptions,
} from "../src"
import { createState } from "../src/core/lib/oauth/state-handler"
import { InternalUrl } from "../src/utils/parse-url"
import { JWT, JWTOptions, encode, decode } from "../src/jwt"
import { CredentialInput } from "../src/providers"
let logger: LoggerInstance
let url: InternalUrl
let provider: InternalProvider<"oauth">
let jwt: JWTOptions
let callbacks: CallbacksOptions
let cookies: CookiesOptions
let options: InternalOptions<"oauth">
beforeEach(() => {
logger = mockLogger()
url = {
origin: "http://localhost:3000",
host: "localhost:3000",
path: "/api/auth",
base: "http://localhost:3000/api/auth",
toString: () => "http://localhost:3000/api/auth",
}
provider = {
type: "oauth",
id: "testId",
name: "testName",
signinUrl: "/",
callbackUrl: "/",
checks: ["pkce", "state"],
}
jwt = {
secret: "secret",
maxAge: 0,
encode,
decode,
}
callbacks = {
signIn: function (params: {
user: User
account: Account
profile: Profile & Record<string, unknown>
email: { verificationRequest?: boolean | undefined }
credentials?: Record<string, CredentialInput> | undefined
}): Awaitable<string | boolean> {
throw new Error("Function not implemented.")
},
redirect: function (params: {
url: string
baseUrl: string
}): Awaitable<string> {
throw new Error("Function not implemented.")
},
session: function (params: {
session: Session
user: User
token: JWT
}): Awaitable<Session> {
throw new Error("Function not implemented.")
},
jwt: function (params: {
token: JWT
user?: User | undefined
account?: Account | undefined
profile?: Profile | undefined
isNewUser?: boolean | undefined
}): Awaitable<JWT> {
throw new Error("Function not implemented.")
},
}
cookies = {
sessionToken: { name: "", options: undefined },
callbackUrl: { name: "", options: undefined },
csrfToken: { name: "", options: undefined },
pkceCodeVerifier: { name: "", options: undefined },
state: { name: "", options: {} },
nonce: { name: "", options: undefined },
}
options = {
url,
action: "session",
provider,
secret: "",
debug: false,
logger,
session: { strategy: "jwt", maxAge: 0, updateAge: 0 },
pages: {},
jwt,
events: {},
callbacks,
cookies,
callbackUrl: "",
providers: [],
theme: {},
}
})
describe("createState", () => {
it("returns a state, and cookie", async () => {
const state = await createState(options)
expect(state?.value).not.toBeNull()
expect(state?.cookie).not.toBeNull()
})
it("does not return a state when the provider does not support state", async () => {
options.provider.checks = ["pkce"]
const state = await createState(options)
expect(state).toBeUndefined()
})
it("sets the cookie expiration to a default of 15 minutes when the max age option is not provided", async () => {
const state = await createState(options)
const defaultMaxAge = 60 * 15 // 15 minutes in seconds
const expires = new Date()
expires.setTime(expires.getTime() + defaultMaxAge * 1000)
validateCookieExpiration({ state, expires })
expect(state?.cookie.options.maxAge).toBeUndefined()
})
it("sets the cookie expiration and max age to the provided max age from the options", async () => {
const maxAge = 60 * 20 // 20 minutes
cookies.state.options.maxAge = maxAge
const state = await createState(options)
const expires = new Date()
expires.setTime(expires.getTime() + maxAge * 1000)
validateCookieExpiration({ state, expires })
expect(state?.cookie.options.maxAge).toEqual(maxAge)
})
})
// comparing the parts instead of getTime() because the milliseconds
// will not match since the two Date objects are created milliseconds apart
const validateCookieExpiration = ({ state, expires }) => {
const cookieExpires = state?.cookie.options.expires
expect(cookieExpires.getFullYear()).toEqual(expires.getFullYear())
expect(cookieExpires.getMonth()).toEqual(expires.getMonth())
expect(cookieExpires.getFullYear()).toEqual(expires.getFullYear())
expect(cookieExpires.getHours()).toEqual(expires.getHours())
expect(cookieExpires.getMinutes()).toEqual(expires.getMinutes())
}