Skip to main content
Glama
config.test.ts10.5 kB
/** * Unit tests for configuration module */ import { jest } from '@jest/globals'; import { mockEnv } from '../utils/test-helpers.js'; describe('Configuration Module', () => { let restoreEnv: () => void; beforeEach(() => { // Clear module cache to get fresh config jest.resetModules(); }); afterEach(() => { if (restoreEnv) { restoreEnv(); } }); describe('CONFIG object', () => { it('should have default values when no environment variables are set', async () => { restoreEnv = mockEnv({}); const { CONFIG } = await import('../../src/lib/config.js'); expect(CONFIG.WP_API_URL).toBe('https://example.com'); expect(CONFIG.OAUTH_ENABLED).toBe(false); // OAuth is disabled by default expect(CONFIG.OAUTH_CALLBACK_PORT).toBeUndefined(); // Default is undefined for auto-select expect(CONFIG.OAUTH_HOST).toBe('127.0.0.1'); expect(CONFIG.WP_OAUTH_CLIENT_ID).toBe(''); expect(CONFIG.OAUTH_FLOW_TYPE).toBe('authorization_code'); expect(CONFIG.OAUTH_USE_PKCE).toBe(true); expect(CONFIG.NODE_ENV).toBe('test'); // NODE_ENV is set to 'test' in test environment }); it('should override defaults with environment variables', async () => { restoreEnv = mockEnv({ WP_API_URL: 'https://custom-site.com', OAUTH_ENABLED: 'false', OAUTH_CALLBACK_PORT: '4000', OAUTH_HOST: '0.0.0.0', WP_OAUTH_CLIENT_ID: 'custom_client_id', OAUTH_FLOW_TYPE: 'implicit', OAUTH_USE_PKCE: 'false', NODE_ENV: 'production', }); const { CONFIG } = await import('../../src/lib/config.js'); expect(CONFIG.WP_API_URL).toBe('https://custom-site.com'); expect(CONFIG.OAUTH_ENABLED).toBe(false); expect(CONFIG.OAUTH_CALLBACK_PORT).toBe(4000); expect(CONFIG.OAUTH_HOST).toBe('0.0.0.0'); expect(CONFIG.WP_OAUTH_CLIENT_ID).toBe('custom_client_id'); expect(CONFIG.OAUTH_FLOW_TYPE).toBe('implicit'); expect(CONFIG.OAUTH_USE_PKCE).toBe(false); expect(CONFIG.NODE_ENV).toBe('production'); }); it('should handle invalid port numbers gracefully', async () => { restoreEnv = mockEnv({ OAUTH_CALLBACK_PORT: 'invalid', }); const { CONFIG } = await import('../../src/lib/config.js'); expect(CONFIG.OAUTH_CALLBACK_PORT).toBeNaN(); }); }); describe('validateConfig function', () => { it('should validate a complete configuration', async () => { restoreEnv = mockEnv({ WP_API_URL: 'https://test-site.wordpress.com', WP_OAUTH_CLIENT_ID: 'test_client_id', OAUTH_CALLBACK_PORT: '7665', OAUTH_ENABLED: 'true', // Enable OAuth for validation to pass }); const { validateConfig } = await import('../../src/lib/config.js'); const result = validateConfig(); expect(result.isValid).toBe(true); expect(result.errors).toHaveLength(0); }); it('should fail validation when required fields are missing', async () => { restoreEnv = mockEnv({ WP_API_URL: '', WP_OAUTH_CLIENT_ID: '', }); const { validateConfig } = await import('../../src/lib/config.js'); const result = validateConfig(); expect(result.isValid).toBe(false); expect(result.errors.some(error => error.includes('WP_API_URL must be set to your WordPress site URL'))).toBe(true); }); it('should pass validation with valid URL format', async () => { restoreEnv = mockEnv({ WP_API_URL: 'https://test-site.com', WP_OAUTH_CLIENT_ID: 'test_client_id', OAUTH_ENABLED: 'true', // Enable OAuth for validation to pass }); const { validateConfig } = await import('../../src/lib/config.js'); const result = validateConfig(); expect(result.isValid).toBe(true); }); it('should validate port number range', async () => { restoreEnv = mockEnv({ WP_API_URL: 'https://test-site.com', WP_OAUTH_CLIENT_ID: 'test_client_id', OAUTH_CALLBACK_PORT: '99999', OAUTH_ENABLED: 'true', // Enable OAuth for port validation to trigger }); const { validateConfig } = await import('../../src/lib/config.js'); const result = validateConfig(); expect(result.isValid).toBe(false); expect(result.errors.some(error => error.includes('OAUTH_CALLBACK_PORT must be a valid port number (1-65535)'))).toBe(true); }); it('should require some authentication method even when OAuth is disabled', async () => { restoreEnv = mockEnv({ WP_API_URL: 'https://test-site.com', OAUTH_ENABLED: 'false', WP_OAUTH_CLIENT_ID: '', // This would normally be required }); const { validateConfig } = await import('../../src/lib/config.js'); const result = validateConfig(); expect(result.isValid).toBe(false); expect(result.errors.some(error => error.includes('No authentication method configured. Please set one of: JWT_TOKEN, WP_API_USERNAME+WP_API_PASSWORD, or enable OAuth'))).toBe(true); }); }); describe('getDefaultOAuthScopes function', () => { it('should return default OAuth scopes', async () => { const { getDefaultOAuthScopes } = await import('../../src/lib/config.js'); const scopes = getDefaultOAuthScopes(); expect(scopes).toEqual(['read', 'write']); }); it('should respect custom scopes from environment variable', async () => { restoreEnv = mockEnv({ OAUTH_SCOPES: 'custom,scopes,test', }); const { getDefaultOAuthScopes } = await import('../../src/lib/config.js'); const scopes = getDefaultOAuthScopes(); expect(scopes).toEqual(['custom', 'scopes', 'test']); }); it('should handle empty scopes environment variable', async () => { restoreEnv = mockEnv({ OAUTH_SCOPES: '', }); const { getDefaultOAuthScopes } = await import('../../src/lib/config.js'); const scopes = getDefaultOAuthScopes(); expect(scopes).toEqual(['read', 'write']); }); }); describe('OAuth 2.1 compliance', () => { it('should have OAuth 2.1 features enabled by default', async () => { restoreEnv = mockEnv({}); const { CONFIG } = await import('../../src/lib/config.js'); expect(CONFIG.OAUTH_USE_PKCE).toBe(true); expect(CONFIG.OAUTH_DYNAMIC_REGISTRATION).toBe(true); expect(CONFIG.OAUTH_RESOURCE_INDICATOR).toBe(true); }); it('should allow disabling OAuth 2.1 features via environment variables', async () => { restoreEnv = mockEnv({ OAUTH_USE_PKCE: 'false', OAUTH_DYNAMIC_REGISTRATION: 'false', OAUTH_RESOURCE_INDICATOR: 'false', }); const { CONFIG } = await import('../../src/lib/config.js'); expect(CONFIG.OAUTH_USE_PKCE).toBe(false); expect(CONFIG.OAUTH_DYNAMIC_REGISTRATION).toBe(false); expect(CONFIG.OAUTH_RESOURCE_INDICATOR).toBe(false); }); }); describe('timeout configuration', () => { it('should have reasonable default timeouts', async () => { const { CONFIG } = await import('../../src/lib/config.js'); expect(CONFIG.OAUTH_TIMEOUT).toBe(30000); // 30 seconds expect(CONFIG.LOCK_TIMEOUT).toBe(300000); // 5 minutes }); }); describe('directory configuration', () => { it('should use home directory for config by default', async () => { const { CONFIG } = await import('../../src/lib/config.js'); expect(CONFIG.WP_MCP_CONFIG_DIR).toMatch(/\.mcp-auth$/); expect(CONFIG.WP_MCP_CONFIG_DIR).toContain(require('os').homedir()); }); it('should allow custom config directory', async () => { restoreEnv = mockEnv({ WP_MCP_CONFIG_DIR: '/custom/config/dir', }); const { CONFIG } = await import('../../src/lib/config.js'); expect(CONFIG.WP_MCP_CONFIG_DIR).toBe('/custom/config/dir'); }); }); describe('parseOAuthScopes function', () => { it('should return default scopes when environment variable is empty', async () => { const { parseOAuthScopes } = await import('../../src/lib/config.js'); const defaultScopes = ['read', 'write']; expect(parseOAuthScopes('', defaultScopes)).toEqual(['read', 'write']); expect(parseOAuthScopes(' ', defaultScopes)).toEqual(['read', 'write']); }); it('should parse comma-separated scopes correctly', async () => { const { parseOAuthScopes } = await import('../../src/lib/config.js'); const defaultScopes = ['read', 'write']; expect(parseOAuthScopes('global', defaultScopes)).toEqual(['global']); expect(parseOAuthScopes('read,write,admin', defaultScopes)).toEqual(['read', 'write', 'admin']); expect(parseOAuthScopes(' read , write , admin ', defaultScopes)).toEqual(['read', 'write', 'admin']); }); it('should filter out empty scopes', async () => { const { parseOAuthScopes } = await import('../../src/lib/config.js'); const defaultScopes = ['read', 'write']; expect(parseOAuthScopes('read,,write', defaultScopes)).toEqual(['read', 'write']); expect(parseOAuthScopes(',read,write,', defaultScopes)).toEqual(['read', 'write']); }); it('should handle single scope correctly', async () => { const { parseOAuthScopes } = await import('../../src/lib/config.js'); const defaultScopes = ['read', 'write']; expect(parseOAuthScopes('global', defaultScopes)).toEqual(['global']); }); }); describe('Health status function', () => { it('should return health status with configuration state', async () => { restoreEnv = mockEnv({ WP_API_URL: 'https://test-site.com', JWT_TOKEN: 'test-token', }); const { getConfigHealthStatus } = await import('../../src/lib/config.js'); const status = getConfigHealthStatus(); expect(status.status).toBe('healthy'); expect(status.version).toBe('0.2.9'); expect(status.uptime).toBeGreaterThan(0); expect(status.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/); }); it('should return unhealthy status for invalid configuration', async () => { restoreEnv = mockEnv({ WP_API_URL: '', // Invalid }); const { getConfigHealthStatus } = await import('../../src/lib/config.js'); const status = getConfigHealthStatus(); expect(status.status).toBe('unhealthy'); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Automattic/mcp-wordpress-remote'

If you have feedback or need assistance with the MCP directory API, please join our Discord server