140 lines
5.5 KiB
Python
140 lines
5.5 KiB
Python
|
|
# -*- coding: utf-8 -*-
|
||
|
|
"""Tests für Praxis-Beitritt / Erststart-Onboarding."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import os
|
||
|
|
import sqlite3
|
||
|
|
import unittest
|
||
|
|
|
||
|
|
|
||
|
|
class TestPracticeJoinHelpers(unittest.TestCase):
|
||
|
|
def test_normalize_invite_code(self):
|
||
|
|
from aza_practice_join_helpers import normalize_invite_code
|
||
|
|
self.assertEqual(normalize_invite_code(" chat-abcd-efgh "), "CHAT-ABCD-EFGH")
|
||
|
|
|
||
|
|
def test_should_show_dialog_without_practice(self):
|
||
|
|
from aza_practice_join_helpers import should_show_connect_practice_dialog
|
||
|
|
self.assertTrue(should_show_connect_practice_dialog({}))
|
||
|
|
self.assertTrue(should_show_connect_practice_dialog({"practice_id": ""}))
|
||
|
|
self.assertFalse(should_show_connect_practice_dialog({"practice_id": "prac_abc"}))
|
||
|
|
|
||
|
|
def test_provision_payload_includes_pending_invite(self):
|
||
|
|
from aza_practice_join_helpers import build_empfang_provision_payload
|
||
|
|
prof = {
|
||
|
|
"name": "Dr. Test",
|
||
|
|
"email": "test@example.com",
|
||
|
|
"pending_chat_invite_code": "CHAT-ABCD-1234",
|
||
|
|
}
|
||
|
|
payload = build_empfang_provision_payload(prof)
|
||
|
|
self.assertIsNotNone(payload)
|
||
|
|
self.assertEqual(payload.get("invite_code"), "CHAT-ABCD-1234")
|
||
|
|
self.assertNotIn("practice_id", payload)
|
||
|
|
|
||
|
|
def test_provision_payload_no_invite_without_pending(self):
|
||
|
|
from aza_practice_join_helpers import build_empfang_provision_payload
|
||
|
|
prof = {"name": "Dr. Test", "email": "test@example.com"}
|
||
|
|
payload = build_empfang_provision_payload(prof)
|
||
|
|
self.assertIsNotNone(payload)
|
||
|
|
self.assertNotIn("invite_code", payload)
|
||
|
|
|
||
|
|
def test_apply_join_response_updates_profile(self):
|
||
|
|
from aza_practice_join_helpers import apply_join_existing_practice_response
|
||
|
|
prof = {
|
||
|
|
"practice_id": "",
|
||
|
|
"pending_chat_invite_code": "CHAT-XXXX-YYYY",
|
||
|
|
"license_key": "AZA-TEST",
|
||
|
|
}
|
||
|
|
resp = {
|
||
|
|
"practice_id": "prac_target",
|
||
|
|
"user_id": "u_join_1",
|
||
|
|
"display_name": "Dr. Neu",
|
||
|
|
}
|
||
|
|
out, changed = apply_join_existing_practice_response(prof, resp)
|
||
|
|
self.assertTrue(changed)
|
||
|
|
self.assertEqual(out["practice_id"], "prac_target")
|
||
|
|
self.assertEqual(out["empfang_user_id"], "u_join_1")
|
||
|
|
self.assertEqual(out["empfang_display_name"], "Dr. Neu")
|
||
|
|
self.assertNotIn("pending_chat_invite_code", out)
|
||
|
|
|
||
|
|
def test_apply_join_invalid_response_unchanged(self):
|
||
|
|
from aza_practice_join_helpers import apply_join_existing_practice_response
|
||
|
|
prof = {"practice_id": "prac_old", "license_key": "X"}
|
||
|
|
out, changed = apply_join_existing_practice_response(prof, {})
|
||
|
|
self.assertFalse(changed)
|
||
|
|
self.assertEqual(out["practice_id"], "prac_old")
|
||
|
|
|
||
|
|
|
||
|
|
class TestPracticeJoinBackend(unittest.TestCase):
|
||
|
|
def test_resolve_invite_lookup(self):
|
||
|
|
from empfang_routes import (
|
||
|
|
_generate_chat_invite_code,
|
||
|
|
_invite_code_key,
|
||
|
|
_load_practices,
|
||
|
|
_lookup_practice_id_by_invite,
|
||
|
|
_save_practices,
|
||
|
|
)
|
||
|
|
import empfang_routes as er
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
orig = er._PRACTICES_FILE
|
||
|
|
try:
|
||
|
|
import tempfile
|
||
|
|
td = tempfile.mkdtemp()
|
||
|
|
er._PRACTICES_FILE = Path(td) / "practices.json"
|
||
|
|
code = _generate_chat_invite_code()
|
||
|
|
pid = "prac_test_join_001"
|
||
|
|
_save_practices({
|
||
|
|
pid: {
|
||
|
|
"practice_id": pid,
|
||
|
|
"name": "Testpraxis Join",
|
||
|
|
"invite_code": code,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
found = _lookup_practice_id_by_invite(code)
|
||
|
|
self.assertEqual(found, pid)
|
||
|
|
self.assertEqual(_invite_code_key(code), _invite_code_key(code.lower()))
|
||
|
|
finally:
|
||
|
|
er._PRACTICES_FILE = orig
|
||
|
|
|
||
|
|
def test_join_existing_requires_join_mode(self):
|
||
|
|
path = os.path.join(os.path.dirname(__file__), "backend_main.py")
|
||
|
|
with open(path, encoding="utf-8") as fh:
|
||
|
|
src = fh.read()
|
||
|
|
self.assertIn('@app.post("/license/join_existing_practice")', src)
|
||
|
|
self.assertIn("join_mode muss", src)
|
||
|
|
|
||
|
|
def test_device_capacity_stacks_per_license(self):
|
||
|
|
from aza_device_enforcement import DEVICES_PER_LICENSE_FLOOR
|
||
|
|
self.assertEqual(DEVICES_PER_LICENSE_FLOOR, 2)
|
||
|
|
|
||
|
|
|
||
|
|
class TestPracticeJoinUIWiring(unittest.TestCase):
|
||
|
|
def test_connect_dialog_has_ab_choice(self):
|
||
|
|
path = os.path.join(os.path.dirname(__file__), "basis14.py")
|
||
|
|
with open(path, encoding="utf-8") as fh:
|
||
|
|
src = fh.read()
|
||
|
|
block = src.split("def _show_connect_practice_dialog", 1)[-1].split("\n def ", 1)[0]
|
||
|
|
self.assertIn("Neue Praxis / eigene Praxis", block)
|
||
|
|
self.assertIn("Bestehender Praxis beitreten", block)
|
||
|
|
self.assertIn("resolve_invite", block)
|
||
|
|
self.assertIn("aza_practice_join_helpers", block)
|
||
|
|
|
||
|
|
def test_settings_join_uses_license_endpoint(self):
|
||
|
|
path = os.path.join(os.path.dirname(__file__), "basis14.py")
|
||
|
|
with open(path, encoding="utf-8") as fh:
|
||
|
|
src = fh.read()
|
||
|
|
self.assertIn("/license/join_existing_practice", src)
|
||
|
|
self.assertIn("apply_join_existing_practice_response", src)
|
||
|
|
|
||
|
|
def test_admin_control_has_codes_tab(self):
|
||
|
|
path = os.path.join(os.path.dirname(__file__), "aza_admin_control_shell.py")
|
||
|
|
with open(path, encoding="utf-8") as fh:
|
||
|
|
src = fh.read()
|
||
|
|
self.assertIn("Codes / Verbindungen", src)
|
||
|
|
self.assertIn("invite_code", src)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
unittest.main()
|