Migrate all repos into monorepo context folders

Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
      Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
      Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)

Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
This commit is contained in:
2026-06-30 20:39:52 +02:00
parent 2f2b295531
commit a5f8fb49ab
1717 changed files with 447332 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
"""Shared test fixtures for OrgMyLife tests.
Provides:
- Fresh in-memory SQLite DB per test session (avoids stale schema issues)
- Authenticated test client (bypasses session auth via API_SECRET)
"""
import os
import pytest
# Set API_SECRET before importing app so verify_session accepts Bearer token
os.environ["API_SECRET"] = "test-secret"
os.environ["DATABASE_URL"] = "sqlite:///./test_orgmylife.db"
from fastapi.testclient import TestClient
from app.db.session import Base, engine, SessionLocal
from app.main import app
@pytest.fixture(autouse=True)
def fresh_db():
"""Drop and recreate all tables for each test to avoid schema drift."""
Base.metadata.drop_all(bind=engine)
Base.metadata.create_all(bind=engine)
yield
Base.metadata.drop_all(bind=engine)
@pytest.fixture
def client():
"""Authenticated test client with Bearer token."""
c = TestClient(app)
c.headers["Authorization"] = "Bearer test-secret"
return c
@pytest.fixture
def db():
"""Database session for direct DB assertions."""
session = SessionLocal()
yield session
session.close()
+118
View File
@@ -0,0 +1,118 @@
"""Tests for email_sync and nextcloud_sync service logic (with mocks)."""
import pytest
from unittest.mock import MagicMock, patch
from email.mime.text import MIMEText
import email as email_lib
from app.services.email_sync import (
_decode_header_value,
_get_body_snippet,
LABEL_TODO,
LABEL_DONE,
)
# ---------------------------------------------------------------------------
# email_sync unit tests
# ---------------------------------------------------------------------------
def test_decode_header_value_plain():
assert _decode_header_value("Hello World") == "Hello World"
def test_decode_header_value_encoded():
encoded = "=?utf-8?b?SGVsbG8gV29ybGQ=?=" # "Hello World" base64
assert _decode_header_value(encoded) == "Hello World"
def test_decode_header_value_none():
assert _decode_header_value(None) == ""
def test_get_body_snippet_plain():
msg = MIMEText("This is the email body content.")
result = _get_body_snippet(email_lib.message_from_string(msg.as_string()))
assert "This is the email body content." in result
def test_get_body_snippet_truncated():
long_body = "A" * 500
msg = MIMEText(long_body)
result = _get_body_snippet(email_lib.message_from_string(msg.as_string()), max_chars=100)
assert len(result) <= 100
def test_sync_emails_creates_task():
"""sync_emails() should create a Task for each untracked inbox email."""
from app.db.session import SessionLocal
from app.models import Task
# Build a fake raw email bytes
raw_msg = MIMEText("Task body snippet")
raw_msg["Subject"] = "Do the important thing"
raw_msg["From"] = "sender@example.com"
raw_msg["Message-ID"] = "<test-email-001@example.com>"
raw_bytes = raw_msg.as_bytes()
mock_conn = MagicMock()
mock_conn.uid.side_effect = [
# SEARCH call
("OK", [b"1"]),
# FETCH call
("OK", [(b"1 (RFC822 {123})", raw_bytes)]),
# STORE (apply label) call
("OK", []),
]
with patch("app.services.email_sync._get_imap_connection", return_value=mock_conn):
from app.services.email_sync import sync_emails
result = sync_emails()
assert result is True
db = SessionLocal()
task = db.query(Task).filter(Task.source_id == "<test-email-001@example.com>").first()
assert task is not None
assert task.title == "Do the important thing"
assert task.origin == "dhive_email"
db.delete(task)
db.commit()
db.close()
def test_mark_email_done_and_archive():
"""mark_email_done_and_archive() should swap labels and copy to Archive."""
mock_conn = MagicMock()
# SEARCH returns one UID
mock_conn.uid.side_effect = [
("OK", [b"42"]), # SEARCH
("OK", []), # STORE remove todo
("OK", []), # STORE add done
("OK", []), # COPY to archive
("OK", []), # STORE add \Deleted
]
mock_conn.expunge.return_value = ("OK", [])
with patch("app.services.email_sync._get_imap_connection", return_value=mock_conn):
from app.services.email_sync import mark_email_done_and_archive
result = mark_email_done_and_archive("<test-email-001@example.com>")
assert result is True
# ---------------------------------------------------------------------------
# nextcloud_sync unit tests
# ---------------------------------------------------------------------------
def test_update_remote_todo_not_found():
"""update_remote_todo() should return False when UID not found in any calendar."""
mock_principal = MagicMock()
mock_calendar = MagicMock()
mock_principal.calendars.return_value = [mock_calendar]
mock_calendar.todos.return_value = [] # no todos
with patch("app.services.nextcloud_sync._get_caldav_principal", return_value=mock_principal):
from app.services.nextcloud_sync import update_remote_todo
result = update_remote_todo("nonexistent-uid", {"status": "completed"})
assert result is False
+33
View File
@@ -0,0 +1,33 @@
"""Tests for task CRUD API endpoints."""
from app.models import Task
def test_update_task(client, db):
"""Create a task, update it, verify changes persisted."""
# 1. Create a task
response = client.post("/api/tasks", json={
"title": "Initial Task",
"description": "Initial description",
"priority": 3
})
assert response.status_code == 200
task_id = response.json()["task_id"]
# 2. Update title, description, and priority
update_data = {
"title": "Updated Task",
"description": "Updated description",
"priority": 1
}
response = client.put(f"/api/tasks/{task_id}", json=update_data)
# 3. Assert success
assert response.status_code == 200
assert response.json()["status"] == "success"
# 4. Verify in DB
task = db.query(Task).filter(Task.id == task_id).first()
assert task.title == "Updated Task"
assert task.description == "Updated description"
assert task.priority == 1