roksta 0.3.2__cp311-cp311-macosx_10_9_universal2.whl → 0.3.8__cp311-cp311-macosx_10_9_universal2.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- roksta/__init__.cpython-311-darwin.so +0 -0
- roksta/ai/__init__.cpython-311-darwin.so +0 -0
- roksta/ai/call_ai.cpython-311-darwin.so +0 -0
- roksta/ai/gemini.cpython-311-darwin.so +0 -0
- roksta/ai/generic.cpython-311-darwin.so +0 -0
- roksta/ai/llm.cpython-311-darwin.so +0 -0
- roksta/ai/openai.cpython-311-darwin.so +0 -0
- roksta/ai/tools/__init__.cpython-311-darwin.so +0 -0
- roksta/ai/tools/delete_file.cpython-311-darwin.so +0 -0
- roksta/ai/tools/edit_file.cpython-311-darwin.so +0 -0
- roksta/ai/tools/final_response.cpython-311-darwin.so +0 -0
- roksta/ai/tools/get_file_summaries.cpython-311-darwin.so +0 -0
- roksta/ai/tools/read_file.cpython-311-darwin.so +0 -0
- roksta/ai/tools/regex_replace.cpython-311-darwin.so +0 -0
- roksta/ai/tools/shell_any.cpython-311-darwin.so +0 -0
- roksta/ai/tools/shell_limited.cpython-311-darwin.so +0 -0
- roksta/ai/tools/tool_defs.cpython-311-darwin.so +0 -0
- roksta/ai/tools/tool_utils.cpython-311-darwin.so +0 -0
- roksta/ai/tools/web_fetch.cpython-311-darwin.so +0 -0
- roksta/ai/tools/write_file.cpython-311-darwin.so +0 -0
- roksta/analytics.cpython-311-darwin.so +0 -0
- roksta/balance.cpython-311-darwin.so +0 -0
- roksta/build_project.cpython-311-darwin.so +0 -0
- roksta/chat_workflow.cpython-311-darwin.so +0 -0
- roksta/check_for_updates.cpython-311-darwin.so +0 -0
- roksta/check_subtask_sequence.cpython-311-darwin.so +0 -0
- roksta/checkpoints.cpython-311-darwin.so +0 -0
- roksta/clarify_goal.cpython-311-darwin.so +0 -0
- roksta/codebase_listing.cpython-311-darwin.so +0 -0
- roksta/command_handlers/__init__.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_activate_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_add_funds_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_auto_charge_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_auto_commit_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_building_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_chat_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_dev_rate_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_feedback_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_goal_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_help_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_init_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_linting_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_login_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_logout_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_payment_details_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_quit_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_redeem_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_request_activation_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_testing_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_usage_command.cpython-311-darwin.so +0 -0
- roksta/create_default_config.cpython-311-darwin.so +0 -0
- roksta/create_default_ignore_file.cpython-311-darwin.so +0 -0
- roksta/default_config.cpython-311-darwin.so +0 -0
- roksta/default_ignores.cpython-311-darwin.so +0 -0
- roksta/discover_test_command.cpython-311-darwin.so +0 -0
- roksta/enums.cpython-311-darwin.so +0 -0
- roksta/env.cpython-311-darwin.so +0 -0
- roksta/extended_text_area.cpython-311-darwin.so +0 -0
- roksta/firebase.cpython-311-darwin.so +0 -0
- roksta/firebase_auth_web.cpython-311-darwin.so +0 -0
- roksta/firebase_config.cpython-311-darwin.so +0 -0
- roksta/fix_tests.cpython-311-darwin.so +0 -0
- roksta/gen_codebase_summaries.cpython-311-darwin.so +0 -0
- roksta/gen_one_line_goal.cpython-311-darwin.so +0 -0
- roksta/gen_subtasks.cpython-311-darwin.so +0 -0
- roksta/get_codebase_structure.cpython-311-darwin.so +0 -0
- roksta/get_failing_tests.cpython-311-darwin.so +0 -0
- roksta/goal_workflow.cpython-311-darwin.so +0 -0
- roksta/init_codebase.cpython-311-darwin.so +0 -0
- roksta/lint_code.cpython-311-darwin.so +0 -0
- roksta/logger.cpython-311-darwin.so +0 -0
- roksta/main.cpython-311-darwin.so +0 -0
- roksta/make_issue.cpython-311-darwin.so +0 -0
- roksta/new_features.cpython-311-darwin.so +0 -0
- roksta/parse_directive_cli_tokens.cpython-311-darwin.so +0 -0
- roksta/parse_readme.cpython-311-darwin.so +0 -0
- roksta/propose_solution.cpython-311-darwin.so +0 -0
- roksta/response_formats.cpython-311-darwin.so +0 -0
- roksta/rewrite_goal.cpython-311-darwin.so +0 -0
- roksta/roksta.cpython-311-darwin.so +0 -0
- roksta/run_cli_goal.cpython-311-darwin.so +0 -0
- roksta/save_chat_transcript.cpython-311-darwin.so +0 -0
- roksta/select_files.cpython-311-darwin.so +0 -0
- roksta/tips.cpython-311-darwin.so +0 -0
- roksta/utils.cpython-311-darwin.so +0 -0
- roksta/write_code.cpython-311-darwin.so +0 -0
- roksta-0.3.8.dist-info/METADATA +471 -0
- roksta-0.3.8.dist-info/RECORD +91 -0
- {roksta-0.3.2.dist-info → roksta-0.3.8.dist-info}/top_level.txt +0 -1
- roksta-0.3.2.dist-info/METADATA +0 -40
- roksta-0.3.2.dist-info/RECORD +0 -121
- tests/__init__.py +0 -2
- tests/conftest.py +0 -211
- tests/functions/__init__.py +0 -2
- tests/functions/api_v1_00/__init__.py +0 -2
- tests/functions/api_v1_00/test__analytics.py +0 -416
- tests/functions/api_v1_00/test__gemini_proxy.py +0 -352
- tests/functions/api_v1_00/test__generic_proxy.py +0 -428
- tests/functions/api_v1_00/test__get_payment_details.py +0 -356
- tests/functions/api_v1_00/test__openai_proxy.py +0 -449
- tests/functions/api_v1_00/test__redeem_credit_code.py +0 -167
- tests/functions/api_v1_00/test__sync_emails.py +0 -325
- tests/functions/api_v1_00/test__take_payment.py +0 -491
- tests/functions/api_v1_00/test__use_activation_code.py +0 -438
- tests/functions/api_v1_01/__init__.py +0 -2
- tests/functions/api_v1_01/test__analytics.py +0 -416
- tests/functions/api_v1_01/test__gemini_proxy.py +0 -352
- tests/functions/api_v1_01/test__generic_proxy.py +0 -428
- tests/functions/api_v1_01/test__get_payment_details.py +0 -356
- tests/functions/api_v1_01/test__openai_proxy.py +0 -449
- tests/functions/api_v1_01/test__redeem_credit_code.py +0 -167
- tests/functions/api_v1_01/test__sync_emails.py +0 -325
- tests/functions/api_v1_01/test__take_payment.py +0 -491
- tests/functions/api_v1_01/test__use_activation_code.py +0 -438
- tests/functions/api_v1_02/__init__.py +0 -2
- tests/functions/api_v1_02/test__analytics.py +0 -416
- tests/functions/api_v1_02/test__gemini_proxy.py +0 -352
- tests/functions/api_v1_02/test__generic_proxy.py +0 -428
- tests/functions/api_v1_02/test__get_payment_details.py +0 -356
- tests/functions/api_v1_02/test__openai_proxy.py +0 -449
- tests/functions/api_v1_02/test__redeem_credit_code.py +0 -167
- tests/functions/api_v1_02/test__sync_emails.py +0 -325
- tests/functions/api_v1_02/test__take_payment.py +0 -491
- tests/functions/api_v1_02/test__use_activation_code.py +0 -438
- tests/functions/api_v1_02/test_proxy_keyword_replacement.py +0 -557
- tests/functions/api_v1_02/test_replace_keywords.py +0 -74
- tests/functions/test_auth.py +0 -24
- tests/functions/test_main.py +0 -73
- tests/functions/test_utils.py +0 -484
- {roksta-0.3.2.dist-info → roksta-0.3.8.dist-info}/WHEEL +0 -0
- {roksta-0.3.2.dist-info → roksta-0.3.8.dist-info}/entry_points.txt +0 -0
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import sys
|
|
3
|
-
import json
|
|
4
|
-
import types
|
|
5
|
-
import importlib
|
|
6
|
-
from unittest.mock import patch
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
# Ensure the functions/ directory is importable as a top-level module location
|
|
10
|
-
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
|
11
|
-
FUNCTIONS_DIR = os.path.join(PROJECT_ROOT, 'functions')
|
|
12
|
-
if FUNCTIONS_DIR not in sys.path:
|
|
13
|
-
sys.path.insert(0, FUNCTIONS_DIR)
|
|
14
|
-
|
|
15
|
-
# -----------------------------
|
|
16
|
-
# Provide lightweight fake modules to satisfy imports inside _sync_emails
|
|
17
|
-
# These are minimal and will be patched in individual tests as needed.
|
|
18
|
-
# -----------------------------
|
|
19
|
-
# Save original sys.modules entries so we can restore them after importing the module under test
|
|
20
|
-
_orig_sys_modules = {}
|
|
21
|
-
_names_to_fake = ['firebase_functions', 'utils', 'auth', 'firebase_admin']
|
|
22
|
-
for name in _names_to_fake:
|
|
23
|
-
_orig_sys_modules[name] = sys.modules.get(name)
|
|
24
|
-
|
|
25
|
-
# Fake firebase_functions.https_fn.Response to capture returned data
|
|
26
|
-
firebase_functions = types.ModuleType('firebase_functions')
|
|
27
|
-
|
|
28
|
-
class FakeResponse:
|
|
29
|
-
def __init__(self, response=None, mimetype=None, status=200, **kwargs):
|
|
30
|
-
# Mirror the small subset of the interface tests expect
|
|
31
|
-
self.status_code = status
|
|
32
|
-
if isinstance(response, (dict, list)):
|
|
33
|
-
self._body_text = json.dumps(response)
|
|
34
|
-
else:
|
|
35
|
-
self._body_text = '' if response is None else response
|
|
36
|
-
self.headers = kwargs.get('headers', {})
|
|
37
|
-
|
|
38
|
-
def get_data(self, as_text=False):
|
|
39
|
-
if as_text:
|
|
40
|
-
return self._body_text
|
|
41
|
-
return self._body_text.encode('utf-8')
|
|
42
|
-
|
|
43
|
-
firebase_functions.https_fn = types.SimpleNamespace(Request=object, Response=FakeResponse)
|
|
44
|
-
sys.modules['firebase_functions'] = firebase_functions
|
|
45
|
-
|
|
46
|
-
# Fake utils module (verify_firebase_token, create_json_response)
|
|
47
|
-
utils_mod = types.ModuleType('utils')
|
|
48
|
-
|
|
49
|
-
def _dummy_verify_firebase_token(req: object) -> dict:
|
|
50
|
-
# Default behavior: return a decoded token with a uid
|
|
51
|
-
return {'uid': 'test_user'}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def _create_json_response(success: bool, payload=None, status_code: int = 200):
|
|
55
|
-
# Normalize payload to include a message field
|
|
56
|
-
if isinstance(payload, dict):
|
|
57
|
-
message = payload.get('message', '')
|
|
58
|
-
data = {'success': success, 'message': message}
|
|
59
|
-
data['payload'] = payload
|
|
60
|
-
else:
|
|
61
|
-
message = payload if payload is not None else ''
|
|
62
|
-
data = {'success': success, 'message': message}
|
|
63
|
-
return firebase_functions.https_fn.Response(response=data, status=status_code)
|
|
64
|
-
|
|
65
|
-
utils_mod.verify_firebase_token = _dummy_verify_firebase_token
|
|
66
|
-
utils_mod.create_json_response = _create_json_response
|
|
67
|
-
sys.modules['utils'] = utils_mod
|
|
68
|
-
|
|
69
|
-
# Fake auth module (validate_auth_key will be patched per-test as needed)
|
|
70
|
-
auth_mod = types.ModuleType('auth')
|
|
71
|
-
|
|
72
|
-
def _simple_validate_auth_key(val: str) -> bool:
|
|
73
|
-
return True
|
|
74
|
-
|
|
75
|
-
auth_mod.validate_auth_key = _simple_validate_auth_key
|
|
76
|
-
sys.modules['auth'] = auth_mod
|
|
77
|
-
|
|
78
|
-
# Fake firebase_admin to prevent importing the real package during tests
|
|
79
|
-
firebase_admin = types.ModuleType('firebase_admin')
|
|
80
|
-
# Minimal fake auth and firestore objects; tests will patch their behavior as needed
|
|
81
|
-
fake_auth = types.SimpleNamespace(get_user=lambda uid: types.SimpleNamespace(email='test@example.com'))
|
|
82
|
-
# Provide a placeholder firestore client function; will be overridden by tests
|
|
83
|
-
fake_firestore = types.SimpleNamespace(client=lambda: None)
|
|
84
|
-
firebase_admin.auth = fake_auth
|
|
85
|
-
firebase_admin.firestore = fake_firestore
|
|
86
|
-
sys.modules['firebase_admin'] = firebase_admin
|
|
87
|
-
|
|
88
|
-
# -----------------------------
|
|
89
|
-
# Import the module under test after preparing the fake imports
|
|
90
|
-
# -----------------------------
|
|
91
|
-
repo_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
|
92
|
-
functions_root = os.path.join(repo_root, 'functions')
|
|
93
|
-
module_path = os.path.join(functions_root, 'api_v1_00', '_sync_emails.py')
|
|
94
|
-
spec = importlib.util.spec_from_file_location('api_v1_00._sync_emails', module_path)
|
|
95
|
-
_sync = importlib.util.module_from_spec(spec)
|
|
96
|
-
spec.loader.exec_module(_sync)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
# Restore original sys.modules mappings to avoid side-effects for other tests
|
|
100
|
-
for name, orig in _orig_sys_modules.items():
|
|
101
|
-
if orig is None:
|
|
102
|
-
try:
|
|
103
|
-
del sys.modules[name]
|
|
104
|
-
except KeyError:
|
|
105
|
-
pass
|
|
106
|
-
else:
|
|
107
|
-
sys.modules[name] = orig
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# -----------------------------
|
|
111
|
-
# Fake Firestore implementation used by tests
|
|
112
|
-
# -----------------------------
|
|
113
|
-
class FakeDocumentSnapshot:
|
|
114
|
-
def __init__(self, exists: bool, data: dict | None):
|
|
115
|
-
self.exists = exists
|
|
116
|
-
self._data = data
|
|
117
|
-
|
|
118
|
-
def to_dict(self):
|
|
119
|
-
return self._data
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
class FakeDocumentReference:
|
|
123
|
-
def __init__(self, client, collection: str, doc_id: str):
|
|
124
|
-
self.client = client
|
|
125
|
-
self.collection = collection
|
|
126
|
-
self.doc_id = doc_id
|
|
127
|
-
|
|
128
|
-
def get(self):
|
|
129
|
-
coll = self.client._data.get(self.collection, {})
|
|
130
|
-
if self.doc_id in coll:
|
|
131
|
-
return FakeDocumentSnapshot(True, coll[self.doc_id])
|
|
132
|
-
return FakeDocumentSnapshot(False, None)
|
|
133
|
-
|
|
134
|
-
def update(self, update_dict: dict):
|
|
135
|
-
# Record the update
|
|
136
|
-
self.client._updates.append((self.collection, self.doc_id, update_dict))
|
|
137
|
-
coll = self.client._data.setdefault(self.collection, {})
|
|
138
|
-
# Apply update to stored doc if it exists and is a dict
|
|
139
|
-
if isinstance(coll.get(self.doc_id), dict):
|
|
140
|
-
coll[self.doc_id].update(update_dict)
|
|
141
|
-
else:
|
|
142
|
-
coll[self.doc_id] = update_dict
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
class FakeCollectionReference:
|
|
146
|
-
def __init__(self, client, name: str):
|
|
147
|
-
self.client = client
|
|
148
|
-
self.name = name
|
|
149
|
-
|
|
150
|
-
def document(self, doc_id: str):
|
|
151
|
-
return FakeDocumentReference(self.client, self.name, doc_id)
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
class FakeFirestoreClient:
|
|
155
|
-
def __init__(self, initial_data: dict | None = None):
|
|
156
|
-
# initial_data should be a dict mapping collection_name -> {doc_id: doc_data}
|
|
157
|
-
self._data = initial_data.copy() if initial_data else {}
|
|
158
|
-
self._updates = []
|
|
159
|
-
|
|
160
|
-
def collection(self, name: str):
|
|
161
|
-
return FakeCollectionReference(self, name)
|
|
162
|
-
|
|
163
|
-
def get_updates(self):
|
|
164
|
-
return self._updates
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
# Simple helper request stub used in the tests
|
|
168
|
-
class DummyRequest:
|
|
169
|
-
def __init__(self, headers=None, method='POST', json_data=None, raise_on_get_json=False):
|
|
170
|
-
self.headers = headers or {}
|
|
171
|
-
self.method = method
|
|
172
|
-
self._json_data = json_data
|
|
173
|
-
self._raise = raise_on_get_json
|
|
174
|
-
|
|
175
|
-
def get_json(self, silent=True):
|
|
176
|
-
if self._raise:
|
|
177
|
-
raise Exception('Malformed JSON')
|
|
178
|
-
return self._json_data
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
def _parse_response(resp):
|
|
182
|
-
data = resp.get_data(as_text=True)
|
|
183
|
-
return json.loads(data)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
# -----------------------------
|
|
187
|
-
# Tests
|
|
188
|
-
# -----------------------------
|
|
189
|
-
|
|
190
|
-
def test_missing_auth_header_returns_401():
|
|
191
|
-
req = DummyRequest(headers={}, method='POST')
|
|
192
|
-
# Ensure verify_firebase_token is not called when header is missing
|
|
193
|
-
with patch.object(_sync, 'verify_firebase_token', side_effect=Exception('Should not be called')):
|
|
194
|
-
resp = _sync._sync_emails(req)
|
|
195
|
-
|
|
196
|
-
assert resp.status_code == 401
|
|
197
|
-
payload = _parse_response(resp)
|
|
198
|
-
assert payload['success'] is False
|
|
199
|
-
assert 'Missing app authentication key' in payload['message']
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
def test_invalid_auth_key_returns_403():
|
|
203
|
-
headers = {_sync.AUTH_HEADER_NAME: 'bad-token'}
|
|
204
|
-
req = DummyRequest(headers=headers, method='POST')
|
|
205
|
-
with patch.object(_sync, 'validate_auth_key', return_value=False):
|
|
206
|
-
resp = _sync._sync_emails(req)
|
|
207
|
-
assert resp.status_code == 403
|
|
208
|
-
payload = _parse_response(resp)
|
|
209
|
-
assert payload['success'] is False
|
|
210
|
-
assert 'Invalid app authentication key' in payload['message']
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
def test_verify_token_raises_returns_403():
|
|
214
|
-
headers = {_sync.AUTH_HEADER_NAME: 'ok'}
|
|
215
|
-
req = DummyRequest(headers=headers, method='POST')
|
|
216
|
-
with patch.object(_sync, 'validate_auth_key', return_value=True), patch.object(_sync, 'verify_firebase_token', side_effect=Exception('boom')):
|
|
217
|
-
resp = _sync._sync_emails(req)
|
|
218
|
-
|
|
219
|
-
assert resp.status_code == 403
|
|
220
|
-
payload = _parse_response(resp)
|
|
221
|
-
assert payload['success'] is False
|
|
222
|
-
assert 'Authentication failed' in payload['message']
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
def test_missing_uid_in_token_returns_403():
|
|
226
|
-
headers = {_sync.AUTH_HEADER_NAME: 'ok'}
|
|
227
|
-
req = DummyRequest(headers=headers, method='POST')
|
|
228
|
-
with patch.object(_sync, 'validate_auth_key', return_value=True), patch.object(_sync, 'verify_firebase_token', return_value={}):
|
|
229
|
-
resp = _sync._sync_emails(req)
|
|
230
|
-
|
|
231
|
-
assert resp.status_code == 403
|
|
232
|
-
payload = _parse_response(resp)
|
|
233
|
-
assert payload['success'] is False
|
|
234
|
-
assert 'UID missing' in payload['message']
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
def test_get_user_failure_returns_500():
|
|
238
|
-
headers = {_sync.AUTH_HEADER_NAME: 'ok'}
|
|
239
|
-
req = DummyRequest(headers=headers, method='POST')
|
|
240
|
-
with patch.object(_sync, 'validate_auth_key', return_value=True), patch.object(_sync, 'verify_firebase_token', return_value={'uid': 'u'}), patch.object(_sync.auth, 'get_user', side_effect=Exception('nope')):
|
|
241
|
-
resp = _sync._sync_emails(req)
|
|
242
|
-
|
|
243
|
-
assert resp.status_code == 500
|
|
244
|
-
payload = _parse_response(resp)
|
|
245
|
-
assert payload['success'] is False
|
|
246
|
-
assert 'Failed to retrieve user data from Firebase Authentication' in payload['message']
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
def test_no_updates_when_emails_match_returns_200():
|
|
250
|
-
headers = {_sync.AUTH_HEADER_NAME: 'ok'}
|
|
251
|
-
req = DummyRequest(headers=headers, method='POST')
|
|
252
|
-
|
|
253
|
-
fake_data = {
|
|
254
|
-
'users': {'u': {'email': 'auth@example.com'}},
|
|
255
|
-
'billing': {'u': {'email': 'auth@example.com'}}
|
|
256
|
-
}
|
|
257
|
-
fake_client = FakeFirestoreClient(initial_data=fake_data)
|
|
258
|
-
|
|
259
|
-
with patch.object(_sync, 'validate_auth_key', return_value=True), \
|
|
260
|
-
patch.object(_sync, 'verify_firebase_token', return_value={'uid': 'u'}), \
|
|
261
|
-
patch.object(_sync.auth, 'get_user', return_value=types.SimpleNamespace(email='auth@example.com')), \
|
|
262
|
-
patch.object(_sync.firestore, 'client', return_value=fake_client):
|
|
263
|
-
resp = _sync._sync_emails(req)
|
|
264
|
-
|
|
265
|
-
assert resp.status_code == 200
|
|
266
|
-
payload = _parse_response(resp)
|
|
267
|
-
assert payload['success'] is True
|
|
268
|
-
assert 'No email updates were necessary' in payload['message']
|
|
269
|
-
assert fake_client.get_updates() == []
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
def test_updates_when_mismatch_calls_update_returns_200():
|
|
273
|
-
headers = {_sync.AUTH_HEADER_NAME: 'ok'}
|
|
274
|
-
req = DummyRequest(headers=headers, method='POST')
|
|
275
|
-
|
|
276
|
-
fake_data = {
|
|
277
|
-
'users': {'u': {'email': 'old_user@example.com'}},
|
|
278
|
-
'billing': {'u': {'email': 'old_billing@example.com'}}
|
|
279
|
-
}
|
|
280
|
-
fake_client = FakeFirestoreClient(initial_data=fake_data)
|
|
281
|
-
|
|
282
|
-
with patch.object(_sync, 'validate_auth_key', return_value=True), \
|
|
283
|
-
patch.object(_sync, 'verify_firebase_token', return_value={'uid': 'u'}), \
|
|
284
|
-
patch.object(_sync.auth, 'get_user', return_value=types.SimpleNamespace(email='auth@example.com')), \
|
|
285
|
-
patch.object(_sync.firestore, 'client', return_value=fake_client):
|
|
286
|
-
resp = _sync._sync_emails(req)
|
|
287
|
-
|
|
288
|
-
assert resp.status_code == 200
|
|
289
|
-
payload = _parse_response(resp)
|
|
290
|
-
assert payload['success'] is True
|
|
291
|
-
assert 'User profile email updated.' in payload['message']
|
|
292
|
-
assert 'Billing email updated.' in payload['message']
|
|
293
|
-
|
|
294
|
-
updates = fake_client.get_updates()
|
|
295
|
-
# Ensure we have two updates and that both updated emails match the auth email
|
|
296
|
-
assert any(u for u in updates if u[0] == 'users' and u[1] == 'u' and u[2] == {'email': 'auth@example.com'})
|
|
297
|
-
assert any(u for u in updates if u[0] == 'billing' and u[1] == 'u' and u[2] == {'email': 'auth@example.com'})
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
def test_billing_exists_without_email_field_only_user_updated_returns_200():
|
|
301
|
-
headers = {_sync.AUTH_HEADER_NAME: 'ok'}
|
|
302
|
-
req = DummyRequest(headers=headers, method='POST')
|
|
303
|
-
|
|
304
|
-
fake_data = {
|
|
305
|
-
'users': {'u': {'email': 'old_user@example.com'}},
|
|
306
|
-
'billing': {'u': {'some_other_key': 'value'}}
|
|
307
|
-
}
|
|
308
|
-
fake_client = FakeFirestoreClient(initial_data=fake_data)
|
|
309
|
-
|
|
310
|
-
with patch.object(_sync, 'validate_auth_key', return_value=True), \
|
|
311
|
-
patch.object(_sync, 'verify_firebase_token', return_value={'uid': 'u'}), \
|
|
312
|
-
patch.object(_sync.auth, 'get_user', return_value=types.SimpleNamespace(email='auth@example.com')), \
|
|
313
|
-
patch.object(_sync.firestore, 'client', return_value=fake_client):
|
|
314
|
-
resp = _sync._sync_emails(req)
|
|
315
|
-
|
|
316
|
-
assert resp.status_code == 200
|
|
317
|
-
payload = _parse_response(resp)
|
|
318
|
-
assert payload['success'] is True
|
|
319
|
-
assert 'User profile email updated.' in payload['message']
|
|
320
|
-
assert 'Billing email updated.' not in payload['message']
|
|
321
|
-
|
|
322
|
-
updates = fake_client.get_updates()
|
|
323
|
-
assert any(u for u in updates if u[0] == 'users' and u[1] == 'u' and u[2] == {'email': 'auth@example.com'})
|
|
324
|
-
# Ensure billing was not updated
|
|
325
|
-
assert not any(u for u in updates if u[0] == 'billing')
|