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 | 1 | package httpd |
| 2 | 2 | |
| 3 | 3 | import ( |
| 4 | "html/template" |
| 4 | 5 | "net/http" |
| 5 | 6 | "net/http/httptest" |
| 6 | 7 | "net/url" |
| @@ -10,8 +11,34 @@ import ( |
| 10 | 11 | |
| 11 | 12 | "gitbay.org/gitbay/internal/config" |
| 12 | 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 | 42 | // sessionCookieFor gives uid a real web session, the way canWriteRepo's |
| 16 | 43 | // call to s.viewer(r) needs (internal/httpd/accounts.go:37-47), since |
| 17 | 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 | 77 | // The watch button names all three states it cycles through, including |
| 63 | 78 | // muted, which MR 1 made reachable (#271). |
| 64 | 79 | func TestRepoHeaderWatchButtonNamesMutedState(t *testing.T) { |
internal/web/templates/issue.html
+1
| @@ -10,6 +10,7 @@ |
| 10 | 10 | |
| 11 | 11 | <div class="withaside"> |
| 12 | 12 | <div class="mainside"> |
| 13 | <h2>Discussion</h2> |
| 13 | 14 | {{if .CanEdit}}<details class="editbox"{{if .Draft.Is "edit"}} open{{end}}><summary>edit</summary> |
| 14 | 15 | {{if .Draft.Is "edit"}}{{template "previewblock" .Draft.HTML}}{{end}} |
| 15 | 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 | 27 | {{if eq .View "conversation"}} |
| 28 | 28 | <div class="prose"> |
| 29 | <h2>Discussion</h2> |
| 29 | 30 | {{if .CanEdit}}<details class="editbox"{{if .Draft.Is "edit"}} open{{end}}><summary>Edit</summary> |
| 30 | 31 | {{if .Draft.Is "edit"}}{{template "previewblock" .Draft.HTML}}{{end}} |
| 31 | 32 | <form method="post" action="{{$base}}/edit" class="commentform"> |