require 'rails_helper' # O catálogo é a fonte única de "o que dá para liberar". Estas travas existem # porque um erro aqui não aparece na tela: uma chave escrita errado no # PADRAO_POR_ROLE simplesmente não bate com nada e tira acesso de todo um papel # em silêncio. RSpec.describe Permissao do describe 'catálogo' do it 'toda chave segue o padrão area.acao e pertence a um grupo declarado' do described_class::TODAS.each do |chave, cfg| expect(chave.count('.')).to eq(1), "#{chave} fora do padrão area.acao" expect(described_class::GRUPOS).to have_key(cfg[:grupo]), "#{chave}: grupo #{cfg[:grupo]} não existe" expect(cfg[:label]).to be_present expect(cfg[:descricao]).to be_present, "#{chave} sem descrição (é o texto que o ADM lê na tela)" end end it 'por_grupo cobre todas as chaves' do total = described_class.por_grupo.values.sum(&:size) expect(total).to eq(described_class.chaves.size) end it 'filtrar descarta chave inexistente e repetida' do expect(described_class.filtrar(['consolidacao.ver', 'nao.existe', 'consolidacao.ver'])) .to eq(['consolidacao.ver']) end end describe 'PADRAO_POR_ROLE' do it 'só usa chaves que existem no catálogo' do described_class::PADRAO_POR_ROLE.each do |role, lista| next if lista == :todas lista.each do |chave| expect(described_class).to be_existe(chave), "#{role} referencia chave inexistente: #{chave}" end end end it 'admin recebe o catálogo inteiro' do expect(described_class.do_role('admin')).to match_array(described_class.chaves) end # O fallback é o que mantém o comportamento de hoje para quem ainda não tem # perfil. Se estes pares mudarem, alguém perde acesso no dia do deploy. it 'reproduz pode_consolidar? e pode_ver_config? de cada papel' do { 'admin' => [true, true], 'gerente' => [true, true], 'operador' => [true, false], 'motorista' => [false, false], 'externo' => [false, false] }.each do |role, (consolidar, config)| chaves = described_class.do_role(role) expect(chaves.include?('consolidacao.ver')).to eq(consolidar), "#{role}: consolidar" expect(chaves.include?('admin.configuracoes')).to eq(config), "#{role}: config" end end # As duas mudanças de comportamento deliberadas desta entrega. it 'externo não enxerga o financeiro (era o furo do skip_authorization)' do expect(described_class.do_role('externo')).not_to include('dashboard.financeiro') end it 'operador não enxerga a auditoria (o menu nunca ofereceu)' do expect(described_class.do_role('operador')).not_to include('admin.auditoria') end it 'motorista não usa permissão — o acesso dele é por tipo de conta' do expect(described_class.do_role('motorista')).to be_empty end end end