nextog-cli 1.0.0__py3-none-any.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.
Files changed (51) hide show
  1. nextog/__init__.py +4 -0
  2. nextog/cli.py +545 -0
  3. nextog/config/__init__.py +1 -0
  4. nextog/config/settings.py +132 -0
  5. nextog/core/__init__.py +1 -0
  6. nextog/core/engine.py +193 -0
  7. nextog/core/permissions.py +129 -0
  8. nextog/core/privacy.py +130 -0
  9. nextog/core/reporter.py +204 -0
  10. nextog/core/runner.py +236 -0
  11. nextog/data/__init__.py +1 -0
  12. nextog/data/local_db.py +367 -0
  13. nextog/data/models.py +72 -0
  14. nextog/data/sync.py +65 -0
  15. nextog/engines/__init__.py +1 -0
  16. nextog/engines/api/__init__.py +1 -0
  17. nextog/engines/api/graphql.py +54 -0
  18. nextog/engines/api/rest.py +346 -0
  19. nextog/engines/api/websocket.py +59 -0
  20. nextog/engines/embedded/__init__.py +1 -0
  21. nextog/engines/embedded/firmware.py +53 -0
  22. nextog/engines/embedded/hardware.py +330 -0
  23. nextog/engines/mobile/__init__.py +1 -0
  24. nextog/engines/mobile/android.py +333 -0
  25. nextog/engines/mobile/cross.py +48 -0
  26. nextog/engines/mobile/ios.py +46 -0
  27. nextog/engines/system/__init__.py +1 -0
  28. nextog/engines/system/load.py +121 -0
  29. nextog/engines/system/performance.py +128 -0
  30. nextog/engines/system/security.py +170 -0
  31. nextog/engines/web/__init__.py +1 -0
  32. nextog/engines/web/accessibility.py +191 -0
  33. nextog/engines/web/browser.py +387 -0
  34. nextog/engines/web/elements.py +285 -0
  35. nextog/engines/web/responsive.py +79 -0
  36. nextog/live/__init__.py +1 -0
  37. nextog/live/dashboard.py +30 -0
  38. nextog/live/panel.py +325 -0
  39. nextog/reports/__init__.py +1359 -0
  40. nextog/training/__init__.py +1 -0
  41. nextog/training/learner.py +269 -0
  42. nextog/training/patterns.py +102 -0
  43. nextog/utils/__init__.py +1 -0
  44. nextog/utils/helpers.py +91 -0
  45. nextog/utils/logger.py +37 -0
  46. nextog/utils/validators.py +98 -0
  47. nextog_cli-1.0.0.dist-info/METADATA +344 -0
  48. nextog_cli-1.0.0.dist-info/RECORD +51 -0
  49. nextog_cli-1.0.0.dist-info/WHEEL +5 -0
  50. nextog_cli-1.0.0.dist-info/entry_points.txt +2 -0
  51. nextog_cli-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,48 @@
1
+ """Cross-platform mobile testing - runs tests on both Android and iOS"""
2
+
3
+ from typing import Dict, List
4
+ from rich.console import Console
5
+
6
+ console = Console()
7
+
8
+
9
+ class CrossPlatformTestEngine:
10
+ """Run tests across both Android and iOS platforms"""
11
+
12
+ def __init__(self, settings, db, privacy):
13
+ self.settings = settings
14
+ self.db = db
15
+ self.privacy = privacy
16
+
17
+ def run_tests(self, android_app: str = None, ios_app: str = None,
18
+ test_suite: str = "default", coverage_target: int = 90) -> Dict:
19
+ """Run same test suite on both platforms"""
20
+ results = {
21
+ "total": 0, "passed": 0, "failed": 0, "skipped": 0,
22
+ "coverage": 0, "platforms": {}
23
+ }
24
+
25
+ # Test on Android
26
+ if android_app:
27
+ from nextog.engines.mobile.android import MobileTestEngine
28
+ android_engine = MobileTestEngine(self.settings, self.db, self.privacy)
29
+ android_results = android_engine.run_tests(android_app, "android")
30
+ results["platforms"]["android"] = android_results
31
+
32
+ # Test on iOS
33
+ if ios_app:
34
+ from nextog.engines.mobile.ios import iOSTestEngine
35
+ ios_engine = iOSTestEngine(self.settings, self.db, self.privacy)
36
+ ios_results = ios_engine.run_tests(ios_app, "ios")
37
+ results["platforms"]["ios"] = ios_results
38
+
39
+ # Aggregate results
40
+ for platform_data in results["platforms"].values():
41
+ results["total"] += platform_data.get("total", 0)
42
+ results["passed"] += platform_data.get("passed", 0)
43
+ results["failed"] += platform_data.get("failed", 0)
44
+
45
+ if results["total"] > 0:
46
+ results["coverage"] = round((results["passed"] / results["total"]) * 100, 2)
47
+
48
+ return results
@@ -0,0 +1,46 @@
1
+ """iOS Testing Module"""
2
+
3
+ from typing import Dict
4
+ from nextog.engines.mobile.android import MobileTestEngine
5
+
6
+
7
+ class iOSTestEngine(MobileTestEngine):
8
+ """iOS-specific testing via Appium XCUITest"""
9
+
10
+ def _setup_driver(self, app_path: str, platform: str, device: str):
11
+ """Setup iOS Appium driver"""
12
+ try:
13
+ from appium import webdriver
14
+ from appium.options.ios import XCUITestOptions
15
+
16
+ options = XCUITestOptions()
17
+ options.platform_name = "iOS"
18
+ options.app = app_path
19
+ options.device_name = device or "iPhone 14"
20
+ options.automation_name = "XCUITest"
21
+ options.platform_version = "16.0"
22
+ options.no_reset = True
23
+
24
+ self.driver = webdriver.Remote("http://127.0.0.1:4723", options=options)
25
+ except ImportError:
26
+ raise ImportError("Install Appium-Python-Client for iOS testing")
27
+
28
+ def _test_ui_elements(self) -> Dict:
29
+ """iOS-specific UI element tests"""
30
+ results = {"total": 0, "passed": 0, "failed": 0}
31
+
32
+ if not self.driver:
33
+ return results
34
+
35
+ # Test: XCUIElements exist
36
+ results["total"] += 1
37
+ try:
38
+ elements = self.driver.find_elements("class name", "XCUIElementTypeAny")
39
+ if len(elements) > 0:
40
+ results["passed"] += 1
41
+ else:
42
+ results["failed"] += 1
43
+ except Exception:
44
+ results["failed"] += 1
45
+
46
+ return results
@@ -0,0 +1 @@
1
+ """System testing engines"""
@@ -0,0 +1,121 @@
1
+ """Load Testing Engine"""
2
+
3
+ from typing import Dict
4
+ from concurrent.futures import ThreadPoolExecutor
5
+ import time
6
+
7
+
8
+ class LoadTestEngine:
9
+ """Load testing with configurable scenarios"""
10
+
11
+ def __init__(self, settings, db, privacy):
12
+ self.settings = settings
13
+ self.db = db
14
+ self.privacy = privacy
15
+
16
+ def run_tests(self, target: str, scenario: str = "ramp",
17
+ max_users: int = 100, duration: int = 60) -> Dict:
18
+ """Run load tests"""
19
+ results = {"total": 0, "passed": 0, "failed": 0, "metrics": {}}
20
+
21
+ if scenario == "ramp":
22
+ results = self._ramp_test(target, max_users, duration)
23
+ elif scenario == "constant":
24
+ results = self._constant_test(target, max_users, duration)
25
+ elif scenario == "spike":
26
+ results = self._spike_test(target, max_users)
27
+
28
+ return results
29
+
30
+ def _ramp_test(self, target: str, max_users: int, duration: int) -> Dict:
31
+ """Gradually increase load"""
32
+ return self._run_load_scenario(target, max_users, duration, "ramp")
33
+
34
+ def _constant_test(self, target: str, users: int, duration: int) -> Dict:
35
+ """Constant load"""
36
+ return self._run_load_scenario(target, users, duration, "constant")
37
+
38
+ def _spike_test(self, target: str, users: int) -> Dict:
39
+ """Sudden spike in load"""
40
+ return self._run_load_scenario(target, users, 10, "spike")
41
+
42
+ def _run_load_scenario(self, target: str, max_users: int, duration: int, scenario: str) -> Dict:
43
+ """Execute a load test scenario"""
44
+ results = {
45
+ "total": 1, "passed": 0, "failed": 0,
46
+ "metrics": {
47
+ "scenario": scenario,
48
+ "max_users": max_users,
49
+ "duration": duration,
50
+ "total_requests": 0,
51
+ "successful": 0,
52
+ "failed": 0,
53
+ "avg_response_ms": 0,
54
+ "p95_ms": 0,
55
+ "p99_ms": 0,
56
+ "requests_per_sec": 0,
57
+ "error_rate": 0,
58
+ }
59
+ }
60
+
61
+ try:
62
+ import httpx
63
+
64
+ all_times = []
65
+ success_count = 0
66
+ fail_count = 0
67
+ start_time = time.time()
68
+
69
+ def make_request(_):
70
+ try:
71
+ s = time.time()
72
+ resp = httpx.get(target, timeout=10)
73
+ elapsed = time.time() - s
74
+ return (resp.status_code < 500, elapsed)
75
+ except Exception:
76
+ return (False, 0)
77
+
78
+ with ThreadPoolExecutor(max_workers=min(max_users, 50)) as executor:
79
+ futures = [executor.submit(make_request, i) for i in range(max_users * 3)]
80
+
81
+ for f in futures:
82
+ success, elapsed = f.result()
83
+ if success:
84
+ success_count += 1
85
+ else:
86
+ fail_count += 1
87
+ if elapsed > 0:
88
+ all_times.append(elapsed)
89
+
90
+ total_time = time.time() - start_time
91
+ total_req = success_count + fail_count
92
+
93
+ sorted_times = sorted(all_times)
94
+ p95_idx = int(len(sorted_times) * 0.95) if sorted_times else 0
95
+ p99_idx = int(len(sorted_times) * 0.99) if sorted_times else 0
96
+
97
+ results["metrics"] = {
98
+ "scenario": scenario,
99
+ "max_users": max_users,
100
+ "duration": duration,
101
+ "total_requests": total_req,
102
+ "successful": success_count,
103
+ "failed": fail_count,
104
+ "avg_response_ms": round(sum(all_times) / len(all_times) * 1000, 2) if all_times else 0,
105
+ "p95_ms": round(sorted_times[p95_idx] * 1000, 2) if sorted_times else 0,
106
+ "p99_ms": round(sorted_times[p99_idx] * 1000, 2) if sorted_times else 0,
107
+ "requests_per_sec": round(total_req / total_time, 2) if total_time > 0 else 0,
108
+ "error_rate": round((fail_count / total_req * 100), 2) if total_req > 0 else 0,
109
+ }
110
+
111
+ # Pass if error rate < 5%
112
+ if results["metrics"]["error_rate"] < 5:
113
+ results["passed"] = 1
114
+ else:
115
+ results["failed"] = 1
116
+
117
+ except Exception as e:
118
+ results["failed"] = 1
119
+ results["metrics"]["error"] = str(e)
120
+
121
+ return results
@@ -0,0 +1,128 @@
1
+ """
2
+ Performance Testing Engine - Load, stress, and benchmark testing
3
+ """
4
+
5
+ import time
6
+ import asyncio
7
+ from typing import Dict, List
8
+ from concurrent.futures import ThreadPoolExecutor
9
+ import threading
10
+
11
+
12
+ class PerformanceTestEngine:
13
+ """Performance, load, and stress testing"""
14
+
15
+ def __init__(self, settings, db, privacy):
16
+ self.settings = settings
17
+ self.db = db
18
+ self.privacy = privacy
19
+
20
+ def run_tests(self, target: str, concurrent_users: int = 10,
21
+ duration: int = 30, ramp_up: int = 5) -> Dict:
22
+ """Run performance tests"""
23
+ results = {"total": 0, "passed": 0, "failed": 0, "metrics": {}}
24
+
25
+ # Phase 1: Baseline Performance
26
+ baseline = self._test_baseline(target)
27
+ results["metrics"]["baseline"] = baseline
28
+
29
+ # Phase 2: Load Test
30
+ load = self._test_load(target, concurrent_users, duration)
31
+ results["metrics"]["load"] = load
32
+
33
+ # Phase 3: Stress Test
34
+ stress = self._test_stress(target, concurrent_users * 5)
35
+ results["metrics"]["stress"] = stress
36
+
37
+ # Phase 4: Spike Test
38
+ spike = self._test_spike(target, concurrent_users * 10)
39
+ results["metrics"]["spike"] = spike
40
+
41
+ # Calculate overall
42
+ results["total"] = 4
43
+ passed = sum(1 for k, v in results["metrics"].items() if v.get("status") == "pass")
44
+ results["passed"] = passed
45
+ results["failed"] = results["total"] - passed
46
+
47
+ if results["total"] > 0:
48
+ results["coverage"] = round((results["passed"] / results["total"]) * 100, 2)
49
+
50
+ return results
51
+
52
+ def _test_baseline(self, target: str) -> Dict:
53
+ """Test baseline response time"""
54
+ try:
55
+ import httpx
56
+
57
+ times = []
58
+ for _ in range(10):
59
+ start = time.time()
60
+ resp = httpx.get(target, timeout=10)
61
+ elapsed = time.time() - start
62
+ times.append(elapsed)
63
+
64
+ avg = sum(times) / len(times)
65
+ p95 = sorted(times)[int(len(times) * 0.95)]
66
+ p99 = sorted(times)[int(len(times) * 0.99)]
67
+
68
+ status = "pass" if avg < 2.0 else "fail"
69
+
70
+ return {
71
+ "avg_ms": round(avg * 1000, 2),
72
+ "p95_ms": round(p95 * 1000, 2),
73
+ "p99_ms": round(p99 * 1000, 2),
74
+ "min_ms": round(min(times) * 1000, 2),
75
+ "max_ms": round(max(times) * 1000, 2),
76
+ "status": status,
77
+ }
78
+ except Exception as e:
79
+ return {"status": "fail", "error": str(e)}
80
+
81
+ def _test_load(self, target: str, users: int, duration: int) -> Dict:
82
+ """Simulate concurrent load"""
83
+ try:
84
+ import httpx
85
+
86
+ results = {"success": 0, "failed": 0, "total_time": 0, "times": []}
87
+
88
+ def make_request(_):
89
+ try:
90
+ start = time.time()
91
+ resp = httpx.get(target, timeout=10)
92
+ elapsed = time.time() - start
93
+ return {"success": resp.status_code < 500, "time": elapsed}
94
+ except Exception:
95
+ return {"success": False, "time": 0}
96
+
97
+ with ThreadPoolExecutor(max_workers=users) as executor:
98
+ futures = [executor.submit(make_request, i) for i in range(users * 3)]
99
+
100
+ for future in futures:
101
+ result = future.result()
102
+ if result["success"]:
103
+ results["success"] += 1
104
+ else:
105
+ results["failed"] += 1
106
+ results["times"].append(result["time"])
107
+
108
+ total = results["success"] + results["failed"]
109
+ success_rate = (results["success"] / total * 100) if total > 0 else 0
110
+
111
+ status = "pass" if success_rate >= 95 else "fail"
112
+
113
+ return {
114
+ "total_requests": total,
115
+ "success_rate": round(success_rate, 2),
116
+ "avg_response_ms": round(sum(results["times"]) / len(results["times"]) * 1000, 2) if results["times"] else 0,
117
+ "status": status,
118
+ }
119
+ except Exception as e:
120
+ return {"status": "fail", "error": str(e)}
121
+
122
+ def _test_stress(self, target: str, users: int) -> Dict:
123
+ """Stress test with high concurrency"""
124
+ return self._test_load(target, users, 10)
125
+
126
+ def _test_spike(self, target: str, users: int) -> Dict:
127
+ """Spike test - sudden burst of requests"""
128
+ return self._test_load(target, users, 5)
@@ -0,0 +1,170 @@
1
+ """Security Testing Engine"""
2
+
3
+ from typing import Dict, List
4
+ import time
5
+
6
+
7
+ class SecurityTestEngine:
8
+ """Security and vulnerability testing"""
9
+
10
+ def __init__(self, settings, db, privacy):
11
+ self.settings = settings
12
+ self.db = db
13
+ self.privacy = privacy
14
+
15
+ def run_tests(self, target: str, scan_type: str = "basic") -> Dict:
16
+ """Run security tests"""
17
+ results = {"total": 0, "passed": 0, "failed": 0, "vulnerabilities": []}
18
+
19
+ # Test: SSL/TLS
20
+ results["total"] += 1
21
+ ssl_ok = self._check_ssl(target)
22
+ if ssl_ok:
23
+ results["passed"] += 1
24
+ else:
25
+ results["failed"] += 1
26
+ results["vulnerabilities"].append({"type": "SSL", "severity": "high", "detail": "SSL certificate issue"})
27
+
28
+ # Test: Security Headers
29
+ results["total"] += 1
30
+ headers_ok = self._check_security_headers(target)
31
+ if headers_ok:
32
+ results["passed"] += 1
33
+ else:
34
+ results["failed"] += 1
35
+ results["vulnerabilities"].append({"type": "Headers", "severity": "medium", "detail": "Missing security headers"})
36
+
37
+ # Test: Open Ports
38
+ results["total"] += 1
39
+ ports_ok = self._check_open_ports(target)
40
+ if ports_ok:
41
+ results["passed"] += 1
42
+ else:
43
+ results["failed"] += 1
44
+ results["vulnerabilities"].append({"type": "Ports", "severity": "medium", "detail": "Unexpected open ports"})
45
+
46
+ # Test: SQL Injection (basic)
47
+ results["total"] += 1
48
+ sqli_ok = self._check_sqli(target)
49
+ if sqli_ok:
50
+ results["passed"] += 1
51
+ else:
52
+ results["failed"] += 1
53
+ results["vulnerabilities"].append({"type": "SQLi", "severity": "critical", "detail": "Possible SQL injection"})
54
+
55
+ # Test: XSS (basic)
56
+ results["total"] += 1
57
+ xss_ok = self._check_xss(target)
58
+ if xss_ok:
59
+ results["passed"] += 1
60
+ else:
61
+ results["failed"] += 1
62
+ results["vulnerabilities"].append({"type": "XSS", "severity": "high", "detail": "Possible XSS vulnerability"})
63
+
64
+ # Test: CORS Configuration
65
+ results["total"] += 1
66
+ cors_ok = self._check_cors(target)
67
+ if cors_ok:
68
+ results["passed"] += 1
69
+ else:
70
+ results["failed"] += 1
71
+ results["vulnerabilities"].append({"type": "CORS", "severity": "medium", "detail": "Overly permissive CORS"})
72
+
73
+ if results["total"] > 0:
74
+ results["coverage"] = round((results["passed"] / results["total"]) * 100, 2)
75
+
76
+ return results
77
+
78
+ def _check_ssl(self, target: str) -> bool:
79
+ """Check SSL/TLS configuration"""
80
+ try:
81
+ import ssl
82
+ import socket
83
+
84
+ hostname = target.replace("http://", "").replace("https://", "").split("/")[0].split(":")[0]
85
+ context = ssl.create_default_context()
86
+
87
+ with socket.create_connection((hostname, 443), timeout=5) as sock:
88
+ with context.wrap_socket(sock, server_hostname=hostname) as ssock:
89
+ cert = ssock.getpeercert()
90
+ return cert is not None
91
+ except Exception:
92
+ return False
93
+
94
+ def _check_security_headers(self, target: str) -> bool:
95
+ """Check for security headers"""
96
+ try:
97
+ import httpx
98
+ resp = httpx.get(target, timeout=10)
99
+
100
+ required = ["x-content-type-options", "x-frame-options"]
101
+ present = sum(1 for h in required if h in resp.headers)
102
+ return present >= 1
103
+ except Exception:
104
+ return False
105
+
106
+ def _check_open_ports(self, target: str) -> bool:
107
+ """Check for unexpected open ports"""
108
+ try:
109
+ import socket
110
+ hostname = target.replace("http://", "").replace("https://", "").split("/")[0].split(":")[0]
111
+
112
+ dangerous_ports = [21, 23, 3389, 5900] # FTP, Telnet, RDP, VNC
113
+ open_dangerous = []
114
+
115
+ for port in dangerous_ports:
116
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
117
+ sock.settimeout(2)
118
+ result = sock.connect_ex((hostname, port))
119
+ sock.close()
120
+ if result == 0:
121
+ open_dangerous.append(port)
122
+
123
+ return len(open_dangerous) == 0
124
+ except Exception:
125
+ return True # Assume safe if can't check
126
+
127
+ def _check_sqli(self, target: str) -> bool:
128
+ """Basic SQL injection check"""
129
+ try:
130
+ import httpx
131
+ # Test with common SQL injection payloads
132
+ payloads = ["' OR 1=1 --", "'; DROP TABLE users --"]
133
+
134
+ for payload in payloads:
135
+ resp = httpx.get(f"{target}?id={payload}", timeout=10)
136
+ # Check for SQL error messages in response
137
+ sql_errors = ["sql", "syntax", "mysql", "postgres", "sqlite", "oracle"]
138
+ content = resp.text.lower()
139
+ if any(err in content for err in sql_errors):
140
+ return False
141
+
142
+ return True
143
+ except Exception:
144
+ return True
145
+
146
+ def _check_xss(self, target: str) -> bool:
147
+ """Basic XSS check"""
148
+ try:
149
+ import httpx
150
+ payload = "<script>alert('xss')</script>"
151
+ resp = httpx.get(f"{target}?q={payload}", timeout=10)
152
+
153
+ # If payload is reflected without encoding, potential XSS
154
+ if payload in resp.text:
155
+ return False
156
+ return True
157
+ except Exception:
158
+ return True
159
+
160
+ def _check_cors(self, target: str) -> bool:
161
+ """Check CORS configuration"""
162
+ try:
163
+ import httpx
164
+ resp = httpx.options(target, headers={"Origin": "http://evil.com"}, timeout=10)
165
+ cors = resp.headers.get("access-control-allow-origin", "")
166
+
167
+ # Should not allow all origins
168
+ return cors != "*"
169
+ except Exception:
170
+ return True
@@ -0,0 +1 @@
1
+ """Web testing engines"""