- Consolidate 3 duplicate server processes into 1 session-scoped
live_server fixture in conftest.py (port 5111, shared across all
visual test modules). Reduces startup overhead from ~3× to 1×.
- Fix init_db mock: patch padelnomics.app.init_db (where it's used)
instead of core.init_db (where it's defined). The before_serving
hook imported init_db locally — patching core alone didn't prevent
the real init_db from replacing the in-memory test DB.
- Keep patches active through app.run_task() so before_serving hooks
can't replace the test DB during the server's lifetime.
- Force RESEND_API_KEY="" in the visual test server subprocess to
prevent real email sends (dev mode: prints to stdout, returns "dev").
- Remove 4 screenshot-only no-op tests, replace with single
test_capture_screenshots that grabs all pages in one pass.
- Fix test_planner_tab_switching: remove nonexistent "metrics" tab.
- Delete ~200 lines of duplicated boilerplate from 3 test files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add requires_weasyprint marker to TestGenerateBusinessPlan and TestWorkerHandler
(these need libgobject/pango/cairo which CI python:3.12-slim lacks)
- Fix export route tests: use opaque tokens instead of integer IDs
- Replace deprecated datetime.utcnow() with datetime.now(UTC)
- Add missing jsonify/Response imports to admin routes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add /scenarios/<id>/pdf admin route for direct PDF generation via WeasyPrint.
Fix plan.html Jinja template: .items → ['items'] to avoid dict method collision.
Add scenario fixture in conftest.py and comprehensive test suite for business
plan sections, PDF generation, worker handler, and export routes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Playtomic tenants API recycles results past its internal limit —
stop after 3 consecutive pages with zero new unique IDs.
Calculator tests: replace hardcoded default values (6 courts, specific
sqm/capex) with DEFAULTS references so tests don't break when
defaults change.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sequential IDs in /planner/export/<id> and /leads/<id>/unlock leaked
business volume (e.g. export_id=47 reveals ~47 PDFs sold). Replace with
22-char URL-safe tokens that carry no countable information.
- Migration 0017: adds `token TEXT` to business_plan_exports and
lead_requests, backfills existing rows with secrets.token_urlsafe(16),
creates unique indexes for fast lookups
- billing/routes.py: INSERT into business_plan_exports includes token
- leads/routes.py: INSERT into lead_requests includes token; enqueue
payload includes lead_token; verify_quote() looks up by token
- planner/routes.py: /export/<token> route (was /export/<int:export_id>)
- suppliers/routes.py: /leads/<token>/unlock (was /leads/<int:lead_id>)
- worker.py: email links use token for both export and verify URLs
- Templates: url_for() calls use token= param
- test_phase0.py: _submit_guest_quote() returns (lead_id, auth_token,
lead_token); verify URL tests use opaque lead token
Integer PKs unchanged; admin routes unchanged.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- test_planner_calculate_htmx: click capex tab to reveal #tab-content
(it starts display:none and only shows after tab switch)
- test_planner_quote_sidebar_visible_wide: use browser.new_page() instead
of page.context.new_page() (default contexts don't support new_page)
- test_login/signup/quote_step1_loads: add .first to avoid strict mode
violation from the feedback popover form
- test_language_switcher_en_to_de: verify footer link href + navigate
directly instead of click (avoids off-screen element timing issues)
- test_landing_nav_no_overlap: filter display:none elements (zero-width
bounding rect) so mobile-only nav div doesn't skew overlap check
- test_quote_wizard_*: replace schema.sql (doesn't exist) with migrate()
approach matching test_visual.py and test_e2e_flows.py; fix URL from
/leads/quote to /en/leads/quote; use label click for display:none pill
radios; add missing required fields for steps 6 (financing_status +
decision_process) and 8 (services_needed); add contact_phone to step 9
All 1018 unit tests + 61 e2e tests now pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Article slug is template_slug + city_slug ("city-cost-miami"),
not just the city slug ("miami").
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
git mv all tracked files from the nested padelnomics/ workspace
directory to the git repo root. Merged .gitignore files.
No code changes — pure path rename.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>