carlos / todomvc-bakeoff Public

Clone
git clone https://amadan.net/carlos/todomvc-bakeoff

Plain git — no account needed to clone.

Download

Download this file

1package report
2
3import (
4 "bytes"
5 "fmt"
6 "html"
7 "os"
8 "regexp"
9 "strconv"
10 "strings"
11 "testing"
12
13 b "bakeoff/harness"
14)
15
16func fixture() []b.AppResult {
17 live := b.AppResult{
18 Slug: "go", Language: "Go", Status: "LIVE", URL: "https://todo-go.bfj.oncarlos.com", Version: "abc1234",
19 Stack: "net/http, html/template, modernc.org/sqlite",
20 BehaviourJSOn: b.Behaviour{Passed: 35}, BehaviourJSOff: b.Behaviour{Passed: 33, Skipped: 2},
21 TTFBEmpty: b.Stats{N: 30, P50: 41.2}, TTFB50: b.Stats{N: 30, P50: 45.9},
22 Wake: []float64{120, 140, 130},
23 Load: []b.LoadResult{{Scenario: "read", Concurrency: 1, RPS: 20, Status: map[string]int{"200": 1}}, {Scenario: "read", Concurrency: 2, RPS: 40, Status: map[string]int{"200": 1}},
24 {Scenario: "read", Concurrency: 4, RPS: 41, Status: map[string]int{"200": 1}}, {Scenario: "toggle", Concurrency: 1, RPS: 15, Status: map[string]int{"200": 1}},
25 {Scenario: "toggle", Concurrency: 2, RPS: 30, Status: map[string]int{"200": 1}}, {Scenario: "toggle", Concurrency: 4, RPS: 31, ErrorRate: 0.4, Status: map[string]int{"303": 6, "503": 4}},
26 {Scenario: "read-after", Concurrency: 1, RPS: 20, Status: map[string]int{"200": 1}}, {Scenario: "read-after", Concurrency: 2, RPS: 9, ErrorRate: 0.5, Status: map[string]int{"200": 5, "502": 5}}},
27 Weight: b.Weight{HTMLBytes: 9000, JSBytes: 2400},
28 Code: b.CodeStats{Server: 300, Templates: 80, JS: 120, Tests: 200, Deps: 1},
29 Build: b.Build{ColdSeconds: 1097.4, WarmSeconds: 2, EditSeconds: 1.1, Bytes: 9_400_000, Host: "docs-t1"},
30 TokensBuild: b.Tokens{Output: 50000, CostUSD: 4.2, Seconds: 1800}, TokensFix: b.Tokens{Output: 5000, CostUSD: 0.5},
31 Readability: b.Readability{Overall: 8, Naming: 4, Structure: 4, Traceability: 5, Errors: 4, Comments: 3, Notes: "Clear & tidy <ok>"},
32 }
33 blocked := b.AppResult{Slug: "mojo", Language: "Mojo", Status: "BLOCKED platform: single-file binaries only"}
34 return []b.AppResult{live, blocked}
35}
36
37func TestRenderAllApps(t *testing.T) {
38 var buf bytes.Buffer
39 raw, err := os.ReadFile("../../copy-review/strings.json")
40 if err != nil {
41 t.Fatal(err)
42 }
43 copy, err := LoadStrings(raw)
44 if err != nil {
45 t.Fatal(err)
46 }
47 copy["page.intro"] = "Nine apps.\n\nOne brief."
48 copy["method.body"] = "- one\n- two [link](https://example.com)"
49 if err := Render(fixture(), copy, &buf); err != nil {
50 t.Fatal(err)
51 }
52 out := buf.String()
53 for _, want := range []string{
54 "Go", "Mojo", "single-file binaries only", "https://todo-go.bfj.oncarlos.com", "<svg",
55 "<p>Nine apps.</p>", `<a href="https://example.com">link</a>`, "Clear &amp; tidy &lt;ok&gt;", "9.4 MB", "2 connections", "2 connections · Carloku turned some requests away from 4", "35/35 · 33/33", "18.3 min", "1 connections · requests started failing from 2",
56 } {
57 if !strings.Contains(out, want) {
58 t.Errorf("output lacks %q", want)
59 }
60 }
61 for _, bad := range []string{"NaN", "<no value>", "Inf", "<script", "⟦"} {
62 if strings.Contains(out, bad) {
63 t.Errorf("output contains %q", bad)
64 }
65 }
66}
67
68func TestMissingCopyIsVisible(t *testing.T) {
69 var buf bytes.Buffer
70 if err := Render(fixture(), Copy{}, &buf); err != nil {
71 t.Fatal(err)
72 }
73 if !strings.Contains(buf.String(), "⟦page.title⟧") {
74 t.Fatal("a missing string must render as ⟦id⟧")
75 }
76}
77
78func TestValueLabelsFitTheChart(t *testing.T) {
79 c := Chart{Title: "t", Format: func(v float64) string { return fmt.Sprintf("%.0f connections", v) }, Rows: []Row{
80 {Language: "Rust", Value: 64, Suffix: " · Carloku turned some requests away from 128"},
81 {Language: "Go", Value: 8},
82 }}
83 svg := string(c.SVG())
84 re := regexp.MustCompile(`<text class="value" x="([0-9.]+)" y="[0-9]+">([^<]*)</text>`)
85 ms := re.FindAllStringSubmatch(svg, -1)
86 if len(ms) != 2 {
87 t.Fatalf("want 2 value labels, got %d", len(ms))
88 }
89 for _, m := range ms {
90 x, _ := strconv.ParseFloat(m[1], 64)
91 if end := x + textWidth(html.UnescapeString(m[2])); end > chartW {
92 t.Errorf("label %q ends at %.0f, past the chart's %d", m[2], end, chartW)
93 }
94 }
95}
96
97func TestMarkdownHeadingsAndTables(t *testing.T) {
98 got := string(markdown("# Title\n\nIntro with **bold**.\n\n## Section\n\n| A | B |\n|---|---|\n| 1 | x & y |\n| 2 | `z` |"))
99 for _, want := range []string{"<h1>Title</h1>", "<p>Intro with <strong>bold</strong>.</p>", "<h2>Section</h2>",
100 "<table>", "<th>A</th>", "<td>x &amp; y</td>", "<td><code>z</code></td>", "</table>"} {
101 if !strings.Contains(got, want) {
102 t.Errorf("markdown lacks %q in:\n%s", want, got)
103 }
104 }
105 if strings.Contains(got, "|---") {
106 t.Error("the table's separator row leaked into the output")
107 }
108}
109
110func TestRenderWriteup(t *testing.T) {
111 var buf bytes.Buffer
112 if err := RenderWriteup("# 🤖 What it tells us\n\nPara.\n\n| A |\n|---|\n| 1 |", Copy{"writeup.back": "Back to the report"}, &buf); err != nil {
113 t.Fatal(err)
114 }
115 out := buf.String()
116 for _, want := range []string{"<title>🤖 What it tells us</title>", "<h1>🤖 What it tells us</h1>", "<td>1</td>", `<a href="./">Back to the report</a>`, "--plane"} {
117 if !strings.Contains(out, want) {
118 t.Errorf("write-up page lacks %q", want)
119 }
120 }
121}
122