| 1 | using AgentForge.Contracts; |
| 2 | using AgentForge.Services; |
| 3 | |
| 4 | namespace AgentForge.Tests; |
| 5 | |
| 6 | public sealed class BracketCodeReferenceFormatterTests |
| 7 | { |
| 8 | [Fact] |
| 9 | public void Format_full_anchor_omits_empty_axes() |
| 10 | { |
| 11 | var anchor = new CodeAnchor("src/hello.py", 4, 5, "main"); |
| 12 | Assert.Equal("[F:src/hello.py; M:main; L:4-5]", BracketCodeReferenceFormatter.Format(anchor)); |
| 13 | } |
| 14 | |
| 15 | [Fact] |
| 16 | public void Format_includes_syntax_scope() |
| 17 | { |
| 18 | var anchor = new CodeAnchor("src/Foo.cs", 10, 25, "Run", "for:2"); |
| 19 | Assert.Equal("[F:src/Foo.cs; M:Run; L:10-25; S:for:2]", BracketCodeReferenceFormatter.Format(anchor)); |
| 20 | } |
| 21 | |
| 22 | [Fact] |
| 23 | public void TryParse_round_trips() |
| 24 | { |
| 25 | var original = new CodeAnchor("src/hello.py", 4, 5, "main", "for:2"); |
| 26 | var text = BracketCodeReferenceFormatter.Format(original); |
| 27 | Assert.True(BracketCodeReferenceFormatter.TryParse(text, out var parsed)); |
| 28 | Assert.True(CodeAnchorJson.AnchorsEqual(original, parsed)); |
| 29 | } |
| 30 | |
| 31 | [Fact] |
| 32 | public void TryParse_rejects_forge_bracket() |
| 33 | { |
| 34 | Assert.False(BracketCodeReferenceFormatter.TryParse("[FRG:pilot/issues/1]", out _)); |
| 35 | } |
| 36 | |
| 37 | [Fact] |
| 38 | public void ParseMany_skips_invalid() |
| 39 | { |
| 40 | var anchors = BracketCodeReferenceFormatter.ParseMany( |
| 41 | [ |
| 42 | "[F:a.cs; L:1]", |
| 43 | "[FRG:pilot/issues/1]", |
| 44 | "not-a-bracket", |
| 45 | ]); |
| 46 | Assert.Single(anchors); |
| 47 | Assert.Equal("a.cs", anchors[0].File); |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | public sealed class ForgeArtifactBracketTests |
| 52 | { |
| 53 | [Fact] |
| 54 | public void Format_issue_and_mr() |
| 55 | { |
| 56 | Assert.Equal("[FRG:pilot/issues/7]", ForgeArtifactBracket.FormatIssue("pilot", 7)); |
| 57 | Assert.Equal("[FRG:cad-tools/mr/3]", ForgeArtifactBracket.FormatMergeRequest("cad-tools", 3)); |
| 58 | } |
| 59 | |
| 60 | [Fact] |
| 61 | public void TryParse_issue() |
| 62 | { |
| 63 | Assert.True(ForgeArtifactBracket.TryParseIssue("[FRG:pilot/issues/7]", out var repo, out var number)); |
| 64 | Assert.Equal("pilot", repo); |
| 65 | Assert.Equal(7, number); |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | public sealed class ForgeLinkBuilderTests |
| 70 | { |
| 71 | [Fact] |
| 72 | public void Issue_magic_link_uses_authority() |
| 73 | { |
| 74 | var link = ForgeLinkBuilder.IssueMagicLink("http://127.0.0.1:8770", "pilot", 1); |
| 75 | Assert.Equal("forge://127.0.0.1:8770/issue?repo=pilot&n=1", link); |
| 76 | } |
| 77 | |
| 78 | [Fact] |
| 79 | public void Lens_magic_link_includes_bracket() |
| 80 | { |
| 81 | var anchor = new CodeAnchor("src/hello.py", 4, 5, "main"); |
| 82 | var link = ForgeLinkBuilder.LensMagicLink("http://127.0.0.1:8770", "pilot", 1, anchor); |
| 83 | Assert.StartsWith("forge://127.0.0.1:8770/lens?repo=pilot&n=1&b=", link, StringComparison.Ordinal); |
| 84 | Assert.Contains("F%3Asrc%2Fhello.py", link, StringComparison.Ordinal); |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | public sealed class IssueAnchorResolverTests |
| 89 | { |
| 90 | [Fact] |
| 91 | public void Resolve_merges_structured_and_brackets() |
| 92 | { |
| 93 | var resolved = IssueAnchorResolver.Resolve( |
| 94 | [new CodeAnchor("src/A.cs", 1)], |
| 95 | ["[F:src/B.cs; L:2]"]); |
| 96 | Assert.NotNull(resolved); |
| 97 | Assert.Equal(2, resolved!.Count); |
| 98 | } |
| 99 | } |
| 100 | |