Public Access
128 lines
5.8 KiB
C#
128 lines
5.8 KiB
C#
using MeetingAssistant.MeetingNotes;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace MeetingAssistant.Tests;
|
|
|
|
public sealed class MeetingNoteStoreTests
|
|
{
|
|
[Fact]
|
|
public async Task StoreWritesTemplateFrontmatterAndReadsUserNotesBody()
|
|
{
|
|
var (vaultRoot, store) = CreateStore();
|
|
var note = MeetingNoteTemplate.Create(
|
|
title: "Leadership Sync",
|
|
startTime: DateTimeOffset.Parse("2026-05-19T10:00:00+02:00"),
|
|
endTime: DateTimeOffset.Parse("2026-05-19T10:30:00+02:00"),
|
|
attendees:
|
|
[
|
|
"Mike <m.ike@ibm.com>",
|
|
"Ada"
|
|
],
|
|
projects:
|
|
[
|
|
"Meeting Assistant",
|
|
"Alaric"
|
|
],
|
|
transcriptPath: Path.Combine(vaultRoot, "Meetings", "Transcripts", "20260519-transcript.md"),
|
|
assistantContextPath: Path.Combine(vaultRoot, "Meetings", "Assistant Context", "20260519-context.md"),
|
|
summaryPath: Path.Combine(vaultRoot, "Meetings", "Summaries", "20260519-summary.md"),
|
|
userNotes: "Discuss rollout risks.");
|
|
|
|
var saved = await store.SaveAsync(note, CancellationToken.None);
|
|
var content = await File.ReadAllTextAsync(saved.Path);
|
|
var loaded = await store.ReadAsync(saved.Path, CancellationToken.None);
|
|
|
|
Assert.EndsWith(".md", saved.Path, StringComparison.Ordinal);
|
|
Assert.Contains("attendees:", content);
|
|
Assert.Contains("- Mike <m.ike@ibm.com>", content);
|
|
Assert.Contains("- Ada", content);
|
|
Assert.Contains("projects:", content);
|
|
Assert.Contains("- Meeting Assistant", content);
|
|
Assert.DoesNotContain("purpose:", content);
|
|
Assert.Contains("start_time: \"2026-05-19T10:00:00.0000000+02:00\"", content);
|
|
Assert.Contains("end_time: \"2026-05-19T10:30:00.0000000+02:00\"", content);
|
|
Assert.Contains("transcript: \"[[../Transcripts/20260519-transcript|Transcript]]\"", content);
|
|
Assert.Contains("assistant_context: \"[[../Assistant Context/20260519-context|Assistant Context]]\"", content);
|
|
Assert.Contains("summary: \"[[../Summaries/20260519-summary|Summary]]\"", content);
|
|
Assert.DoesNotContain("decisions:", content);
|
|
Assert.DoesNotContain("next_steps:", content);
|
|
Assert.Equal("Discuss rollout risks.", loaded.UserNotes);
|
|
Assert.Equal(["Mike <m.ike@ibm.com>", "Ada"], loaded.Frontmatter.Attendees);
|
|
Assert.Equal(["Meeting Assistant", "Alaric"], loaded.Frontmatter.Projects);
|
|
Assert.Equal(DateTimeOffset.Parse("2026-05-19T10:00:00+02:00"), loaded.Frontmatter.StartTime);
|
|
Assert.Equal(DateTimeOffset.Parse("2026-05-19T10:30:00+02:00"), loaded.Frontmatter.EndTime);
|
|
Assert.Equal("[[../Transcripts/20260519-transcript|Transcript]]", loaded.Frontmatter.Transcript);
|
|
Assert.Equal("[[../Assistant Context/20260519-context|Assistant Context]]", loaded.Frontmatter.AssistantContext);
|
|
Assert.Equal("[[../Summaries/20260519-summary|Summary]]", loaded.Frontmatter.Summary);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task FrontmatterUpdatePreservesExistingUserNotesBody()
|
|
{
|
|
var (vaultRoot, store) = CreateStore();
|
|
var userNotes = """
|
|
## User notes
|
|
|
|
- First point
|
|
- Second point
|
|
|
|
```text
|
|
Keep this block exactly.
|
|
```
|
|
|
|
""";
|
|
var saved = await store.SaveAsync(
|
|
MeetingNoteTemplate.Create(
|
|
title: "Body Preservation",
|
|
attendees: [],
|
|
projects: [],
|
|
transcriptPath: Path.Combine(vaultRoot, "Meetings", "Transcripts", "20260519-transcript.md"),
|
|
assistantContextPath: Path.Combine(vaultRoot, "Meetings", "Assistant Context", "20260519-context.md"),
|
|
summaryPath: Path.Combine(vaultRoot, "Meetings", "Summaries", "20260519-summary.md"),
|
|
userNotes: userNotes),
|
|
CancellationToken.None);
|
|
|
|
var loaded = await store.ReadAsync(saved.Path, CancellationToken.None);
|
|
loaded.Frontmatter.Title = "Updated title";
|
|
await store.SaveAsync(loaded, CancellationToken.None);
|
|
var reloaded = await store.ReadAsync(saved.Path, CancellationToken.None);
|
|
|
|
Assert.Equal("Updated title", reloaded.Frontmatter.Title);
|
|
Assert.Equal(userNotes, reloaded.UserNotes);
|
|
}
|
|
|
|
[Fact]
|
|
public void ActionLinkEscapesSummaryFileName()
|
|
{
|
|
var link = MeetingNoteActionLinks.CreateSummaryRetryLink(
|
|
"http://localhost:5090/",
|
|
"C:\\Vault\\Meetings\\Summaries\\summary with spaces.md");
|
|
|
|
Assert.Equal(
|
|
"[Retry summary generation](http://localhost:5090/meetings/summary/retry?summaryPath=summary%20with%20spaces.md)",
|
|
link);
|
|
}
|
|
|
|
private static (string VaultRoot, MarkdownMeetingNoteStore Store) CreateStore()
|
|
{
|
|
var vaultRoot = Path.Combine(Path.GetTempPath(), "meeting-assistant-tests", Guid.NewGuid().ToString("N"));
|
|
var store = new MarkdownMeetingNoteStore(
|
|
Options.Create(new MeetingAssistantOptions
|
|
{
|
|
Vault = new VaultOptions
|
|
{
|
|
MeetingNotesFolder = Path.Combine(vaultRoot, "Meetings", "Notes"),
|
|
TranscriptsFolder = Path.Combine(vaultRoot, "Meetings", "Transcripts"),
|
|
AssistantContextFolder = Path.Combine(vaultRoot, "Meetings", "Assistant Context"),
|
|
SummariesFolder = Path.Combine(vaultRoot, "Meetings", "Summaries"),
|
|
ProjectsFolder = Path.Combine(vaultRoot, "Projects"),
|
|
DictationWordsPath = Path.Combine(vaultRoot, "Meetings", "dictation-words.md")
|
|
}
|
|
}),
|
|
NullLogger<MarkdownMeetingNoteStore>.Instance);
|
|
|
|
return (vaultRoot, store);
|
|
}
|
|
}
|