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

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}