e2e/feeds_test.go

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

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