server/env.test.ts
Rama main · réplica de lectura del repositorio original.
import { type Env, validateEnv } from '@server/env'
import { describe, expect, it } from 'vitest'
describe('validateEnv', () => {
it('fails fast when required bindings or secrets are missing', () => {
expect(() => validateEnv({} as Env, 'https://tenant.example.com/api/health')).toThrow(
'DB binding is not configured for this deployment.',
)
})
it('fails fast for each required Cloudflare deployment binding', () => {
expect(() => validateEnv(createEnv({ ASSETS: undefined }), 'https://tenant.example.com')).toThrow(
'ASSETS binding is not configured for this deployment.',
)
expect(() => validateEnv(createEnv({ ASSET_BUCKET: undefined }), 'https://tenant.example.com')).toThrow(
'ASSET_BUCKET binding is not configured for this deployment.',
)
})
it('allows email binding and sender settings to be completed from Console later', () => {
expect(() =>
validateEnv(
createEnv({ EMAIL: undefined, EMAIL_FROM: undefined, EMAIL_FROM_NAME: undefined }),
'https://tenant.example.com',
),
).not.toThrow()
})
it('rejects an invalid fallback sender email', () => {
expect(() => validateEnv(createEnv({ EMAIL_FROM: 'not-an-email' }), 'https://tenant.example.com')).toThrow(
'EMAIL_FROM must be a valid email address.',
)
})
it('normalizes trusted origins and rejects non-origin entries', () => {
expect(
validateEnv(
createEnv({ TRUSTED_ORIGINS: 'https://tenant.example.com/, https://tenant.example.com' }),
'https://tenant.example.com/api/health',
).trustedOrigins,
).toEqual(['https://tenant.example.com'])
expect(() =>
validateEnv(createEnv({ TRUSTED_ORIGINS: 'https://tenant.example.com/path' }), 'https://tenant.example.com'),
).toThrow('TRUSTED_ORIGINS entry must be an origin: https://tenant.example.com/path')
})
it('normalizes base URL and rejects non-origin base URLs', () => {
expect(
validateEnv(createEnv({ BETTER_AUTH_URL: 'https://auth.example.com/' }), 'https://tenant.example.com').baseURL,
).toBe('https://auth.example.com')
expect(() =>
validateEnv(createEnv({ BETTER_AUTH_URL: 'https://auth.example.com/api/auth' }), 'https://tenant.example.com'),
).toThrow('BETTER_AUTH_URL must be an origin: https://auth.example.com/api/auth')
})
it('returns typed runtime config for a valid environment', () => {
const env = createEnv({
TRUSTED_ORIGINS: 'https://tenant.example.com, https://admin.example.com',
})
expect(validateEnv(env, 'https://tenant.example.com/api/health')).toEqual({
authSecret: 'secret',
baseURL: 'https://tenant.example.com',
credentialEncryptionKey: 'credential-encryption-key-for-tests-2026',
emailFrom: 'noreply@example.com',
emailFromName: undefined,
trustedOrigins: ['https://tenant.example.com', 'https://admin.example.com'],
securityPolicy: {
mfa: {
mode: 'optional',
authenticatorAppEnabled: true,
emailOtpEnabled: false,
backupCodesEnabled: true,
},
passkeys: {
enabled: true,
rpId: 'tenant.example.com',
rpName: 'Realmroot',
origins: ['https://tenant.example.com', 'https://admin.example.com'],
},
sessions: {
expiresInSeconds: 60 * 60 * 24 * 7,
updateAgeSeconds: 60 * 60 * 24,
freshAgeSeconds: 60 * 60 * 24,
cookieCacheSeconds: 60 * 5,
},
password: {
minLength: 8,
requiredCharacterTypes: 1,
customWords: [],
rejectUserInfo: true,
rejectSequential: true,
rejectCustomWords: false,
},
captcha: {
enabled: false,
provider: 'turnstile',
siteKey: '',
projectId: null,
secretKey: '',
},
blocklist: {
blockSubaddressing: false,
entries: [],
},
},
})
})
it('parses deployment security policy and explicit WebAuthn origins', () => {
expect(
validateEnv(
createEnv({
MFA_POLICY: 'required',
PASSKEY_ENABLED: 'false',
WEBAUTHN_RP_ID: 'auth.example.com',
WEBAUTHN_RP_NAME: 'Example Auth',
WEBAUTHN_ORIGINS: 'https://auth.example.com, https://preview.example.workers.dev',
SESSION_DURATION_SECONDS: '3600',
SESSION_UPDATE_AGE_SECONDS: '300',
SESSION_FRESH_AGE_SECONDS: '600',
SESSION_COOKIE_CACHE_SECONDS: '60',
}),
'https://tenant.example.com/api/health',
).securityPolicy,
).toEqual({
mfa: {
mode: 'required',
authenticatorAppEnabled: true,
emailOtpEnabled: false,
backupCodesEnabled: true,
},
passkeys: {
enabled: false,
rpId: 'auth.example.com',
rpName: 'Example Auth',
origins: ['https://auth.example.com', 'https://preview.example.workers.dev'],
},
sessions: {
expiresInSeconds: 3600,
updateAgeSeconds: 300,
freshAgeSeconds: 600,
cookieCacheSeconds: 60,
},
password: {
minLength: 8,
requiredCharacterTypes: 1,
customWords: [],
rejectUserInfo: true,
rejectSequential: true,
rejectCustomWords: false,
},
captcha: {
enabled: false,
provider: 'turnstile',
siteKey: '',
projectId: null,
secretKey: '',
},
blocklist: {
blockSubaddressing: false,
entries: [],
},
})
})
it('fails fast for invalid security policy values', () => {
expect(() => validateEnv(createEnv({ MFA_POLICY: 'sometimes' }), 'https://tenant.example.com')).toThrow(
'MFA_POLICY must be one of: optional, required',
)
expect(() =>
validateEnv(createEnv({ WEBAUTHN_RP_ID: 'https://auth.example.com' }), 'https://tenant.example.com'),
).toThrow('WEBAUTHN_RP_ID must be a domain name or localhost: https://auth.example.com')
expect(() => validateEnv(createEnv({ SESSION_DURATION_SECONDS: '0' }), 'https://tenant.example.com')).toThrow(
'SESSION_DURATION_SECONDS must be greater than 0',
)
})
})
function createEnv(overrides: Partial<Env> = {}): Env {
return {
DB: {},
ASSETS: {},
EMAIL: {
send: async () => ({ messageId: 'email-1' }),
},
ASSET_BUCKET: {},
BETTER_AUTH_SECRET: 'secret',
CREDENTIAL_ENCRYPTION_KEY: 'credential-encryption-key-for-tests-2026',
EMAIL_FROM: 'noreply@example.com',
...overrides,
} as unknown as Env
}