internal/httpd/suggestion_test.go
74 lines · 3293 bytes
1package httpd
2
3import (
4 "html/template"
5 "strings"
6 "testing"
7
8 "gitbay.org/gitbay/internal/control"
9 "gitbay.org/gitbay/internal/store"
10 "gitbay.org/gitbay/internal/web"
11)
12
13func renderSuggestion(t *testing.T, sg *control.SuggestionOut, canApply bool) string {
14 t.Helper()
15 view := newSuggestionView(sg, canApply, "gitbay mr apply-suggestion alice/app 1 7")
16 var sb strings.Builder
17 if err := web.Render(&sb, "mr.html", mrPageData{
18 repoPage: testRepoPage(), MR: testMR("open"), View: "conversation",
19 DetachedThreads: []diffThread{{ID: 7, Suggestion: view,
20 Comments: []renderedComment{{Author: "bob", BodyHTML: template.HTML("<p>try</p>")}}}},
21 }); err != nil {
22 t.Fatalf("render: %v", err)
23 }
24 return sb.String()
25}
26
27// A suggestion renders as the lines it replaces and the ones it proposes,
28// with a button for someone who can push to the source branch.
29func TestSuggestionRendersAsDiff(t *testing.T) {
30 sg := &control.SuggestionOut{StartLine: 4, EndLine: 5, Original: "old a\r\nold b\r\n",
31 Replacement: "new a\n", Apply: "server"}
32 out := renderSuggestion(t, sg, true)
33 for _, w := range []string{
34 `<tr class="del"><td class="ln">4</td><td class="src">old a</td>`,
35 `<tr class="del"><td class="ln">5</td><td class="src">old b</td>`,
36 `<tr class="add"><td class="ln">4</td><td class="src">new a</td>`,
37 `action="/krz/gitbay/mrs/42/suggestion"`, `name="thread" value="7"`, "Apply suggestion",
38 } {
39 if !strings.Contains(out, w) {
40 t.Errorf("page lacks %q", w)
41 }
42 }
43 if out := renderSuggestion(t, sg, false); strings.Contains(out, "Apply suggestion") {
44 t.Error("apply button shown to someone who cannot push to the source branch")
45 }
46}
47
48// Where the server cannot sign, the page gives the command; an outdated
49// suggestion says why and offers neither.
50func TestSuggestionLocalAndOutdated(t *testing.T) {
51 local := renderSuggestion(t, &control.SuggestionOut{StartLine: 1, EndLine: 1, Original: "a\n",
52 Replacement: "b\n", Apply: "local"}, true)
53 if !strings.Contains(local, "<code>gitbay mr apply-suggestion alice/app 1 7</code>") || strings.Contains(local, "Apply suggestion</button>") {
54 t.Error("require-signed suggestion does not give the CLI command in place of the button")
55 }
56 stale := renderSuggestion(t, &control.SuggestionOut{StartLine: 1, EndLine: 1, Original: "a\n",
57 Replacement: "b\n", Apply: "server", Outdated: true, Reason: "the lines it replaces have changed"}, true)
58 if !strings.Contains(stale, "outdated suggestion: the lines it replaces have changed") || strings.Contains(stale, "Apply suggestion</button>") {
59 t.Error("outdated suggestion is not marked, or still offers the button")
60 }
61}
62
63// The thread body renders without the raw block the diff stands in for.
64func TestAttachThreadsStripsSuggestionBlock(t *testing.T) {
65 md := func(src, _ string) template.HTML { return template.HTML(src) }
66 cm := store.DiffComment{ID: 3, Author: "bob", HeadSHA: "h", Path: "a.go", Side: "new", Line: 2,
67 Body: "try this\n```suggestion\nx\n```\n"}
68 view := &suggestionView{}
69 _, detached := attachThreads(nil, []store.DiffComment{cm}, "h", md, reviewRights{},
70 map[int64]*suggestionView{3: view})
71 if len(detached) != 1 || detached[0].Suggestion != view || string(detached[0].Comments[0].BodyHTML) != "try this" {
72 t.Fatalf("thread = %+v", detached)
73 }
74}