personal memory agent
1# SPDX-License-Identifier: AGPL-3.0-only
2# Copyright (c) 2026 sol pbc
3
4"""Tests for transcripts CLI commands (sol call transcripts ...)."""
5
6from typer.testing import CliRunner
7
8from think.call import call_app
9
10runner = CliRunner()
11
12
13class TestScan:
14 def test_scan_day(self):
15 result = runner.invoke(call_app, ["transcripts", "scan", "20240101"])
16 assert result.exit_code == 0
17 assert "Transcripts:" in result.output
18 assert "Percepts:" in result.output
19
20 def test_scan_empty_day(self):
21 result = runner.invoke(call_app, ["transcripts", "scan", "20990101"])
22 assert result.exit_code == 0
23 assert "(none)" in result.output
24
25
26class TestSegments:
27 def test_segments_day(self):
28 result = runner.invoke(call_app, ["transcripts", "segments", "20240101"])
29 assert result.exit_code == 0
30 assert "123456_300" in result.output
31
32 def test_segments_empty(self):
33 result = runner.invoke(call_app, ["transcripts", "segments", "20990101"])
34 assert result.exit_code == 0
35 assert "No segments" in result.output
36
37
38class TestRead:
39 def test_read_default(self):
40 result = runner.invoke(call_app, ["transcripts", "read", "20240101"])
41 assert result.exit_code == 0
42 assert "## " in result.output
43
44 def test_read_full(self):
45 result = runner.invoke(call_app, ["transcripts", "read", "20240101", "--full"])
46 assert result.exit_code == 0
47
48 def test_read_raw(self):
49 result = runner.invoke(call_app, ["transcripts", "read", "20240101", "--raw"])
50 assert result.exit_code == 0
51
52 def test_read_segment(self):
53 result = runner.invoke(
54 call_app, ["transcripts", "read", "20240101", "--segment", "123456_300"]
55 )
56 assert result.exit_code == 0
57
58 def test_read_range(self):
59 result = runner.invoke(
60 call_app,
61 ["transcripts", "read", "20240101", "--start", "123456", "--length", "5"],
62 )
63 assert result.exit_code == 0
64
65 def test_read_full_and_raw_error(self):
66 result = runner.invoke(
67 call_app, ["transcripts", "read", "20240101", "--full", "--raw"]
68 )
69 assert result.exit_code == 1
70 assert "Cannot use --full and --raw" in result.output
71
72 def test_read_start_without_length(self):
73 result = runner.invoke(
74 call_app, ["transcripts", "read", "20240101", "--start", "123456"]
75 )
76 assert result.exit_code == 1
77 assert "--start and --length must be used together" in result.output
78
79 def test_read_segment_with_start(self):
80 result = runner.invoke(
81 call_app,
82 [
83 "transcripts",
84 "read",
85 "20240101",
86 "--segment",
87 "123456_300",
88 "--start",
89 "123456",
90 ],
91 )
92 assert result.exit_code == 1
93
94
95class TestStats:
96 def test_stats_month(self):
97 result = runner.invoke(call_app, ["transcripts", "stats", "202401"])
98 assert result.exit_code == 0
99 assert "20240101" in result.output
100 assert "Total: 1 days with data" in result.output
101
102 def test_stats_empty(self):
103 result = runner.invoke(call_app, ["transcripts", "stats", "209901"])
104 assert result.exit_code == 0
105 assert "No data" in result.output
106
107
108class TestSolEnvResolution:
109 """Tests for SOL_* env var resolution in transcripts commands."""
110
111 def test_scan_from_sol_day(self, monkeypatch):
112 """scan with SOL_DAY env and no arg works."""
113 monkeypatch.setenv("SOL_DAY", "20240101")
114 result = runner.invoke(call_app, ["transcripts", "scan"])
115 assert result.exit_code == 0
116 assert "Transcripts:" in result.output
117
118 def test_read_from_sol_day(self, monkeypatch):
119 """read with SOL_DAY env and no arg works."""
120 monkeypatch.setenv("SOL_DAY", "20240101")
121 result = runner.invoke(call_app, ["transcripts", "read"])
122 assert result.exit_code == 0
123
124 def test_read_from_sol_day_and_segment(self, monkeypatch):
125 """read with SOL_DAY + SOL_SEGMENT env works."""
126 monkeypatch.setenv("SOL_DAY", "20240101")
127 monkeypatch.setenv("SOL_SEGMENT", "123456_300")
128 result = runner.invoke(call_app, ["transcripts", "read"])
129 assert result.exit_code == 0