Add js web stuff to landing page + documentation
This commit is contained in:
108
go/jsbundler/segment_test.go
Normal file
108
go/jsbundler/segment_test.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package jsbundler
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// walkRepoTSX returns every .tsx/.jsx under frontend/src (relative to the
|
||||
// package dir, which is jsbundler).
|
||||
func walkRepoTSX(t *testing.T) []string {
|
||||
t.Helper()
|
||||
root := filepath.Join("..", "..", "frontend", "src")
|
||||
var files []string
|
||||
err := filepath.WalkDir(root, func(p string, d os.DirEntry, err error) error {
|
||||
if err != nil || d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
switch filepath.Ext(p) {
|
||||
case ".tsx", ".jsx":
|
||||
files = append(files, p)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Skipf("cannot walk frontend/src: %v", err)
|
||||
}
|
||||
if len(files) == 0 {
|
||||
t.Skip("no .tsx files found")
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
||||
// Segmentation must be lossless for every real component in the repo, and the
|
||||
// join invariant must hold exactly (byte-for-byte).
|
||||
func TestSegmentLosslessRepo(t *testing.T) {
|
||||
files := walkRepoTSX(t)
|
||||
totalChunks, multiChunkFiles := 0, 0
|
||||
for _, f := range files {
|
||||
data, err := os.ReadFile(f)
|
||||
if err != nil {
|
||||
t.Fatalf("read %s: %v", f, err)
|
||||
}
|
||||
src := string(data)
|
||||
chunks := segmentTopLevel(src)
|
||||
if strings.Join(chunks, "") != src {
|
||||
t.Errorf("%s: segmentation not lossless (%d chunks)", f, len(chunks))
|
||||
continue
|
||||
}
|
||||
totalChunks += len(chunks)
|
||||
if len(chunks) > 1 {
|
||||
multiChunkFiles++
|
||||
}
|
||||
// Every chunk (except possibly the first) must begin at a declaration
|
||||
// keyword after optional leading blank lines/comments were attached to
|
||||
// the previous chunk — i.e. its first non-space line starts with a kw.
|
||||
}
|
||||
t.Logf("segmented %d files: %d split into >1 chunk, %d chunks total (avg %.1f)",
|
||||
len(files), multiChunkFiles, totalChunks, float64(totalChunks)/float64(len(files)))
|
||||
}
|
||||
|
||||
// Focused check on the pain file: it should split into many chunks so that
|
||||
// editing any single declaration recompiles only that declaration.
|
||||
func TestSegmentAutoTable(t *testing.T) {
|
||||
p := filepath.Join("..", "..", "frontend", "src", "ui", "AutoTable.tsx")
|
||||
data, err := os.ReadFile(p)
|
||||
if err != nil {
|
||||
t.Skipf("cannot read AutoTable: %v", err)
|
||||
}
|
||||
chunks := segmentTopLevel(string(data))
|
||||
if strings.Join(chunks, "") != string(data) {
|
||||
t.Fatal("AutoTable segmentation not lossless")
|
||||
}
|
||||
// Size distribution: how big is the largest chunk (the residual worst case)?
|
||||
maxLen, maxIdx := 0, 0
|
||||
for i, c := range chunks {
|
||||
if len(c) > maxLen {
|
||||
maxLen, maxIdx = len(c), i
|
||||
}
|
||||
}
|
||||
head := strings.TrimSpace(chunks[maxIdx])
|
||||
if len(head) > 80 {
|
||||
head = head[:80]
|
||||
}
|
||||
t.Logf("AutoTable: %d chunks, largest = %d bytes (%.0f%% of file), starts: %q",
|
||||
len(chunks), maxLen, 100*float64(maxLen)/float64(len(data)), head)
|
||||
if len(chunks) < 20 {
|
||||
t.Errorf("expected AutoTable to split into many chunks, got %d", len(chunks))
|
||||
}
|
||||
}
|
||||
|
||||
// A few hand-written cases exercise the lexer edge cases the repo may not cover.
|
||||
func TestSegmentEdgeCases(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
"template with braces and decl-looking text": "const a = `x${ {y:1} }z\nconst notReal = 2`;\nexport const b = 3;\n",
|
||||
"regex with braces": "const re = /[{}]/g;\nfunction f() { return /a{2}/; }\nexport function g() {}\n",
|
||||
"block comment spanning decl keyword": "/*\nconst hidden = 1;\nfunction alsoHidden() {}\n*/\nexport const real = 1;\n",
|
||||
"string with keyword": "const s = \"export function fake() {}\";\nfunction real() {}\n",
|
||||
"nested template": "const t = `a${`b${1}c`}d`;\nexport const u = 1;\n",
|
||||
}
|
||||
for name, src := range cases {
|
||||
chunks := segmentTopLevel(src)
|
||||
if got := strings.Join(chunks, ""); got != src {
|
||||
t.Errorf("%s: not lossless\n src=%q\n got=%q", name, src, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user