using Xunit; using NozCli.Core.Config; using NozCli.Core.Models; using NozCli.Repl; namespace NozCli.Tests; public class ReplContextTests { // Builds a ReplContext with a fixed NoteCache — no API calls made. private static ReplContext BuildCtx(params NoteInfo[] notes) { var cfg = new LocalConfig { ServerUrl = "http://localhost:9999", Token = "test" }; var ctx = new ReplContext(null!, cfg); // Api is null — not used in navigation ctx.NoteCache = [.. notes]; return ctx; } private static NoteInfo Note(string slug, string topic, string status = "seed") => new(slug, $"Title {slug}", status, topic, "de", false, null); // ── CurrentPath ────────────────────────────────────────────────────────── [Fact] public void CurrentPath_AtRoot_IsWave() { var ctx = BuildCtx(); Assert.Equal("~", ctx.CurrentPath); } [Fact] public void CurrentPath_InTopic_ShowsTopic() { var ctx = BuildCtx(Note("psychologie/test", "psychologie")); ctx.NavigateTo("psychologie"); Assert.Equal("~/psychologie", ctx.CurrentPath); } [Fact] public void CurrentPath_InSubfolder_ShowsFullPath() { var ctx = BuildCtx(Note("psychologie/sub/deep", "psychologie")); ctx.NavigateTo("psychologie"); ctx.NavigateTo("sub"); Assert.Equal("~/psychologie/sub", ctx.CurrentPath); } // ── FoldersInView ──────────────────────────────────────────────────────── [Fact] public void FoldersInView_AtRoot_ReturnsDistinctTopics() { var ctx = BuildCtx( Note("psychologie/a", "psychologie"), Note("psychologie/b", "psychologie"), Note("biosysteme/c", "biosysteme")); var folders = ctx.FoldersInView().OrderBy(f => f).ToList(); Assert.Equal(["biosysteme", "psychologie"], folders); } [Fact] public void FoldersInView_InTopic_ReturnsSubfolders() { var ctx = BuildCtx( Note("psychologie/sub/note", "psychologie"), Note("psychologie/flat-note", "psychologie")); ctx.NavigateTo("psychologie"); var folders = ctx.FoldersInView().ToList(); Assert.Contains("sub", folders); Assert.DoesNotContain("flat-note", folders); } // ── NavigateTo / NavigateUp ────────────────────────────────────────────── [Fact] public void NavigateTo_ValidTopic_ReturnsTrue() { var ctx = BuildCtx(Note("psychologie/test", "psychologie")); Assert.True(ctx.NavigateTo("psychologie")); Assert.Equal("psychologie", ctx.CurrentTopic); } [Fact] public void NavigateTo_UnknownTopic_ReturnsFalse() { var ctx = BuildCtx(Note("psychologie/test", "psychologie")); Assert.False(ctx.NavigateTo("doesnotexist")); Assert.Null(ctx.CurrentTopic); } [Fact] public void NavigateUp_FromTopic_ReturnsToRoot() { var ctx = BuildCtx(Note("psychologie/test", "psychologie")); ctx.NavigateTo("psychologie"); ctx.NavigateUp(); Assert.Null(ctx.CurrentTopic); Assert.Equal("~", ctx.CurrentPath); } [Fact] public void NavigateUp_FromSubfolder_ReturnsToTopic() { var ctx = BuildCtx(Note("psychologie/sub/deep", "psychologie")); ctx.NavigateTo("psychologie"); ctx.NavigateTo("sub"); ctx.NavigateUp(); Assert.Equal("psychologie", ctx.CurrentTopic); Assert.Null(ctx.CurrentSubPath); } // ── SlugRelative ───────────────────────────────────────────────────────── [Fact] public void SlugRelative_InTopic_StripsTopicPrefix() { var ctx = BuildCtx(Note("psychologie/flow", "psychologie")); ctx.NavigateTo("psychologie"); Assert.Equal("flow", ctx.SlugRelative("psychologie/flow")); } [Fact] public void SlugRelative_AtRoot_ReturnsFullSlug() { var ctx = BuildCtx(Note("psychologie/flow", "psychologie")); Assert.Equal("psychologie/flow", ctx.SlugRelative("psychologie/flow")); } // ── NotesInView ────────────────────────────────────────────────────────── [Fact] public void NotesInView_InTopic_FiltersCorrectly() { var ctx = BuildCtx( Note("psychologie/a", "psychologie"), Note("biosysteme/b", "biosysteme")); ctx.NavigateTo("psychologie"); var notes = ctx.NotesInView().ToList(); Assert.Single(notes); Assert.Equal("psychologie/a", notes[0].Slug); } // ── ResolveSlug ────────────────────────────────────────────────────────── [Fact] public void ResolveSlug_ShortName_InTopic_ResolvesToFullSlug() { var ctx = BuildCtx(Note("psychologie/flow", "psychologie")); ctx.NavigateTo("psychologie"); Assert.Equal("psychologie/flow", ctx.ResolveSlug("flow")); } [Fact] public void ResolveSlug_AlreadyFullSlug_ReturnsUnchanged() { var ctx = BuildCtx(Note("psychologie/flow", "psychologie")); Assert.Equal("psychologie/flow", ctx.ResolveSlug("psychologie/flow")); } }