Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Blame · server/activity_pages_test.go

Line attribution on main · 75 line(s)

c8cdb6ac
Keenan Nemetz
9d ago
1 package server_test
2
3 // The activity feed is complete and paginated: the pages show the whole history,
4 // one page at a time, with the filters travelling through the page links.
5
6 import (
7 "fmt"
8 "strings"
9 "testing"
10 "time"
11
d37d301f
Keenan Nemetz
16h ago
12 "rodent.software/vole/metadata"
c8cdb6ac
Keenan Nemetz
9d ago
13 )
14
15 func TestActivityFeedIsPaginatedAcrossItsWholeHistory(t *testing.T) {
16 t.Parallel()
17 f := newFixture(t)
18 f.publish(f.repo)
19 m := mustRepo(t, f)
20 base := time.Date(2026, 10, 30, 12, 0, 0, 0, time.UTC)
21 const total = 55
22 for i := 0; i < total; i++ {
23 iss, err := metadata.NewIssue(fmt.Sprintf("issue %02d", i), "body\n", "keenan", nil, nil, base.Add(time.Duration(i)*time.Minute))
24 if err != nil {
25 t.Fatal(err)
26 }
27 if err := metadata.CreateIssue(m.Git(), iss, "keenan"); err != nil {
28 t.Fatal(err)
29 }
30 }
31
32 count := func(body string) int { return strings.Count(body, `class="activity-event"`) }
33
34 // Repository feed: page one is the newest 50 of 55, page two is the rest.
ed03b3d1
Keenan Nemetz
3h ago
35 code, body := f.get("/" + f.repo + "/activity")
c8cdb6ac
Keenan Nemetz
9d ago
36 if code != 200 {
37 t.Fatalf("activity page = %d", code)
38 }
39 if n := count(body); n != 50 {
40 t.Fatalf("page one shows %d events, want 50", n)
41 }
42 if !strings.Contains(body, "issue 54") || strings.Contains(body, "issue 00") {
43 t.Fatalf("page one is not the newest 50:\n%s", body)
44 }
45 if !strings.Contains(body, "Showing 1–50 of 55") || !strings.Contains(body, "page=2") {
46 t.Fatalf("page one has no pager:\n%s", body)
47 }
48
ed03b3d1
Keenan Nemetz
3h ago
49 _, body = f.get("/" + f.repo + "/activity?page=2")
c8cdb6ac
Keenan Nemetz
9d ago
50 if n := count(body); n != 5 {
51 t.Fatalf("page two shows %d events, want 5", n)
52 }
53 if !strings.Contains(body, "issue 00") || strings.Contains(body, "issue 54") {
54 t.Fatalf("page two is not the oldest 5:\n%s", body)
55 }
56 if !strings.Contains(body, "Showing 51–55 of 55") {
57 t.Fatalf("page two does not describe itself:\n%s", body)
58 }
59
60 // The instance feed carries the same history.
ed03b3d1
Keenan Nemetz
3h ago
61 _, body = f.get("/-/activity")
c8cdb6ac
Keenan Nemetz
9d ago
62 if n := count(body); n != 50 {
63 t.Fatalf("instance page one shows %d events, want 50", n)
64 }
ed03b3d1
Keenan Nemetz
3h ago
65 _, body = f.get("/-/activity?page=2")
c8cdb6ac
Keenan Nemetz
9d ago
66 if n := count(body); n != 5 || !strings.Contains(body, "issue 00") {
67 t.Fatalf("instance page two shows %d events:\n%s", n, body)
68 }
69
70 // A filter travels with the page links, so paging never widens the feed.
ed03b3d1
Keenan Nemetz
3h ago
71 _, body = f.get("/" + f.repo + "/activity?kind=issues&actor=keenan")
c8cdb6ac
Keenan Nemetz
9d ago
72 if !strings.Contains(body, "kind=issue") || !strings.Contains(body, "actor=keenan") || !strings.Contains(body, "page=2") {
73 t.Fatalf("filtered pager lost a filter:\n%s", body)
74 }
75 }