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,356 +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
|
-
# Prepare lightweight fake modules to satisfy imports inside _get_payment_details
|
|
16
|
-
# We'll temporarily inject these into sys.modules while importing the module
|
|
17
|
-
|
|
18
|
-
_orig_sys_modules = {}
|
|
19
|
-
_names_to_fake = [
|
|
20
|
-
'firebase_functions',
|
|
21
|
-
'utils',
|
|
22
|
-
'firebase_admin',
|
|
23
|
-
'firebase_admin.auth',
|
|
24
|
-
'firebase_admin.firestore',
|
|
25
|
-
'stripe',
|
|
26
|
-
'ulid',
|
|
27
|
-
]
|
|
28
|
-
for name in _names_to_fake:
|
|
29
|
-
_orig_sys_modules[name] = sys.modules.get(name)
|
|
30
|
-
|
|
31
|
-
# Fake firebase_functions.https_fn.Response to capture returned data
|
|
32
|
-
firebase_functions = types.ModuleType('firebase_functions')
|
|
33
|
-
|
|
34
|
-
class FakeResponse:
|
|
35
|
-
def __init__(self, response=None, mimetype=None, status=200, **kwargs):
|
|
36
|
-
# Mirror a small subset of the interface tests expect
|
|
37
|
-
self.status_code = status
|
|
38
|
-
if isinstance(response, (dict, list)):
|
|
39
|
-
self._body_text = json.dumps(response)
|
|
40
|
-
else:
|
|
41
|
-
self._body_text = '' if response is None else response
|
|
42
|
-
# Accept either a mimetype arg (used in source) or explicit headers
|
|
43
|
-
self.headers = kwargs.get('headers', {})
|
|
44
|
-
|
|
45
|
-
def get_data(self, as_text=False):
|
|
46
|
-
if as_text:
|
|
47
|
-
return self._body_text
|
|
48
|
-
return self._body_text.encode('utf-8')
|
|
49
|
-
|
|
50
|
-
firebase_functions.https_fn = types.SimpleNamespace(Request=object, Response=FakeResponse)
|
|
51
|
-
sys.modules['firebase_functions'] = firebase_functions
|
|
52
|
-
|
|
53
|
-
# Fake utils module
|
|
54
|
-
utils_mod = types.ModuleType('utils')
|
|
55
|
-
|
|
56
|
-
# Default implementations; tests will patch attributes on the imported module when needed
|
|
57
|
-
def _fake_get_secret_key(name: str):
|
|
58
|
-
return 'DUMMY_STRIPE_KEY'
|
|
59
|
-
|
|
60
|
-
def _fake_verify_firebase_token(req):
|
|
61
|
-
# Default: successful verification
|
|
62
|
-
return {'uid': 'user_1'}
|
|
63
|
-
|
|
64
|
-
# create_json_response: tests expect the payload to be merged at top-level when payload is a dict,
|
|
65
|
-
# or under the 'message' key when payload is a string. Return the firebase_functions.https_fn.Response
|
|
66
|
-
# compatible FakeResponse defined above.
|
|
67
|
-
def _fake_create_json_response(success: bool, payload, status_code: int):
|
|
68
|
-
body = {"success": success}
|
|
69
|
-
if isinstance(payload, dict):
|
|
70
|
-
body.update(payload)
|
|
71
|
-
else:
|
|
72
|
-
body["message"] = payload
|
|
73
|
-
return firebase_functions.https_fn.Response(response=body, status=status_code, mimetype="application/json")
|
|
74
|
-
|
|
75
|
-
utils_mod.get_secret_key = _fake_get_secret_key
|
|
76
|
-
utils_mod.verify_firebase_token = _fake_verify_firebase_token
|
|
77
|
-
utils_mod.create_json_response = _fake_create_json_response
|
|
78
|
-
sys.modules['utils'] = utils_mod
|
|
79
|
-
|
|
80
|
-
# Fake firebase_admin with auth and firestore
|
|
81
|
-
firebase_admin_mod = types.ModuleType('firebase_admin')
|
|
82
|
-
|
|
83
|
-
# auth fake
|
|
84
|
-
auth_mod = types.ModuleType('firebase_admin.auth')
|
|
85
|
-
|
|
86
|
-
def _fake_get_user(uid):
|
|
87
|
-
# Return an object with an email attribute
|
|
88
|
-
return types.SimpleNamespace(email='user@example.com')
|
|
89
|
-
|
|
90
|
-
auth_mod.get_user = _fake_get_user
|
|
91
|
-
firebase_admin_mod.auth = auth_mod
|
|
92
|
-
sys.modules['firebase_admin.auth'] = auth_mod
|
|
93
|
-
|
|
94
|
-
# firestore fake: minimal in-memory store for collections -> documents
|
|
95
|
-
fake_db_data = {}
|
|
96
|
-
|
|
97
|
-
class DocumentSnapshot:
|
|
98
|
-
def __init__(self, exists, data):
|
|
99
|
-
self.exists = exists
|
|
100
|
-
self._data = data
|
|
101
|
-
|
|
102
|
-
def to_dict(self):
|
|
103
|
-
return self._data
|
|
104
|
-
|
|
105
|
-
def get(self, key):
|
|
106
|
-
if not self._data:
|
|
107
|
-
return None
|
|
108
|
-
return self._data.get(key)
|
|
109
|
-
|
|
110
|
-
class DocumentRef:
|
|
111
|
-
def __init__(self, collection_name, doc_id):
|
|
112
|
-
self.collection = collection_name
|
|
113
|
-
self.doc_id = doc_id
|
|
114
|
-
|
|
115
|
-
def get(self, transaction=None):
|
|
116
|
-
coll = fake_db_data.get(self.collection, {})
|
|
117
|
-
if self.doc_id in coll:
|
|
118
|
-
return DocumentSnapshot(True, coll[self.doc_id])
|
|
119
|
-
return DocumentSnapshot(False, None)
|
|
120
|
-
|
|
121
|
-
def update(self, update_dict):
|
|
122
|
-
coll = fake_db_data.setdefault(self.collection, {})
|
|
123
|
-
doc = coll.setdefault(self.doc_id, {})
|
|
124
|
-
doc.update(update_dict)
|
|
125
|
-
|
|
126
|
-
def set(self, data):
|
|
127
|
-
coll = fake_db_data.setdefault(self.collection, {})
|
|
128
|
-
coll[self.doc_id] = data
|
|
129
|
-
|
|
130
|
-
class CollectionRef:
|
|
131
|
-
def __init__(self, name):
|
|
132
|
-
self.name = name
|
|
133
|
-
|
|
134
|
-
def document(self, doc_id):
|
|
135
|
-
return DocumentRef(self.name, doc_id)
|
|
136
|
-
|
|
137
|
-
class FakeFirestoreClient:
|
|
138
|
-
def __init__(self):
|
|
139
|
-
pass
|
|
140
|
-
|
|
141
|
-
def collection(self, name):
|
|
142
|
-
return CollectionRef(name)
|
|
143
|
-
|
|
144
|
-
# Provide a minimal firestore module with client() and transactional decorator
|
|
145
|
-
fake_firestore_mod = types.ModuleType('firebase_admin.firestore')
|
|
146
|
-
fake_firestore_mod.client = lambda: FakeFirestoreClient()
|
|
147
|
-
# transactional decorator: just return the function unchanged in this fake
|
|
148
|
-
fake_firestore_mod.transactional = lambda f: f
|
|
149
|
-
|
|
150
|
-
firebase_admin_mod.firestore = fake_firestore_mod
|
|
151
|
-
sys.modules['firebase_admin'] = firebase_admin_mod
|
|
152
|
-
sys.modules['firebase_admin.firestore'] = fake_firestore_mod
|
|
153
|
-
|
|
154
|
-
# Fake stripe module
|
|
155
|
-
stripe_mod = types.ModuleType('stripe')
|
|
156
|
-
|
|
157
|
-
class StripeError(Exception):
|
|
158
|
-
pass
|
|
159
|
-
|
|
160
|
-
stripe_mod.error = types.SimpleNamespace(StripeError=StripeError)
|
|
161
|
-
stripe_mod.api_key = None
|
|
162
|
-
|
|
163
|
-
class _Customer:
|
|
164
|
-
@staticmethod
|
|
165
|
-
def create(email=None, metadata=None):
|
|
166
|
-
# Simulate creating a Stripe customer
|
|
167
|
-
return types.SimpleNamespace(id='cus_new')
|
|
168
|
-
|
|
169
|
-
stripe_mod.Customer = _Customer
|
|
170
|
-
|
|
171
|
-
class _Session:
|
|
172
|
-
@staticmethod
|
|
173
|
-
def create(**kwargs):
|
|
174
|
-
# Return a dummy checkout session
|
|
175
|
-
return types.SimpleNamespace(id='sess_123', url='https://checkout.example/sess_123')
|
|
176
|
-
|
|
177
|
-
stripe_mod.checkout = types.SimpleNamespace(Session=_Session)
|
|
178
|
-
sys.modules['stripe'] = stripe_mod
|
|
179
|
-
|
|
180
|
-
# Fake ulid
|
|
181
|
-
ulid_mod = types.ModuleType('ulid')
|
|
182
|
-
ulid_mod.new = lambda: 'ULID123'
|
|
183
|
-
sys.modules['ulid'] = ulid_mod
|
|
184
|
-
|
|
185
|
-
# Import the module under test after preparing fake imports
|
|
186
|
-
# Load the module directly from the functions/ tree so the test's fake sys.modules entries are respected
|
|
187
|
-
repo_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
|
188
|
-
functions_root = os.path.join(repo_root, 'functions')
|
|
189
|
-
module_path = os.path.join(functions_root, 'api_v1_00', '_get_payment_details.py')
|
|
190
|
-
spec = importlib.util.spec_from_file_location('api_v1_00._get_payment_details', module_path)
|
|
191
|
-
_get_payment_details = importlib.util.module_from_spec(spec)
|
|
192
|
-
spec.loader.exec_module(_get_payment_details)
|
|
193
|
-
|
|
194
|
-
# Restore original sys.modules mappings to avoid side-effects for other tests
|
|
195
|
-
for name, orig in _orig_sys_modules.items():
|
|
196
|
-
if orig is None:
|
|
197
|
-
try:
|
|
198
|
-
del sys.modules[name]
|
|
199
|
-
except KeyError:
|
|
200
|
-
pass
|
|
201
|
-
else:
|
|
202
|
-
sys.modules[name] = orig
|
|
203
|
-
|
|
204
|
-
# Import env constants for auth header usage in tests
|
|
205
|
-
import env as functions_env # noqa: E402
|
|
206
|
-
AUTH_HEADER_NAME = functions_env.AUTH_HEADER_NAME
|
|
207
|
-
VALID_ENCRYPTED_KEY = functions_env.ENCRYPTED_AUTH_KEY.decode('utf-8')
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
# Helper request stub used in tests
|
|
211
|
-
class DummyRequest:
|
|
212
|
-
def __init__(self, headers=None, method='POST', json_data=None, raise_on_get_json=False):
|
|
213
|
-
self.headers = headers or {}
|
|
214
|
-
self.method = method
|
|
215
|
-
self._json_data = json_data
|
|
216
|
-
self._raise = raise_on_get_json
|
|
217
|
-
|
|
218
|
-
def get_json(self, silent=True):
|
|
219
|
-
if self._raise:
|
|
220
|
-
raise Exception('Malformed JSON')
|
|
221
|
-
return self._json_data
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
def _parse_response(resp):
|
|
225
|
-
data = resp.get_data(as_text=True)
|
|
226
|
-
return json.loads(data)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
# -----------------------------
|
|
230
|
-
# Tests
|
|
231
|
-
# -----------------------------
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
def test_verify_firebase_token_failure_returns_403():
|
|
235
|
-
req = DummyRequest(headers={AUTH_HEADER_NAME: VALID_ENCRYPTED_KEY, 'Authorization': 'Bearer TOK'}, method='POST')
|
|
236
|
-
with patch.object(_get_payment_details, 'verify_firebase_token', side_effect=Exception('invalid token')):
|
|
237
|
-
resp = _get_payment_details._get_payment_details(req)
|
|
238
|
-
|
|
239
|
-
assert resp.status_code == 403
|
|
240
|
-
payload = _parse_response(resp)
|
|
241
|
-
assert payload['success'] is False
|
|
242
|
-
assert 'Authentication failed' in payload.get('message', '')
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
def test_missing_json_payload_returns_400():
|
|
246
|
-
fake_db_data.clear()
|
|
247
|
-
req = DummyRequest(headers={AUTH_HEADER_NAME: VALID_ENCRYPTED_KEY, 'Authorization': 'Bearer TOK'}, method='POST', json_data=None)
|
|
248
|
-
with patch.object(_get_payment_details, 'verify_firebase_token', return_value={'uid': 'user_1'}), \
|
|
249
|
-
patch.object(_get_payment_details, 'get_secret_key', return_value='DUMMY_STRIPE_KEY'):
|
|
250
|
-
resp = _get_payment_details._get_payment_details(req)
|
|
251
|
-
|
|
252
|
-
assert resp.status_code == 400
|
|
253
|
-
payload = _parse_response(resp)
|
|
254
|
-
assert payload['success'] is False
|
|
255
|
-
assert 'Invalid or missing JSON payload' in payload.get('message', '')
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
def test_billing_info_missing_returns_404():
|
|
259
|
-
fake_db_data.clear()
|
|
260
|
-
# provide a non-empty payload so code proceeds to check Firestore
|
|
261
|
-
req = DummyRequest(headers={AUTH_HEADER_NAME: VALID_ENCRYPTED_KEY, 'Authorization': 'Bearer TOK'}, method='POST', json_data={'dummy': True})
|
|
262
|
-
with patch.object(_get_payment_details, 'verify_firebase_token', return_value={'uid': 'user_1'}), \
|
|
263
|
-
patch.object(_get_payment_details, 'get_secret_key', return_value='DUMMY_STRIPE_KEY'):
|
|
264
|
-
resp = _get_payment_details._get_payment_details(req)
|
|
265
|
-
|
|
266
|
-
assert resp.status_code == 404
|
|
267
|
-
payload = _parse_response(resp)
|
|
268
|
-
assert payload['success'] is False
|
|
269
|
-
assert 'Billing information is missing' in payload.get('message', '')
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
def test_setup_session_with_existing_customer_returns_session_url():
|
|
273
|
-
# Pre-populate billing doc with an existing stripe_customer_id
|
|
274
|
-
fake_db_data.clear()
|
|
275
|
-
fake_db_data.setdefault('billing', {})['user_1'] = {'stripe_customer_id': 'cus_existing'}
|
|
276
|
-
|
|
277
|
-
req = DummyRequest(headers={AUTH_HEADER_NAME: VALID_ENCRYPTED_KEY, 'Authorization': 'Bearer TOK'}, method='POST', json_data={'dummy': True})
|
|
278
|
-
with patch.object(_get_payment_details, 'verify_firebase_token', return_value={'uid': 'user_1'}), \
|
|
279
|
-
patch.object(_get_payment_details, 'get_secret_key', return_value='DUMMY_STRIPE_KEY'):
|
|
280
|
-
resp = _get_payment_details._get_payment_details(req)
|
|
281
|
-
|
|
282
|
-
assert resp.status_code == 200
|
|
283
|
-
payload = _parse_response(resp)
|
|
284
|
-
assert payload['success'] is True
|
|
285
|
-
assert payload['session_url'] == 'https://checkout.example/sess_123'
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
def test_create_customer_and_setup_session_when_no_stripe_customer():
|
|
289
|
-
fake_db_data.clear()
|
|
290
|
-
fake_db_data.setdefault('billing', {})['user_1'] = {} # no stripe id
|
|
291
|
-
|
|
292
|
-
req = DummyRequest(headers={AUTH_HEADER_NAME: VALID_ENCRYPTED_KEY, 'Authorization': 'Bearer TOK'}, method='POST', json_data={'dummy': True})
|
|
293
|
-
with patch.object(_get_payment_details, 'verify_firebase_token', return_value={'uid': 'user_1'}), \
|
|
294
|
-
patch.object(_get_payment_details, 'get_secret_key', return_value='DUMMY_STRIPE_KEY'):
|
|
295
|
-
resp = _get_payment_details._get_payment_details(req)
|
|
296
|
-
|
|
297
|
-
assert resp.status_code == 200
|
|
298
|
-
payload = _parse_response(resp)
|
|
299
|
-
assert payload['success'] is True
|
|
300
|
-
assert payload['session_url'] == 'https://checkout.example/sess_123'
|
|
301
|
-
# billing doc should have been updated with new stripe_customer_id
|
|
302
|
-
assert fake_db_data['billing']['user_1'].get('stripe_customer_id') == 'cus_new'
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
def test_get_secret_key_failure_returns_500():
|
|
306
|
-
fake_db_data.clear()
|
|
307
|
-
fake_db_data.setdefault('billing', {})['user_1'] = {'stripe_customer_id': 'cus_existing'}
|
|
308
|
-
|
|
309
|
-
req = DummyRequest(headers={AUTH_HEADER_NAME: VALID_ENCRYPTED_KEY, 'Authorization': 'Bearer TOK'}, method='POST', json_data={'dummy': True})
|
|
310
|
-
with patch.object(_get_payment_details, 'verify_firebase_token', return_value={'uid': 'user_1'}), \
|
|
311
|
-
patch.object(_get_payment_details, 'get_secret_key', side_effect=Exception('boom')):
|
|
312
|
-
resp = _get_payment_details._get_payment_details(req)
|
|
313
|
-
|
|
314
|
-
assert resp.status_code == 500
|
|
315
|
-
payload = _parse_response(resp)
|
|
316
|
-
assert payload['success'] is False
|
|
317
|
-
assert 'Failed to retrieve Stripe configuration' in payload.get('message', '')
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
def test_invalid_negative_amount_returns_400():
|
|
321
|
-
# Ensure billing doc exists so code reaches amount parsing
|
|
322
|
-
fake_db_data.clear()
|
|
323
|
-
fake_db_data.setdefault('billing', {})['user_1'] = {'stripe_customer_id': 'cus_existing'}
|
|
324
|
-
|
|
325
|
-
req = DummyRequest(headers={AUTH_HEADER_NAME: VALID_ENCRYPTED_KEY, 'Authorization': 'Bearer TOK'}, method='POST', json_data={'amount': '-5'})
|
|
326
|
-
with patch.object(_get_payment_details, 'verify_firebase_token', return_value={'uid': 'user_1'}), \
|
|
327
|
-
patch.object(_get_payment_details, 'get_secret_key', return_value='DUMMY_STRIPE_KEY'):
|
|
328
|
-
resp = _get_payment_details._get_payment_details(req)
|
|
329
|
-
|
|
330
|
-
assert resp.status_code == 400
|
|
331
|
-
payload = _parse_response(resp)
|
|
332
|
-
assert payload['success'] is False
|
|
333
|
-
assert 'Invalid amount value provided' in payload.get('message', '')
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
def test_missing_auth_header_returns_401():
|
|
337
|
-
fake_db_data.clear()
|
|
338
|
-
req = DummyRequest(headers={'Authorization': 'Bearer TOK'}, method='POST', json_data={'dummy': True})
|
|
339
|
-
# No X-Roksta-Auth-Key header provided
|
|
340
|
-
resp = _get_payment_details._get_payment_details(req)
|
|
341
|
-
|
|
342
|
-
assert resp.status_code == 401
|
|
343
|
-
payload = _parse_response(resp)
|
|
344
|
-
assert payload['success'] is False
|
|
345
|
-
assert 'Missing authentication key' in payload.get('message', '')
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
def test_invalid_auth_header_returns_403():
|
|
349
|
-
fake_db_data.clear()
|
|
350
|
-
req = DummyRequest(headers={AUTH_HEADER_NAME: 'bad-key', 'Authorization': 'Bearer TOK'}, method='POST', json_data={'dummy': True})
|
|
351
|
-
resp = _get_payment_details._get_payment_details(req)
|
|
352
|
-
|
|
353
|
-
assert resp.status_code == 403
|
|
354
|
-
payload = _parse_response(resp)
|
|
355
|
-
assert payload['success'] is False
|
|
356
|
-
assert 'Invalid authentication key' in payload.get('message', '')
|