import { test, describe, it } from 'node:test'; import assert from 'node:assert/strict'; import { setupChainRuleTestGraph } from './helpers.js'; describe('ChainRule Comprehensive Tests', () => { describe('Edge Cases and Error Handling', () => { it('handles empty chains gracefully', () => { const arbiter = setupChainRuleTestGraph(); arbiter.setRelationConfig('empty_chain', { type: 'chain', steps: [] // Empty steps }); const result = arbiter.check('user:alice', 'empty_chain', 'project:web-app'); assert.equal(result.possibility, 0); assert.equal(result.reason, 'no_chain_steps_defined'); }); it('handles broken chains correctly', () => { const arbiter = setupChainRuleTestGraph(); arbiter.setRelationConfig('broken_chain', { type: 'chain', steps: [ { relation: 'member_of', direction: 'out' }, { relation: 'nonexistent_relation', direction: 'out' } // Broken link ] }); const result = arbiter.check('user:alice', 'broken_chain', 'project:web-app'); assert.equal(result.possibility, 0); }); it('handles invalid extractFrom indices', () => { const arbiter = setupChainRuleTestGraph(); arbiter.setRelationConfig('invalid_extract', { type: 'chain', steps: [ { relation: 'member_of', direction: 'out' }, { relation: 'manages', direction: 'out' } ], extractValues: true, extractFrom: 10, // Invalid index (only 2 steps) extractRelation: 'has_budget' }); const result = arbiter.check('user:alice', 'invalid_extract', 'budget:tech-2024'); // Should handle gracefully without crashing assert.ok(typeof result.possibility === 'number'); }); it('handles circular chain references', () => { const arbiter = setupChainRuleTestGraph(); // Create a circular reference arbiter.addNode('node:a', 'node'); arbiter.addNode('node:b', 'node'); arbiter.addNode('node:c', 'node'); arbiter.addRelation('node:a', 'connects_to', 'node:b'); arbiter.addRelation('node:b', 'connects_to', 'node:c'); arbiter.addRelation('node:c', 'connects_to', 'node:a'); // Circular arbiter.setRelationConfig('connects_to', { type: 'direct' }); arbiter.setRelationConfig('circular_chain', { type: 'chain', steps: [ { relation: 'connects_to', direction: 'out' }, { relation: 'connects_to', direction: 'out' }, { relation: 'connects_to', direction: 'out' } ] }); const result = arbiter.check('node:a', 'circular_chain', 'node:a'); // Should complete the circle assert.equal(result.possibility, 1); }); it('validates step configuration correctness', () => { const arbiter = setupChainRuleTestGraph(); // Test with malformed step configuration try { arbiter.setRelationConfig('malformed_chain', { type: 'chain', steps: [ { relation: 'member_of' }, // Missing direction { direction: 'out' } // Missing relation ] }); const result = arbiter.check('user:alice', 'malformed_chain', 'project:web-app'); // Should handle gracefully assert.equal(result.possibility, 0); } catch (error) { // Or might throw validation error - both acceptable assert.ok(error.message.includes('relation') || error.message.includes('direction')); } }); }); });