/** * Unit Tests for AdaptiveCommunicationOrchestrator * Tests culturally-adaptive communication to prevent linguistic hierarchy */ const orchestrator = require('../../src/services/AdaptiveCommunicationOrchestrator.service'); describe('AdaptiveCommunicationOrchestrator', () => { beforeEach(() => { // Orchestrator is a singleton instance }); describe('Anti-Patronizing Filter (inst_030)', () => { test('should remove "simply" from messages', () => { const message = 'You can simply implement this feature easily.'; const adapted = orchestrator.adaptCommunication(message); expect(adapted).not.toContain('simply'); }); test('should remove "obviously" from messages', () => { const message = 'Obviously, this approach is the best solution.'; const adapted = orchestrator.adaptCommunication(message); expect(adapted).not.toContain('obviously'); }); test('should remove "as you may know" from messages', () => { const message = 'As you may know, AI governance requires careful consideration.'; const adapted = orchestrator.adaptCommunication(message); expect(adapted).not.toContain('as you may know'); }); test('should track patronizing terms removed', () => { const statsBefore = orchestrator.getStats(); orchestrator.adaptCommunication('Simply put, obviously this is clear.'); const statsAfter = orchestrator.getStats(); expect(statsAfter.patronizing_terms_removed).toBeGreaterThan(statsBefore.patronizing_terms_removed); }); test('should handle multiple patronizing terms', () => { const message = 'Simply put, it is obviously clear that you can just do this, of course.'; const adapted = orchestrator.adaptCommunication(message); expect(adapted).not.toContain('simply'); expect(adapted).not.toContain('obviously'); expect(adapted).not.toContain('of course'); }); }); describe('Pub Test (inst_029)', () => { test('should flag overly formal language', () => { const message = 'Notwithstanding the aforementioned circumstances, we hereby decree...'; const result = orchestrator.pubTest(message); expect(result.passes).toBe(false); expect(result.violations.length).toBeGreaterThan(0); }); test('should pass casual conversational language', () => { const message = 'Right, here\'s what we decided: We\'re going with option A.'; const result = orchestrator.pubTest(message); expect(result.passes).toBe(true); expect(result.violations.length).toBe(0); }); test('should flag "pursuant to" as too legal', () => { const message = 'Pursuant to our discussion, we will proceed accordingly.'; const result = orchestrator.pubTest(message); expect(result.passes).toBe(false); const hasLegalViolation = result.violations.some(v => v.reason.includes('legal')); expect(hasLegalViolation).toBe(true); }); test('should flag "notwithstanding" as unnecessarily complex', () => { const message = 'Notwithstanding your concerns, we shall continue.'; const result = orchestrator.pubTest(message); expect(result.passes).toBe(false); expect(result.violations[0].reason).toContain('Unnecessarily complex'); }); }); describe('Communication Style Detection', () => { test('should detect formal academic style', () => { const message = 'Furthermore, notwithstanding the theoretical implications, we must therefore consider...'; const detected = orchestrator.detectStyle(message); expect(detected).toBe('FORMAL_ACADEMIC'); }); test('should detect casual direct style', () => { const message = 'Right, here\'s the deal. Fair enough?'; const detected = orchestrator.detectStyle(message); expect(detected).toBe('CASUAL_DIRECT'); }); test('should detect Māori protocol indicators', () => { const message = 'Kia ora! Ngā mihi for your contribution to this kōrero.'; const detected = orchestrator.detectStyle(message); expect(detected).toBe('MAORI_PROTOCOL'); }); test('should default to plain language', () => { const message = 'This is a simple message without strong style indicators.'; const detected = orchestrator.detectStyle(message); expect(detected).toBe('PLAIN_LANGUAGE'); }); }); describe('Style Adaptation (inst_029)', () => { test('should adapt to formal academic style', () => { const message = 'We decided to go with this approach.'; const context = { audience: 'FORMAL_ACADEMIC' }; const adapted = orchestrator.adaptCommunication(message, context); expect(adapted).toBeDefined(); // In full implementation, would check for formal register }); test('should adapt to casual direct style', () => { const message = 'I would like to inform you that we have made a decision.'; const context = { audience: 'CASUAL_DIRECT' }; const adapted = orchestrator.adaptCommunication(message, context); // Should simplify formal phrases expect(adapted).not.toContain('I would like to inform you that'); }); test('should track adaptations by style', () => { const statsBefore = orchestrator.getStats(); const beforeCount = statsBefore.by_style.FORMAL_ACADEMIC; orchestrator.adaptCommunication('Test message 1', { audience: 'FORMAL_ACADEMIC' }); orchestrator.adaptCommunication('Test message 2', { audience: 'FORMAL_ACADEMIC' }); const statsAfter = orchestrator.getStats(); const afterCount = statsAfter.by_style.FORMAL_ACADEMIC; expect(afterCount).toBe(beforeCount + 2); }); test('should handle plain language adaptation', () => { const message = 'We must utilize this methodology to facilitate implementation.'; const context = { audience: 'PLAIN_LANGUAGE' }; const adapted = orchestrator.adaptCommunication(message, context); // Should replace jargon with plain equivalents expect(adapted).not.toContain('utilize'); expect(adapted).toContain('use'); }); }); describe('Language Detection (inst_032)', () => { test('should detect Te Reo Māori', () => { const message = 'Kia ora, let me share some whakaaro about this kaupapa.'; const adapted = orchestrator.adaptCommunication(message); // Should detect and track Māori language const stats = orchestrator.getStats(); expect(stats.languages_detected['te-reo-maori']).toBeGreaterThan(0); }); test('should default to English', () => { const message = 'This is a standard English message with no special indicators.'; const adapted = orchestrator.adaptCommunication(message); // Should process as English without issues expect(adapted).toBeDefined(); }); }); describe('Greeting Generation', () => { test('should generate Māori protocol greeting', () => { const greeting = orchestrator.generateGreeting('John', { communication_style: 'MAORI_PROTOCOL' }); expect(greeting).toContain('Kia ora'); expect(greeting).toContain('John'); }); test('should generate casual direct greeting', () => { const greeting = orchestrator.generateGreeting('Jane', { communication_style: 'CASUAL_DIRECT' }); expect(greeting).toBe('Hi Jane'); }); test('should generate formal academic greeting', () => { const greeting = orchestrator.generateGreeting('Dr. Smith', { communication_style: 'FORMAL_ACADEMIC' }); expect(greeting).toContain('Dear Dr. Smith'); }); test('should generate plain language greeting by default', () => { const greeting = orchestrator.generateGreeting('Alex'); expect(greeting).toContain('Hello'); expect(greeting).toContain('Alex'); }); }); describe('Cultural Context Application (inst_031)', () => { test('should apply cultural adaptations when context provided', () => { const message = 'Thank you for your contribution.'; const context = { audience: 'MAORI_PROTOCOL', cultural_context: 'maori' }; const adapted = orchestrator.adaptCommunication(message, context); // Should apply Māori protocol adaptations expect(adapted).toBeDefined(); }); test('should handle multiple cultural contexts', () => { const messages = [ { text: 'Test 1', context: { cultural_context: 'australian' } }, { text: 'Test 2', context: { cultural_context: 'japanese' } }, { text: 'Test 3', context: { cultural_context: 'maori' } } ]; messages.forEach(({ text, context }) => { const adapted = orchestrator.adaptCommunication(text, context); expect(adapted).toBeDefined(); }); }); }); describe('Statistics Tracking', () => { test('should track total adaptations', () => { const statsBefore = orchestrator.getStats(); orchestrator.adaptCommunication('Test message', { audience: 'PLAIN_LANGUAGE' }); const statsAfter = orchestrator.getStats(); expect(statsAfter.total_adaptations).toBeGreaterThan(statsBefore.total_adaptations); }); test('should track adaptations by style', () => { orchestrator.adaptCommunication('Test 1', { audience: 'FORMAL_ACADEMIC' }); orchestrator.adaptCommunication('Test 2', { audience: 'CASUAL_DIRECT' }); const stats = orchestrator.getStats(); expect(stats.by_style.FORMAL_ACADEMIC).toBeGreaterThan(0); expect(stats.by_style.CASUAL_DIRECT).toBeGreaterThan(0); }); test('should track languages detected', () => { orchestrator.adaptCommunication('Kia ora whānau'); const stats = orchestrator.getStats(); expect(stats.languages_detected).toBeDefined(); expect(Object.keys(stats.languages_detected).length).toBeGreaterThan(0); }); }); describe('Preventing Linguistic Hierarchy', () => { test('should not favor formal academic over casual direct', () => { const formalResult = orchestrator.adaptCommunication('Test', { audience: 'FORMAL_ACADEMIC' }); const casualResult = orchestrator.adaptCommunication('Test', { audience: 'CASUAL_DIRECT' }); // Both should be processed without error, neither privileged expect(formalResult).toBeDefined(); expect(casualResult).toBeDefined(); }); test('should support non-Western communication norms', () => { const contexts = [ { audience: 'MAORI_PROTOCOL' }, { audience: 'JAPANESE_FORMAL' } ]; contexts.forEach(context => { const adapted = orchestrator.adaptCommunication('Test message', context); expect(adapted).toBeDefined(); }); }); test('should remove condescension from all styles', () => { const patronizingMessage = 'Simply put, obviously you can just do this.'; const contexts = [ { audience: 'FORMAL_ACADEMIC' }, { audience: 'CASUAL_DIRECT' }, { audience: 'PLAIN_LANGUAGE' } ]; contexts.forEach(context => { const adapted = orchestrator.adaptCommunication(patronizingMessage, context); expect(adapted).not.toContain('simply'); expect(adapted).not.toContain('obviously'); }); }); }); describe('Singleton Pattern', () => { test('should export singleton instance with required methods', () => { expect(typeof orchestrator.adaptCommunication).toBe('function'); expect(typeof orchestrator.pubTest).toBe('function'); expect(typeof orchestrator.detectStyle).toBe('function'); expect(typeof orchestrator.generateGreeting).toBe('function'); expect(typeof orchestrator.getStats).toBe('function'); }); }); describe('Error Handling', () => { test('should handle null message gracefully', () => { expect(() => { orchestrator.adaptCommunication(null); }).not.toThrow(); }); test('should handle empty message', () => { const result = orchestrator.adaptCommunication(''); expect(result).toBeDefined(); expect(result).toBe(''); }); test('should handle unknown communication style', () => { const result = orchestrator.adaptCommunication('Test', { audience: 'UNKNOWN_STYLE' }); expect(result).toBeDefined(); expect(result).toBe('Test'); }); }); describe('Integration Points', () => { test('should be usable by PluralisticDeliberationOrchestrator', () => { // Simulates how PDO would use this service const message = 'We need your input on this values conflict.'; const stakeholder = { communication_style: 'formal_academic', cultural_context: 'western_academic' }; const adapted = orchestrator.adaptCommunication(message, { audience: 'FORMAL_ACADEMIC', cultural_context: stakeholder.cultural_context }); expect(adapted).toBeDefined(); }); test('should handle multiple stakeholder adaptations in sequence', () => { const message = 'Thank you for your contribution to this deliberation.'; const stakeholders = [ { style: 'FORMAL_ACADEMIC', context: 'academic' }, { style: 'CASUAL_DIRECT', context: 'australian' }, { style: 'MAORI_PROTOCOL', context: 'maori' } ]; const adaptations = stakeholders.map(s => orchestrator.adaptCommunication(message, { audience: s.style, cultural_context: s.context }) ); expect(adaptations.length).toBe(3); adaptations.forEach(adapted => { expect(adapted).toBeDefined(); }); }); }); });