e2e/feeds_test.go

v1.40.0
gitbay/e2e/feeds_test.go history · blame · raw

94 lines · 3468 bytes

 1package e2e
 2
 3import (
 4	"net/http"
 5	"os"
 6	"path/filepath"
 7	"strings"
 8	"testing"
 9)
10
11// Atom feeds for releases, commits and an owner's public activity, read
12// with no session; private repositories stay out of them (#192).
13func TestAtomFeeds(t *testing.T) {
14	t.Parallel()
15	inst := startInstance(t)
16	aliceKey := inst.newKey(t, "alice")
17	inst.admin(t, "admin", "user", "create", "alice", "--key", aliceKey+".pub")
18	for _, args := range [][]string{
19		{"repo", "create", "alice/app"},
20		{"repo", "create", "alice/secret", "--private"},
21	} {
22		if _, errOut, code := inst.ssh(t, aliceKey, "", args...); code != 0 {
23			t.Fatalf("%v: %s", args, errOut)
24		}
25	}
26	if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/feed.atom"); code == 0 || !strings.Contains(errOut, ".atom") {
27		t.Fatalf("a repository named like a feed was accepted: %d %s", code, errOut)
28	}
29	env := inst.gitEnv(aliceKey)
30	for _, name := range []string{"app", "secret"} {
31		dir := filepath.Join(t.TempDir(), name)
32		mustGit(t, t.TempDir(), env, "clone", "-q", inst.sshURL("alice/"+name), dir)
33		if err := os.WriteFile(filepath.Join(dir, "a.txt"), []byte("a\n"), 0o644); err != nil {
34			t.Fatal(err)
35		}
36		mustGit(t, dir, env, "checkout", "-q", "-b", "main")
37		mustGit(t, dir, env, "add", ".")
38		mustGit(t, dir, env, "commit", "-q", "-m", "first commit on "+name)
39		mustGit(t, dir, env, "tag", "v1.0")
40		mustGit(t, dir, env, "push", "-q", "origin", "main", "v1.0")
41		if _, errOut, code := inst.ssh(t, aliceKey, "", "release", "create", "alice/"+name, "v1.0",
42			"--title", "'First light'", "--notes", "'notes for "+name+"'"); code != 0 {
43			t.Fatalf("release create: %s", errOut)
44		}
45	}
46
47	anon := &http.Client{}
48	get := func(path string, want int) string {
49		t.Helper()
50		status, body := browserGet(t, anon, inst.base()+path)
51		if status != want {
52			t.Fatalf("GET %s: %d, want %d\n%s", path, status, want, body)
53		}
54		return body
55	}
56	resp, err := http.Get(inst.base() + "/alice/app/releases.atom")
57	if err != nil {
58		t.Fatal(err)
59	}
60	resp.Body.Close()
61	if ct := resp.Header.Get("Content-Type"); !strings.HasPrefix(ct, "application/atom+xml") {
62		t.Fatalf("content type %q", ct)
63	}
64	body := get("/alice/app/releases.atom", 200)
65	for _, want := range []string{`xmlns="http://www.w3.org/2005/Atom"`, "<title>v1.0: First light</title>", "notes for app", "/alice/app/releases#v1.0"} {
66		if !strings.Contains(body, want) {
67			t.Errorf("releases feed missing %s:\n%s", want, body)
68		}
69	}
70	for _, path := range []string{"/alice/app/log.atom", "/alice/app/log.atom/main"} {
71		if body := get(path, 200); !strings.Contains(body, "<title>first commit on app</title>") || !strings.Contains(body, "<name>t</name>") {
72			t.Errorf("%s:\n%s", path, body)
73		}
74	}
75	get("/alice/app/log.atom/nope", 404)
76	body = get("/alice/activity.atom", 200)
77	if !strings.Contains(body, "release.created alice/app v1.0") || strings.Contains(body, "secret") {
78		t.Errorf("activity feed:\n%s", body)
79	}
80	get("/nobody/activity.atom", 404)
81	get("/alice/secret/releases.atom", 404)
82	get("/alice/secret/log.atom", 404)
83
84	// The pages say where their feed is.
85	for path, feed := range map[string]string{
86		"/alice/app/releases": "/alice/app/releases.atom",
87		"/alice/app/log":      "/alice/app/log.atom/main",
88		"/alice":              "/alice/activity.atom",
89	} {
90		if body := get(path, 200); !strings.Contains(body, `type="application/atom+xml" href="`+feed+`"`) {
91			t.Errorf("%s has no discovery link to %s", path, feed)
92		}
93	}
94}