using Agent.Core.Ollama;using Xunit;namespace Agent.Core.DesignTests;public class ChatHistoryStoreTests{ [Fact] public void SaveSession_persists_messages_and_lists_summary() { string root = CreateTempHistoryRoot(); try { var store = new ChatHistoryStore(root); var history = new ChatHistory { new ChatMessage("user", "Design test ping"), new ChatMessage("assistant", "Design test pong", Tokens: 12) }; string id = store.SaveSession("gemma4", history); Assert.True(File.Exists(Path.Combine(root, id + ".xml"))); IReadOnlyList<ChatSessionSummary> sessions = store.ListSessions(); Assert.Single(sessions); Assert.Equal("Design test ping", sessions[0].Title); Assert.Equal(2, sessions[0].MessageCount); Assert.Equal("gemma4", sessions[0].Model); } finally { TryDeleteDirectory(root); } } [Fact] public void LoadSession_restores_messages_and_updates_current_id() { string root = CreateTempHistoryRoot(); try { var store = new ChatHistoryStore(root); var history = new ChatHistory { new ChatMessage("user", "Remember this"), new ChatMessage("assistant", "Acknowledged") }; string id = store.SaveSession("gemma4", history); store.StartNewSession(); SavedChatSession? loaded = store.LoadSession(id); Assert.NotNull(loaded); Assert.Equal(id, store.CurrentSessionId); Assert.Equal(2, loaded!.Messages.Count); Assert.Equal("Remember this", loaded.Messages[0].Content); } finally { TryDeleteDirectory(root); } } [Fact] public void StartNewSession_changes_current_id_without_deleting_files() { string root = CreateTempHistoryRoot(); try { var store = new ChatHistoryStore(root); string first = store.SaveSession("gemma4", new ChatHistory { new ChatMessage("user", "one") }); store.StartNewSession(); string second = store.CurrentSessionId; Assert.NotEqual(first, second); Assert.Single(store.ListSessions()); } finally { TryDeleteDirectory(root); } } [Fact] public void SaveSession_overwrites_same_id_and_bumps_message_count() { string root = CreateTempHistoryRoot(); try { var store = new ChatHistoryStore(root); string id = store.SaveSession("gemma4", new ChatHistory { new ChatMessage("user", "first line") }); store.UseSession(id); store.SaveSession("gemma4", new ChatHistory { new ChatMessage("user", "first line"), new ChatMessage("assistant", "second line") }); SavedChatSession? loaded = store.LoadSession(id); Assert.NotNull(loaded); Assert.Equal(2, loaded!.Messages.Count); Assert.Equal(2, store.ListSessions().Single().MessageCount); } finally { TryDeleteDirectory(root); } } private static string CreateTempHistoryRoot() { string path = Path.Combine(Path.GetTempPath(), "AgentCore-DesignTests", Guid.NewGuid().ToString("N")); Directory.CreateDirectory(path); return path; } private static void TryDeleteDirectory(string path) { try { if (Directory.Exists(path)) { Directory.Delete(path, recursive: true); } } catch { } }}
Documentation
Version 2 design tests
Automated checks for chat, history, and Kokoro TTS (sanitizer + optional live speech).
Quick run
python src/Version2/DesignTests/run-design-tests.py
python src/Version2/DesignTests/run-design-tests.py --live
.\src\Version2\DesignTests\run-design-tests.ps1 -Live
What runs
| Suite | Needs network | Covers | |-------|----------------|--------| | ChatHistoryStoreTests | No | Same as V1 history XML | | OllamaClientHistoryTests | No | Client save/load | | KokoroTtsSanitizerTests | No | Markdown/emoji/URL stripping for speech | | OllamaLiveTests | Yes (--live) | Ollama chat | | KokoroTtsLiveTests | Yes (--live) | Kokoro model load + SpeakAsync |
First Kokoro live run may download ~320MB of model weights.
Console video (testers)
Record Version 2 console sessions (chat + TTS + history):
python src/TestManager/test_manager.py record v2 chat-tts --build
See src/TestManager/README.md.
All versions
python src/run-all-design-tests.py
python src/run-all-design-tests.py --live