package main import ( "os" "path/filepath" "reflect" "regexp" "testing" ) func TestMergeOptions(t *testing.T) { base := options{} base.ESBuild.EntryPoints = []string{"a.js", "b.js"} base.ESBuild.LogLevel = 3 base.ESBuild.Splitting = true base.Copy = []struct { Src string `yaml:"src"` Dest string `yaml:"dest"` }{{Src: "index.html", Dest: "dist"}} overlay := options{} overlay.ESBuild.EntryPoints = []string{"b.js", "c.js"} // b.js duplicates the base overlay.ESBuild.LogLevel = 2 // scalar override overlay.Copy = []struct { Src string `yaml:"src"` Dest string `yaml:"dest"` }{{Src: "index.html", Dest: "dist"}} // exact duplicate of the base entry merged := mergeOptions(base, overlay) want := []string{"a.js", "b.js", "c.js"} if !reflect.DeepEqual(merged.ESBuild.EntryPoints, want) { t.Fatalf("entryPoints = %v, want %v", merged.ESBuild.EntryPoints, want) } if merged.ESBuild.LogLevel != 2 { t.Fatalf("logLevel = %d, want overlay value 2", merged.ESBuild.LogLevel) } if !merged.ESBuild.Splitting { t.Fatal("splitting = false, want inherited true") } if len(merged.Copy) != 1 { t.Fatalf("copy = %d entries, want de-duplicated 1", len(merged.Copy)) } if merged.Extends != "" { t.Fatalf("extends = %q, want cleared after merge", merged.Extends) } } func TestPatternToRegexp(t *testing.T) { cases := []struct { pattern string path string match bool }{ // Production shape: processPaths absolutizes patterns and entries // alike, so matching happens between absolute forward-slash paths. {"/proj/apps/taxes/**", "/proj/apps/taxes/taxes-app.js", true}, {"/proj/apps/taxes/**", "/proj/apps/taxes/elements/tax-script.js", true}, {"/proj/apps/taxes/**", "/proj/apps/journal/journal-app.js", false}, {"/proj/apps/vault/**", "/proj/apps/vaultx/vaultx-app.js", false}, {"/proj/src/*.js", "/proj/src/the-app.js", true}, {"/proj/src/*.js", "/proj/src/admin/the-admin.js", false}, {"/proj/src/the-?.js", "/proj/src/the-a.js", true}, {"/proj/src/the-?.js", "/proj/src/the-ab.js", false}, } for _, c := range cases { re := regexp.MustCompile(patternToRegexp(c.pattern)) if re.MatchString(c.path) != c.match { t.Errorf("pattern %q vs %q: got %v, want %v", c.pattern, c.path, re.MatchString(c.path), c.match) } } } func TestFilterEntryPoints(t *testing.T) { opts := options{} opts.ESBuild.EntryPoints = []string{ "/proj/apps/taxes/taxes-app.js", "/proj/apps/chat/chat-app.js", "/proj/the-terminal.js", } opts.ESBuild.ExcludeEntryPoints = []string{"/proj/apps/taxes/**"} filterEntryPoints(&opts) want := []string{"/proj/apps/chat/chat-app.js", "/proj/the-terminal.js"} if !reflect.DeepEqual(opts.ESBuild.EntryPoints, want) { t.Fatalf("entryPoints = %v, want %v", opts.ESBuild.EntryPoints, want) } } func TestReadCfgExtends(t *testing.T) { dir := t.TempDir() prevWd, err := os.Getwd() if err != nil { t.Fatal(err) } t.Cleanup(func() { os.Chdir(prevWd) }) writeFile := func(name, content string) { if err := os.WriteFile(filepath.Join(dir, name), []byte(content), 0644); err != nil { t.Fatal(err) } } writeFile("base.yaml", `- esbuild: entryPoints: - ./src/base-one.js - ./src/base-two.js outdir: ./dist logLevel: 3 copy: - src: ./index.html dest: ./dist `) writeFile("overlay.yaml", `- extends: ./base.yaml esbuild: entryPoints: - ./src/base-two.js - ./src/overlay.js excludeEntryPoints: - ./src/base-one.js `) if err := os.Chdir(dir); err != nil { t.Fatal(err) } profiles := readCfg("./overlay.yaml") if len(profiles) != 1 { t.Fatalf("profiles = %d, want 1", len(profiles)) } p := profiles[0] want := []string{ filepath.Join(dir, "src/base-two.js"), filepath.Join(dir, "src/overlay.js"), } if !reflect.DeepEqual(p.ESBuild.EntryPoints, want) { t.Fatalf("entryPoints = %v, want %v", p.ESBuild.EntryPoints, want) } if p.ESBuild.LogLevel != 3 { t.Fatalf("logLevel = %d, want inherited 3", p.ESBuild.LogLevel) } if len(p.Copy) != 1 { t.Fatalf("copy = %d entries, want inherited 1", len(p.Copy)) } }