feat(e2e): spec REAL de aprovação de desconto (B-4) + 8 data-testids + fix build main#12
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughO PR introduz fluxo E2E completo para aprovação de desconto quando vendedor excede limite cadastrado (com persistência), adicionando seletores data-testid, marcadores de teste no componente e testes validando UI, diálogo e submissão. Também reimplementa ChangesQuote Discount Approval Flow
useMediaQuery SSR Support
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/quotes/QuoteBuilderSummaryColumn.tsx`:
- Around line 504-510: The rendered data-testid attributes in the
QuoteBuilderSummaryColumn component are inconsistent with the SSOT in Sel.quote,
breaking E2E selectors; update the two divs currently using
data-testid="quote-approval-limit" and data-testid="quote-approval-requested" to
the expected IDs "quote-approval-limit-value" and
"quote-approval-requested-value" respectively so tests can find the elements
(keep the existing content/formatting logic for maxDiscountPercent and the
discountType/discountValue rendering unchanged).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e712055b-d2b1-4605-9d93-85e647a75d37
📒 Files selected for processing (4)
e2e/fixtures/selectors.tse2e/flows/04c-quote-discount-approval.spec.tssrc/components/quotes/QuoteBuilderSummaryColumn.tsxsrc/hooks/ui/useMediaQuery.ts
| <div data-testid="quote-approval-limit"> | ||
| <p className="text-[10px] font-medium text-muted-foreground uppercase tracking-wider">Seu Limite</p> | ||
| <p className="text-sm font-semibold mt-0.5">{maxDiscountPercent}%</p> | ||
| </div> | ||
| <div> | ||
| <div data-testid="quote-approval-requested"> | ||
| <p className="text-[10px] font-medium text-muted-foreground uppercase tracking-wider">Solicitado</p> | ||
| <p className="text-sm font-bold text-amber-500 mt-0.5">{discountType === "percent" ? `${discountValue}%` : formatCurrency(discountValue)}</p> |
There was a problem hiding this comment.
Inconsistência de data-testid quebra os seletores E2E do diálogo
Os IDs usados aqui não batem com o SSOT em Sel.quote: o spec espera quote-approval-limit-value e quote-approval-requested-value, mas o componente renderiza quote-approval-limit e quote-approval-requested.
Diff sugerido
- <div data-testid="quote-approval-limit">
+ <div data-testid="quote-approval-limit-value">
<p className="text-[10px] font-medium text-muted-foreground uppercase tracking-wider">Seu Limite</p>
<p className="text-sm font-semibold mt-0.5">{maxDiscountPercent}%</p>
</div>
- <div data-testid="quote-approval-requested">
+ <div data-testid="quote-approval-requested-value">
<p className="text-[10px] font-medium text-muted-foreground uppercase tracking-wider">Solicitado</p>
<p className="text-sm font-bold text-amber-500 mt-0.5">{discountType === "percent" ? `${discountValue}%` : formatCurrency(discountValue)}</p>
</div>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/quotes/QuoteBuilderSummaryColumn.tsx` around lines 504 - 510,
The rendered data-testid attributes in the QuoteBuilderSummaryColumn component
are inconsistent with the SSOT in Sel.quote, breaking E2E selectors; update the
two divs currently using data-testid="quote-approval-limit" and
data-testid="quote-approval-requested" to the expected IDs
"quote-approval-limit-value" and "quote-approval-requested-value" respectively
so tests can find the elements (keep the existing content/formatting logic for
maxDiscountPercent and the discountType/discountValue rendering unchanged).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7c3c309f54
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| <div data-testid="quote-approval-limit"> | ||
| <p className="text-[10px] font-medium text-muted-foreground uppercase tracking-wider">Seu Limite</p> | ||
| <p className="text-sm font-semibold mt-0.5">{maxDiscountPercent}%</p> | ||
| </div> | ||
| <div> | ||
| <div data-testid="quote-approval-requested"> |
There was a problem hiding this comment.
Align approval-card test IDs with shared selectors
Update these data-testid values to match Sel.quote.approvalLimitValue and Sel.quote.approvalRequestedValue (quote-approval-limit-value / quote-approval-requested-value) defined in e2e/fixtures/selectors.ts; as written, the new spec looks up IDs with the -value suffix and will fail to find the cards in the approval dialog, causing the "dialog de aprovação mostra limite vs solicitado" flow to fail despite correct UI behavior.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Adds a real Playwright E2E flow for quote discount approval, expands quote test selectors, and restores the missing useMediaQuery hook needed by the app layout/build.
Changes:
- Adds a new discount-approval E2E spec covering high-discount UI behavior, approval dialog, and persistence after submit.
- Adds new quote-related
data-testidhooks and selector constants. - Reintroduces an SSR-safe
useMediaQueryhook used by layout code.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
e2e/flows/04c-quote-discount-approval.spec.ts |
New real E2E spec for the discount approval flow. |
e2e/fixtures/selectors.ts |
Adds selector constants for discount/approval UI elements. |
src/components/quotes/QuoteBuilderSummaryColumn.tsx |
Adds data-testid attributes to discount and approval dialog controls. |
src/hooks/ui/useMediaQuery.ts |
Restores responsive media query hook for layout usage. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <div data-testid="quote-approval-limit"> | ||
| <p className="text-[10px] font-medium text-muted-foreground uppercase tracking-wider">Seu Limite</p> | ||
| <p className="text-sm font-semibold mt-0.5">{maxDiscountPercent}%</p> | ||
| </div> | ||
| <div> | ||
| <div data-testid="quote-approval-requested"> |
|
|
||
| // Reload e confere que rota continua válida (quote foi persistido) | ||
| await page.reload({ waitUntil: "domcontentloaded" }); | ||
| expect(page.url()).toContain("/orcamentos/"); | ||
| await expect( | ||
| page.getByText(/Or[çc]amento n[ãa]o encontrado|not found/i), | ||
| ).toHaveCount(0); |
| // Step 1 — sem empresa | ||
| const companySearch = page.locator('[data-testid="company-search-input"]').first(); | ||
| await companySearch.waitFor({ state: "visible", timeout: 10_000 }); | ||
| await companySearch.click(); | ||
| await page.locator(Sel.quote.noCompanyOption).first().click(); | ||
|
|
| const searchInput = page.locator(Sel.quote.productSearchInput).first(); | ||
| await searchInput.waitFor({ state: "visible", timeout: 10_000 }); | ||
|
|
||
| const productCount = await page.locator(Sel.quote.productSearchOption).count(); | ||
| test.skip(productCount === 0, "Catálogo vazio — sem produto pra adicionar (não é falha do spec)"); |
* fix: resolve TS/ESLint errors in items #9–#17 (exhaustive bug fix batch) #9 price-response.adapter.ts — typed 4 helper fns (asRec/str/num/bool/optStr) to eliminate 61 TS errors from snake/camelCase + null-safety issues #10 AdminProductFormPage.tsx — fixed PromobrindProduct field access after expanding ~50 optional fields in product-types.ts #11 AddressTab.tsx — replaced Record<string,unknown> form props with typed interfaces, eliminating 56 TS errors #12 BasicDataTab.tsx — same root cause as #11, typed interfaces applied, 32 TS errors resolved #13 CompareTableView.tsx — changed import from @/types/product.ts (DB snake_case) to @/types/product-catalog.ts (UI camelCase), fixing 26 TS errors #14 SupabaseConnectionsTab.tsx — replaced 17 non-null assertions (!) with nullish coalescing (??) + type casts #15 CatalogContent.tsx + ProductQuickView.tsx — removed unused imports/vars, resolving 32 ESLint warnings #16 useSimulatorWizard.ts — added dispatch to all 15 useCallback/useEffect dep arrays; useGlobalSearch.ts — removed unused imports, stabilised callback, fixed non-null assertions and missing deps #17 T-FIX-5b ESLint guardrail added to eslint.config.js; guards added before forEach+expect loops in commercial-intelligence.test.ts; baselines updated to grandfather existing violations in magic-up tests Baselines: .tsc-baseline.json (1065 errors frozen), .eslint-baseline.json (405) * fix(#17): fix all T-FIX-5b forEach+expect violations in magic-up tests - magic-up-result-panel-keyboard.test.tsx: 64 violations fixed - getDots()/getThumbs() forEach (getAllByRole throws on empty): eslint-disable-next-line - Literal arrays [prev,next], [0,1,2]: eslint-disable-next-line - calls/elements/observedIndices: expect(var).not.toHaveLength(0) guards added - REQUIRED_*_CLASSES consts: eslint-disable-next-line - ids/thumbNames/liveRegions: guards added - magic-up-onda5.test.tsx: 29 violations fixed - required/select.allCards/allMarcar/literal arrays: eslint-disable-next-line - cards/listitems/winnerButtons/buttons/tabIndices: guards added - REQUIRED_FOCUS_CLASSES const: eslint-disable-next-line ESLint baseline updated: 405 → 401 errors (positive drift on all T-FIX-5b work) * fix(#17): suppress T-FIX-5b in commercial-intelligence (guards already in place) All 14 remaining forEach+expect violations suppressed with // eslint-disable-next-line no-restricted-syntax after the existing expect(array).not.toHaveLength(0) guards. Arrays are provably non-empty static constants (PERIOD_OPTIONS=9, MOCK_TRENDING=4, MOCK_OPPORTUNITIES=4) or deterministic generators (generateDateMap(30), generateMockMarketData(360)). Pattern applied consistently with magic-up test fixes from previous commit: - Guard documents intent (catches accidental empty-array mutation) - Disable comment acknowledges guard is in place and suppresses the lint rule Result: 0 T-FIX-5b errors in all 3 test files. T-FIX-5b work fully complete. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Codex Simulation <codex-simulation@example.local>
Contexto
Próximo round aprovado pelo PO depois do PR #11: E2E ponta-a-ponta real de aprovação de desconto, atendendo ao cenário do bloqueador B-4 da auditoria pré-prod (trigger SQL
validate_quote_real_discountcom bypass NULL).O que muda
Spec novo (192 linhas)
e2e/flows/04c-quote-discount-approval.spec.ts— 3 testes que cobrem o fluxo do vendedor ao solicitar aprovação:Test 1 — UI alterna botão quando excede limite
Test 2 — Dialog mostra valores corretos
Test 3 — Submit persiste e redireciona
Skip controlado: se vendedor não tem limite em
seller_discount_limits(ou limite ≥75%), os testes pulam com mensagem explícita explicando a configuração necessária.Infra — 8 data-testids essenciais
Adicionados em
QuoteBuilderSummaryColumn.tsx:quote-discount-inputquote-discount-type-selectquote-request-approval-buttonquote-approval-dialogquote-approval-limitquote-approval-requestedquote-approval-justificationquote-approval-submitSSOT —
Sel.quoteexpandidoe2e/fixtures/selectors.tsganhou 8 novos campos:discountInput,discountTypeSelect,requestApprovalButton,approvalDialog,approvalLimit,approvalRequested,approvalJustification,approvalSubmit.Fix colateral —
src/hooks/ui/useMediaQuery.ts(NOVO)Achado durante validação: build do main estava quebrado.
SidebarReorganized.tsx:49fazimport { useMediaQuery } from "@/hooks/ui/useMediaQuery";mas o arquivo simplesmente não existia. Criada implementação SSR-safe (45 linhas) com:falseem SSR / semwindow.matchMediauseEffectaddEventListener("change")+ fallbackaddListenerpara Safari < 14Sem isso,
vite buildfalha antes de testar qualquer coisa. Este PR desbloqueia o build E entrega o E2E novo.Diferenças vs
e2e/discount-approval.spec.tsexistenteO spec antigo (37 linhas, 4 testes) só verifica que rotas
/admin/aprovacoes-descontoredirecionam para login — smoke puro. Nenhum exercita o fluxo do vendedor ao solicitar aprovação. Este PR cobre o caminho do dinheiro real.Validação
vite build: 1m37s, zero erros (depois do fixuseMediaQuery)npx playwright test --list -g "discount approval":Observações honestas
E2E_USER_*configurado). Validei sintaxe + listagem Playwright + build. Para correr de verdade:E2E_USER_EMAIL/E2E_USER_PASSWORDno CIseller_discount_limits.max_discount_percentcadastrado e menor que 75validate_quote_real_discountem si (que é o bloqueador B-4 server-side). Validar o trigger fail-closed na NULL bypass é tarefa de DB migration + teste SQL, não E2E.Próximo round natural
Se este spec entrar verde, os próximos do mesmo molde seriam:
validate_quote_real_discountcom fail-closed em NULL (fecha o B-4 server-side)Summary by CodeRabbit
Release Notes
Bug Fixes
addEventListener.Tests