import { test, describe, it } from 'node:test'; import assert from 'node:assert/strict'; import { setupChainRuleTestGraph } from './helpers.js'; describe('ChainRule Comprehensive Tests', () => { describe('Basic Chain Traversal', () => { it('performs forward chain traversal correctly', () => { const arbiter = setupChainRuleTestGraph(); // Test: user → group → project chain arbiter.setRelationConfig('can_access_projects', { type: 'chain', steps: [ { relation: 'member_of', direction: 'out' }, // user → group { relation: 'manages', direction: 'out' } // group → project ] }); // Alice should have access to engineering projects const result1 = arbiter.check('user:alice', 'can_access_projects', 'project:web-app'); if (process.env.TEST_DEBUG === '1') console.log(result1); assert.equal(result1.possibility, 1); assert.equal(result1.reason, 'allow_rule_matched'); const result2 = arbiter.check('user:alice', 'can_access_projects', 'project:ai-platform'); assert.equal(result2.possibility, 1); // Alice should NOT have access to QA projects const result3 = arbiter.check('user:alice', 'can_access_projects', 'project:mobile-app'); assert.equal(result3.possibility, 0); }); it('performs backward chain traversal correctly', () => { const arbiter = setupChainRuleTestGraph(); // Test: project ← group ← user chain (reverse direction) arbiter.setRelationConfig('project_members', { type: 'chain', steps: [ { relation: 'manages', direction: 'in' }, // project ← group { relation: 'member_of', direction: 'in' } // group ← user ] }); // web-app project should be connected to Alice via reverse chain const result1 = arbiter.check('project:web-app', 'project_members', 'user:alice'); assert.equal(result1.possibility, 1); // mobile-app project should NOT be connected to Alice const result2 = arbiter.check('project:mobile-app', 'project_members', 'user:alice'); assert.equal(result2.possibility, 0); }); it('handles three-step chains correctly', () => { const arbiter = setupChainRuleTestGraph(); // Test: user → group → department → access_level arbiter.setRelationConfig('user_access_level', { type: 'chain', steps: [ { relation: 'member_of', direction: 'out' }, // user → group { relation: 'belongs_to', direction: 'out' }, // group → department { relation: 'has_access_level', direction: 'out' } // department → access_level ] }); // Alice (engineering → tech → level-5) should have level-5 access const result1 = arbiter.check('user:alice', 'user_access_level', 'access:level-5'); assert.equal(result1.possibility, 1); // Bob (qa → ops → level-3) should have level-3 access const result2 = arbiter.check('user:bob', 'user_access_level', 'access:level-3'); assert.equal(result2.possibility, 1); // Alice should NOT have level-3 access const result3 = arbiter.check('user:alice', 'user_access_level', 'access:level-3'); assert.equal(result3.possibility, 0); }); }); });