File size: 7,635 Bytes
af9cde9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fb88636
af9cde9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cd73917
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
af9cde9
 
 
 
 
 
 
 
 
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
"""Tests for new database methods: user profile and scheduled medications."""

import pytest

from reachy_mini_conversation_app.database import MiniMinderDB


@pytest.fixture
def db() -> MiniMinderDB:
    """Create an in-memory database for testing."""
    return MiniMinderDB(":memory:")


# -----------------------------------------------------------------------------
# User Profile Tests
# -----------------------------------------------------------------------------


def test_get_or_create_profile(db: MiniMinderDB) -> None:
    """Profile should be created on first access."""
    profile = db.get_or_create_profile()
    assert profile is not None
    assert profile["id"] == 1
    assert profile["onboarding_completed"] == 0
    assert profile["onboarding_step"] == "name"


def test_get_or_create_profile_idempotent(db: MiniMinderDB) -> None:
    """Getting profile multiple times should return same data."""
    profile1 = db.get_or_create_profile()
    profile2 = db.get_or_create_profile()
    assert profile1["id"] == profile2["id"]
    assert profile1["created_at"] == profile2["created_at"]


def test_update_profile(db: MiniMinderDB) -> None:
    """Profile updates should persist."""
    db.update_profile(
        {
            "display_name": "Alice",
            "onboarding_completed": 1,
            "onboarding_step": "done",
        }
    )
    profile = db.get_or_create_profile()
    assert profile["display_name"] == "Alice"
    assert profile["onboarding_completed"] == 1
    assert profile["onboarding_step"] == "done"


def test_is_onboarding_complete_default(db: MiniMinderDB) -> None:
    """Onboarding should not be complete by default."""
    assert db.is_onboarding_complete() is False


def test_is_onboarding_complete_after_update(db: MiniMinderDB) -> None:
    """Onboarding should be complete after marking it."""
    db.update_profile({"onboarding_completed": 1})
    assert db.is_onboarding_complete() is True


# -----------------------------------------------------------------------------
# Scheduled Medications Tests
# -----------------------------------------------------------------------------


def test_add_scheduled_medication(db: MiniMinderDB) -> None:
    """Add and retrieve a scheduled medication."""
    med_id = db.add_scheduled_medication(
        {
            "medication_name": "Ibuprofen",
            "dose": "400mg",
            "frequency": "twice daily",
            "times_of_day": ["morning", "evening"],
        }
    )
    assert med_id == 1

    meds = db.get_scheduled_medications()
    assert len(meds) == 1
    assert meds[0]["medication_name"] == "Ibuprofen"
    assert meds[0]["dose"] == "400mg"
    assert meds[0]["times_of_day"] == ["morning", "evening"]


def test_add_multiple_medications(db: MiniMinderDB) -> None:
    """Add multiple medications."""
    db.add_scheduled_medication({"medication_name": "Med A"})
    db.add_scheduled_medication({"medication_name": "Med B"})
    db.add_scheduled_medication({"medication_name": "Med C"})

    meds = db.get_scheduled_medications()
    assert len(meds) == 3
    names = [m["medication_name"] for m in meds]
    assert "Med A" in names
    assert "Med B" in names
    assert "Med C" in names


def test_scheduled_medication_with_reminders(db: MiniMinderDB) -> None:
    """Medications can have reminder times."""
    db.add_scheduled_medication(
        {
            "medication_name": "Blood Pressure Med",
            "reminder_enabled": 1,
            "reminder_times": ["07:55", "19:55"],
        }
    )

    meds = db.get_scheduled_medications()
    assert len(meds) == 1
    assert meds[0]["reminder_enabled"] == 1
    assert meds[0]["reminder_times"] == ["07:55", "19:55"]


def test_update_scheduled_medication(db: MiniMinderDB) -> None:
    """Update an existing medication."""
    med_id = db.add_scheduled_medication(
        {
            "medication_name": "Aspirin",
            "dose": "100mg",
        }
    )

    success = db.update_scheduled_medication(
        med_id,
        {
            "dose": "200mg",
            "frequency": "once daily",
        },
    )
    assert success is True

    meds = db.get_scheduled_medications()
    assert meds[0]["dose"] == "200mg"
    assert meds[0]["frequency"] == "once daily"


def test_deactivate_scheduled_medication(db: MiniMinderDB) -> None:
    """Deactivated medications should not appear in active list."""
    med_id = db.add_scheduled_medication({"medication_name": "Old Med"})

    success = db.deactivate_scheduled_medication(med_id)
    assert success is True

    # Should not appear in active list
    active_meds = db.get_scheduled_medications(active_only=True)
    assert len(active_meds) == 0

    # Should appear in full list
    all_meds = db.get_scheduled_medications(active_only=False)
    assert len(all_meds) == 1
    assert all_meds[0]["active"] == 0


def test_update_nonexistent_medication(db: MiniMinderDB) -> None:
    """Updating a nonexistent medication should return False."""
    success = db.update_scheduled_medication(999, {"dose": "100mg"})
    # Note: SQLite UPDATE returns 0 rows affected, so this returns False
    assert success is False


# -----------------------------------------------------------------------------
# Upsert Scheduled Medication Tests
# -----------------------------------------------------------------------------


def test_upsert_scheduled_medication_new(db: MiniMinderDB) -> None:
    """Upsert should create a new row when no match exists."""
    med_id, is_new = db.upsert_scheduled_medication(
        {"medication_name": "Aspirin", "dose": "100mg"}
    )
    assert is_new is True
    assert med_id >= 1

    meds = db.get_scheduled_medications()
    assert len(meds) == 1
    assert meds[0]["medication_name"] == "Aspirin"


def test_upsert_scheduled_medication_existing(db: MiniMinderDB) -> None:
    """Upsert should update existing row and not create a duplicate."""
    # First call: creates the row
    med_id_1, is_new_1 = db.upsert_scheduled_medication(
        {"medication_name": "Amitriptyline"}
    )
    assert is_new_1 is True

    # Second call: same name, adds dose — should update
    med_id_2, is_new_2 = db.upsert_scheduled_medication(
        {"medication_name": "Amitriptyline", "dose": "10mg"}
    )
    assert is_new_2 is False
    assert med_id_2 == med_id_1

    # Third call: same name, adds frequency — should update again
    med_id_3, is_new_3 = db.upsert_scheduled_medication(
        {"medication_name": "Amitriptyline", "dose": "10mg", "frequency": "once daily"}
    )
    assert is_new_3 is False
    assert med_id_3 == med_id_1

    # Only one row should exist with all the merged data
    meds = db.get_scheduled_medications()
    assert len(meds) == 1
    assert meds[0]["dose"] == "10mg"
    assert meds[0]["frequency"] == "once daily"


def test_upsert_case_insensitive(db: MiniMinderDB) -> None:
    """Upsert should match medication names case-insensitively."""
    db.upsert_scheduled_medication({"medication_name": "Aspirin"})
    med_id, is_new = db.upsert_scheduled_medication(
        {"medication_name": "aspirin", "dose": "200mg"}
    )
    assert is_new is False

    meds = db.get_scheduled_medications()
    assert len(meds) == 1


def test_schema_includes_new_tables(db: MiniMinderDB) -> None:
    """The new tables should exist."""
    conn = db._get_conn()
    tables = conn.execute(
        "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"
    ).fetchall()
    table_names = [t["name"] for t in tables]
    assert "user_profile" in table_names
    assert "scheduled_medications" in table_names