cat / 012
clone

a spreadsheet for the terminal: lotus 1-2-3 looks, google sheets keys and formulas, one go binary

cat/module-path
012 / internal / fileio / html_test.go
html_test.go 4.5K
1package fileio23import (4 "bytes"5 "context"6 "os"7 "path/filepath"8 "regexp"9 "strings"10 "testing"1112 "src.rest/cat/012/internal/sheet"13)1415// htmlBook is a sheet with a header, numbers, a formula, a style, a16// merge, a note and a chart.17func htmlBook(t *testing.T) *sheet.Sheet {18 t.Helper()19 s := sheet.New()20 for a, in := range map[string]string{21 "A1": "Month", "B1": "Sales", "A2": "Jan", "B2": "$1,200", "A3": "Feb", "B3": "900",22 "A4": "Total", "B4": "=SUM(B2:B3)", "A6": "<b>not markup</b>",23 } {24 addr, _ := sheet.ParseAddr(a)25 if err := s.Set(addr, in); err != nil {26 t.Fatal(err)27 }28 }29 s.SetStyle(sheet.Rect{To: sheet.Addr{Col: 1}}, func(st *sheet.Style) { st.Bold = true })30 if err := s.SetNote(sheet.Addr{Row: 3}, "adds up"); err != nil {31 t.Fatal(err)32 }33 if err := s.Merge(sheet.Rect{From: sheet.Addr{Row: 5}, To: sheet.Addr{Col: 1, Row: 5}}, sheet.MergeAll); err != nil {34 t.Fatal(err)35 }36 s.AddChart(sheet.Chart{Type: sheet.ChartColumn, Data: sheet.Rect{To: sheet.Addr{Col: 1, Row: 2}}, Header: true, Labels: true,37 Title: "Sales by month", At: sheet.Addr{Col: 3, Row: 1}, W: 40, H: 14})38 return s39}4041// TestHTMLPage exports a sheet as a page that holds everything it42// needs: fonts, styles, the cells as shown, the chart as SVG.43func TestHTMLPage(t *testing.T) {44 s := htmlBook(t)45 path := filepath.Join(t.TempDir(), "sales.html")46 k, ok := ExportKindOf(path)47 if !ok || k != HTML || k.CanImport() {48 t.Fatalf("ExportKindOf = %v, %v", k, ok)49 }50 if _, ok := KindOf(path); ok {51 t.Errorf("an HTML file is offered for import")52 }53 res, err := Export(context.Background(), path, HTML, Snap(s, sheet.Rect{}, "Sales"), ExportOptions{})54 if err != nil {55 t.Fatal(err)56 }57 if res.Rows != 6 || len(res.Notes) != 0 {58 t.Errorf("rows %d, notes %q", res.Rows, res.Notes)59 }60 data, err := os.ReadFile(path)61 if err != nil {62 t.Fatal(err)63 }64 page := string(data)65 for _, want := range []string{66 "<title>Sales</title>", "@font-face{font-family:'JetBrains Mono'", "data:font/woff2;base64,",67 `<th data-c="A">A</th>`, `data-a="B1" class="b">Sales<`, `data-a="A2" class="clip">Jan<`, `data-a="B2" class="r">$1,200<`,68 `data-f="=SUM(B2:B3)">$2,100<`, `class="clip note" title="adds up"`, `colspan="2" rowspan="1"`, "&lt;b&gt;not markup&lt;/b&gt;",69 `<figure class="chart"`, "<svg", "<figcaption>Sales by month</figcaption>", `class="range">A1:B3<`,70 "prefers-color-scheme:light", "READY",71 } {72 if !strings.Contains(page, want) {73 t.Errorf("page lacks %q", want)74 }75 }76 // Nothing is fetched from elsewhere.77 if m := regexp.MustCompile(`(src|href)="?https?:`).FindString(page); m != "" {78 t.Errorf("page loads %s", m)79 }80}8182// TestHTMLRange exports a range, with the charts anchored in it.83func TestHTMLRange(t *testing.T) {84 s := htmlBook(t)85 var b bytes.Buffer86 snap := Snap(s, sheet.Rect{From: sheet.Addr{Row: 1}, To: sheet.Addr{Col: 1, Row: 2}}, "Sales")87 if _, err := WriteHTML(&b, HTMLPage{Title: "Sales", Snap: snap}); err != nil {88 t.Fatal(err)89 }90 page := b.String()91 if strings.Contains(page, `data-a="A1"`) || !strings.Contains(page, `data-a="B3"`) || strings.Contains(page, "<svg") {92 t.Errorf("range page wrong:\n%s", page[strings.Index(page, "<body>"):])93 }94 if !strings.Contains(page, `id="o12-context">Sales!A2:B3<`) {95 t.Errorf("context line doesn't name the range")96 }97}9899// TestHTMLChartPage draws one chart on its own page.100func TestHTMLChartPage(t *testing.T) {101 s := htmlBook(t)102 c, ok := ChartSnap(s, 0)103 if !ok {104 t.Fatal("no chart")105 }106 if _, ok := ChartSnap(s, 1); ok {107 t.Error("chart 1 found")108 }109 var b bytes.Buffer110 if _, err := WriteHTML(&b, HTMLPage{Title: "Sales by month", Chart: &c}); err != nil {111 t.Fatal(err)112 }113 page := b.String()114 if !strings.Contains(page, `<figure class="chart solo"`) || !strings.Contains(page, "<rect") || strings.Contains(page, "<table") {115 t.Errorf("chart page wrong")116 }117}118119// TestHTMLLooks draws a rule's fill and text color.120func TestHTMLLooks(t *testing.T) {121 s := sheet.New()122 for i, in := range []string{"5", "50"} {123 if err := s.Set(sheet.Addr{Row: i}, in); err != nil {124 t.Fatal(err)125 }126 }127 err := s.AddCondFormat(sheet.CondFormat{Ranges: []sheet.Rect{{To: sheet.Addr{Row: 1}}}, Op: sheet.RuleGreater, Args: [2]string{"10"},128 Style: sheet.RuleStyle{Fill: sheet.ColorGreen, Bold: true}})129 if err != nil {130 t.Fatal(err)131 }132 grid, _ := HTMLGrid(Snap(s, sheet.Rect{}, "S"))133 if !strings.Contains(grid, `data-a="A2" class="r b" style="background:var(--r3);color:var(--i3)"`) {134 t.Errorf("rule not drawn:\n%s", grid)135 }136 if strings.Contains(grid, `data-a="A1" class="r b"`) {137 t.Errorf("rule drawn where it doesn't apply")138 }139}