internal/httpd/suggestion_test.go

v1.42.0
gitbay/internal/httpd/suggestion_test.go history · blame · raw

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}