Skip to content

fix(pdf): diacríticos jurídicos + dead prop + 45 testes do módulo PDF#445

Merged
adm01-debug merged 3 commits into
mainfrom
fix/pdf-diacritics-tests
May 26, 2026
Merged

fix(pdf): diacríticos jurídicos + dead prop + 45 testes do módulo PDF#445
adm01-debug merged 3 commits into
mainfrom
fix/pdf-diacritics-tests

Conversation

@adm01-debug
Copy link
Copy Markdown
Owner

@adm01-debug adm01-debug commented May 26, 2026

Continuação da Auditoria — 3 itens restantes + Suíte de Testes

Complementa o PR #438. 3 commits, 3 arquivos.


🔴 CRÍTICO — Bug #10: Diacríticos removidos dos textos jurídicos

Arquivo: src/components/pdf/proposal/ProposalNotes.tsx

Problema: 18 cedilhas e acentos ausentes nas cláusulas de Condições Comerciais e Termos de Aceite — textos com validade jurídica citados explicitamente no Código Civil Brasileiro.

"Condicoes Comerciais"     → "Condições Comerciais"
"personalizacao"           → "personalização"
"Codigo Civil"             → "Código Civil"
"aceitacao"                → "aceitação"
"especificacoes"           → "especificações"
"Termos de Aceite e Contratacao" → "Termos de Aceite e Contratação"
"destinatario"             → "destinatário"
"expressoes de concordancia" → "expressões de concordância"
... (18 ocorrências no total)

Impacto: Uma proposta enviada a um cliente com texto jurídico malformado pode gerar questionamentos sobre a validade contratual. No mínimo, é antiprofissional.


🟡 MÉDIO — Bug #11: Dead prop quoteNumber em ProposalHeader

Arquivo: src/components/pdf/proposal/ProposalHeader.tsx

Problema: quoteNumber? declarada em Props mas nunca desestruturada nem usada (componente sempre lê data.quoteNumber internamente). Qualquer caller que passasse quoteNumber teria o valor silenciosamente ignorado.

Fix: Prop removida da interface.


✅ NOVO — Suíte de Testes: 45 casos cobrindo todo o módulo PDF

Arquivo: src/components/pdf/__tests__/PdfGenerationModule.test.ts

Organização (9 describe blocks):

Grupo Casos O que testa
formatPaymentMethod 5 boleto, pix, desconhecido, undefined, vazio
formatPaymentTerms 8 6 prazos mapeados + desconhecido + undefined
formatDeliveryTime 9 date:, 5 prazos, desconhecido, undefined, vazio
formatShipping 7 cif, fob, fob_pre c/custo, sem custo, undefined, desconhecido
lineTotal calculation 7 simples, desconto, personalização, pers+desconto, multi-pers, qty=0, sem pers
paginateItems 7 vazio, 1 item, 3 itens, 20 itens, nenhuma página intermediária vazia, StrictMode
downloadPDF 4 URL criada, filename correto, revoke após download, DOM cleanup
generateProposalPDFv2 1 container removido do DOM mesmo em erro html2canvas
Cenários de negócio 7 frete CIF, data entrega, 50/50, kit, desconto global, quoteNumber, proposta vazia

Casos de ponta especialmente importantes:


📊 Total de bugs corrigidos (PR #438 + este PR)

# Severidade Arquivo Descrição
1 🔴 Crítico proposalPdfReactGenerator.ts root.unmount() fora do finally
2 🔴 Crítico PdfGenerationDialog.tsx blobUrl não revogado ao fechar
3 🔴 Crítico ProposalProductTable.tsx lazy + useState("") → imagens brancas no PDF
4 🟠 Alto PdfGenerationDialog.tsx dialog fecha durante geração (async zumbi)
5 🟠 Alto PdfGenerationDialog.tsx progressLabel/pdfVersion não resetados
6 🟠 Alto ProposalProductTable.tsx coluna Total ausente
7 🟡 Médio PropostaComercialTailwind.tsx itemIndex mutável em render (StrictMode)
8 🟡 Médio PdfGenerationDialog.tsx props @deprecated não marcadas
9 🟡 Médio PdfGenerationDialog.tsx variante whatsapp = primary (código morto)
10 🔴 Crítico ProposalNotes.tsx 18 diacríticos ausentes em texto jurídico
11 🟡 Médio ProposalHeader.tsx dead prop quoteNumber na interface

Summary by cubic

Restores proper diacritics in legal texts of the PDF proposal, removes a dead prop, and adds a comprehensive test suite for the PDF module. Improves contract wording and prevents regressions.

  • Bug Fixes

    • Restored diacritics in legal sections of ProposalNotes (e.g., “Condições Comerciais”, “Termos de Aceite e Contratação”).
    • Removed unused quoteNumber prop from ProposalHeader (now always reads data.quoteNumber).
  • New Features

    • Added 45 tests for the PDF module covering formatters, pagination, line totals, downloads, and error handling (e.g., qty=0, React StrictMode, fob_pre cost=0, invalid date: handling, blob URL revoke and DOM cleanup, container removal on html2canvas error).

Written for commit fa501ab. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Corrigidas inconsistências de acentuação e pontuação no texto das notas de proposta em PDF.
    • Atualizada terminologia dos termos de aceite e contratação para melhor clareza.
  • Tests

    • Adicionada cobertura abrangente de testes para o módulo de geração de PDF, incluindo validação de paginação, cálculos de valores e download de arquivos.

Review Change Stack

…dica

CRÍTICO: 18 cedilhas/acentos removidos dos textos de Condições Comerciais
e Termos de Aceite — textos com validade legal segundo o Código Civil.

Problemas corrigidos:
- "Condicoes Comerciais" → "Condições Comerciais"
- "personalizacao" → "personalização"
- "descricao" → "descrição"
- "Termos de Aceite e Contratacao" → "Termos de Aceite e Contratação"
- "Codigo Civil" → "Código Civil"
- "destinatario" → "destinatário"
- "expressoes" → "expressões"
- "concordancia" → "concordância"
- "aceitacao" → "aceitação"
- "especificacoes" → "especificações"
- "valido" → "válido"
- "Representacao" → "Representação"
- "respondente" → respondente (ok)
- "suficientes" → suficientes (ok)
- "contratacao" → "contratação"
- "condicoes" → "condições"

Também: "1. ACEITE -" → "1. ACEITE —" (traço longo, padrão jurídico)
         "2. REPRESENTACAO" → "2. REPRESENTAÇÃO"
A prop quoteNumber era declarada na interface mas nunca desestruturada
no componente (sempre usava data.quoteNumber internamente).
Removida para evitar confusão — callers que passassem quoteNumber
teriam o valor silenciosamente ignorado.
Cobertura:
  - formatPaymentMethod: 5 casos (boleto, pix, desconhecido, undefined, vazio)
  - formatPaymentTerms: 8 casos (todos os 6 mapeados + desconhecido + undefined)
  - formatDeliveryTime: 9 casos (date:, todos os 5 prazos, desconhecido, undefined, vazio)
  - formatShipping: 7 casos (cif, fob, fob_pre c/custo, sem custo, type undefined, desconhecido)
  - lineTotal calculation: 7 casos (simples, desconto, personalização, pers+desconto,
    múltiplas pers, qtd=0, sem personalizations)
  - paginateItems: 7 casos (vazio, 1 item, 3 itens, 20 itens total, StrictMode imutável)
  - downloadPDF: 4 casos (URL criada, filename, revoke URL, DOM cleanup)
  - generateProposalPDFv2: 1 caso (cleanup container em erro html2canvas)
  - Cenários de negócio: 7 cenários reais (frete CIF, data entrega, 50/50,
    kit, desconto global, normalização quoteNumber, proposta vazia)
Copilot AI review requested due to automatic review settings May 26, 2026 11:51
@vercel
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

Deployment failed with the following error:

Invalid vercel.json file provided

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@supabase
Copy link
Copy Markdown

supabase Bot commented May 26, 2026

This pull request has been ignored for the connected project doufsxqlfjyuvxuezpln because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
we-dream-big Error Error May 26, 2026 11:51am

@adm01-debug adm01-debug merged commit 6d4f34a into main May 26, 2026
4 of 6 checks passed
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 89a4f4eb-99f8-4b5d-950a-4c1f381c12d0

📥 Commits

Reviewing files that changed from the base of the PR and between ffd60f5 and fa501ab.

📒 Files selected for processing (3)
  • src/components/pdf/__tests__/PdfGenerationModule.test.ts
  • src/components/pdf/proposal/ProposalHeader.tsx
  • src/components/pdf/proposal/ProposalNotes.tsx

Walkthrough

Este PR introduz testes extensivos (600 linhas) para o módulo de geração de PDF de propostas, validando formatações de pagamento, cálculos de linha, paginação e geração com tratamento de erro. Inclui ajuste de contrato em ProposalHeader removendo prop redundante e correções de ortografia/pontuação em ProposalNotes.

Changes

Testes e Ajustes de Geração de PDF

Layer / File(s) Summary
Setup e fixtures dos testes
src/components/pdf/__tests__/PdfGenerationModule.test.ts
Cabeçalho descrevendo escopo de cobertura, imports e helpers makeItem/makeData para montar dados base com overrides.
Testes de formatação
src/components/pdf/__tests__/PdfGenerationModule.test.ts
formatPaymentMethod, formatPaymentTerms, formatDeliveryTime e formatShipping validam mapeamentos esperados, casos raw desconhecidos e tratamento de undefined.
Testes de cálculo de lineTotal
src/components/pdf/__tests__/PdfGenerationModule.test.ts
Replica lógica de lineTotal com composição de custo unitário (personalizações ÷ quantidade), múltiplas personalizações e desconto de linha, validando cenários sem erros.
Paginação, PDF e error handling
src/components/pdf/__tests__/PdfGenerationModule.test.ts
Testes de regras de paginação (paginateItems), compatibilidade com StrictMode, downloadPDF (blob URL, atributo download, revogação), e cleanup de container em erro mesmo com html2canvas rejeitado.
Cenários de negócio
src/components/pdf/__tests__/PdfGenerationModule.test.ts
Cobre frete CIF, entrega por data, parcelamento 50/50, validação de kit_group_id, desconto global e proposta com 0 itens sem erros.
Contrato simplificado em ProposalHeader
src/components/pdf/proposal/ProposalHeader.tsx
Remove prop quoteNumber redundante da interface Props, sinalizando que o número deve vir sempre de data.quoteNumber.
Conteúdo corrigido em ProposalNotes
src/components/pdf/proposal/ProposalNotes.tsx
Correções de acentuação ("Condições Comerciais", "personalização", "descrição"), pontuação (hífen → travessão) e redação em "Termos de Aceite e Contração".

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pdf-diacritics-tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR improves the proposal PDF output text (Portuguese accents/typography), removes an unused quoteNumber prop from the PDF header component, and introduces a comprehensive Vitest suite covering PDF generation utilities and formatting logic.

Changes:

  • Corrects Portuguese strings in ProposalNotes (accents and punctuation).
  • Removes the quoteNumber prop from ProposalHeader (now read from data.quoteNumber).
  • Adds a large Vitest test suite for PDF formatting, pagination behavior, download behavior, and error cleanup paths.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
src/components/pdf/proposal/ProposalNotes.tsx Text/typography corrections for proposal notes and acceptance terms.
src/components/pdf/proposal/ProposalHeader.tsx Removes dead quoteNumber prop in favor of data.quoteNumber.
src/components/pdf/tests/PdfGenerationModule.test.ts Adds extensive tests for PDF template formatting and PDF generation utilities.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +496 to +512
describe("generateProposalPDFv2 — error handling & cleanup", () => {
beforeEach(() => {
// Mock html2canvas para lançar erro
vi.mock("html2canvas", () => ({
default: vi.fn().mockRejectedValue(new Error("CORS error")),
}));

// Mock mínimo de jsPDF
vi.mock("jspdf", () => ({
jsPDF: vi.fn().mockImplementation(() => ({
internal: { pageSize: { getWidth: () => 210, getHeight: () => 297 } },
addPage: vi.fn(),
addImage: vi.fn(),
output: vi.fn().mockReturnValue(new Blob()),
})),
}));
});
Comment on lines +441 to +444
Object.defineProperty(window, "URL", {
value: { createObjectURL: createObjectURLMock, revokeObjectURL: revokeObjectURLMock },
writable: true,
});
Comment on lines +457 to +459
afterEach(() => {
vi.restoreAllMocks();
});
Comment on lines +199 to +213
function computeLineTotal(item: ProposalItem): number {
const persUnitCost =
item.personalizations?.reduce((sum, p) => {
const pTotal = p.total_cost || 0;
return (
sum +
(item.quantity > 0
? Math.round((pTotal / item.quantity) * 100) / 100
: 0)
);
}, 0) ?? 0;
const allInUnitPrice = item.unitPrice + persUnitCost;
const itemDiscount = item.discount || 0;
return allInUnitPrice * item.quantity - itemDiscount;
}
Comment on lines +290 to +353
describe("paginateItems — regras de negócio", () => {
// Constantes replicadas de PropostaComercialTailwind para alinhamento
const PAGE_H = 1123;
const FIRST_HEADER_H = 128;
const CLIENT_BAR_H = 90;
const TABLE_HEADER_H = 38;
const TOTALS_H = 180;
const NOTES_H = 310;
const NOTES_FOOTER_H = 230;
const SIMPLE_FOOTER_H = 30;
const CONT_HEADER_H = 60;
const CONT_CLIENT_H = 60;
const ROW_H = 76;

function paginateItems(items: ProposalItem[]): ProposalItem[][] {
const singlePageAvailable =
PAGE_H - FIRST_HEADER_H - CLIENT_BAR_H - TABLE_HEADER_H - TOTALS_H - NOTES_H - NOTES_FOOTER_H - SIMPLE_FOOTER_H - 40;
const singlePageRows = Math.max(0, Math.floor(singlePageAvailable / ROW_H));

if (items.length <= singlePageRows && singlePageRows > 0) {
return [items];
}

const pages: ProposalItem[][] = [];
let remaining = [...items];

const firstPageAvailable =
PAGE_H - FIRST_HEADER_H - CLIENT_BAR_H - TABLE_HEADER_H - NOTES_FOOTER_H - SIMPLE_FOOTER_H - 30;
const firstPageRows = Math.max(1, Math.floor(firstPageAvailable / ROW_H));

const fpRows = Math.min(firstPageRows, remaining.length);
pages.push(remaining.slice(0, fpRows));
remaining = remaining.slice(fpRows);

if (remaining.length === 0) {
pages.push([]);
}

while (remaining.length > 0) {
const contPageAvailable =
PAGE_H - CONT_HEADER_H - CONT_CLIENT_H - TABLE_HEADER_H - NOTES_FOOTER_H - SIMPLE_FOOTER_H - 30;
const contPageRows = Math.floor(contPageAvailable / ROW_H);

if (remaining.length <= contPageRows) {
const spaceNeeded =
remaining.length * ROW_H + TABLE_HEADER_H + TOTALS_H + NOTES_H + NOTES_FOOTER_H + SIMPLE_FOOTER_H + CONT_HEADER_H + CONT_CLIENT_H + 40;
if (spaceNeeded <= PAGE_H) {
pages.push(remaining);
remaining = [];
} else {
const fitRows = Math.max(1, Math.floor(contPageAvailable / ROW_H));
pages.push(remaining.slice(0, fitRows));
remaining = remaining.slice(fitRows);
if (remaining.length === 0) pages.push([]);
}
} else {
pages.push(remaining.slice(0, contPageRows));
remaining = remaining.slice(contPageRows);
}
}

return pages;
}

@adm01-debug adm01-debug deleted the fix/pdf-diacritics-tests branch May 29, 2026 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants