Commit 508463cf79
508463cf79be7509772a2a151ea1f7c9fce1dc9e
parent: c0b5c739d1
Verified · cmc
cmc <hello@cleberg.net> · 2026-09-28 22:20 UTC
web: Discussion heading before the comment thread on issue and MR pages
Ref #271
Layout: unified · split
internal/httpd/issuecreate_test.go
+27
| @@ -1,6 +1,7 @@ |
| 1 | package httpd |
1 | package httpd |
| 2 | |
2 | |
| 3 | import ( |
3 | import ( |
| |
4 | "html/template" |
| 4 | "net/http" |
5 | "net/http" |
| 5 | "net/http/httptest" |
6 | "net/http/httptest" |
| 6 | "net/url" |
7 | "net/url" |
| @@ -10,8 +11,34 @@ import ( |
| 10 | |
11 | |
| 11 | "gitbay.org/gitbay/internal/config" |
12 | "gitbay.org/gitbay/internal/config" |
| 12 | "gitbay.org/gitbay/internal/store" |
13 | "gitbay.org/gitbay/internal/store" |
| |
14 | "gitbay.org/gitbay/internal/web" |
| 13 | ) |
15 | ) |
| 14 | |
16 | |
| |
17 | // A heading precedes the issue's comment thread, matching the merge |
| |
18 | // request page, so a screen-reader user skimming by heading has a |
| |
19 | // landmark before the first comment rather than falling straight from |
| |
20 | // the edit box into the body (#271). |
| |
21 | func TestIssuePageHasDiscussionHeading(t *testing.T) { |
| |
22 | var sb strings.Builder |
| |
23 | if err := web.Render(&sb, "issue.html", struct { |
| |
24 | repoPage |
| |
25 | Issue store.Issue |
| |
26 | BodyHTML template.HTML |
| |
27 | Comments []renderedComment |
| |
28 | CanEdit bool |
| |
29 | CanWrite bool |
| |
30 | Milestones []store.Milestone |
| |
31 | Notice string |
| |
32 | LabelColors map[string]template.CSS |
| |
33 | Draft *draft |
| |
34 | }{repoPage: testRepoPage(), Issue: store.Issue{Number: 1, Title: "bug", Author: "cmc", State: "open"}}); err != nil { |
| |
35 | t.Fatalf("render: %v", err) |
| |
36 | } |
| |
37 | if !strings.Contains(sb.String(), "<h2>Discussion</h2>") { |
| |
38 | t.Error("no Discussion heading") |
| |
39 | } |
| |
40 | } |
| |
41 | |
| 15 | // sessionCookieFor gives uid a real web session, the way canWriteRepo's |
42 | // sessionCookieFor gives uid a real web session, the way canWriteRepo's |
| 16 | // call to s.viewer(r) needs (internal/httpd/accounts.go:37-47), since |
43 | // call to s.viewer(r) needs (internal/httpd/accounts.go:37-47), since |
| 17 | // issueCreateForm gates the milestone/assignee fields on it rather than |
44 | // issueCreateForm gates the milestone/assignee fields on it rather than |
internal/httpd/mrpage_test.go
+15
| @@ -59,6 +59,21 @@ func TestMRDiffViewNamesAPrunedHead(t *testing.T) { |
| 59 | } |
59 | } |
| 60 | } |
60 | } |
| 61 | |
61 | |
| |
62 | // A heading precedes the comment thread, so a screen-reader user |
| |
63 | // skimming by heading does not fall from the aside's groups straight |
| |
64 | // into the first comment with no landmark (#271). |
| |
65 | func TestMRPageHasDiscussionHeading(t *testing.T) { |
| |
66 | var sb strings.Builder |
| |
67 | if err := web.Render(&sb, "mr.html", mrPageData{ |
| |
68 | repoPage: testRepoPage(), MR: testMR("open"), View: "conversation", |
| |
69 | }); err != nil { |
| |
70 | t.Fatalf("render: %v", err) |
| |
71 | } |
| |
72 | if !strings.Contains(sb.String(), "<h2>Discussion</h2>") { |
| |
73 | t.Error("no Discussion heading") |
| |
74 | } |
| |
75 | } |
| |
76 | |
| 62 | // The watch button names all three states it cycles through, including |
77 | // The watch button names all three states it cycles through, including |
| 63 | // muted, which MR 1 made reachable (#271). |
78 | // muted, which MR 1 made reachable (#271). |
| 64 | func TestRepoHeaderWatchButtonNamesMutedState(t *testing.T) { |
79 | func TestRepoHeaderWatchButtonNamesMutedState(t *testing.T) { |
internal/web/templates/issue.html
+1
| @@ -10,6 +10,7 @@ |
| 10 | |
10 | |
| 11 | <div class="withaside"> |
11 | <div class="withaside"> |
| 12 | <div class="mainside"> |
12 | <div class="mainside"> |
| |
13 | <h2>Discussion</h2> |
| 13 | {{if .CanEdit}}<details class="editbox"{{if .Draft.Is "edit"}} open{{end}}><summary>edit</summary> |
14 | {{if .CanEdit}}<details class="editbox"{{if .Draft.Is "edit"}} open{{end}}><summary>edit</summary> |
| 14 | {{if .Draft.Is "edit"}}{{template "previewblock" .Draft.HTML}}{{end}} |
15 | {{if .Draft.Is "edit"}}{{template "previewblock" .Draft.HTML}}{{end}} |
| 15 | <form method="post" action="/{{.Repo.OwnerName}}/{{.Repo.Name}}/issues/{{.Issue.Number}}/edit" class="commentform"> |
16 | <form method="post" action="/{{.Repo.OwnerName}}/{{.Repo.Name}}/issues/{{.Issue.Number}}/edit" class="commentform"> |
internal/web/templates/mr.html
+1
| @@ -26,6 +26,7 @@ |
| 26 | |
26 | |
| 27 | {{if eq .View "conversation"}} |
27 | {{if eq .View "conversation"}} |
| 28 | <div class="prose"> |
28 | <div class="prose"> |
| |
29 | <h2>Discussion</h2> |
| 29 | {{if .CanEdit}}<details class="editbox"{{if .Draft.Is "edit"}} open{{end}}><summary>Edit</summary> |
30 | {{if .CanEdit}}<details class="editbox"{{if .Draft.Is "edit"}} open{{end}}><summary>Edit</summary> |
| 30 | {{if .Draft.Is "edit"}}{{template "previewblock" .Draft.HTML}}{{end}} |
31 | {{if .Draft.Is "edit"}}{{template "previewblock" .Draft.HTML}}{{end}} |
| 31 | <form method="post" action="{{$base}}/edit" class="commentform"> |
32 | <form method="post" action="{{$base}}/edit" class="commentform"> |