require 'rails_helper' # A gem entra com `require: false` no Gemfile (é ferramenta de teste, não de runtime). require 'pdf/inspector' # As constantes derivadas SÃO o contrato do documento: elas foram conferidas pixel a # pixel contra Imagens para implantação/Romaneiro_EMAD_SETEMBRO_2026.pdf (render a # 110 dpi). Se alguém mexer numa margem "só um pouquinho", é aqui que aparece. RSpec.describe Pdf::RomaneioPdf do let(:romaneio) { create(:romaneio) } def semear(veiculo, quantidade) quantidade.times do |i| create(:romaneio_linha, romaneio: romaneio, veiculo: veiculo, ordem: i + 1) end end def paginas(pdf) PDF::Inspector::Page.analyze(pdf).pages.size end describe 'geometria' do subject(:documento) { described_class.new(romaneio: romaneio) } it 'é A4 paisagem' do medidas = documento.instance_variable_get(:@pdf).bounds expect([medidas.width.round(2), medidas.height.round(2)]).to eq([785.2, 487.56]) end it 'mantém a altura de linha e os corpos de fonte do documento original' do expect(documento.instance_variable_get(:@linha_h)).to be_within(0.001).of(11.1811) expect(documento.instance_variable_get(:@fonte_dados)).to eq(7.0) expect(documento.instance_variable_get(:@fonte_hdr)).to eq(7.5) end it 'usa a largura útil inteira nas seis colunas' do larguras = documento.instance_variable_get(:@larguras) expect(larguras.size).to eq(6) expect(larguras.sum).to be_within(0.01).of(785.2) end it 'reserva espaço para o rodapé caber na folha cheia' do # 33 paradas + as 2 linhas em branco estouravam o orçamento e o # "ASSINATURA DO MOTORISTA" sumia do papel, sem erro nenhum. expect(documento.instance_variable_get(:@max_linhas_folha)) .to be >= described_class::MAX_LINHAS end end it 'gera uma página por veículo' do semear('GADE_001', 5) semear('GADE_002', 3) expect(paginas(described_class.new(romaneio: romaneio).render)).to eq(2) end it 'imprime só o veículo pedido (é o que a prévia do editor usa)' do semear('GADE_001', 5) semear('GADE_002', 3) expect(paginas(described_class.new(romaneio: romaneio, veiculos: ['GADE_002']).render)).to eq(1) end it 'quebra em folhas de continuação acima de MAX_LINHAS' do semear('GADE_008', described_class::MAX_LINHAS + 1) pdf = described_class.new(romaneio: romaneio).render expect(paginas(pdf)).to eq(2) texto = PDF::Inspector::Text.analyze(pdf).strings.join(' ') expect(texto).to include('FOLHA 1/2').and include('FOLHA 2/2') end it 'assina TODAS as folhas — inclusive a de continuação' do semear('GADE_008', described_class::MAX_LINHAS + 1) texto = PDF::Inspector::Text.analyze(described_class.new(romaneio: romaneio).render).strings expect(texto.count { |t| t.include?('ASSINATURA DO MOTORISTA') }).to eq(2) end it 'numera as paradas continuando entre folhas (bate com a ordem no celular)' do semear('GADE_008', described_class::MAX_LINHAS + 1) texto = PDF::Inspector::Text.analyze(described_class.new(romaneio: romaneio).render).strings expect(texto).to include((described_class::MAX_LINHAS + 1).to_s) end it 'não imprime a parada que saiu do plano' do semear('GADE_001', 3) romaneio.romaneio_linhas.first.update!(removido_em: Time.current, nome: 'NAO DEVE SAIR') texto = PDF::Inspector::Text.analyze(described_class.new(romaneio: romaneio).render).strings.join(' ') expect(texto).not_to include('NAO DEVE SAIR') end it 'escreve o rótulo do plano no cabeçalho' do semear('GADE_001', 2) texto = PDF::Inspector::Text.analyze(described_class.new(romaneio: romaneio).render).strings.join(' ') expect(texto).to include('PLANO:').and include('EMAD 09.2026') end it 'aguenta acento nos endereços (a fonte AFM do Prawn estouraria aqui)' do create(:romaneio_linha, romaneio: romaneio, veiculo: 'GADE_001', endereco: 'RUA INÁCIO DE OLIVEIRA CAMPOS, 182, SÃO PAULO') expect { described_class.new(romaneio: romaneio).render }.not_to raise_error end end