Tests: Reorganize test suite into functional subdirectories
- Categorized scripts into tests/unit/, tests/integration/, tests/e2e/, and tests/tools/. - Adopted consistent naming prefixes (test_unit_*, test_int_*, test_e2e_*, tool_*). - Renamed conftest_mock.py to mock_config_helper.py for clarity. - Updated test_int_boot_diagnosis.py with sys.path setup for root-level execution.
This commit is contained in:
57
tests/integration/test_int_boot_diagnosis.py
Normal file
57
tests/integration/test_int_boot_diagnosis.py
Normal file
@@ -0,0 +1,57 @@
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add project root to path
|
||||
sys.path.append(os.getcwd())
|
||||
|
||||
print("--- Starting Import Diagnosis ---")
|
||||
|
||||
try:
|
||||
print("1. Importing app.config...")
|
||||
from app import config
|
||||
print(f" Success. Settings found: {hasattr(config, 'settings')}")
|
||||
except Exception as e:
|
||||
print(f" FAILED: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
print("2. Importing app.log...")
|
||||
import app.log
|
||||
print(" Success.")
|
||||
except Exception as e:
|
||||
print(f" FAILED: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
print("3. Importing app.db_connection...")
|
||||
import app.db_connection
|
||||
print(" Success.")
|
||||
except Exception as e:
|
||||
print(f" FAILED: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
print("4. Importing app.db_sql...")
|
||||
import app.db_sql
|
||||
print(" Success.")
|
||||
except Exception as e:
|
||||
print(f" FAILED: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
print("5. Importing app.main...")
|
||||
import app.main
|
||||
print(" Success.")
|
||||
except Exception as e:
|
||||
print(f" FAILED: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
print("--- Diagnosis Complete: No top-level import errors found in local env ---")
|
||||
46
tests/integration/test_int_db_connectivity.py
Normal file
46
tests/integration/test_int_db_connectivity.py
Normal file
@@ -0,0 +1,46 @@
|
||||
import sqlalchemy
|
||||
from sqlalchemy import text
|
||||
import json
|
||||
|
||||
# Connection details from .env
|
||||
DB_USER = "aether_dev"
|
||||
DB_PASS = "$1sky.AE_dev.2023"
|
||||
DB_SERVER = "vpn-db.oneskyit.com"
|
||||
DB_PORT = "3306"
|
||||
DB_NAME = "aether_dev"
|
||||
|
||||
# Construct URI
|
||||
DB_URI = f"mysql://{DB_USER}:{DB_PASS}@{DB_SERVER}:{DB_PORT}/{DB_NAME}"
|
||||
|
||||
def test_raw_describe():
|
||||
engine = sqlalchemy.create_engine(DB_URI)
|
||||
print(f"Connecting to {DB_SERVER}...")
|
||||
|
||||
try:
|
||||
with engine.connect() as conn:
|
||||
result = conn.execute(text("DESCRIBE journal"))
|
||||
columns = []
|
||||
for row in result.fetchall():
|
||||
columns.append({
|
||||
"Field": row[0],
|
||||
"Type": row[1],
|
||||
"Null": row[2],
|
||||
"Default": row[4]
|
||||
})
|
||||
|
||||
# Print as a nice JSON snippet
|
||||
print("\n--- Raw DB Metadata for 'journal' (Sample) ---")
|
||||
print(json.dumps(columns[:5], indent=2))
|
||||
|
||||
# Highlight the specific fields mentioned in the task
|
||||
print("\n--- Target Fields ---")
|
||||
targets = ["name", "enable", "passcode_timeout", "created_on"]
|
||||
for col in columns:
|
||||
if col["Field"] in targets:
|
||||
print(f"Field: {col['Field']:16} | Type: {col['Type']:15} | Null: {col['Null']:3} | Default: {col['Default']}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_raw_describe()
|
||||
29
tests/integration/test_int_email_live.py
Normal file
29
tests/integration/test_int_email_live.py
Normal file
@@ -0,0 +1,29 @@
|
||||
import sys
|
||||
import os
|
||||
import logging
|
||||
|
||||
# Add current directory to path
|
||||
sys.path.append(os.getcwd())
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
try:
|
||||
from app.lib_email import send_email
|
||||
print("Successfully imported send_email.")
|
||||
|
||||
print("Running send_email in TEST mode...")
|
||||
result = send_email(
|
||||
from_email="test@example.com",
|
||||
to_email="test@example.com",
|
||||
subject="Test Email",
|
||||
body_html="<p>Test</p>",
|
||||
test=True
|
||||
)
|
||||
|
||||
print(f"Result: {result}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during email test: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
36
tests/integration/test_int_import_verification.py
Normal file
36
tests/integration/test_int_import_verification.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add current directory to path
|
||||
sys.path.append(os.getcwd())
|
||||
|
||||
print("Attempting to import app.lib_general_v3...")
|
||||
try:
|
||||
import app.lib_general_v3
|
||||
print("Success: app.lib_general_v3")
|
||||
except Exception as e:
|
||||
print(f"Failed: app.lib_general_v3 - {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
print("-" * 20)
|
||||
|
||||
print("Attempting to import app.routers.api_crud_v3...")
|
||||
try:
|
||||
import app.routers.api_crud_v3
|
||||
print("Success: app.routers.api_crud_v3")
|
||||
except Exception as e:
|
||||
print(f"Failed: app.routers.api_crud_v3 - {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
print("-" * 20)
|
||||
|
||||
print("Attempting to import app.routers.agent_bridge...")
|
||||
try:
|
||||
import app.routers.agent_bridge
|
||||
print("Success: app.routers.agent_bridge")
|
||||
except Exception as e:
|
||||
print(f"Failed: app.routers.agent_bridge - {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
56
tests/integration/test_int_schema_v3.py
Normal file
56
tests/integration/test_int_schema_v3.py
Normal file
@@ -0,0 +1,56 @@
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import sqlalchemy
|
||||
from sqlalchemy import text
|
||||
|
||||
# Add current directory to path
|
||||
sys.path.append(os.getcwd())
|
||||
|
||||
# MUST BE FIRST: Mock app.config
|
||||
import tests.mock_config_helper
|
||||
|
||||
# Connection details from .env (Bypassing app.config)
|
||||
DB_USER = "aether_dev"
|
||||
DB_PASS = "$1sky.AE_dev.2023"
|
||||
DB_SERVER = "vpn-db.oneskyit.com"
|
||||
DB_PORT = "3306"
|
||||
DB_NAME = "aether_dev"
|
||||
DB_URI = f"mysql://{DB_USER}:{DB_PASS}@{DB_SERVER}:{DB_PORT}/{DB_NAME}"
|
||||
|
||||
# Mock the db object before importing lib_schema_v3
|
||||
from app.db_sql import db
|
||||
db.engine = sqlalchemy.create_engine(DB_URI)
|
||||
|
||||
from app.lib_schema_v3 import get_object_schema_info
|
||||
|
||||
def verify_enhanced_schema():
|
||||
print("Testing enhanced get_object_schema_info for 'journal'...")
|
||||
try:
|
||||
info = get_object_schema_info("journal")
|
||||
|
||||
if "error" in info:
|
||||
print(f"Error: {info['error']}")
|
||||
return
|
||||
|
||||
cols = info["database"]["columns"]
|
||||
targets = ["name", "enable", "passcode_timeout", "created_on"]
|
||||
|
||||
print("\n--- Verified Enhanced Metadata ---")
|
||||
for col in cols:
|
||||
if col["field"] in targets:
|
||||
print(f"Field: {col['field']:16} | DB Type: {col['db_type']:15} | Required: {str(col['required']):5} | Default: {col['db_default']}")
|
||||
|
||||
# Basic check to ensure new keys exist
|
||||
assert "db_type" in cols[0]
|
||||
assert "required" in cols[0]
|
||||
assert "db_default" in cols[0]
|
||||
print("\nSuccess: New schema keys are present and populated.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Test failed: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
if __name__ == "__main__":
|
||||
verify_enhanced_schema()
|
||||
50
tests/integration/test_int_v3_auth_security.py
Normal file
50
tests/integration/test_int_v3_auth_security.py
Normal file
@@ -0,0 +1,50 @@
|
||||
|
||||
import sys
|
||||
import os
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
# Add the project root to sys.path so we can import 'app'
|
||||
sys.path.append(os.getcwd())
|
||||
|
||||
from app.main import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
def test_site_domain_unauthenticated_search():
|
||||
"""Test that searching site_domain works without authentication."""
|
||||
print("Testing unauthenticated site_domain search...")
|
||||
# Using a simple search query that would typically be used to resolve FQDN
|
||||
search_payload = {
|
||||
"and_filters": [
|
||||
{"field": "fqdn", "op": "eq", "value": "aether.osit.dev"}
|
||||
]
|
||||
}
|
||||
response = client.post("/v3/crud/site_domain/search", json=search_payload)
|
||||
print(f"Response Status: {response.status_code}")
|
||||
print(f"Response Body: {response.json()}")
|
||||
|
||||
# We expect 200 OK (even if empty results, the point is it's not 403)
|
||||
assert response.status_code == 200
|
||||
assert response.json()["status"] == "success"
|
||||
|
||||
def test_account_unauthenticated_search_blocked():
|
||||
"""Test that searching other objects (e.g., account) is blocked without authentication."""
|
||||
print("\nTesting unauthenticated account search (should be blocked)...")
|
||||
search_payload = {
|
||||
"and_filters": []
|
||||
}
|
||||
response = client.post("/v3/crud/account/search", json=search_payload)
|
||||
print(f"Response Status: {response.status_code}")
|
||||
|
||||
# We expect 403 Forbidden
|
||||
assert response.status_code == 403
|
||||
assert "Authentication required" in response.json()["status_message"]
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
test_site_domain_unauthenticated_search()
|
||||
test_account_unauthenticated_search_blocked()
|
||||
print("\nSUCCESS: V3 Auth Isolation bypass for site_domain is working correctly.")
|
||||
except Exception as e:
|
||||
print(f"\nFAILURE: {e}")
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user