personal memory agent
at main 131 lines 4.4 kB view raw
1# SPDX-License-Identifier: AGPL-3.0-only 2# Copyright (c) 2026 sol pbc 3 4"""Self-contained fixtures for todos app tests. 5 6These fixtures are fully standalone and only depend on pytest builtins. 7No shared dependencies from the root conftest.py are required. 8""" 9 10from __future__ import annotations 11 12import json 13from datetime import datetime 14 15import pytest 16 17 18@pytest.fixture(autouse=True) 19def _skip_supervisor_check(monkeypatch): 20 """Allow app CLI tests to run without a live solstone supervisor.""" 21 monkeypatch.setenv("SOL_SKIP_SUPERVISOR_CHECK", "1") 22 23 24@pytest.fixture 25def todo_env(tmp_path, monkeypatch): 26 """Create a temporary journal facet with optional todo entries. 27 28 This fixture is self-contained and provides a complete test environment 29 for todo operations without any external dependencies. 30 31 Usage: 32 def test_example(todo_env): 33 day, facet, todo_path = todo_env([ 34 {"text": "First item"}, 35 {"text": "Second item", "completed": True} 36 ]) 37 # Now _SOLSTONE_JOURNAL_OVERRIDE is set and todo file exists 38 """ 39 40 def _create( 41 entries: list[dict] | None = None, 42 day: str | None = None, 43 facet: str = "personal", 44 ): 45 if day is None: 46 day = datetime.now().strftime("%Y%m%d") 47 todos_dir = tmp_path / "facets" / facet / "todos" 48 todos_dir.mkdir(parents=True, exist_ok=True) 49 todo_path = todos_dir / f"{day}.jsonl" 50 if entries is not None: 51 lines = [json.dumps(e, ensure_ascii=False) for e in entries] 52 todo_path.write_text("\n".join(lines) + "\n", encoding="utf-8") 53 monkeypatch.setenv("_SOLSTONE_JOURNAL_OVERRIDE", str(tmp_path)) 54 return day, facet, todo_path 55 56 return _create 57 58 59@pytest.fixture 60def facet_env(tmp_path, monkeypatch): 61 """Create a temporary facet with full structure for testing. 62 63 Includes facet.json configuration, todos directory, and logs directory. 64 Suitable for testing action logging and other facet-scoped operations. 65 """ 66 journal = tmp_path / "journal" 67 journal.mkdir() 68 69 def _create(facet: str = "test_facet"): 70 facet_path = journal / "facets" / facet 71 facet_path.mkdir(parents=True) 72 73 # Create facet.json 74 facet_json = facet_path / "facet.json" 75 facet_json.write_text( 76 json.dumps({"title": f"Test {facet}", "description": "Test facet"}), 77 encoding="utf-8", 78 ) 79 80 # Create todos directory 81 (facet_path / "todos").mkdir() 82 83 monkeypatch.setenv("_SOLSTONE_JOURNAL_OVERRIDE", str(journal)) 84 return journal, facet 85 86 return _create 87 88 89@pytest.fixture 90def move_env(tmp_path, monkeypatch): 91 """Create a two-facet environment for move tests.""" 92 monkeypatch.setenv("_SOLSTONE_JOURNAL_OVERRIDE", str(tmp_path)) 93 94 def _create( 95 entries: list[dict] | None = None, 96 day: str = "20240101", 97 src_facet: str = "work", 98 dst_facet: str = "personal", 99 ): 100 for facet in [src_facet, dst_facet]: 101 facet_dir = tmp_path / "facets" / facet 102 facet_dir.mkdir(parents=True, exist_ok=True) 103 (facet_dir / "facet.json").write_text( 104 json.dumps({"title": f"Test {facet}", "description": "Test facet"}), 105 encoding="utf-8", 106 ) 107 108 todos_dir = tmp_path / "facets" / src_facet / "todos" 109 todos_dir.mkdir(parents=True, exist_ok=True) 110 todo_path = todos_dir / f"{day}.jsonl" 111 if entries: 112 now_ms = int(datetime.now().timestamp() * 1000) 113 lines = [] 114 for entry in entries: 115 data = { 116 "text": entry["text"], 117 "created_at": entry.get("created_at", now_ms), 118 "updated_at": entry.get("updated_at", now_ms), 119 } 120 if entry.get("cancelled"): 121 data["cancelled"] = True 122 if entry.get("completed"): 123 data["completed"] = True 124 if entry.get("nudge"): 125 data["nudge"] = entry["nudge"] 126 lines.append(json.dumps(data, ensure_ascii=False)) 127 todo_path.write_text("\n".join(lines) + "\n", encoding="utf-8") 128 129 return tmp_path, src_facet, dst_facet 130 131 return _create