Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

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 := "![" + alt + "](data:image/svg+xml;base64,"
 53	uassert.True(t, strings.HasPrefix(out, 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}