Some checks failed
Migrates scanning pipeline from marketing-.lu-domains app into Orion module. Supports digital (domain scan) and offline (manual capture) lead channels with enrichment, scoring, campaign management, and interaction tracking. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
232 lines
6.0 KiB
Python
232 lines
6.0 KiB
Python
# app/modules/prospecting/tests/conftest.py
|
|
"""
|
|
Module-specific fixtures for prospecting tests.
|
|
Core fixtures (db, client, etc.) are inherited from the root conftest.py.
|
|
"""
|
|
|
|
import json
|
|
import uuid
|
|
|
|
import pytest
|
|
|
|
from app.modules.prospecting.models import (
|
|
CampaignTemplate,
|
|
Prospect,
|
|
ProspectContact,
|
|
ProspectInteraction,
|
|
ProspectPerformanceProfile,
|
|
ProspectScore,
|
|
ProspectTechProfile,
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def digital_prospect(db):
|
|
"""Create a digital prospect with a domain."""
|
|
prospect = Prospect(
|
|
channel="digital",
|
|
domain_name=f"test-{uuid.uuid4().hex[:8]}.lu",
|
|
status="active",
|
|
source="domain_scan",
|
|
has_website=True,
|
|
uses_https=True,
|
|
http_status_code=200,
|
|
country="LU",
|
|
)
|
|
db.add(prospect)
|
|
db.commit()
|
|
db.refresh(prospect)
|
|
return prospect
|
|
|
|
|
|
@pytest.fixture
|
|
def offline_prospect(db):
|
|
"""Create an offline prospect with business details."""
|
|
prospect = Prospect(
|
|
channel="offline",
|
|
business_name=f"Test Business {uuid.uuid4().hex[:8]}",
|
|
status="pending",
|
|
source="networking_event",
|
|
city="Luxembourg",
|
|
postal_code="1234",
|
|
country="LU",
|
|
notes="Met at networking event",
|
|
tags=json.dumps(["networking", "no-website"]),
|
|
)
|
|
db.add(prospect)
|
|
db.commit()
|
|
db.refresh(prospect)
|
|
return prospect
|
|
|
|
|
|
@pytest.fixture
|
|
def prospect_with_tech(db, digital_prospect):
|
|
"""Create a digital prospect with tech profile."""
|
|
tech = ProspectTechProfile(
|
|
prospect_id=digital_prospect.id,
|
|
cms="WordPress",
|
|
cms_version="5.9",
|
|
server="nginx",
|
|
js_framework="jQuery",
|
|
analytics="Google Analytics",
|
|
ecommerce_platform=None,
|
|
)
|
|
db.add(tech)
|
|
db.commit()
|
|
db.refresh(digital_prospect)
|
|
return digital_prospect
|
|
|
|
|
|
@pytest.fixture
|
|
def prospect_with_performance(db, digital_prospect):
|
|
"""Create a digital prospect with performance profile."""
|
|
perf = ProspectPerformanceProfile(
|
|
prospect_id=digital_prospect.id,
|
|
performance_score=45,
|
|
accessibility_score=70,
|
|
seo_score=60,
|
|
first_contentful_paint_ms=2500,
|
|
largest_contentful_paint_ms=4200,
|
|
total_blocking_time_ms=350,
|
|
cumulative_layout_shift=0.15,
|
|
is_mobile_friendly=False,
|
|
)
|
|
db.add(perf)
|
|
db.commit()
|
|
db.refresh(digital_prospect)
|
|
return digital_prospect
|
|
|
|
|
|
@pytest.fixture
|
|
def prospect_with_contacts(db, digital_prospect):
|
|
"""Create a digital prospect with contacts."""
|
|
contacts = [
|
|
ProspectContact(
|
|
prospect_id=digital_prospect.id,
|
|
contact_type="email",
|
|
value="info@test.lu",
|
|
source_url="https://test.lu/contact",
|
|
is_primary=True,
|
|
),
|
|
ProspectContact(
|
|
prospect_id=digital_prospect.id,
|
|
contact_type="phone",
|
|
value="+352 123 456",
|
|
source_url="https://test.lu/contact",
|
|
is_primary=True,
|
|
),
|
|
]
|
|
db.add_all(contacts)
|
|
db.commit()
|
|
db.refresh(digital_prospect)
|
|
return digital_prospect
|
|
|
|
|
|
@pytest.fixture
|
|
def prospect_with_score(db, digital_prospect):
|
|
"""Create a digital prospect with a score."""
|
|
score = ProspectScore(
|
|
prospect_id=digital_prospect.id,
|
|
score=72,
|
|
technical_health_score=25,
|
|
modernity_score=20,
|
|
business_value_score=20,
|
|
engagement_score=7,
|
|
reason_flags=json.dumps(["no_ssl", "slow"]),
|
|
score_breakdown=json.dumps({"no_ssl": 15, "slow": 10}),
|
|
lead_tier="top_priority",
|
|
)
|
|
db.add(score)
|
|
db.commit()
|
|
db.refresh(digital_prospect)
|
|
return digital_prospect
|
|
|
|
|
|
@pytest.fixture
|
|
def prospect_full(db):
|
|
"""Create a fully enriched digital prospect with all related data."""
|
|
prospect = Prospect(
|
|
channel="digital",
|
|
domain_name=f"full-{uuid.uuid4().hex[:8]}.lu",
|
|
status="active",
|
|
source="domain_scan",
|
|
has_website=True,
|
|
uses_https=False,
|
|
http_status_code=200,
|
|
country="LU",
|
|
)
|
|
db.add(prospect)
|
|
db.flush()
|
|
|
|
tech = ProspectTechProfile(
|
|
prospect_id=prospect.id,
|
|
cms="Drupal",
|
|
cms_version="7.0",
|
|
server="Apache",
|
|
js_framework="jQuery",
|
|
)
|
|
perf = ProspectPerformanceProfile(
|
|
prospect_id=prospect.id,
|
|
performance_score=25,
|
|
accessibility_score=50,
|
|
seo_score=40,
|
|
is_mobile_friendly=False,
|
|
)
|
|
contact = ProspectContact(
|
|
prospect_id=prospect.id,
|
|
contact_type="email",
|
|
value="info@full-test.lu",
|
|
is_primary=True,
|
|
)
|
|
score = ProspectScore(
|
|
prospect_id=prospect.id,
|
|
score=85,
|
|
technical_health_score=35,
|
|
modernity_score=20,
|
|
business_value_score=20,
|
|
engagement_score=10,
|
|
reason_flags=json.dumps(["no_ssl", "very_slow", "outdated_cms", "not_mobile_friendly"]),
|
|
lead_tier="top_priority",
|
|
)
|
|
|
|
db.add_all([tech, perf, contact, score])
|
|
db.commit()
|
|
db.refresh(prospect)
|
|
return prospect
|
|
|
|
|
|
@pytest.fixture
|
|
def campaign_template(db):
|
|
"""Create a campaign template."""
|
|
template = CampaignTemplate(
|
|
name="Test Template",
|
|
lead_type="bad_website",
|
|
channel="email",
|
|
language="fr",
|
|
subject_template="Votre site {domain} a des problèmes",
|
|
body_template="Bonjour {business_name},\n\nVotre site {domain} a un score de {score}.\n\nIssues: {issues}",
|
|
is_active=True,
|
|
)
|
|
db.add(template)
|
|
db.commit()
|
|
db.refresh(template)
|
|
return template
|
|
|
|
|
|
@pytest.fixture
|
|
def interaction(db, digital_prospect):
|
|
"""Create a prospect interaction."""
|
|
interaction = ProspectInteraction(
|
|
prospect_id=digital_prospect.id,
|
|
interaction_type="call",
|
|
subject="Initial contact",
|
|
notes="Discussed website needs",
|
|
outcome="positive",
|
|
next_action="Send proposal",
|
|
created_by_user_id=1,
|
|
)
|
|
db.add(interaction)
|
|
db.commit()
|
|
db.refresh(interaction)
|
|
return interaction
|