// @vitest-environment happy-dom
import { afterEach, describe, expect, it } from 'vitest'
import { cleanup, render, screen } from '@testing-library/react'
// Sin `globals: true` en vitest, RTL no auto-limpia entre tests.
afterEach(cleanup)
import {
PermissionsProvider,
useCan,
usePermissionsActive,
makeCan,
capabilityForActionKey,
modelCapability,
} from '../permissions-context'
function Probe({ capability }: { capability: string }) {
const can = useCan()
return {can(capability) ? 'allowed' : 'denied'}
}
function ActiveProbe() {
const active = usePermissionsActive()
return {active ? 'yes' : 'no'}
}
describe('makeCan', () => {
it('isAdmin permite todo', () => {
const can = makeCan([], true)
expect(can('pos_orders.create')).toBe(true)
expect(can('cualquier.cosa')).toBe(true)
})
it('capability exacta en la lista → true; ausente → false', () => {
const can = makeCan(['pos_orders.index', 'general.work_after_hours'], false)
expect(can('pos_orders.index')).toBe(true)
expect(can('general.work_after_hours')).toBe(true)
expect(can('pos_orders.create')).toBe(false)
})
it('wildcard "*" permite todo', () => {
const can = makeCan(['*'], false)
expect(can('pos_orders.delete')).toBe(true)
expect(can('lo.que.sea')).toBe(true)
})
})
describe('useCan', () => {
it('sin provider → siempre true (comportamiento legacy, nada se oculta)', () => {
render()
expect(screen.getByTestId('probe').textContent).toBe('allowed')
})
it('con provider no-admin: exacta permitida, resto denegado', () => {
render(
,
)
expect(screen.getByTestId('probe').textContent).toBe('allowed')
render(
,
)
expect(screen.getAllByTestId('probe')[1].textContent).toBe('denied')
})
it('con provider isAdmin → todo permitido', () => {
render(
,
)
expect(screen.getByTestId('probe').textContent).toBe('allowed')
})
it('usePermissionsActive refleja la presencia del provider', () => {
render()
expect(screen.getByTestId('active').textContent).toBe('no')
render(
,
)
expect(screen.getAllByTestId('active')[1].textContent).toBe('yes')
})
})
describe('capability mapping', () => {
it('view→index, edit→update, resto verbatim', () => {
expect(capabilityForActionKey('view')).toBe('index')
expect(capabilityForActionKey('edit')).toBe('update')
expect(capabilityForActionKey('delete')).toBe('delete')
expect(capabilityForActionKey('pagar')).toBe('pagar')
})
it('modelCapability lowercasea el modelo', () => {
expect(modelCapability('PosOrders', 'create')).toBe('posorders.create')
expect(modelCapability('pos_orders', 'edit')).toBe('pos_orders.update')
})
})