internal/control/view_test.go

9df917e73a67d15adecc3f45976690f6fcd4e47a
gitbay/internal/control/view_test.go history · blame · raw

128 lines · 4050 bytes

  1package control
  2
  3import (
  4	"bytes"
  5	"strings"
  6	"testing"
  7
  8	"gitbay.org/gitbay/internal/protocol"
  9	"gitbay.org/gitbay/internal/store"
 10)
 11
 12func showIssue(t *testing.T, term Term) string {
 13	t.Helper()
 14	st, repo, uid := newQueueTestRepo(t)
 15	n, err := st.CreateIssue(repo.ID, uid, "A title", "Body with a [link](/x/y).", "md")
 16	if err != nil {
 17		t.Fatal(err)
 18	}
 19	issue, err := st.IssueByNumber(repo.ID, n)
 20	if err != nil {
 21		t.Fatal(err)
 22	}
 23	if err := st.AddIssueSystemComment(issue.ID, uid, "referenced in commit [abc1234567](/o/r/commit/abc) by [alice](/alice)"); err != nil {
 24		t.Fatal(err)
 25	}
 26	c, errOut := pruneCtx(st, t.TempDir(), store.User{ID: uid, Username: "alice"})
 27	c.Cfg.Server.SiteURL = "https://forge.test"
 28	c.Term = term
 29	if code := Dispatch(c, []string{"issue", "show", repo.Path(), "1"}); code != protocol.ExitOK {
 30		t.Fatalf("exit %d: %s", code, errOut)
 31	}
 32	return c.Stdout.(*bytes.Buffer).String()
 33}
 34
 35func TestIssueShowPlain(t *testing.T) {
 36	out := showIssue(t, Term{})
 37	for _, want := range []string{
 38		"#1  A title  open\n",
 39		"  author  alice, ",
 40		"  url     https://forge.test/",
 41		"Body with a link (https://forge.test/x/y).",
 42		"  · referenced in commit abc1234567 by alice  ",
 43	} {
 44		if !strings.Contains(out, want) {
 45			t.Errorf("missing %q in:\n%s", want, out)
 46		}
 47	}
 48	if strings.Contains(out, "\x1b") || strings.Contains(out, "](") {
 49		t.Errorf("markup or SGR in plain view:\n%s", out)
 50	}
 51}
 52
 53func TestIssueShowTerminal(t *testing.T) {
 54	out := showIssue(t, Term{Cols: 60, Color: true})
 55	if !strings.Contains(out, sgrGreen+"open"+sgrReset) {
 56		t.Errorf("state not coloured:\n%s", out)
 57	}
 58	if !strings.Contains(out, " UTC") {
 59		t.Errorf("no web-format timestamp:\n%s", out)
 60	}
 61	for _, line := range strings.Split(stripSGR(out), "\n") {
 62		if cells(line) > 60 {
 63			t.Errorf("line over 60 cells: %q", line)
 64		}
 65	}
 66}
 67
 68// TestIssueShowNarrowWraps: a long title and long labels must not push
 69// any line past the terminal width, and no content is lost to it.
 70func TestIssueShowNarrowWraps(t *testing.T) {
 71	st, repo, uid := newQueueTestRepo(t)
 72	title := strings.TrimSpace(strings.Repeat("a very long issue title that keeps going on and on ", 3))[:90]
 73	n, err := st.CreateIssue(repo.ID, uid, title, "body", "md")
 74	if err != nil {
 75		t.Fatal(err)
 76	}
 77	for _, name := range []string{"needs-review-before-merge", "blocked-on-release", "requires-design-signoff"} {
 78		if err := st.SetLabel(repo, name, "888888"); err != nil {
 79			t.Fatal(err)
 80		}
 81		if err := st.SetIssueLabel(repo, issueIDFor(t, st, repo.ID, n), name, true); err != nil {
 82			t.Fatal(err)
 83		}
 84	}
 85	// No SiteURL set: the url field stays a short path so it does not
 86	// itself force an unbreakable line over width, which is not what
 87	// this test is about (title/labels/author wrapping is).
 88	c, errOut := pruneCtx(st, t.TempDir(), store.User{ID: uid, Username: "alice"})
 89	c.Term = Term{Cols: 40, Color: true}
 90	if code := Dispatch(c, []string{"issue", "show", repo.Path(), "1"}); code != protocol.ExitOK {
 91		t.Fatalf("exit %d: %s", code, errOut)
 92	}
 93	out := c.Stdout.(*bytes.Buffer).String()
 94
 95	var titleLines []string
 96	inTitle := false
 97	for _, line := range strings.Split(stripSGR(out), "\n") {
 98		if cells(line) > 40 {
 99			t.Errorf("line over 40 cells: %q", line)
100		}
101		switch {
102		case strings.HasPrefix(line, "#1  "):
103			inTitle = true
104			titleLines = append(titleLines, strings.TrimPrefix(line, "#1  "))
105		case inTitle && strings.HasPrefix(line, "    "):
106			titleLines = append(titleLines, strings.TrimSpace(line))
107		default:
108			inTitle = false
109		}
110	}
111	got := strings.Join(strings.Fields(strings.Join(titleLines, " ")), " ")
112	want := strings.Join(strings.Fields(title+" open"), " ")
113	if got != want {
114		t.Errorf("title text lost across wrap: got %q, want %q", got, want)
115	}
116	if n := strings.Count(stripSGR(out), "open"); n != 1 {
117		t.Errorf("state word appears %d times, want 1:\n%s", n, out)
118	}
119}
120
121func issueIDFor(t *testing.T, st *store.Store, repoID, n int64) int64 {
122	t.Helper()
123	issue, err := st.IssueByNumber(repoID, n)
124	if err != nil {
125		t.Fatal(err)
126	}
127	return issue.ID
128}