forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_notifications_integration.py
More file actions
239 lines (172 loc) · 8.47 KB
/
Copy pathtest_notifications_integration.py
File metadata and controls
239 lines (172 loc) · 8.47 KB
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
232
233
234
235
236
237
238
239
"""
Simplified integration tests for notification system.
Tests real Firebase notifications.
Setup:
1. pip install pytest pytest-asyncio
2. Set TEST_USER_ID environment variable (a real Firebase user)
3. Run: pytest backend/tests/integration/test_notifications_integration.py -v
"""
import pytest
import os
from datetime import datetime, timedelta
from backend.utils.notifications import (
send_notification,
send_bulk_notification,
send_action_item_created_notification,
send_action_item_completed_notification,
send_training_data_submitted_notification,
)
import database.notifications as notification_db
@pytest.fixture
def test_user_id():
"""Get test user ID from environment"""
user_id = os.getenv('TEST_USER_ID')
if not user_id:
pytest.skip("TEST_USER_ID environment variable not set")
return user_id
@pytest.fixture
def test_tokens():
"""Get test tokens from environment (comma-separated)"""
tokens = os.getenv('TEST_FCM_TOKENS', '').split(',')
tokens = [t.strip() for t in tokens if t.strip()]
if not tokens:
pytest.skip("TEST_FCM_TOKENS environment variable not set")
return tokens
class TestBasicNotifications:
"""Test basic notification functionality"""
def test_send_basic_notification(self, test_user_id):
"""Test sending a basic notification"""
print(f"\n📱 Sending notification to user: {test_user_id}")
send_notification(
user_id=test_user_id,
title="Integration Test",
body="This is a test notification from integration tests",
data={"test": "true", "timestamp": str(datetime.now())},
)
print("✅ Notification sent successfully")
def test_send_notification_no_data(self, test_user_id):
"""Test sending notification without data payload"""
send_notification(user_id=test_user_id, title="Simple Test", body="Notification without data")
print("✅ Simple notification sent")
def test_send_notification_with_emoji(self, test_user_id):
"""Test notification with emoji"""
send_notification(user_id=test_user_id, title="Emoji Test 🎉", body="Testing emojis: ✅ 🚀 💡")
print("✅ Emoji notification sent")
class TestBulkNotifications:
"""Test bulk notification sending"""
@pytest.mark.asyncio
async def test_bulk_send_small(self, test_tokens):
"""Test bulk send to a few tokens"""
print(f"\n📢 Sending bulk notification to {len(test_tokens)} tokens")
await send_bulk_notification(
user_tokens=test_tokens, title="Bulk Test", body="This is a bulk notification test"
)
print("✅ Bulk notifications sent")
@pytest.mark.asyncio
async def test_bulk_send_large(self, test_tokens):
"""Test bulk send with many tokens (simulated)"""
# Duplicate tokens to test batching (500+ tokens)
large_token_list = test_tokens * 200 # Creates 200x the test tokens
print(f"\n📢 Sending bulk notification to {len(large_token_list)} tokens")
await send_bulk_notification(
user_tokens=large_token_list, title="Large Bulk Test", body="Testing batch processing"
)
print("✅ Large bulk notifications sent")
class TestActionItemNotifications:
"""Test action item notifications"""
def test_action_created(self, test_user_id):
"""Test action item created notification"""
send_action_item_created_notification(user_id=test_user_id, action_item_description="Buy groceries for dinner")
print("✅ Action created notification sent")
def test_action_completed(self, test_user_id):
"""Test action item completed notification"""
send_action_item_completed_notification(user_id=test_user_id, action_item_description="Finish quarterly report")
print("✅ Action completed notification sent")
def test_action_long_description(self, test_user_id):
"""Test action with very long description (should truncate)"""
long_desc = "A" * 100 # 100 characters
send_action_item_created_notification(user_id=test_user_id, action_item_description=long_desc)
print("✅ Long description notification sent (truncated)")
class TestOtherNotifications:
"""Test other notification types"""
def test_training_data_notification(self, test_user_id):
"""Test training data submitted notification"""
send_training_data_submitted_notification(user_id=test_user_id)
print("✅ Training data notification sent")
class TestErrorHandling:
"""Test error handling"""
def test_nonexistent_user(self):
"""Test sending to non-existent user (should handle gracefully)"""
send_notification(user_id="nonexistent-user-12345", title="Test", body="Should not crash")
print("✅ Handled non-existent user gracefully")
@pytest.mark.asyncio
async def test_empty_token_list(self):
"""Test bulk send with empty list (should handle gracefully)"""
await send_bulk_notification(user_tokens=[], title="Empty Test", body="Testing empty list")
print("✅ Handled empty token list gracefully")
class TestTokenManagement:
"""Test token management functionality"""
def test_remove_bulk_tokens(self, test_user_id):
"""Test bulk token removal"""
print(f"\n🗑️ Testing bulk token removal")
# Create test tokens
test_tokens = [
f"test-token-bulk-1-{datetime.now().timestamp()}",
f"test-token-bulk-2-{datetime.now().timestamp()}",
f"test-token-bulk-3-{datetime.now().timestamp()}",
]
# Save test tokens
for i, token in enumerate(test_tokens):
notification_db.save_token(
test_user_id, {'fcm_token': token, 'device_key': f'test-device-{i}', 'time_zone': 'America/New_York'}
)
print(f"Created {len(test_tokens)} test tokens")
# Verify tokens were saved
saved_tokens = notification_db.get_all_tokens(test_user_id)
for token in test_tokens:
assert token in saved_tokens, f"Token {token} not saved"
print("✅ Tokens saved successfully")
# Remove tokens in bulk
notification_db.remove_bulk_tokens(test_tokens)
print("Removed tokens in bulk")
# Verify tokens were removed
remaining_tokens = notification_db.get_all_tokens(test_user_id)
for token in test_tokens:
assert token not in remaining_tokens, f"Token {token} not removed"
print("✅ All test tokens removed successfully")
def test_remove_bulk_tokens_large_batch(self, test_user_id):
"""Test bulk removal with more than 30 tokens (tests chunking)"""
print(f"\n🗑️ Testing bulk token removal with large batch (40 tokens)")
# Create 40 test tokens (more than the 30 item IN query limit)
test_tokens = [f"test-token-large-{i}-{datetime.now().timestamp()}" for i in range(40)]
# Save test tokens
for i, token in enumerate(test_tokens):
notification_db.save_token(
test_user_id,
{'fcm_token': token, 'device_key': f'test-device-large-{i}', 'time_zone': 'America/New_York'},
)
print(f"Created {len(test_tokens)} test tokens")
# Remove tokens in bulk (tests chunking logic)
notification_db.remove_bulk_tokens(test_tokens)
print("Removed tokens in bulk with chunking")
# Verify all tokens were removed
remaining_tokens = notification_db.get_all_tokens(test_user_id)
removed_count = sum(1 for token in test_tokens if token not in remaining_tokens)
print(f"✅ Removed {removed_count}/{len(test_tokens)} tokens")
assert removed_count == len(test_tokens), "Not all tokens were removed"
def test_remove_bulk_tokens_empty_list(self):
"""Test bulk removal with empty list (should handle gracefully)"""
print(f"\n🗑️ Testing bulk token removal with empty list")
# Should not crash
notification_db.remove_bulk_tokens([])
print("✅ Handled empty list gracefully")
# For manual testing
if __name__ == "__main__":
print("\n" + "=" * 60)
print("NOTIFICATION INTEGRATION TESTS")
print("=" * 60)
print("\nSet these environment variables:")
print(" export TEST_USER_ID='your-firebase-user-id'")
print(" export TEST_FCM_TOKENS='token1,token2,token3'\n")
print("Then run: pytest backend/tests/integration/test_notifications_integration.py -v -s")
print("=" * 60 + "\n")