/* * Tests for the capability catalog and default roles used by the RBAC system. * Roles are stored in the database and editable at runtime; this validates the * static catalog/defaults and the pure capability-matching helpers. */ const accessControl = require('./accessControl'); describe('access control', () => { test('capability catalog is well-formed', () => { const { CAPABILITIES, CAPABILITY_KEYS } = accessControl; expect(CAPABILITIES.length).toBeGreaterThan(0); for (const cap of CAPABILITIES) { expect(typeof cap.key).toBe('string'); expect(typeof cap.label).toBe('string'); expect(typeof cap.group).toBe('string'); } // Keys are unique. expect(new Set(CAPABILITY_KEYS).size).toBe(CAPABILITY_KEYS.length); }); test('default roles include the built-ins and PM roles', () => { const keys = accessControl.DEFAULT_ROLES.map((r) => r.key); for (const key of ['admin', 'finance', 'operations', 'pm_admin', 'pm_user', 'viewer']) { expect(keys).toContain(key); } const admin = accessControl.DEFAULT_ROLES.find((r) => r.key === 'admin'); expect(admin.capabilities).toEqual(['*']); const pmUser = accessControl.DEFAULT_ROLES.find((r) => r.key === 'pm_user'); expect(pmUser.capabilities).toContain('pm.complete'); expect(pmUser.capabilities).not.toContain('pm.manage'); }); test('capabilitySetIncludes honors the wildcard', () => { expect(accessControl.capabilitySetIncludes(['*'], 'anything')).toBe(true); expect(accessControl.capabilitySetIncludes(['assets.view'], 'assets.view')).toBe(true); expect(accessControl.capabilitySetIncludes(['assets.view'], 'assets.delete')).toBe(false); }); test('sanitizeCapabilities drops unknown keys and collapses wildcard', () => { expect(accessControl.sanitizeCapabilities(['assets.view', 'made.up'])).toEqual(['assets.view']); expect(accessControl.sanitizeCapabilities(['assets.view', '*'])).toEqual(['*']); }); });