using Xunit; using System.Reflection; namespace NozCli.Tests; // Tests the private ReplaceReferences + PatchTopicIfNeeded methods via reflection // so we don't expose them publicly just for testing. public class NoteRenamerTests { private static string ReplaceReferences(string md, string oldSlug, string newSlug) { var method = typeof(NozCli.Core.Client.NoteRenamer) .GetMethod("ReplaceReferences", BindingFlags.NonPublic | BindingFlags.Static)!; return (string)method.Invoke(null, [md, oldSlug, newSlug])!; } private static string PatchTopicIfNeeded(string md, string oldSlug, string newSlug) { var method = typeof(NozCli.Core.Client.NoteRenamer) .GetMethod("PatchTopicIfNeeded", BindingFlags.NonPublic | BindingFlags.Static)!; return (string)method.Invoke(null, [md, oldSlug, newSlug])!; } // ── Wikilink replacement ───────────────────────────────────────────────── [Fact] public void ReplaceReferences_BareWikilink_IsReplaced() { var md = "Siehe [[psychologie/flow]] für Details."; var result = ReplaceReferences(md, "psychologie/flow", "psychologie/new-flow"); Assert.Equal("Siehe [[psychologie/new-flow]] für Details.", result); } [Fact] public void ReplaceReferences_WikilinkWithDisplay_PreservesDisplay() { var md = "Lies [[psychologie/flow|Flow-Zustand]] weiter."; var result = ReplaceReferences(md, "psychologie/flow", "psychologie/new-flow"); Assert.Equal("Lies [[psychologie/new-flow|Flow-Zustand]] weiter.", result); } [Fact] public void ReplaceReferences_MarkdownLink_IsReplaced() { var md = "Siehe [Flow](/noosphere/psychologie/flow) hier."; var result = ReplaceReferences(md, "psychologie/flow", "psychologie/new-flow"); Assert.Equal("Siehe [Flow](/noosphere/psychologie/new-flow) hier.", result); } [Fact] public void ReplaceReferences_MarkdownLinkWithAnchor_PreservesAnchor() { var md = "[Abschnitt](/noosphere/psychologie/flow#abschnitt-2)"; var result = ReplaceReferences(md, "psychologie/flow", "psychologie/new-flow"); Assert.Equal("[Abschnitt](/noosphere/psychologie/new-flow#abschnitt-2)", result); } [Fact] public void ReplaceReferences_UnrelatedLinks_AreUntouched() { var md = "[[other/note]] und [Ext](https://example.com/psychologie/flow)"; var result = ReplaceReferences(md, "psychologie/flow", "psychologie/new-flow"); Assert.Equal(md, result); } [Fact] public void ReplaceReferences_MultipleOccurrences_AllReplaced() { var md = "[[psychologie/flow]] und nochmal [[psychologie/flow|Flow]]."; var result = ReplaceReferences(md, "psychologie/flow", "psychologie/new-flow"); Assert.DoesNotContain("psychologie/flow]]", result); Assert.Equal(2, result.Split("psychologie/new-flow").Length - 1); } // ── Topic frontmatter patch ─────────────────────────────────────────────── [Fact] public void PatchTopic_SameTopic_NoChange() { var md = "---\ntitle: Flow\ntopic: psychologie\n---\nInhalt"; var result = PatchTopicIfNeeded(md, "psychologie/flow", "psychologie/new-flow"); Assert.Equal(md, result); } [Fact] public void PatchTopic_DifferentTopic_UpdatesFrontmatter() { var md = "---\ntitle: Flow\ntopic: psychologie\n---\nInhalt"; var result = PatchTopicIfNeeded(md, "psychologie/flow", "biosysteme/flow"); Assert.Contains("topic: biosysteme", result); Assert.DoesNotContain("topic: psychologie", result); Assert.Contains("Inhalt", result); // body untouched } [Fact] public void PatchTopic_NoFrontmatter_NoChange() { var md = "# Kein Frontmatter\nNur Inhalt"; var result = PatchTopicIfNeeded(md, "psychologie/flow", "biosysteme/flow"); Assert.Equal(md, result); } }