File size: 3,317 Bytes
b324c71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
"""
Unit tests for the public Business Footing Framework route (routes/bff_form.py)
and the shared public-form checks (utils/public_forms.py). Firestore is mocked.
"""
from unittest.mock import MagicMock, patch

import pytest
from fastapi import HTTPException

from routes import bff_form
from routes.bff_form import SubmissionIn, submit
from utils.public_forms import clean_phone


@pytest.fixture(autouse=True)
def _reset_limits():
    bff_form.limiter.reset()


def _body(**over):
    base = dict(
        name=" Ada Obi ", email=" Ada@Example.com ", phone="0803 123 4567", consent=True,
        what=dict(businessStage="early", businessName="Ada Books", sectorId="retail_trade",
                  subsectorId="bookshops", nicheId="other", customNiche="Children's books",
                  products=["Story books", "  ", "School texts"]),
        why=dict(whyRaw=" I love reading ", valueProposition="Good books at fair prices"),
        how=dict(locationType="physical", state="Lagos", city="Ikeja",
                 hours={"monday": {"open": "09:00", "close": "18:00", "off": False}},
                 demographics={"ageRanges": ["21–25"]}, channels={"social_media": ["Instagram"]},
                 revenueStreams="Book sales"),
        startedAt=1, sessionId="s-1",
    )
    base.update(over)
    return SubmissionIn(**base)


def _db():
    db = MagicMock()
    db.collection.return_value.add.return_value = (None, MagicMock(id="doc1"))
    return db


def test_stores_answers_contact_and_labels():
    db = _db()
    with patch.object(bff_form.firestore, "client", return_value=db):
        out = submit(_body())
    assert out == {"success": True, "id": "doc1"}
    db.collection.assert_called_with("bff_submissions")
    doc = db.collection.return_value.add.call_args[0][0]
    assert (doc["name"], doc["email"], doc["phone"]) == ("Ada Obi", "ada@example.com", "0803 123 4567")
    assert doc["what"]["products"] == ["Story books", "School texts"]
    assert doc["why"]["whyRaw"] == "I love reading"
    assert doc["labels"]["niche"] == "Children's books" and doc["labels"]["stage"].startswith("Running for 1")
    assert doc["how"]["hours"]["monday"]["open"] == "09:00"


@pytest.mark.parametrize("over", [
    {"consent": False}, {"email": "nope"}, {"phone": "12345"},
    {"what": dict(businessStage="unknown", businessName="X", sectorId="a", subsectorId="b", nicheId="c")},
    {"what": dict(businessStage="idea", businessName="X", sectorId="a", subsectorId="b", nicheId="other")},
])
def test_rejects_bad_submissions(over):
    with pytest.raises(HTTPException) as e:
        submit(_body(**over))
    assert e.value.status_code == 400


def test_rate_limits_per_browser():
    with patch.object(bff_form.firestore, "client", return_value=_db()):
        for _ in range(5):
            submit(_body())
        with pytest.raises(HTTPException) as e:
            submit(_body())
    assert e.value.status_code == 429


@pytest.mark.parametrize("raw,ok", [
    ("+234 803 123 4567", True), ("(0803) 123-4567", True), ("08031234567", True),
    ("123", False), ("0803 abc 4567", False), ("+1234567890123456", False),
])
def test_phone_check(raw, ok):
    if ok:
        assert clean_phone(raw) == " ".join(raw.split())
    else:
        with pytest.raises(HTTPException):
            clean_phone(raw)