feat: affiliates disclosure — per-retailer tooltip copy + first-encounter banner constants
This commit is contained in:
parent
4c3f3a95a5
commit
73cec07bd2
2 changed files with 78 additions and 0 deletions
49
circuitforge_core/affiliates/disclosure.py
Normal file
49
circuitforge_core/affiliates/disclosure.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
"""Affiliate disclosure copy constants.
|
||||
|
||||
Follows the plain-language disclosure design from the affiliate links design
|
||||
doc. All copy is centralized here so products don't drift out of sync and
|
||||
legal/copy review has a single file to audit.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
# Per-retailer tooltip copy (shown on hover/tap of affiliate link indicator)
|
||||
_TOOLTIP: dict[str, str] = {
|
||||
"ebay": (
|
||||
"Affiliate link — CircuitForge earns a small commission if you purchase "
|
||||
"on eBay. No purchase data is shared with us. [Opt out in Settings]"
|
||||
),
|
||||
"amazon": (
|
||||
"Affiliate link — CircuitForge earns a small commission if you purchase "
|
||||
"on Amazon. No purchase data is shared with us. [Opt out in Settings]"
|
||||
),
|
||||
}
|
||||
|
||||
_GENERIC_TOOLTIP = (
|
||||
"Affiliate link — CircuitForge may earn a small commission if you purchase. "
|
||||
"No purchase data is shared with us. [Opt out in Settings]"
|
||||
)
|
||||
|
||||
# First-encounter banner copy (shown once, then preference saved)
|
||||
BANNER_COPY: dict[str, str] = {
|
||||
"title": "A note on purchase links",
|
||||
"body": (
|
||||
"Some links in this product go to retailers using our affiliate code. "
|
||||
"When you click one, the retailer knows you came from CircuitForge. "
|
||||
"We don't see or store what you buy. The retailer may track your "
|
||||
"purchase — that's between you and them.\n\n"
|
||||
"If you'd rather use plain links with no tracking code, you can opt "
|
||||
"out in Settings."
|
||||
),
|
||||
"dismiss_label": "Got it",
|
||||
"opt_out_label": "Opt out now",
|
||||
"learn_more_label": "Learn more",
|
||||
}
|
||||
|
||||
|
||||
def get_disclosure_text(retailer: str) -> str:
|
||||
"""Return the tooltip disclosure string for *retailer*.
|
||||
|
||||
Falls back to a generic string for unregistered retailers so callers
|
||||
never receive an empty string.
|
||||
"""
|
||||
return _TOOLTIP.get(retailer, _GENERIC_TOOLTIP)
|
||||
29
tests/test_affiliates/test_disclosure.py
Normal file
29
tests/test_affiliates/test_disclosure.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
"""Tests for affiliate disclosure text."""
|
||||
import pytest
|
||||
from circuitforge_core.affiliates.disclosure import get_disclosure_text, BANNER_COPY
|
||||
|
||||
|
||||
class TestGetDisclosureText:
|
||||
def test_returns_string_for_known_retailer(self):
|
||||
text = get_disclosure_text("ebay")
|
||||
assert isinstance(text, str)
|
||||
assert len(text) > 0
|
||||
|
||||
def test_ebay_copy_mentions_ebay(self):
|
||||
text = get_disclosure_text("ebay")
|
||||
assert "eBay" in text
|
||||
|
||||
def test_amazon_copy_mentions_amazon(self):
|
||||
text = get_disclosure_text("amazon")
|
||||
assert "Amazon" in text
|
||||
|
||||
def test_unknown_retailer_returns_generic(self):
|
||||
text = get_disclosure_text("not_a_retailer")
|
||||
assert isinstance(text, str)
|
||||
assert len(text) > 0
|
||||
|
||||
def test_banner_copy_has_required_keys(self):
|
||||
assert "title" in BANNER_COPY
|
||||
assert "body" in BANNER_COPY
|
||||
assert "opt_out_label" in BANNER_COPY
|
||||
assert "dismiss_label" in BANNER_COPY
|
||||
Loading…
Reference in a new issue