bdf9e3c59e
- Move integration tests to tests/; fix .gitignore to scope root-only
- Remove tracked debug artefacts (probe2_stderr/stdout.txt)
- __init__.py: version via importlib.metadata; export create_server in __all__
- server.py: unified JSON error format {"error":"..."} for all tools
- server.py: date validation (YYYY-MM-DD) for all meal-plan tools
- server.py: clear_list reports partial failures (failed_count, failed_ids)
- server.py: -> str annotations on get_circles, get_tasks, get_activities
- server.py: document TODO:94 as known limitation (no name in sortingIndexByTaskList)
- server.py: date validation also added to get_meal_plan
- Add LICENSE (MIT, Marcus van Elst)
- Add CHANGELOG.md (Keep a Changelog, v0.1.0–v1.0.0)
- README.md: restructured by use case; 🔒 marks write tools
- CLAUDE.md: update to v1.0.0 state; condense roadmap history
- SPEC.md: add version stamp
- pyproject.toml: version 1.0.0 (single source of truth)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
99 lines
3.5 KiB
Python
99 lines
3.5 KiB
Python
"""Integration test for emoji + color in get_lists / create_list (v0.5.1)."""
|
|
import sys, json
|
|
sys.path.insert(0, "src")
|
|
|
|
import keyring
|
|
class _K:
|
|
def get_password(self, s, k): return {"email": "marcus@gecheckt.de", "password": "Lasdas1234"}.get(k)
|
|
keyring.get_password = _K().get_password
|
|
|
|
from mcp_familywall.server import create_list, delete_list, get_lists
|
|
|
|
errors = []
|
|
|
|
def log(msg):
|
|
sys.stdout.buffer.write((str(msg) + "\n").encode("utf-8"))
|
|
|
|
def check(label, result, **expect):
|
|
try:
|
|
obj = json.loads(result)
|
|
except Exception:
|
|
errors.append(f"FAIL [{label}]: not JSON -- {result!r}")
|
|
return None
|
|
for k, v in expect.items():
|
|
if obj.get(k) != v:
|
|
errors.append(f"FAIL [{label}]: {k}={obj.get(k)!r}, expected {v!r}")
|
|
return None
|
|
log(f"OK [{label}]: {dict((k, obj.get(k)) for k in expect)}")
|
|
return obj
|
|
|
|
# --- Test 1: create with emoji + color ---
|
|
r1 = create_list("__test_emoji__", "TODOS", emoji="\U0001F331", color="#E53935")
|
|
log(f"create with emoji+color = {r1}")
|
|
o1 = check("create_emoji_color", r1, created=True, emoji="\U0001F331", color="#E53935")
|
|
id1 = o1["id"] if o1 else None
|
|
|
|
# --- Test 2: create without emoji/color ---
|
|
r2 = create_list("__test_plain__", "SHOPPING_LIST")
|
|
log(f"create plain = {r2}")
|
|
o2 = check("create_plain", r2, created=True, emoji=None, color=None)
|
|
id2 = o2["id"] if o2 else None
|
|
|
|
# --- Test 3: get_lists shows emoji + color ---
|
|
lists_json = get_lists()
|
|
try:
|
|
all_lists = json.loads(lists_json)
|
|
by_id = {l["id"]: l for l in all_lists}
|
|
|
|
if id1 and id1 in by_id:
|
|
l = by_id[id1]
|
|
if l.get("emoji") == "\U0001F331" and l.get("color") == "#E53935":
|
|
log(f"OK [get_lists emoji+color]: emoji={l['emoji']!r} color={l['color']!r}")
|
|
else:
|
|
errors.append(f"FAIL [get_lists emoji+color]: emoji={l.get('emoji')!r} color={l.get('color')!r}")
|
|
elif id1:
|
|
errors.append(f"FAIL [get_lists emoji+color]: {id1} not in lists")
|
|
|
|
if id2 and id2 in by_id:
|
|
l = by_id[id2]
|
|
if l.get("emoji") is None and l.get("color") is None:
|
|
log(f"OK [get_lists plain]: emoji={l.get('emoji')!r} color={l.get('color')!r}")
|
|
else:
|
|
errors.append(f"FAIL [get_lists plain]: emoji={l.get('emoji')!r} color={l.get('color')!r}")
|
|
elif id2:
|
|
errors.append(f"FAIL [get_lists plain]: {id2} not in lists")
|
|
|
|
# Test 4: system lists have emoji=None (API returns ""), color=None (absent)
|
|
sys_lists = [l for l in all_lists if "SYS-CAT" in l.get("name", "") or
|
|
l.get("name") in ("Aufgaben", "Einkaufsliste")]
|
|
for sl in sys_lists:
|
|
if sl.get("emoji") is None and sl.get("color") is None:
|
|
log(f"OK [get_lists sys emoji/color=null]: {sl.get('name')}")
|
|
else:
|
|
errors.append(f"FAIL [get_lists sys emoji/color]: name={sl.get('name')!r} emoji={sl.get('emoji')!r} color={sl.get('color')!r}")
|
|
|
|
except Exception as e:
|
|
errors.append(f"FAIL [get_lists parse]: {e}")
|
|
|
|
# --- Cleanup ---
|
|
for lid, label in [(id1, "emoji"), (id2, "plain")]:
|
|
if lid:
|
|
r = delete_list(lid)
|
|
try:
|
|
obj = json.loads(r)
|
|
if obj.get("deleted"):
|
|
log(f"OK [cleanup {label}]: deleted {lid}")
|
|
else:
|
|
errors.append(f"FAIL [cleanup {label}]: {r}")
|
|
except Exception:
|
|
errors.append(f"FAIL [cleanup {label}]: {r}")
|
|
|
|
# --- Summary ---
|
|
if errors:
|
|
log("\nFAILURES:")
|
|
for e in errors:
|
|
log(" " + e)
|
|
sys.exit(1)
|
|
else:
|
|
log("\nAll tests passed.")
|