Forge
csharp3407750f
1using System.Net.Http.Json;
2
3namespace AgentForge.Tests;
4
5public sealed class ForgeBlobViewTests(ForgeWebApplicationFactory factory) : IClassFixture<ForgeWebApplicationFactory>
6{
7 private readonly HttpClient _client = factory.CreateClient();
8
9 [Fact]
10 public async Task Blob_view_renders_line_numbers_syntax_and_split_layout()
11 {
12 await _client.PostAsJsonAsync("/api/v1/repos", new { name = "blob-view" });
13 factory.Git.CreateCommitOnBranch(
14 "blob-view",
15 "main",
16 "sample.py",
17 "# comment\nprint(\"hi\")\n",
18 "seed");
19
20 var view = await _client.GetAsync("/view/repos/blob-view/blob?branch=main&path=sample.py&line=2");
21 view.EnsureSuccessStatusCode();
22 var html = await view.Content.ReadAsStringAsync();
23
24 Assert.Contains("file-table", html, StringComparison.Ordinal);
25 Assert.Contains("file-num-link", html, StringComparison.Ordinal);
26 Assert.Contains("id=\"L2\"", html, StringComparison.Ordinal);
27 Assert.Contains("anchor-line", html, StringComparison.Ordinal);
28 Assert.Contains("syn-cmt", html, StringComparison.Ordinal);
29 Assert.Contains("syn-kw", html, StringComparison.Ordinal);
30 Assert.Contains("syn-str", html, StringComparison.Ordinal);
31 Assert.Contains("code-nav", html, StringComparison.Ordinal);
32 Assert.Contains("split-layout", html, StringComparison.Ordinal);
33 Assert.Contains("iop-sidebar", html, StringComparison.Ordinal);
34 Assert.Contains("view-status-bar", html, StringComparison.Ordinal);
35 Assert.Contains("header-tabs", html, StringComparison.Ordinal);
36 Assert.Contains("header-repo-select", html, StringComparison.Ordinal);
37 Assert.Contains("header-search", html, StringComparison.Ordinal);
38 Assert.Contains("header-avatar", html, StringComparison.Ordinal);
39 Assert.Contains("brand-mark", html, StringComparison.Ordinal);
40 Assert.Contains("View only · write via MCP/CIDE", html, StringComparison.Ordinal);
41 }
42
43 [Fact]
44 public async Task Blob_view_shows_open_mr_in_iop_sidebar()
45 {
46 await _client.PostAsJsonAsync("/api/v1/repos", new { name = "blob-mr" });
47 factory.Git.CreateCommitOnBranch("blob-mr", "main", "README.md", "main", "main");
48 factory.Git.CreateCommitOnBranch("blob-mr", "feat/x", "src/X.cs", "x", "feat");
49 await _client.PostAsJsonAsync("/api/v1/repos/blob-mr/merge-requests", new
50 {
51 title = "add X",
52 sourceBranch = "feat/x",
53 targetBranch = "main",
54 });
55
56 var view = await _client.GetAsync("/view/repos/blob-mr/blob?branch=feat/x&path=src/X.cs");
57 view.EnsureSuccessStatusCode();
58 var html = await view.Content.ReadAsStringAsync();
59
60 Assert.Contains("IOP thread", html, StringComparison.Ordinal);
61 Assert.Contains("!1", html, StringComparison.Ordinal);
62 Assert.Contains("add X", html, StringComparison.Ordinal);
63 Assert.Contains("iop-subtabs", html, StringComparison.Ordinal);
64 Assert.Contains("btn-approve", html, StringComparison.Ordinal);
65 }
66
67 [Fact]
68 public async Task Merge_request_view_uses_split_layout_and_ci_badge()
69 {
70 await _client.PostAsJsonAsync("/api/v1/repos", new { name = "mr-layout" });
71 factory.Git.CreateCommitOnBranch("mr-layout", "main", "README.md", "main", "main");
72 factory.Git.CreateCommitOnBranch("mr-layout", "feat/y", "src/Y.cs", "y", "feat");
73 await _client.PostAsJsonAsync("/api/v1/repos/mr-layout/merge-requests", new
74 {
75 title = "feature Y",
76 sourceBranch = "feat/y",
77 });
78 await _client.PostAsJsonAsync("/api/v1/ci/callback", new
79 {
80 repo = "mr-layout",
81 mr = 1,
82 commit = "abc123",
83 status = "success",
84 });
85
86 var view = await _client.GetAsync("/view/repos/mr-layout/merge-requests/1");
87 view.EnsureSuccessStatusCode();
88 var html = await view.Content.ReadAsStringAsync();
89
90 Assert.Contains("split-layout", html, StringComparison.Ordinal);
91 Assert.Contains("iop-sidebar", html, StringComparison.Ordinal);
92 Assert.Contains("diff-table", html, StringComparison.Ordinal);
93 Assert.Contains("ci-pass", html, StringComparison.Ordinal);
94 Assert.Contains("Approve merge", html, StringComparison.Ordinal);
95 Assert.Contains("iop-subtabs", html, StringComparison.Ordinal);
96 Assert.Contains("Conversation", html, StringComparison.Ordinal);
97 Assert.Contains("Changes", html, StringComparison.Ordinal);
98 Assert.Contains("Checks", html, StringComparison.Ordinal);
99 Assert.Contains("view-status-bar", html, StringComparison.Ordinal);
100 }
101
102 [Fact]
103 public async Task Search_view_finds_issue_and_file()
104 {
105 await _client.PostAsJsonAsync("/api/v1/repos", new { name = "search-ui" });
106 factory.Git.CreateCommitOnBranch("search-ui", "main", "README.md", "main", "main");
107 factory.Git.CreateCommitOnBranch("search-ui", "main", "src/Needle.cs", "needle", "add needle");
108 await _client.PostAsJsonAsync("/api/v1/repos/search-ui/issues", new { title = "Find the Needle" });
109
110 var view = await _client.GetAsync("/view/repos/search-ui/search?q=Needle");
111 view.EnsureSuccessStatusCode();
112 var html = await view.Content.ReadAsStringAsync();
113
114 Assert.Contains("search-page-form", html, StringComparison.Ordinal);
115 Assert.Contains("#1", html, StringComparison.Ordinal);
116 Assert.Contains("Find the Needle", html, StringComparison.Ordinal);
117 Assert.Contains("src/Needle.cs", html, StringComparison.Ordinal);
118 }
119}
120
View only · write via MCP/CIDE