tractatus/tests/unit/AdaptiveCommunicationOrchestrator.test.js
TheFlow ac2db33732 fix(submissions): restructure Economist package and fix article display
- Create Economist SubmissionTracking package correctly:
  * mainArticle = full blog post content
  * coverLetter = 216-word SIR— letter
  * Links to blog post via blogPostId
- Archive 'Letter to The Economist' from blog posts (it's the cover letter)
- Fix date display on article cards (use published_at)
- Target publication already displaying via blue badge

Database changes:
- Make blogPostId optional in SubmissionTracking model
- Economist package ID: 68fa85ae49d4900e7f2ecd83
- Le Monde package ID: 68fa2abd2e6acd5691932150

Next: Enhanced modal with tabs, validation, export

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 08:47:42 +13:00

402 lines
13 KiB
JavaScript

/**
* 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();
});
});
});
});