repos / git-pr

a self-hosted git collaboration server
git clone https://github.com/picosh/git-pr.git

Eric Bower  ·  2024-11-06

e2e_test.go

  1package git
  2
  3import (
  4	"log/slog"
  5	"os"
  6	"testing"
  7	"time"
  8
  9	"github.com/gkampitakis/go-snaps/snaps"
 10	"github.com/picosh/git-pr/fixtures"
 11	"github.com/picosh/git-pr/util"
 12)
 13
 14func TestE2E(t *testing.T) {
 15	testSingleTenantE2E(t)
 16	testMultiTenantE2E(t)
 17}
 18
 19func testSingleTenantE2E(t *testing.T) {
 20	t.Log("single tenant end-to-end tests")
 21	dataDir := util.CreateTmpDir()
 22	defer func() {
 23		os.RemoveAll(dataDir)
 24	}()
 25	suite := setupTest(dataDir, cfgSingleTenantTmpl)
 26	done := make(chan error)
 27	go GitSshServer(suite.cfg, done)
 28	// Hack to wait for startup
 29	time.Sleep(time.Millisecond * 100)
 30
 31	t.Log("User cannot create repo")
 32	_, err := suite.userKey.Cmd(suite.patch, "pr create test")
 33	if err == nil {
 34		t.Fatal("user should not be able to create a PR")
 35	}
 36	suite.adminKey.MustCmd(suite.patch, "pr create test")
 37
 38	t.Log("User should be able to create a patch")
 39	suite.userKey.MustCmd(suite.patch, "pr create test")
 40
 41	t.Log("Snapshot test ls command")
 42	actual, err := suite.userKey.Cmd(nil, "pr ls")
 43	bail(err)
 44	snaps.MatchSnapshot(t, actual)
 45
 46	done <- nil
 47}
 48
 49func testMultiTenantE2E(t *testing.T) {
 50	t.Log("multi tenant end-to-end tests")
 51	dataDir := util.CreateTmpDir()
 52	defer func() {
 53		os.RemoveAll(dataDir)
 54	}()
 55	suite := setupTest(dataDir, cfgMultiTenantTmpl)
 56	done := make(chan error)
 57	go GitSshServer(suite.cfg, done)
 58
 59	time.Sleep(time.Millisecond * 100)
 60
 61	t.Log("Admin should be able to create a repo")
 62	suite.adminKey.MustCmd(nil, "repo create test")
 63
 64	t.Log("Accepted pr")
 65	suite.userKey.MustCmd(suite.patch, "pr create admin/test")
 66	suite.userKey.MustCmd(nil, "pr edit 1 Accepted patch")
 67	_, err := suite.userKey.Cmd(nil, "pr accept 1")
 68	if err == nil {
 69		t.Fatal("contrib should not be able to accept their own PR")
 70	}
 71	suite.adminKey.MustCmd(nil, "pr accept 1")
 72
 73	t.Log("Closed pr (admin)")
 74	suite.userKey.MustCmd(suite.patch, "pr create test")
 75	suite.userKey.MustCmd(nil, "pr edit 2 Closed patch (admin)")
 76	suite.adminKey.MustCmd(nil, "pr close 2")
 77
 78	t.Log("Closed pr (contributor)")
 79	suite.userKey.MustCmd(suite.patch, "pr create test")
 80	suite.userKey.MustCmd(nil, "pr edit 3 Closed patch (contributor)")
 81	suite.userKey.MustCmd(nil, "pr close 3")
 82
 83	t.Log("Reviewed pr")
 84	suite.userKey.MustCmd(suite.patch, "pr create test")
 85	suite.userKey.MustCmd(nil, "pr edit 4 Reviewed patch")
 86	suite.adminKey.MustCmd(suite.otherPatch, "pr add --review 4")
 87
 88	t.Log("Accepted pr with review")
 89	suite.userKey.MustCmd(suite.patch, "pr create test")
 90	suite.userKey.MustCmd(nil, "pr edit 5 Accepted patch with review")
 91	suite.adminKey.MustCmd(suite.otherPatch, "pr add --accept 5")
 92
 93	t.Log("Closed pr with review")
 94	suite.userKey.MustCmd(suite.patch, "pr create test")
 95	suite.userKey.MustCmd(nil, "pr edit 6 Closed patch with review")
 96	suite.adminKey.MustCmd(suite.otherPatch, "pr add --close 6")
 97
 98	t.Log("Create pr with user repo and user can accept")
 99	suite.userKey.MustCmd(nil, "repo create ai")
100	suite.adminKey.MustCmd(suite.patch, "pr create contributor/ai")
101	suite.userKey.MustCmd(suite.otherPatch, "pr accept 7")
102
103	t.Log("Create pr with user repo and admin can accept")
104	suite.adminKey.MustCmd(nil, "repo create ai")
105	suite.userKey.MustCmd(suite.patch, "pr create admin/ai")
106	suite.adminKey.MustCmd(suite.otherPatch, "pr add --accept 8")
107
108	t.Log("Create pr with default `bin` repo")
109	actual, err := suite.userKey.Cmd(suite.patch, "pr create")
110	bail(err)
111	snaps.MatchSnapshot(t, actual)
112
113	t.Log("Snapshot test ls command")
114	actual, err = suite.userKey.Cmd(nil, "pr ls")
115	bail(err)
116	snaps.MatchSnapshot(t, actual)
117
118	t.Log("Snapshot test logs command")
119	actual, err = suite.userKey.Cmd(nil, "logs --repo admin/ai")
120	bail(err)
121	snaps.MatchSnapshot(t, actual)
122
123	done <- nil
124}
125
126type TestSuite struct {
127	cfg        *GitCfg
128	userKey    util.UserSSH
129	adminKey   util.UserSSH
130	patch      []byte
131	otherPatch []byte
132}
133
134func setupTest(dataDir string, cfgTmpl string) TestSuite {
135	opts := &slog.HandlerOptions{
136		AddSource: true,
137	}
138	logger := slog.New(
139		slog.NewTextHandler(os.Stdout, opts),
140	)
141
142	adminKey, userKey := util.GenerateKeys()
143	cfgPath := util.CreateCfgFile(dataDir, cfgTmpl, adminKey)
144	LoadConfigFile(cfgPath, logger)
145	cfg := NewGitCfg(logger)
146
147	// so outputs dont show dates
148	cfg.TimeFormat = ""
149
150	patch, err := fixtures.Fixtures.ReadFile("single.patch")
151	if err != nil {
152		panic(err)
153	}
154	otherPatch, err := fixtures.Fixtures.ReadFile("with-cover.patch")
155	if err != nil {
156		panic(err)
157	}
158
159	return TestSuite{cfg, userKey, adminKey, patch, otherPatch}
160}
161
162var cfgSingleTenantTmpl = `
163url = "localhost"
164data_dir = %q
165admins = [%q]
166time_format = "01/02/2006 15:04:05 07:00"
167create_repo = "admin"`
168
169var cfgMultiTenantTmpl = `
170url = "localhost"
171data_dir = %q
172admins = [%q]
173time_format = "01/02/2006 15:04:05 07:00"
174create_repo = "user"`