charts_test.gno
6.53 Kb · 139 lines
1package home
2
3import (
4 "encoding/base64"
5 "strconv"
6 "strings"
7 "testing"
8
9 "gno.land/p/nt/avl/v0"
10 "gno.land/p/nt/testutils/v0"
11 "gno.land/p/nt/uassert/v0"
12)
13
14func TestParseActivity(t *testing.T) {
15 a := parseActivity("title reviews; series gnolang/gno,Peer Dev; scale Peer Dev,10,commits; scale bad\n" +
16 "2025-12 3 21; 2026-01 0 0; bad; 2026-13 1 1; 2026-02 x 1; 2026-02 5; 2026-02 5 2")
17 uassert.Equal(t, "reviews", a.noun)
18 uassert.Equal(t, "Peer Dev", a.scaled)
19 uassert.Equal(t, 10, a.scaleDiv)
20 uassert.Equal(t, "commits", a.scaleUnit)
21 uassert.Equal(t, 3, len(a.months))
22 uassert.Equal(t, "Dec 25", a.months[0].label)
23 uassert.Equal(t, 21, a.months[0].counts[1])
24 uassert.Equal(t, 3, a.drawn(1, 21)) // rounded up
25 uassert.Equal(t, 3, a.drawn(0, 3)) // an unscaled series draws its count
26 uassert.Equal(t, "Jan 26", a.months[1].label)
27 uassert.Equal(t, "Feb", a.months[2].label)
28 uassert.Equal(t, 2, a.months[2].counts[1])
29
30 b := parseActivity("title x; series a; outline opened; updated 2026-09-24; " +
31 "2026-01 1 | 8; 2026-02 2 |; 2026-03 3 | y; 2026-04 4")
32 uassert.Equal(t, "opened", b.outline)
33 uassert.Equal(t, "24 Sep 2026", b.updated)
34 uassert.Equal(t, 2, len(b.months)) // "|" with no count and a non-number are rejected
35 uassert.Equal(t, 8, b.months[0].outline)
36 uassert.Equal(t, 0, b.months[1].outline)
37 uassert.Equal(t, "", formatDay("2026-13-01"))
38}
39
40func TestFillKeepsRepoColour(t *testing.T) {
41 // gnodaokit keeps its colour wherever it sits in a chart's series.
42 a := activity{series: []string{"gnolang/gno", "gnodaokit"}}
43 b := activity{series: []string{"gnodaokit"}}
44 uassert.Equal(t, repoFills["gnodaokit"], a.fill(1))
45 uassert.Equal(t, repoFills["gnodaokit"], b.fill(0))
46 c := activity{series: []string{"unlisted-repo", "Others"}}
47 uassert.Equal(t, c.fill(0), c.fill(0))
48 uassert.Equal(t, othersFill, c.fill(1))
49}
50
51func decodeChart(t *testing.T, out, alt string) string {
52 prefix := ", "prefix of "+alt)
54 raw, err := base64.StdEncoding.DecodeString(strings.TrimSuffix(out[len(prefix):], ")\n"))
55 uassert.NoError(t, err)
56 return string(raw)
57}
58
59func TestCharts(t *testing.T) {
60 prs := decodeChart(t, renderChart(activitySlot), "Merged pull requests per month, by repository")
61 for _, want := range []string{
62 ">104 merged pull requests</text>", ">gnolang/gno 70</text>", ">gnodaokit 6</text>",
63 ">Others 17</text>", ">Peer Dev 234 commits, drawn 1 per 10</text>", ">May 25</text>",
64 ">Jan 26</text>", ">23</text>", // June 2026: 16 + 6 + 1
65 ">5</text>", // July 2025 counts its 5 pull requests and not its 48 commits
66 } {
67 uassert.True(t, strings.Contains(prs, want), "pull requests chart: "+want)
68 }
69 // One amber bar per month with Peer Dev commits, May to November 2025, plus the legend's.
70 uassert.Equal(t, 8, strings.Count(prs, `fill="#fbbf24"`))
71 // One striped bar per month with opened pull requests, plus the legend's.
72 uassert.Equal(t, 15, strings.Count(prs, `fill="url(#o)"`))
73 uassert.True(t, strings.Contains(prs, ">gnolang/gno pull requests opened 131</text>"))
74 uassert.True(t, strings.Contains(prs, ">updated 24 Sep 2026</text>"))
75
76 revs := decodeChart(t, renderChart(reviewActivitySlot), "Reviews per month, by repository")
77 for _, want := range []string{">404 reviews</text>", ">gnolang/gno 357</text>", ">Others 47</text>", ">per month, on the same repositories</text>"} {
78 uassert.True(t, strings.Contains(revs, want), "reviews chart: "+want)
79 }
80 uassert.False(t, strings.Contains(revs, "#fbbf24"))
81 uassert.False(t, strings.Contains(revs, ">gnolove"))
82 uassert.False(t, strings.Contains(revs, `fill="url(#o)"`))
83 uassert.True(t, strings.Contains(revs, ">updated 24 Sep 2026</text>"))
84
85 page := Render("")
86 uassert.True(t, strings.Index(page, "Merged pull requests per month") < strings.Index(page, "Reviews per month"))
87}
88
89func TestChartEmpty(cur realm, t *testing.T) {
90 testing.SetRealm(testing.NewUserRealm(admin))
91 old := Get(activitySlot)
92 Set(cross(cur), activitySlot, "")
93 uassert.Equal(t, "", renderChart(activitySlot))
94 Set(cross(cur), activitySlot, old)
95 uassert.AbortsWithMessage(t, cur, "reserved section: banner", func() { Set(cross(cur), "banner", "x") })
96 uassert.AbortsWithMessage(t, cur, "reserved section: reviews", func() { Set(cross(cur), "reviews", "x") })
97 uassert.AbortsWithMessage(t, cur, "reserved section: hero", func() { Set(cross(cur), "hero", "x") })
98 uassert.AbortsWithMessage(t, cur, "reserved section: areachart", func() { Set(cross(cur), "areachart", "x") })
99}
100
101func TestAreas(t *testing.T) {
102 noun, subtitle, updated, slices := parseAreas("title x; subtitle y; updated 2026-09-24; slice 3 Docs; slice 0 Empty; slice y Bad; slice 2 Chain: tm2, consensus")
103 uassert.Equal(t, "x", noun)
104 uassert.Equal(t, "y", subtitle)
105 uassert.Equal(t, "24 Sep 2026", updated)
106 uassert.Equal(t, 2, len(slices))
107 uassert.Equal(t, "Chain: tm2, consensus", slices[1].label)
108
109 ring := decodeChart(t, renderAreas(), "Pull requests by area, merged into gnolang/gno")
110 for _, want := range []string{">70</text>", ">Pull requests by area</text>", ">merged into gnolang/gno</text>", ">Docs</text>", ">26</text>", ">37%</text>", ">updated 24 Sep 2026</text>"} {
111 uassert.True(t, strings.Contains(ring, want), "area ring: "+want)
112 }
113 // The shares add up to the whole ring, the last one taking the rounding.
114 uassert.True(t, strings.Contains(ring, `stroke-dasharray="371 1000" stroke-dashoffset="0"`))
115 uassert.True(t, strings.Contains(ring, `stroke-dashoffset="-941"`))
116 uassert.True(t, strings.Contains(ring, `stroke-dasharray="59 1000"`))
117}
118
119func TestHeartsWall(cur realm, t *testing.T) {
120 hearts = avl.NewTree()
121 wall := decodeChart(t, renderHeartsWall(), "0 hearts")
122 uassert.Equal(t, wallCols, strings.Count(wall, `<use href="#h"`))
123 uassert.Equal(t, 0, strings.Count(wall, `fill="#e63946"`))
124 for i := 0; i < 25; i++ {
125 hearts.Set(testutils.TestAddress("fan"+strconv.Itoa(i)).String(), int64(i))
126 }
127 wall = decodeChart(t, renderHeartsWall(), "25 hearts")
128 uassert.Equal(t, 2*wallCols, strings.Count(wall, `<use href="#h"`))
129 uassert.Equal(t, 25, strings.Count(wall, `fill="#e63946"`))
130 uassert.False(t, strings.Contains(wall, "more</text>"))
131 for i := 25; i < 250; i++ {
132 hearts.Set(testutils.TestAddress("fan"+strconv.Itoa(i)).String(), int64(i))
133 }
134 wall = decodeChart(t, renderHeartsWall(), "250 hearts")
135 uassert.Equal(t, wallCols*wallMaxRows, strings.Count(wall, `fill="#e63946"`))
136 uassert.True(t, strings.Contains(wall, ">and 10 more</text>"))
137 uassert.True(t, strings.Contains(wall, `<text x="348" y="316" text-anchor="middle" fill="#9fc9b4" style="font:13px sans-serif">and 10 more</text>`))
138 hearts = avl.NewTree()
139}