| 1 | using CascadeIDE.Features.MagicLink; |
| 2 | using Xunit; |
| 3 | |
| 4 | namespace CascadeIDE.Tests; |
| 5 | |
| 6 | public sealed class CideMagicLinkUriTests |
| 7 | { |
| 8 | [Fact] |
| 9 | public void TryParse_RevealWithFileAndLine() |
| 10 | { |
| 11 | const string uri = "cide://reveal?root=D:%2Frepo&f=Features%2FFoo.cs&l=10&le=12"; |
| 12 | Assert.True(CideMagicLinkUri.TryParse(uri, out var req, out var err), err); |
| 13 | Assert.Equal(CideMagicLinkAction.Reveal, req.Action); |
| 14 | Assert.Equal("D:\\repo", req.WorkspaceRoot); |
| 15 | Assert.Equal("Features/Foo.cs", req.File); |
| 16 | Assert.Equal(10, req.LineStart); |
| 17 | Assert.Equal(12, req.LineEnd); |
| 18 | } |
| 19 | |
| 20 | [Fact] |
| 21 | public void TryParse_RevealWithBracket() |
| 22 | { |
| 23 | const string uri = "cide://reveal?root=D:%2Frepo&b=F%3AFeatures%2FFoo.cs%3B%20M%3ABar"; |
| 24 | Assert.True(CideMagicLinkUri.TryParse(uri, out var req, out _)); |
| 25 | Assert.Equal("F:Features/Foo.cs; M:Bar", req.BracketInner); |
| 26 | } |
| 27 | |
| 28 | [Fact] |
| 29 | public void TryParse_MdRequiresDoc() |
| 30 | { |
| 31 | Assert.False(CideMagicLinkUri.TryParse("cide://md?root=D:%2Fr", out _, out var err)); |
| 32 | Assert.Contains("doc", err, StringComparison.OrdinalIgnoreCase); |
| 33 | } |
| 34 | |
| 35 | [Fact] |
| 36 | public void WorkspaceGuard_RejectsTraversal() |
| 37 | { |
| 38 | Assert.False(CideMagicLinkWorkspaceGuard.TryResolveUnderRoot( |
| 39 | @"C:\ws", |
| 40 | "../outside.cs", |
| 41 | out _, |
| 42 | out var error)); |
| 43 | Assert.Contains("traversal", error, StringComparison.OrdinalIgnoreCase); |
| 44 | } |
| 45 | } |
| 46 | |