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.

sparkline_test.gno

3.66 Kb · 125 lines
  1package sparkline
  2
  3import (
  4	"testing"
  5
  6	"gno.land/p/nt/uassert/v0"
  7)
  8
  9func TestInts(t *testing.T) {
 10	tests := []struct {
 11		name   string
 12		values []int
 13		want   string
 14	}{
 15		{"empty", nil, ""},
 16		{"empty slice", []int{}, ""},
 17		// A single value is its own min and max, i.e. flat: mid-ramp.
 18		{"single", []int{42}, "▅"},
 19		{"flat", []int{7, 7, 7}, "▅▅▅"},
 20		{"flat at zero", []int{0, 0}, "▅▅"},
 21		{"two apart", []int{0, 1}, "▁█"},
 22		{"ramp", []int{0, 1, 2, 3, 4, 5, 6, 7}, "▁▂▃▄▅▆▇█"},
 23		{"descending", []int{7, 6, 5, 4, 3, 2, 1, 0}, "█▇▆▅▄▃▂▁"},
 24		{"negatives only", []int{-7, -4, 0}, "▁▄█"},
 25		{"spans zero", []int{-7, 0, 7}, "▁▄█"},
 26		{"wide range", []int{0, 50, 100}, "▁▄█"},
 27	}
 28	for _, tt := range tests {
 29		t.Run(tt.name, func(t *testing.T) {
 30			uassert.Equal(t, tt.want, Ints(tt.values))
 31		})
 32	}
 33}
 34
 35func TestScaledClampsOutliers(t *testing.T) {
 36	// The window is the contract: anything outside it pins to an end rather
 37	// than rescaling the picture or panicking.
 38	uassert.Equal(t, "▁▁▄██", Scaled([]int{-100, 0, 50, 100, 999}, 0, 100))
 39}
 40
 41func TestScaledEmpty(t *testing.T) {
 42	uassert.Equal(t, "", Scaled(nil, 0, 10))
 43}
 44
 45func TestScaledFlatWindow(t *testing.T) {
 46	// hi <= lo carries no shape; every value lands mid-ramp.
 47	uassert.Equal(t, "▅▅▅", Scaled([]int{1, 500, 9}, 5, 5))
 48	uassert.Equal(t, "▅▅", Scaled([]int{1, 2}, 10, 3))
 49}
 50
 51func TestLevel(t *testing.T) {
 52	tests := []struct {
 53		name       string
 54		v, lo, hi  int
 55		want       int
 56	}{
 57		{"at floor", 0, 0, 7, 0},
 58		{"at ceiling", 7, 0, 7, 7},
 59		{"below floor clamps", -5, 0, 7, 0},
 60		{"above ceiling clamps", 99, 0, 7, 7},
 61		{"flat window", 3, 5, 5, Steps / 2},
 62		{"inverted window", 3, 9, 2, Steps / 2},
 63		// Floor rounding: only hi itself reaches the top.
 64		{"just below ceiling", 99, 0, 100, 6},
 65		{"exact ceiling", 100, 0, 100, 7},
 66		{"midpoint", 50, 0, 100, 3},
 67	}
 68	for _, tt := range tests {
 69		t.Run(tt.name, func(t *testing.T) {
 70			uassert.Equal(t, tt.want, Level(tt.v, tt.lo, tt.hi))
 71		})
 72	}
 73}
 74
 75// Level must stay inside the ramp for every input, including the extremes that
 76// make the scaling arithmetic wrap. An out-of-range index here would panic the
 77// realm that called Scaled, so this is the load-bearing invariant.
 78func TestLevelAlwaysInRange(t *testing.T) {
 79	const minInt = -maxInt - 1
 80	vals := []int{minInt, -maxInt, -1000, -1, 0, 1, 1000, maxInt}
 81	windows := [][2]int{
 82		{0, 7}, {0, 100}, {-100, 100}, {5, 5}, {9, 2},
 83		{minInt, maxInt}, // span wraps int
 84		{0, maxInt},      // span survives, but d*top would wrap
 85		{minInt, 0},
 86	}
 87	for _, w := range windows {
 88		for _, v := range vals {
 89			got := Level(v, w[0], w[1])
 90			if got < 0 || got >= Steps {
 91				t.Fatalf("Level(%d, %d, %d) = %d, outside [0,%d)", v, w[0], w[1], got, Steps)
 92			}
 93		}
 94	}
 95}
 96
 97// The huge-span path halves its way down to safe arithmetic; it must still be
 98// monotonic, or the picture would lie about the direction of the trend.
 99func TestLevelMonotonicOnHugeSpan(t *testing.T) {
100	prev := -1
101	for _, v := range []int{0, maxInt / 8, maxInt / 4, maxInt / 2, maxInt} {
102		got := Level(v, 0, maxInt)
103		if got < prev {
104			t.Fatalf("Level(%d, 0, maxInt) = %d, went down from %d", v, got, prev)
105		}
106		prev = got
107	}
108}
109
110func TestBounds(t *testing.T) {
111	lo, hi, ok := Bounds([]int{3, -1, 9, 4})
112	uassert.True(t, ok, "non-empty series should report ok")
113	uassert.Equal(t, -1, lo)
114	uassert.Equal(t, 9, hi)
115
116	lo, hi, ok = Bounds(nil)
117	uassert.False(t, ok, "empty series should report not-ok")
118	uassert.Equal(t, 0, lo)
119	uassert.Equal(t, 0, hi)
120}
121
122func TestLevelsRampIsEightRunes(t *testing.T) {
123	// Scaled indexes this ramp by Level's result, so the two must agree.
124	uassert.Equal(t, Steps, len([]rune(Levels)))
125}