import type { configure as ConfigureType, getConfig as GetConfigType } from './config.js'; import { AuthKitConfig } from './interfaces.js'; describe('config', () => { let configure: typeof ConfigureType; let getConfig: typeof GetConfigType; beforeEach(() => { jest.resetModules(); ({ configure, getConfig } = require('./config.js')); }); it('reads values from process.env with no configure call', () => { expect(getConfig('clientId')).toBe(process.env.WORKOS_CLIENT_ID); expect(getConfig('apiKey')).toBe(process.env.WORKOS_API_KEY); }); it('reads values from the provided config', () => { configure({ clientId: 'client_1234567890', apiKey: 'sk_test_1234567890', }); expect(getConfig('clientId')).toBe('client_1234567890'); expect(getConfig('apiKey')).toBe('sk_test_1234567890'); }); it('reads env variables from the provided config', () => { configure( {}, { WORKOS_CLIENT_ID: 'client_123456789', WORKOS_API_KEY: 'sk_test_123456789', }, ); expect(getConfig('clientId')).toBe('client_123456789'); expect(getConfig('apiKey')).toBe('sk_test_123456789'); }); it('reads values from the provided config', () => { configure({ clientId: 'client_1234567890', }); expect(getConfig('clientId')).toBe('client_1234567890'); expect(getConfig('apiKey')).toBe(process.env.WORKOS_API_KEY); }); it('reads values from the provided source', () => { configure((key) => { if (key === 'WORKOS_CLIENT_ID') { return 'client_1234567890'; } else if (key === 'WORKOS_API_KEY') { return 'sk_test_1234567890'; } return undefined; }); expect(getConfig('clientId')).toBe('client_1234567890'); expect(getConfig('apiKey')).toBe('sk_test_1234567890'); }); it('reads from provided config, falling back to provided source', () => { configure( { clientId: 'overridden client id', redirectUri: 'http://localhost:5173/callback', cookiePassword: 'a really long cookie password that is definitely more than 32 characters', }, (key) => { if (key === 'WORKOS_API_KEY') { return 'overridden api key'; } }, ); expect(getConfig('clientId')).toBe('overridden client id'); expect(getConfig('apiKey')).toBe('overridden api key'); }); it('reads from defaults when no values are provided', () => { configure(() => undefined); expect(getConfig('apiHttps')).toBe(true); expect(getConfig('apiHostname')).toBe('api.workos.com'); }); it('returns undefined for unknown values', () => { expect(getConfig('unknown' as keyof AuthKitConfig)).toBeUndefined(); }); it('converts strings to appropriate types', () => { configure((key) => { switch (key) { case 'WORKOS_API_PORT': return '3000'; case 'WORKOS_COOKIE_MAX_AGE': return '3600'; case 'WORKOS_API_HTTPS': return 'true'; default: return undefined; } }); expect(typeof getConfig('apiPort')).toBe('number'); expect(typeof getConfig('cookieMaxAge')).toBe('number'); expect(typeof getConfig('apiHttps')).toBe('boolean'); }); it('parses a comma-separated WORKOS_ISSUER into a list', () => { configure((key) => (key === 'WORKOS_ISSUER' ? 'https://a.example.com, https://b.example.com,' : undefined)); expect(getConfig('issuer')).toEqual(['https://a.example.com', 'https://b.example.com']); }); it('keeps a single WORKOS_ISSUER as a string', () => { configure((key) => (key === 'WORKOS_ISSUER' ? 'https://a.example.com' : undefined)); expect(getConfig('issuer')).toBe('https://a.example.com'); }); it('throws an error if cookiePassword is too short', () => { expect(() => { configure({ cookiePassword: 'short' }); }).toThrow('cookiePassword must be at least 32 characters long'); }); it('throws an error if required values are missing', () => { expect(() => { configure(() => undefined); getConfig('clientId'); }).toThrow('Missing required configuration value for clientId (WORKOS_CLIENT_ID).'); }); describe('public client (no API key)', () => { const publicEnv = { WORKOS_CLIENT_ID: 'client_public', WORKOS_REDIRECT_URI: 'http://localhost:5173/callback', WORKOS_COOKIE_PASSWORD: 'kR620keEzOIzPThfnMEAba8XYgKdQ5vg', }; let savedApiKey: string | undefined; beforeEach(() => { savedApiKey = process.env.WORKOS_API_KEY; delete process.env.WORKOS_API_KEY; }); afterEach(() => { if (savedApiKey !== undefined) process.env.WORKOS_API_KEY = savedApiKey; }); it('resolves apiKey to undefined instead of throwing', () => { configure(() => undefined); expect(getConfig('apiKey')).toBeUndefined(); }); it('works with env-only configuration from process.env', () => { // process.env from jest.setup minus WORKOS_API_KEY expect(getConfig('apiKey')).toBeUndefined(); expect(getConfig('clientId')).toBe(process.env.WORKOS_CLIENT_ID); expect(getConfig('redirectUri')).toBe(process.env.WORKOS_REDIRECT_URI); expect(getConfig('cookiePassword')).toBe(process.env.WORKOS_COOKIE_PASSWORD); }); it('works with an env-only value source', () => { configure({}, publicEnv); expect(getConfig('apiKey')).toBeUndefined(); expect(getConfig('clientId')).toBe('client_public'); expect(getConfig('redirectUri')).toBe('http://localhost:5173/callback'); expect(getConfig('cookiePassword')).toBe(publicEnv.WORKOS_COOKIE_PASSWORD); }); it('accepts a programmatic config without apiKey', () => { configure( { clientId: 'client_public', redirectUri: 'http://localhost:5173/callback', cookiePassword: publicEnv.WORKOS_COOKIE_PASSWORD, }, () => undefined, ); expect(getConfig('apiKey')).toBeUndefined(); expect(getConfig('clientId')).toBe('client_public'); }); it.each([ ['clientId', 'WORKOS_CLIENT_ID'], ['redirectUri', 'WORKOS_REDIRECT_URI'], ['cookiePassword', 'WORKOS_COOKIE_PASSWORD'], ] as const)('still requires %s', (key, envKey) => { const rest: Record = { ...publicEnv }; delete rest[envKey]; configure({}, rest); expect(() => getConfig(key)).toThrow(`Missing required configuration value for ${key} (${envKey}).`); }); it('still validates the cookie password length', () => { expect(() => configure({ clientId: 'client_public', cookiePassword: 'short' })).toThrow( 'cookiePassword must be at least 32 characters long', ); }); }); });