Skip to main content
Glama
I18nIntegrationTests.test.ts16 kB
/** * Internationalization Integration Tests * * Tests the complete i18n functionality across the entire system, * ensuring proper locale/timezone handling in all services and tools. */ import { CastPlanUltimateAutomationServer } from '../../CastPlanUltimateAutomationServer.js'; import { ServiceMockFactory, ConfigMockFactory } from '../helpers/MockFactories.js'; import { TestDataFactory, TestFileSystem, MockLoggerFactory } from '../helpers/TestUtils.js'; import { I18nTestUtils, I18nTestEnvironment, TEST_LOCALES, LocaleTestCaseGenerator, LocaleTestUtils, I18nTestAssertions } from '../helpers/I18nTestUtils.js'; import type { I18nTestConfig, LocaleTestCase } from '../helpers/I18nTestUtils.js'; describe('I18n Integration Tests', () => { let server: CastPlanUltimateAutomationServer; let i18nEnvironment: I18nTestEnvironment; let tempProjectPath: string; beforeEach(async () => { i18nEnvironment = new I18nTestEnvironment(); tempProjectPath = await TestFileSystem.createTestProject('i18n-integration-test'); }); afterEach(async () => { if (server) { await server.cleanup?.(); } i18nEnvironment?.restoreEnvironment(); await TestFileSystem.cleanupTempDir(); }); describe('Server Initialization with Different Locales', () => { const localeTestCases = LocaleTestCaseGenerator.generateLocaleTestCases({ expectedFormats: {} }, ['en-US', 'ko-KR', 'ja-JP', 'de-DE', 'fr-FR']); localeTestCases.forEach(testCase => { test(`should initialize server with ${testCase.name}`, async () => { i18nEnvironment.setTestEnvironment(testCase.config); const config = ConfigMockFactory.createLocaleSpecificConfig( testCase.config.locale as keyof typeof TEST_LOCALES, { projectRoot: tempProjectPath, services: { bmad: true, documentation: true, hooks: true, enhanced: true } } ); server = new CastPlanUltimateAutomationServer(config); await server.initialize(); expect(server).toBeDefined(); expect(server.config.timeZone).toBe(testCase.config.timezone); expect(server.config.locale).toBe(testCase.config.locale); }); }); }); describe('DateTime Service Locale Integration', () => { const multiTimezoneTestCases = LocaleTestCaseGenerator.generateTimezoneTestCases({ expectedFormats: {} }, ['UTC', 'America/New_York', 'Asia/Seoul', 'Europe/London', 'Asia/Tokyo', 'Australia/Sydney']); multiTimezoneTestCases.forEach(testCase => { test(`should handle date/time operations in ${testCase.name}`, async () => { i18nEnvironment.setTestEnvironment(testCase.config); const config = ConfigMockFactory.createUltimateAutomationConfig({ projectRoot: tempProjectPath, i18n: testCase.config, timeZone: testCase.config.timezone, locale: testCase.config.locale }); server = new CastPlanUltimateAutomationServer(config); await server.initialize(); // Test datetime operations through tools const initArgs = { projectRoot: tempProjectPath, enableAI: false, timeZone: testCase.config.timezone }; const toolHandler = server.getToolHandler('initialize_documentation_system'); expect(toolHandler).toBeDefined(); const result = await toolHandler!(initArgs); expect(result.success).toBe(true); expect(result.message).toContain(testCase.config.timezone); // Verify timestamp consistency const trackingArgs = { workType: 'frontend', workDescription: 'Test work for timezone validation', filePaths: [`${tempProjectPath}/test.ts`] }; const trackHandler = server.getToolHandler('track_document_work'); if (trackHandler) { const trackResult = await trackHandler(trackingArgs); expect(trackResult.success).toBe(true); expect(trackResult.timestamp).toBeTruthy(); I18nTestAssertions.assertValidDateInTimezone(trackResult.timestamp, testCase.config.timezone); } }); }); }); describe('Cross-Locale Content Processing', () => { test('should handle multilingual content processing', async () => { const testContent = { 'en-US': 'Hello World - Testing Documentation', 'ko-KR': '안녕하세요 - 문서화 테스트', 'ja-JP': 'こんにちは - ドキュメンテーションテスト', 'de-DE': 'Hallo Welt - Dokumentationstest', 'fr-FR': 'Bonjour le Monde - Test de Documentation' }; for (const [localeKey, content] of Object.entries(testContent)) { const config = TEST_LOCALES[localeKey as keyof typeof TEST_LOCALES]; i18nEnvironment.setTestEnvironment(config); // Create locale-specific test file const testFileName = `test-${localeKey}.md`; await TestFileSystem.createTempFile( tempProjectPath, testFileName, `# ${content}\n\nThis is a test document for ${localeKey} locale.\n\n## Features\n- Internationalization\n- Locale-specific formatting` ); const serverConfig = ConfigMockFactory.createLocaleSpecificConfig( localeKey as keyof typeof TEST_LOCALES, { projectRoot: tempProjectPath } ); server = new CastPlanUltimateAutomationServer(serverConfig); await server.initialize(); // Test document quality analysis with locale-specific content const analyzeHandler = server.getToolHandler('analyze_document_quality'); if (analyzeHandler) { const analyzeResult = await analyzeHandler({ documentPath: `${tempProjectPath}/${testFileName}`, includeAI: false, analysisTypes: ['quality'] }); expect(analyzeResult.success).toBe(true); expect(analyzeResult.basicMetrics).toBeDefined(); expect(Array.isArray(analyzeResult.basicMetrics)).toBe(true); // Verify content is processed correctly regardless of locale const hasContentMetrics = analyzeResult.basicMetrics.some((metric: string) => metric.includes('Lines') || metric.includes('Words') || metric.includes('File Size') ); expect(hasContentMetrics).toBe(true); } await server.cleanup?.(); } }); }); describe('Timezone Boundary Testing', () => { test('should handle timezone transitions correctly', async () => { // Test dates that cross timezone boundaries const boundaryTestCases = [ { utcTime: '2024-12-31T23:30:00.000Z', // New Year's Eve description: 'New Year boundary' }, { utcTime: '2024-03-10T07:00:00.000Z', // DST transition in US description: 'DST spring forward' }, { utcTime: '2024-11-03T06:00:00.000Z', // DST transition end in US description: 'DST fall back' }, { utcTime: '2024-06-21T12:00:00.000Z', // Summer solstice description: 'Summer solstice' } ]; const timezones = ['UTC', 'America/New_York', 'Asia/Seoul', 'Europe/London', 'Australia/Sydney']; for (const testCase of boundaryTestCases) { for (const timezone of timezones) { const config = { ...TEST_LOCALES['en-US'], timezone }; i18nEnvironment.setTestEnvironment(config); const serverConfig = ConfigMockFactory.createUltimateAutomationConfig({ projectRoot: tempProjectPath, i18n: config, timeZone: timezone }); server = new CastPlanUltimateAutomationServer(serverConfig); await server.initialize(); // Test document lifecycle with timezone-specific timestamps const updateHandler = server.getToolHandler('update_document_lifecycle'); if (updateHandler) { const updateResult = await updateHandler({ documentId: 'test-doc', newState: 'published', reviewComment: `${testCase.description} test in ${timezone}`, scheduledReview: testCase.utcTime }); expect(updateResult.success).toBe(true); expect(updateResult.updatedAt).toBeTruthy(); expect(updateResult.scheduledReview).toBeTruthy(); // Verify timezone handling I18nTestAssertions.assertValidDateInTimezone(updateResult.updatedAt, timezone); if (updateResult.scheduledReview) { I18nTestAssertions.assertValidDateInTimezone(updateResult.scheduledReview, timezone); } } await server.cleanup?.(); } } }); }); describe('Locale-Specific Report Generation', () => { const reportLocales = ['en-US', 'ko-KR', 'ja-JP', 'de-DE'] as const; reportLocales.forEach(localeKey => { test(`should generate reports with ${localeKey} formatting`, async () => { const config = TEST_LOCALES[localeKey]; i18nEnvironment.setTestEnvironment(config); const serverConfig = ConfigMockFactory.createLocaleSpecificConfig(localeKey, { projectRoot: tempProjectPath }); server = new CastPlanUltimateAutomationServer(serverConfig); await server.initialize(); // Generate different types of reports const reportTypes = ['lifecycle', 'quality', 'connections', 'comprehensive'] as const; for (const reportType of reportTypes) { const reportHandler = server.getToolHandler('generate_documentation_report'); if (reportHandler) { const reportResult = await reportHandler({ reportType, timeRange: { start: '2024-01-01T00:00:00.000Z', end: '2024-12-31T23:59:59.999Z' }, includeAI: false }); expect(reportResult.success).toBe(true); expect(reportResult.reportType).toBe(reportType); expect(reportResult.report).toBeDefined(); expect(reportResult.generatedAt).toBeTruthy(); // Verify timestamp formatting I18nTestAssertions.assertValidDateInTimezone(reportResult.generatedAt, config.timezone); // Verify report structure remains consistent across locales expect(reportResult.report.title).toBeTruthy(); expect(typeof reportResult.report.title).toBe('string'); if (reportResult.report.period) { expect(reportResult.report.period.start).toBeTruthy(); expect(reportResult.report.period.end).toBeTruthy(); } } } }); }); }); describe('Performance Across Locales', () => { test('should maintain performance consistency across different locales', async () => { const locales = ['en-US', 'ko-KR', 'ja-JP', 'de-DE'] as const; const performanceResults: { locale: string; duration: number }[] = []; for (const localeKey of locales) { const config = TEST_LOCALES[localeKey]; i18nEnvironment.setTestEnvironment(config); const serverConfig = ConfigMockFactory.createLocaleSpecificConfig(localeKey, { projectRoot: tempProjectPath }); const startTime = Date.now(); server = new CastPlanUltimateAutomationServer(serverConfig); await server.initialize(); // Perform typical operations const initHandler = server.getToolHandler('initialize_documentation_system'); if (initHandler) { await initHandler({ projectRoot: tempProjectPath, enableAI: false, timeZone: config.timezone }); } const treeHandler = server.getToolHandler('get_document_tree'); if (treeHandler) { await treeHandler({}); } const endTime = Date.now(); const duration = endTime - startTime; performanceResults.push({ locale: localeKey, duration }); await server.cleanup?.(); } // Verify performance is consistent across locales (within 50% variance) const durations = performanceResults.map(r => r.duration); const avgDuration = durations.reduce((sum, d) => sum + d, 0) / durations.length; const maxVariance = avgDuration * 0.5; // 50% variance threshold performanceResults.forEach(result => { const variance = Math.abs(result.duration - avgDuration); expect(variance).toBeLessThan(maxVariance); }); // All operations should complete within reasonable time (10 seconds) performanceResults.forEach(result => { expect(result.duration).toBeLessThan(10000); }); }); }); describe('Error Handling Internationalization', () => { test('should provide consistent error handling across locales', async () => { const locales = ['en-US', 'ko-KR', 'ja-JP', 'de-DE'] as const; const errorScenarios = [ { name: 'invalid timezone', args: { projectRoot: tempProjectPath, timeZone: 'Invalid/Timezone' }, shouldSucceedWithFallback: true }, { name: 'missing project root', args: { enableAI: true }, shouldSucceedWithFallback: false }, { name: 'invalid document path', handler: 'analyze_document_quality', args: { documentPath: '/non/existent/path.md' }, shouldSucceedWithFallback: false } ]; for (const localeKey of locales) { const config = TEST_LOCALES[localeKey]; i18nEnvironment.setTestEnvironment(config); const serverConfig = ConfigMockFactory.createLocaleSpecificConfig(localeKey, { projectRoot: tempProjectPath }); server = new CastPlanUltimateAutomationServer(serverConfig); await server.initialize(); for (const scenario of errorScenarios) { const handlerName = scenario.handler || 'initialize_documentation_system'; const handler = server.getToolHandler(handlerName); if (handler) { if (scenario.shouldSucceedWithFallback) { const result = await handler(scenario.args); expect(result.success).toBe(true); // Should succeed with fallback } else { await expect(handler(scenario.args)).rejects.toThrow(); } } } await server.cleanup?.(); } }); }); describe('Backward Compatibility', () => { test('should maintain backward compatibility with Korean locale defaults', async () => { // Test that the system still works with legacy Korean configuration const legacyConfig = ConfigMockFactory.createUltimateAutomationConfig({ projectRoot: tempProjectPath, timeZone: 'Asia/Seoul', locale: 'ko-KR', // Legacy format without i18n object services: { enhanced: true } }); server = new CastPlanUltimateAutomationServer(legacyConfig); await server.initialize(); expect(server.config.timeZone).toBe('Asia/Seoul'); expect(server.config.locale).toBe('ko-KR'); // Should still work with new i18n configuration if (server.config.i18n) { expect(server.config.i18n.timezone).toBe('Asia/Seoul'); expect(server.config.i18n.locale).toBe('ko-KR'); } // Basic operations should work const initHandler = server.getToolHandler('initialize_documentation_system'); if (initHandler) { const result = await initHandler({ projectRoot: tempProjectPath, enableAI: false }); expect(result.success).toBe(true); } }); }); });

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/Ghostseller/CastPlan_mcp'

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