internal/control/orglabel_test.go

v1.24.1
gitbay/internal/control/orglabel_test.go history · blame · raw

125 lines · 4991 bytes

  1package control
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gitbay.org/gitbay/internal/protocol"
  8)
  9
 10func TestOrgLabelSetListRemove(t *testing.T) {
 11	f := newOrgFixture(t)
 12	// Two repos already hold bug; the org set folds them in.
 13	f.st.SetLabel(f.core, "bug", "")
 14	f.st.SetLabel(f.priv, "bug", "")
 15	c, out := f.ctx(f.alice)
 16	if code := runOrgLabelSet(c, []string{"acme", "bug", "--color", "ff0000"}); code != protocol.ExitOK ||
 17		!strings.Contains(out.String(), `"folded":2`) {
 18		t.Fatalf("set: exit %d %s", code, out.String())
 19	}
 20	out.Reset()
 21	if code := runOrgLabelList(c, []string{"acme"}); code != protocol.ExitOK ||
 22		!strings.Contains(out.String(), `"name":"bug"`) || !strings.Contains(out.String(), `"color":"#ff0000"`) {
 23		t.Fatalf("list: exit %d %s", code, out.String())
 24	}
 25	out.Reset()
 26	if code := runOrgLabelRemove(c, []string{"acme", "bug"}); code != protocol.ExitOK {
 27		t.Fatalf("remove: exit %d %s", code, out.String())
 28	}
 29	out.Reset()
 30	if code := runOrgLabelRemove(c, []string{"acme", "bug"}); code != protocol.ExitNotFound {
 31		t.Fatalf("second remove: exit %d %s", code, out.String())
 32	}
 33}
 34
 35func TestOrgLabelWritesNeedOrgAdmin(t *testing.T) {
 36	f := newOrgFixture(t)
 37	c, out := f.ctx(f.bob)
 38	if code := runOrgLabelSet(c, []string{"acme", "bug"}); code != protocol.ExitDenied {
 39		t.Fatalf("member set: exit %d %s", code, out.String())
 40	}
 41	if code := runOrgLabelRemove(c, []string{"acme", "bug"}); code != protocol.ExitDenied {
 42		t.Fatalf("member remove: exit %d %s", code, out.String())
 43	}
 44	c, out = f.ctx(f.alice)
 45	if code := runOrgLabelSet(c, []string{"nope", "bug"}); code != protocol.ExitNotFound {
 46		t.Fatalf("missing org: exit %d %s", code, out.String())
 47	}
 48	if code := runOrgLabelSet(c, []string{"acme", "bug", "--color", "zz"}); code != protocol.ExitUsage {
 49		t.Fatalf("bad colour: exit %d %s", code, out.String())
 50	}
 51}
 52
 53func TestOrgLabelListVisibility(t *testing.T) {
 54	f := newOrgFixture(t)
 55	f.st.SetOrgLabel(f.org, "bug", "")
 56	// Members read; an outsider reads because acme/core is public.
 57	for _, uid := range []int64{f.bob, f.carol} {
 58		c, out := f.ctx(uid)
 59		if code := runOrgLabelList(c, []string{"acme"}); code != protocol.ExitOK {
 60			t.Fatalf("user %d list: exit %d %s", uid, code, out.String())
 61		}
 62	}
 63	// With every repo private, the outsider is refused, not told the org
 64	// is missing.
 65	f.st.SetRepoVisibility(f.core.ID, "private")
 66	c, out := f.ctx(f.carol)
 67	if code := runOrgLabelList(c, []string{"acme"}); code != protocol.ExitDenied ||
 68		!strings.Contains(out.String(), "visible to its members") {
 69		t.Fatalf("outsider list: exit %d %s", code, out.String())
 70	}
 71}
 72
 73func TestOrgMilestoneLifecycle(t *testing.T) {
 74	f := newOrgFixture(t)
 75	f.st.CreateMilestone(f.core, "v1", "", "")
 76	c, out := f.ctx(f.alice)
 77	if code := runOrgMilestoneCreate(c, []string{"acme", "v1", "--due", "2027-01-01"}); code != protocol.ExitOK ||
 78		!strings.Contains(out.String(), `"folded":1`) {
 79		t.Fatalf("create: exit %d %s", code, out.String())
 80	}
 81	out.Reset()
 82	if code := runOrgMilestoneCreate(c, []string{"acme", "v1"}); code != protocol.ExitFailure {
 83		t.Fatalf("duplicate create: exit %d %s", code, out.String())
 84	}
 85	out.Reset()
 86	if code := runOrgMilestoneCreate(c, []string{"acme", "v2", "--due", "soon"}); code != protocol.ExitUsage {
 87		t.Fatalf("bad due: exit %d %s", code, out.String())
 88	}
 89	out.Reset()
 90	// An issue in each repo attaches by title; progress spans both.
 91	f.st.CreateIssue(f.core.ID, f.alice, "c1", "", "md")
 92	f.st.CreateIssue(f.priv.ID, f.alice, "p1", "", "md")
 93	runIssueMilestone(c, []string{"acme/core", "1", "v1"})
 94	runIssueMilestone(c, []string{"acme/priv", "1", "v1"})
 95	out.Reset()
 96	if code := runOrgMilestoneList(c, []string{"acme"}); code != protocol.ExitOK ||
 97		!strings.Contains(out.String(), `"open":2`) || !strings.Contains(out.String(), `"due":"2027-01-01"`) {
 98		t.Fatalf("list: exit %d %s", code, out.String())
 99	}
100	out.Reset()
101	// carol reads only the public repo's count.
102	cc, cout := f.ctx(f.carol)
103	if code := runOrgMilestoneList(cc, []string{"acme"}); code != protocol.ExitOK || !strings.Contains(cout.String(), `"open":1`) {
104		t.Fatalf("outsider list: exit %d %s", code, cout.String())
105	}
106	if code := runOrgMilestoneClose(c, []string{"acme", "v1"}); code != protocol.ExitOK {
107		t.Fatalf("close: exit %d %s", code, out.String())
108	}
109	out.Reset()
110	if code := runOrgMilestoneList(c, []string{"acme"}); code != protocol.ExitOK || strings.Contains(out.String(), `"title":"v1"`) {
111		t.Fatalf("closed still listed as open: %s", out.String())
112	}
113	out.Reset()
114	if code := runOrgMilestoneReopen(c, []string{"acme", "v1"}); code != protocol.ExitOK {
115		t.Fatalf("reopen: exit %d %s", code, out.String())
116	}
117	out.Reset()
118	if code := runOrgMilestoneClose(c, []string{"acme", "nope"}); code != protocol.ExitNotFound {
119		t.Fatalf("close missing: exit %d %s", code, out.String())
120	}
121	bc, bout := f.ctx(f.bob)
122	if code := runOrgMilestoneClose(bc, []string{"acme", "v1"}); code != protocol.ExitDenied {
123		t.Fatalf("member close: exit %d %s", code, bout.String())
124	}
125}