import { describe, expect, it } from 'vitest'; import { isRuleShadowed, sameGrantSubject, scopeSpecificity } from './conflicts'; import type { Grant } from './types'; const grant = (over: Partial): Grant => ({ subjectType: 'user', subjectId: 'u1', role: 'editor', scopeType: 'pond', scopeId: null, effect: 'allow', ...over, }); describe('scopeSpecificity', () => { it('orders page > label > pond', () => { expect(scopeSpecificity('page')).toBeGreaterThan(scopeSpecificity('label')); expect(scopeSpecificity('label')).toBeGreaterThan(scopeSpecificity('pond')); }); }); describe('sameGrantSubject', () => { it('matches the same user and the same pseudo-subject', () => { expect(sameGrantSubject(grant({}), grant({ role: 'reader' }))).toBe(true); expect( sameGrantSubject( grant({ subjectType: 'public', subjectId: null }), grant({ subjectType: 'public', subjectId: null }), ), ).toBe(true); }); it('distinguishes different users and subject types', () => { expect(sameGrantSubject(grant({}), grant({ subjectId: 'u2' }))).toBe(false); expect( sameGrantSubject(grant({}), grant({ subjectType: 'authenticated', subjectId: null })), ).toBe(false); }); }); describe('isRuleShadowed', () => { it('flags a pond rule shadowed by an opposite, more specific label rule for the same subject', () => { const existing = [grant({ scopeType: 'label', scopeId: 'l1', effect: 'deny' })]; expect(isRuleShadowed(grant({ scopeType: 'pond', effect: 'allow' }), existing)).toBe(true); }); it('does not flag when the more specific rule agrees in effect', () => { const existing = [grant({ scopeType: 'label', scopeId: 'l1', effect: 'allow' })]; expect(isRuleShadowed(grant({ scopeType: 'pond', effect: 'allow' }), existing)).toBe(false); }); it('does not flag a more specific candidate against a less specific existing rule', () => { const existing = [grant({ scopeType: 'pond', effect: 'deny' })]; expect( isRuleShadowed(grant({ scopeType: 'page', scopeId: 'p1', effect: 'allow' }), existing), ).toBe(false); }); it('ignores rules for other subjects', () => { const existing = [grant({ subjectId: 'u2', scopeType: 'page', scopeId: 'p1', effect: 'deny' })]; expect(isRuleShadowed(grant({ scopeType: 'pond', effect: 'allow' }), existing)).toBe(false); }); });