sefrone-api-e2e 1.1.8__tar.gz → 1.2.0__tar.gz
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.
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/PKG-INFO +1 -1
- sefrone_api_e2e-1.2.0/sefrone_api_e2e/env_patch.py +77 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/runner_email_mock.py +12 -52
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/runner_satim_mock.py +7 -40
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/runner_webhook_mock.py +7 -42
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e.egg-info/PKG-INFO +1 -1
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e.egg-info/SOURCES.txt +1 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/setup.py +1 -1
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/README.md +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/__init__.py +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/api_e2e_manager.py +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/e2e/Scenarios/Auth/0_check_features.yaml +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/e2e/Scenarios/Auth/1_normal_auth_flow.yaml +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/e2e/Scenarios/Auth/2_account_endpoints.yaml +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/e2e/Scenarios/Auth/3_admin_account_endpoints.yaml +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/e2e/Scenarios/Auth/4_workspace_endpoints.yaml +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/e2e/Scenarios/Auth/5_apikey_endpoints.yaml +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/e2e/Scenarios/Auth/6_project_endpoints.yaml +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/e2e/Scenarios/Auth/7_email_2fa_flow.yaml +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/e2e_scenarios_manager.py +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/json_mock_server.py +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/runner_assets.py +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/runner_rest_api.py +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e/step_runner.py +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e.egg-info/dependency_links.txt +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e.egg-info/requires.txt +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e.egg-info/top_level.txt +0 -0
- {sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/setup.cfg +0 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Dict, Optional
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def apply_env_overrides(
|
|
6
|
+
env_file_path: str,
|
|
7
|
+
overrides: Dict[str, Optional[str]],
|
|
8
|
+
process_env_strategy: str = "none",
|
|
9
|
+
) -> None:
|
|
10
|
+
"""
|
|
11
|
+
Apply key/value overrides to a .env file.
|
|
12
|
+
|
|
13
|
+
- value is None: remove key from .env
|
|
14
|
+
- value is str: set/replace key in .env
|
|
15
|
+
|
|
16
|
+
process_env_strategy:
|
|
17
|
+
- "none": do not modify os.environ
|
|
18
|
+
- "sync": apply same set/unset semantics to os.environ
|
|
19
|
+
- "unset": remove every overridden key from os.environ
|
|
20
|
+
"""
|
|
21
|
+
if process_env_strategy == "sync":
|
|
22
|
+
for key, val in overrides.items():
|
|
23
|
+
if val is None:
|
|
24
|
+
os.environ.pop(key, None)
|
|
25
|
+
else:
|
|
26
|
+
os.environ[key] = str(val)
|
|
27
|
+
elif process_env_strategy == "unset":
|
|
28
|
+
for key in overrides.keys():
|
|
29
|
+
os.environ.pop(key, None)
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
with open(env_file_path, "r", encoding="utf-8") as f:
|
|
33
|
+
lines = f.readlines()
|
|
34
|
+
except FileNotFoundError:
|
|
35
|
+
lines = []
|
|
36
|
+
|
|
37
|
+
new_lines = []
|
|
38
|
+
replaced = set()
|
|
39
|
+
|
|
40
|
+
for line in lines:
|
|
41
|
+
stripped = line.strip()
|
|
42
|
+
if stripped.startswith("#") or "=" not in stripped:
|
|
43
|
+
new_lines.append(line)
|
|
44
|
+
continue
|
|
45
|
+
|
|
46
|
+
key = stripped.split("=", 1)[0].strip()
|
|
47
|
+
if key not in overrides:
|
|
48
|
+
new_lines.append(line)
|
|
49
|
+
continue
|
|
50
|
+
|
|
51
|
+
val = overrides[key]
|
|
52
|
+
if val is not None:
|
|
53
|
+
new_lines.append(f"{key}={val}\n")
|
|
54
|
+
replaced.add(key)
|
|
55
|
+
|
|
56
|
+
for key, val in overrides.items():
|
|
57
|
+
if key not in replaced and val is not None:
|
|
58
|
+
new_lines.append(f"{key}={val}\n")
|
|
59
|
+
|
|
60
|
+
with open(env_file_path, "w", encoding="utf-8") as f:
|
|
61
|
+
f.writelines(new_lines)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def read_env_value(env_file_path: str, key: str) -> Optional[str]:
|
|
65
|
+
"""Read one key from .env and strip optional surrounding quotes."""
|
|
66
|
+
try:
|
|
67
|
+
with open(env_file_path, "r", encoding="utf-8") as f:
|
|
68
|
+
for line in f:
|
|
69
|
+
stripped = line.strip()
|
|
70
|
+
if stripped.startswith("#") or "=" not in stripped:
|
|
71
|
+
continue
|
|
72
|
+
k, _, v = stripped.partition("=")
|
|
73
|
+
if k.strip() == key:
|
|
74
|
+
return v.strip().strip('"').strip("'")
|
|
75
|
+
except FileNotFoundError:
|
|
76
|
+
pass
|
|
77
|
+
return None
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import re
|
|
3
2
|
import time
|
|
4
3
|
from typing import Optional
|
|
@@ -6,6 +5,7 @@ from typing import Optional
|
|
|
6
5
|
import requests
|
|
7
6
|
|
|
8
7
|
from .step_runner import StepRunner, RunContext, StepResult
|
|
8
|
+
from .env_patch import apply_env_overrides, read_env_value
|
|
9
9
|
|
|
10
10
|
class EmailMockRunner(StepRunner):
|
|
11
11
|
"""
|
|
@@ -110,54 +110,25 @@ class EmailMockRunner(StepRunner):
|
|
|
110
110
|
Variables with string values will be set to those values.
|
|
111
111
|
|
|
112
112
|
Note: this also applies the same overrides to the current Python
|
|
113
|
-
process environment
|
|
114
|
-
Compose
|
|
113
|
+
process environment key space by unsetting every patched key. This
|
|
114
|
+
prevents Docker Compose from resolving stale ${VAR} values from the
|
|
115
|
+
process env before reading .env.
|
|
115
116
|
"""
|
|
116
117
|
overrides = {
|
|
117
118
|
**EmailMockRunner._ENV_OVERRIDES,
|
|
118
119
|
"MAIL_SERVER": host,
|
|
119
120
|
"MAIL_SERVER_PORT": str(smtp_port),
|
|
120
121
|
}
|
|
121
|
-
|
|
122
|
-
# Keep process env in sync with file overrides so docker-compose
|
|
123
|
-
# interpolation does not pick stale MAIL_* values from OS env vars.
|
|
124
|
-
for key, val in overrides.items():
|
|
125
|
-
if val is None:
|
|
126
|
-
os.environ.pop(key, None)
|
|
127
|
-
else:
|
|
128
|
-
os.environ[key] = val
|
|
129
|
-
|
|
130
122
|
try:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
123
|
+
apply_env_overrides(
|
|
124
|
+
env_file_path=env_file_path,
|
|
125
|
+
overrides=overrides,
|
|
126
|
+
process_env_strategy="unset",
|
|
127
|
+
)
|
|
128
|
+
except Exception as e:
|
|
129
|
+
print(f"[WARN] env file patch failed for EmailMockRunner: {env_file_path} -> {e}")
|
|
135
130
|
return
|
|
136
131
|
|
|
137
|
-
new_lines = []
|
|
138
|
-
replaced = set()
|
|
139
|
-
for line in lines:
|
|
140
|
-
stripped = line.strip()
|
|
141
|
-
if stripped.startswith("#") or "=" not in stripped:
|
|
142
|
-
new_lines.append(line)
|
|
143
|
-
continue
|
|
144
|
-
key = stripped.split("=", 1)[0].strip()
|
|
145
|
-
if key in overrides:
|
|
146
|
-
# If override value is None, skip (unset) this variable
|
|
147
|
-
if overrides[key] is not None:
|
|
148
|
-
new_lines.append(f"{key}={overrides[key]}\n")
|
|
149
|
-
replaced.add(key)
|
|
150
|
-
else:
|
|
151
|
-
new_lines.append(line)
|
|
152
|
-
|
|
153
|
-
# Add any new overrides that weren't in the original file
|
|
154
|
-
for key, val in overrides.items():
|
|
155
|
-
if key not in replaced and val is not None:
|
|
156
|
-
new_lines.append(f"{key}={val}\n")
|
|
157
|
-
|
|
158
|
-
with open(env_file_path, "w", encoding="utf-8") as f:
|
|
159
|
-
f.writelines(new_lines)
|
|
160
|
-
|
|
161
132
|
unset_vars = [k for k, v in EmailMockRunner._ENV_OVERRIDES.items() if v is None]
|
|
162
133
|
print(f"[EmailMockRunner] Patched {env_file_path}:")
|
|
163
134
|
print(f" Set: MAIL_SERVER={host}:{smtp_port}, MAIL_USE_SECURITY=false")
|
|
@@ -435,15 +406,4 @@ class EmailMockRunner(StepRunner):
|
|
|
435
406
|
@staticmethod
|
|
436
407
|
def _read_env_value(env_file_path: str, key: str) -> Optional[str]:
|
|
437
408
|
"""Read a single key's value from a .env file, stripping surrounding quotes."""
|
|
438
|
-
|
|
439
|
-
with open(env_file_path, "r", encoding="utf-8") as f:
|
|
440
|
-
for line in f:
|
|
441
|
-
stripped = line.strip()
|
|
442
|
-
if stripped.startswith("#") or "=" not in stripped:
|
|
443
|
-
continue
|
|
444
|
-
k, _, v = stripped.partition("=")
|
|
445
|
-
if k.strip() == key:
|
|
446
|
-
return v.strip().strip('"').strip("'")
|
|
447
|
-
except FileNotFoundError:
|
|
448
|
-
pass
|
|
449
|
-
return None
|
|
409
|
+
return read_env_value(env_file_path, key)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import json
|
|
2
1
|
import os
|
|
3
2
|
import re
|
|
4
3
|
import time
|
|
@@ -7,6 +6,7 @@ from typing import Optional
|
|
|
7
6
|
import requests
|
|
8
7
|
|
|
9
8
|
from .step_runner import StepRunner, RunContext, StepResult
|
|
9
|
+
from .env_patch import apply_env_overrides, read_env_value
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
_SERVER_SCRIPT = r"""
|
|
@@ -338,45 +338,12 @@ class SatimMockRunner(StepRunner):
|
|
|
338
338
|
|
|
339
339
|
@staticmethod
|
|
340
340
|
def _patch_env_file(env_file_path: str, key: str, value: str) -> None:
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
new_lines = []
|
|
348
|
-
found = False
|
|
349
|
-
for line in lines:
|
|
350
|
-
stripped = line.strip()
|
|
351
|
-
if stripped.startswith("#") or "=" not in stripped:
|
|
352
|
-
new_lines.append(line)
|
|
353
|
-
continue
|
|
354
|
-
k = stripped.split("=", 1)[0].strip()
|
|
355
|
-
if k == key:
|
|
356
|
-
new_lines.append(f"{key}={value}\n")
|
|
357
|
-
found = True
|
|
358
|
-
else:
|
|
359
|
-
new_lines.append(line)
|
|
360
|
-
|
|
361
|
-
if not found:
|
|
362
|
-
if new_lines and not new_lines[-1].endswith("\n"):
|
|
363
|
-
new_lines[-1] = new_lines[-1] + "\n"
|
|
364
|
-
new_lines.append(f"{key}={value}\n")
|
|
365
|
-
|
|
366
|
-
with open(env_file_path, "w", encoding="utf-8") as f:
|
|
367
|
-
f.writelines(new_lines)
|
|
341
|
+
apply_env_overrides(
|
|
342
|
+
env_file_path=env_file_path,
|
|
343
|
+
overrides={key: value},
|
|
344
|
+
process_env_strategy="unset",
|
|
345
|
+
)
|
|
368
346
|
|
|
369
347
|
@staticmethod
|
|
370
348
|
def _read_env_value(env_file_path: str, key: str) -> Optional[str]:
|
|
371
|
-
|
|
372
|
-
with open(env_file_path, "r", encoding="utf-8") as f:
|
|
373
|
-
for line in f:
|
|
374
|
-
stripped = line.strip()
|
|
375
|
-
if stripped.startswith("#") or "=" not in stripped:
|
|
376
|
-
continue
|
|
377
|
-
k, _, v = stripped.partition("=")
|
|
378
|
-
if k.strip() == key:
|
|
379
|
-
return v.strip()
|
|
380
|
-
except FileNotFoundError:
|
|
381
|
-
pass
|
|
382
|
-
return None
|
|
349
|
+
return read_env_value(env_file_path, key)
|
|
@@ -8,6 +8,7 @@ from typing import Optional
|
|
|
8
8
|
import requests
|
|
9
9
|
|
|
10
10
|
from .step_runner import StepRunner, RunContext, StepResult
|
|
11
|
+
from .env_patch import apply_env_overrides, read_env_value
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
# ---------------------------------------------------------------------------
|
|
@@ -498,49 +499,13 @@ class WebhookMockRunner(StepRunner):
|
|
|
498
499
|
|
|
499
500
|
@staticmethod
|
|
500
501
|
def _patch_env_file(env_file_path: str, key: str, value: str) -> None:
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
lines = []
|
|
507
|
-
|
|
508
|
-
new_lines = []
|
|
509
|
-
found = False
|
|
510
|
-
for line in lines:
|
|
511
|
-
stripped = line.strip()
|
|
512
|
-
if stripped.startswith("#") or "=" not in stripped:
|
|
513
|
-
new_lines.append(line)
|
|
514
|
-
continue
|
|
515
|
-
k = stripped.split("=", 1)[0].strip()
|
|
516
|
-
if k == key:
|
|
517
|
-
new_lines.append(f"{key}={value}\n")
|
|
518
|
-
found = True
|
|
519
|
-
else:
|
|
520
|
-
new_lines.append(line)
|
|
521
|
-
|
|
522
|
-
if not found:
|
|
523
|
-
# Ensure the previously copied last line ends with a newline,
|
|
524
|
-
# otherwise the new key gets concatenated and corrupts .env.
|
|
525
|
-
if new_lines and not new_lines[-1].endswith("\n"):
|
|
526
|
-
new_lines[-1] = new_lines[-1] + "\n"
|
|
527
|
-
new_lines.append(f"{key}={value}\n")
|
|
528
|
-
|
|
529
|
-
with open(env_file_path, "w", encoding="utf-8") as f:
|
|
530
|
-
f.writelines(new_lines)
|
|
502
|
+
apply_env_overrides(
|
|
503
|
+
env_file_path=env_file_path,
|
|
504
|
+
overrides={key: value},
|
|
505
|
+
process_env_strategy="unset",
|
|
506
|
+
)
|
|
531
507
|
|
|
532
508
|
@staticmethod
|
|
533
509
|
def _read_env_value(env_file_path: str, key: str) -> Optional[str]:
|
|
534
510
|
"""Read a single value from an env file."""
|
|
535
|
-
|
|
536
|
-
with open(env_file_path, "r", encoding="utf-8") as f:
|
|
537
|
-
for line in f:
|
|
538
|
-
stripped = line.strip()
|
|
539
|
-
if stripped.startswith("#") or "=" not in stripped:
|
|
540
|
-
continue
|
|
541
|
-
k, _, v = stripped.partition("=")
|
|
542
|
-
if k.strip() == key:
|
|
543
|
-
return v.strip()
|
|
544
|
-
except FileNotFoundError:
|
|
545
|
-
pass
|
|
546
|
-
return None
|
|
511
|
+
return read_env_value(env_file_path, key)
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name="sefrone_api_e2e",
|
|
8
|
-
version="1.
|
|
8
|
+
version="1.2.0",
|
|
9
9
|
author="Sefrone",
|
|
10
10
|
author_email="contact@sefrone.com",
|
|
11
11
|
description="A Python package to provide e2e testing helpers for sefrone API projects",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sefrone_api_e2e-1.1.8 → sefrone_api_e2e-1.2.0}/sefrone_api_e2e.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|