cat / 012
clone

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

main
012 / e2e / sources_test.go
sources_test.go 3.3K
1package e2e23import (4 "os"5 "path/filepath"6 "strings"7 "testing"8 "time"910 "github.com/parquet-go/parquet-go"11)1213// trip is a row of the Parquet file the linked sources' tests read: a14// ride, how it was paid, its fare, its miles and its day.15type trip struct {16 Trip int64 `parquet:"trip"`17 Payment string `parquet:"payment,dict"`18 Fare int64 `parquet:"fare,decimal(2:12)"`19 Miles float64 `parquet:"miles"`20 Day int32 `parquet:"day,date"`21}2223// payments are the ways trips are paid, in the order rows take them.24var payments = []string{"card", "cash", "card", "app", "card", "cash", "voucher"}2526// tripAt is trip i, the same whenever it's asked for.27func tripAt(i int) trip {28 day := int32(time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC).Unix()/86400) + int32(i%270)29 return trip{Trip: int64(i + 1), Payment: payments[i%len(payments)],30 Fare: int64(i*7919%9000 + 300), Miles: float64((i*104729)%400) / 10, Day: day}31}3233// writeTrips writes rows trips to trips.parquet in dir.34func writeTrips(t *testing.T, dir string, rows int) {35 t.Helper()36 f, err := os.Create(filepath.Join(dir, "trips.parquet"))37 if err != nil {38 t.Fatal(err)39 }40 defer f.Close()41 w := parquet.NewGenericWriter[trip](f, parquet.MaxRowsPerRowGroup(1<<18))42 batch := make([]trip, 1<<14)43 for i := 0; i < rows; i += len(batch) {44 n := min(len(batch), rows-i)45 for j := range n {46 batch[j] = tripAt(i + j)47 }48 if _, err := w.Write(batch[:n]); err != nil {49 t.Fatal(err)50 }51 }52 if err := w.Close(); err != nil {53 t.Fatal(err)54 }55}5657// tripRows is how many rows the screens' source has: past the grid's58// last row.59const tripRows = 2_000_0006061// linkSource links name as a source through the palette, and waits for62// its rows.63func (s *session) linkSource(name string) {64 s.t.Helper()65 s.keys("<ctrl+k>", "Link a source")66 s.waitFor("Link a source")67 s.keys("<enter>")68 s.waitFor("Type to filter, or a path")69 s.keys(name, "<enter>")70 s.waitFor("Linked " + name)71 s.keys("<down>", "<up>") // the note gives way to the source's line72 s.waitFor("▦ " + name)73}7475func TestLinkedSource(t *testing.T) {76 t.Parallel()77 dir := t.TempDir()78 writeTrips(t, dir, tripRows)79 s := start(t, dir)80 s.linkSource("trips.parquet")81 s.waitFor("2,000,000 rows, 5 columns")82 s.waitFor("card")8384 // The last row, numbered past the grid's last row.85 s.keys("<ctrl+down>")86 s.waitFor("2000001 ")8788 // Sorted by fare, Z to A, in the background.89 s.keys("<ctrl+home>", "<right>", "<right>")90 s.keys("<ctrl+k>", "Sort sheet Z to A", "<enter>")91 s.waitFor("sorted by fare Z to A")92 s.eventually("the top fare", func() bool { return strings.Contains(s.line(1), "92.99") })9394 // A formula on another sheet reads the whole source.95 s.keys("<ctrl+pgup>")96 s.waitFor("Sheet1")97 s.keys("=COUNTIF(trips[payment],\"voucher\")", "<enter>")98 s.waitFor("285,714") // tripRows / 7, a count grouped99100 // Saved, the workbook keeps the link, and reads the source again.101 s.keys("<ctrl+s>")102 s.waitFor("Save as:")103 s.keys("rides", "<enter>")104 s.waitFor("rides.012")105 data, err := os.ReadFile(filepath.Join(dir, "rides.012"))106 if err != nil || !strings.Contains(string(data), `"paged":true`) || !strings.Contains(string(data), `"version": 7`) {107 t.Fatalf("the file: %v\n%s", err, data)108 }109 s.keys("<ctrl+q>")110 s.waitExit()111 s = start(t, dir, "rides.012")112 s.waitFor("285,714") // tripRows / 7, a count grouped113}