import {describe, expect, it} from 'vitest'; import { ACCESS_ROLE, appsOf, isAppPermission, isAppRole, toPermissions } from '../../src/models/admin/admin.schema.js'; /** * The permission model is (app, role). These tests pin the two properties the * rest of the module leans on: that the older `['tickets']` shape still means * "tickets at the access role", and that nothing outside APP_ROLES gets in. */ describe('toPermissions', () => { it('reads the full (app, role) form', () => { expect(toPermissions([{app: 'tickets', role: 'access'}])).toEqual([ {app: 'tickets', role: 'access'} ]); }); it('reads a plain app list as that app at the access role', () => { expect(toPermissions(['feedback', 'admin'])).toEqual([ {app: 'feedback', role: ACCESS_ROLE}, {app: 'admin', role: ACCESS_ROLE} ]); }); it('accepts the two forms mixed, which is what a half-migrated caller sends', () => { expect(toPermissions(['feedback', {app: 'tickets', role: 'access'}])).toEqual([ {app: 'feedback', role: ACCESS_ROLE}, {app: 'tickets', role: ACCESS_ROLE} ]); }); it('drops duplicates of the same (app, role)', () => { expect(toPermissions(['tickets', {app: 'tickets', role: 'access'}])).toEqual([ {app: 'tickets', role: ACCESS_ROLE} ]); }); it('rejects rather than silently dropping an unknown app', () => { // Silently ignoring it would let "grant calendar + nonsense" look like a // success while granting less than the caller asked for. expect(toPermissions(['calendar', 'nonsense'])).toBeNull(); }); it('rejects an unknown role', () => { expect(toPermissions([{app: 'tickets', role: 'refund'}])).toBeNull(); }); it('rejects anything that is not a list', () => { expect(toPermissions('admin')).toBeNull(); expect(toPermissions(null)).toBeNull(); expect(toPermissions({app: 'admin', role: 'access'})).toBeNull(); }); it('reads an empty list as "no permissions", not as invalid', () => { expect(toPermissions([])).toEqual([]); }); }); describe('isAppRole', () => { it('accepts the access role for every app', () => { expect(isAppRole('admin', ACCESS_ROLE)).toBe(true); expect(isAppRole('calendar', ACCESS_ROLE)).toBe(true); }); it('rejects a role that does not exist yet', () => { expect(isAppRole('tickets', 'refund')).toBe(false); }); }); describe('isAppPermission', () => { it('needs both halves to be valid', () => { expect(isAppPermission({app: 'tickets', role: ACCESS_ROLE})).toBe(true); expect(isAppPermission({app: 'tickets'})).toBe(false); expect(isAppPermission({role: ACCESS_ROLE})).toBe(false); expect(isAppPermission(null)).toBe(false); }); }); describe('appsOf', () => { it('collapses several roles on one app to a single entry', () => { // The point of the derived list: a user with two roles on tickets has // access to tickets once, not twice. const apps = appsOf([ {app: 'tickets', role: ACCESS_ROLE}, {app: 'tickets', role: 'future-role'}, {app: 'admin', role: ACCESS_ROLE} ]); expect(apps).toEqual(['tickets', 'admin']); }); it('is empty for no permissions', () => { expect(appsOf([])).toEqual([]); }); });