initial project commit

This commit is contained in:
georg.sinn-schirwitz
2025-08-29 15:07:58 +02:00
parent 38708e6d1d
commit 23a67d7fe1
31 changed files with 3433 additions and 0 deletions

7
tests/conftest.py Normal file
View File

@@ -0,0 +1,7 @@
import sys
from pathlib import Path
# Ensure project root is on sys.path so `web` package can be imported
root = Path(__file__).resolve().parents[1]
if str(root) not in sys.path:
sys.path.insert(0, str(root))

View File

@@ -0,0 +1,152 @@
import os
import time
from datetime import datetime, timezone
import pytest
import web.db as db
from web.utils import now_iso
# Skip this entire test module unless explicitly enabled and DB is reachable
if not os.getenv("RUN_DB_TESTS"):
pytest.skip("Set RUN_DB_TESTS=1 to run MySQL integration tests",
allow_module_level=True)
@pytest.fixture(scope="module")
def db_ready():
try:
db.db_init()
return True
except Exception as e:
pytest.skip(f"MySQL DB not reachable or init failed: {e}")
def unique_suffix() -> str:
# Time-based unique suffix for test records
return datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S%f")
def test_user_create_and_auth(db_ready):
uname = f"it_user_{unique_suffix()}"
pw = "P@ssw0rd!"
uid = db.create_or_update_user(
uname, password=pw, is_admin=False, is_active=True)
assert isinstance(uid, int)
assert db.verify_user_credentials(uname, pw) is True
assert db.verify_user_credentials(uname, "wrong") is False
def test_regions_keywords_upsert_and_list(db_ready):
rname = f"it_region_{unique_suffix()}"
kname = f"it_keyword_{unique_suffix()}"
rid = db.upsert_region(rname)
kid = db.upsert_keyword(kname)
assert isinstance(rid, int) and rid > 0
assert isinstance(kid, int) and kid > 0
regions = db.get_all_regions()
keywords = db.get_all_keywords()
assert rname in regions
assert kname in keywords
def test_user_preferences_roundtrip(db_ready):
uname = f"it_pref_user_{unique_suffix()}"
db.create_or_update_user(uname, is_active=True)
r1, r2 = f"it_r1_{unique_suffix()}", f"it_r2_{unique_suffix()}"
k1, k2 = f"it_k1_{unique_suffix()}", f"it_k2_{unique_suffix()}"
# Set preferences (upserts regions/keywords internally if missing)
db.set_user_regions(uname, [r1, r2])
db.set_user_keywords(uname, [k1, k2])
assert set(db.get_user_regions(uname)) >= {r1, r2}
assert set(db.get_user_keywords(uname)) >= {k1, k2}
def test_upsert_listing_details_and_urls(db_ready):
# Create a unique URL
jid_suffix = unique_suffix()
url = f"https://example.org/it/{jid_suffix}.html"
db.upsert_listing(
url=url,
region="it",
keyword="integration",
title=f"IT Listing {jid_suffix}",
pay="N/A",
location="Test City",
timestamp=now_iso(),
)
job_data = {
"url": url,
"title": f"IT Job {jid_suffix}",
"company": "Acme Corp",
"location": "Test City",
"description": "A test job for integration",
"id": jid_suffix, # normalize_job_id should use this or fall back to URL
"posted_time": now_iso(),
}
db.upsert_job_details(job_data)
urls = db.db_get_all_job_urls()
assert url in urls
# Cleanup (best-effort)
try:
db.db_delete_job(jid_suffix)
except Exception:
pass
def test_cached_page_upsert_and_get(db_ready):
jid_suffix = unique_suffix()
url = f"https://example.org/it/{jid_suffix}.html"
# Ensure a listing exists for FK relation if enforced
db.upsert_listing(
url=url,
region="it",
keyword="cache",
title=f"IT Cache {jid_suffix}",
pay="N/A",
location="Test City",
timestamp=now_iso(),
)
fp = f"/tmp/integration_{jid_suffix}.html"
db.upsert_cached_page(
file_path=fp,
url_guess=url,
last_modified=now_iso(),
size_bytes=123,
job_id=int(jid_suffix) if jid_suffix.isdigit() else None,
)
row = db.db_get_cache_url(url)
if row is not None:
assert row["url_guess"] == url
# Cleanup
try:
db.remove_cached_page(fp)
db.db_remove_cached_url(url)
db.db_delete_job(jid_suffix)
except Exception:
pass
def test_user_interactions_mark_and_visit(db_ready):
uname = f"it_user_{unique_suffix()}"
db.create_or_update_user(uname, is_active=True)
jid_suffix = unique_suffix()
url = f"https://example.org/it/{jid_suffix}.html"
db.upsert_listing(
url=url,
region="it",
keyword="interact",
title=f"IT Interact {jid_suffix}",
pay="N/A",
location="Test City",
timestamp=now_iso(),
)
# Exercise helpers — absence of exceptions is success for integration
db.mark_favorite(jid_suffix, uname, True)
db.record_visit(jid_suffix, uname, url=url)
# Cleanup
try:
db.db_delete_job(jid_suffix)
except Exception:
pass

19
tests/test_users.py Normal file
View File

@@ -0,0 +1,19 @@
import pytest
from web.db import db_init, create_or_update_user, verify_user_credentials, get_users
from web.utils import initialize_users_from_settings
def test_initialize_users_from_settings():
db_init()
n = initialize_users_from_settings()
assert n >= 1 # should at least add 'anonymous'
users = get_users()
assert any(u['username'] == 'anonymous' for u in users)
def test_create_and_auth_user():
db_init()
create_or_update_user('testuser', password='secret',
is_admin=True, is_active=True)
assert verify_user_credentials('testuser', 'secret') is True
assert verify_user_credentials('testuser', 'wrong') is False

View File

@@ -0,0 +1,18 @@
import importlib
import os
import web.utils as utils
def test_config_loaded():
cfg = utils.get_config()
assert isinstance(cfg, dict)
def test_http_settings_helpers():
assert isinstance(utils.get_user_agent(), str)
assert isinstance(utils.get_request_timeout(), int)
assert isinstance(utils.get_max_retries(), int)
assert isinstance(utils.get_backoff_factor(), int)
assert isinstance(utils.get_min_delay(), int)
assert isinstance(utils.get_max_delay(), int)