Files
2026-09-15 13:11:20 +01:00

203 lines
5.5 KiB
Go

package renderer
import (
"strings"
"testing"
"git.flo.fo/FLO/dirmd/internal/config"
"git.flo.fo/FLO/dirmd/internal/tree"
)
func TestCountLines_empty(t *testing.T) {
if got := countLines(""); got != 0 {
t.Errorf("countLines(\"\") = %d; want 0", got)
}
}
func TestCountLines_basic(t *testing.T) {
tests := []struct {
name string
input string
want int
}{
{"one_line_no_newline", "hello", 1},
{"one_line_with_newline", "hello\n", 1},
{"two_lines", "hello\nworld", 2},
{"two_lines_trailing", "hello\nworld\n", 2},
{"three_lines", "a\nb\nc", 3},
{"empty_lines", "a\n\nb", 3},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := countLines(tt.input); got != tt.want {
t.Errorf("countLines(%q) = %d; want %d", tt.input, got, tt.want)
}
})
}
}
func TestStripTestBlocks_rust(t *testing.T) {
tests := []struct {
name string
input string
want string
}{
{"no_test_block", "fn main() {}\nfn helper() {}", "fn main() {}\nfn helper() {}"},
{"cfg_test_block", "#[cfg(test)]\nmod tests {\n #[test]\n fn test_one() {}\n}", ""},
{"mixed_content", "pub fn main() {}\n#[cfg(test)]\nmod tests {\n #[test]\n fn t() {}\n}\npub fn end() {}", "pub fn main() {}\npub fn end() {}"},
{"nested_braces", "#[cfg(test)]\nmod tests {\n mod inner {\n #[test]\n fn t() {}\n }\n}", ""},
{"multiple_blocks", "#[cfg(test)]\nmod t1 {}\n#[cfg(test)]\nmod t2 {}", ""},
{"cfg_all_test", "#[cfg(all(test, unix))]\nmod tests {}", ""},
{"cfg_any_test", "#[cfg(any(test, feature = \"foo\"))]\nmod tests {}", ""},
{"empty_after_strip", "#[cfg(test)]\nmod tests {}", ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := stripTestBlocks(tt.input); got != tt.want {
t.Errorf("stripTestBlocks(%q)\ngot:\n%s\nwant:\n%s", tt.input, got, tt.want)
}
})
}
}
func TestExtToLang(t *testing.T) {
tests := []struct {
name string
ext string
want string
}{
{"go", ".go", "go"},
{"markdown", ".md", "markdown"},
{"yaml_upper", ".YAML", "yaml"},
{"yaml_yml", ".yml", "yaml"},
{"javascript", ".js", "javascript"},
{"typescript", ".ts", "typescript"},
{"css", ".css", "css"},
{"html", ".html", "html"},
{"json", ".json", "json"},
{"xml", ".xml", "xml"},
{"sql", ".sql", "sql"},
{"bash", ".sh", "bash"},
{"python", ".py", "python"},
{"rust", ".rs", "rust"},
{"c", ".c", "c"},
{"cpp", ".cpp", "cpp"},
{"txt", ".txt", "text"},
{"toml", ".toml", "toml"},
{"unknown", ".xyz", ""},
{"empty", "", ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := extToLang(tt.ext); got != tt.want {
t.Errorf("extToLang(%q) = %q; want %q", tt.ext, got, tt.want)
}
})
}
}
func TestHasAnyAnnotation_none(t *testing.T) {
root := &tree.Node{Name: "root", IsDir: true, Children: map[string]*tree.Node{
"file.go": {Name: "file.go", IsDir: false},
}}
if hasAnyAnnotation(root) {
t.Error("hasAnyAnnotation should be false for clean tree")
}
}
func TestHasAnyAnnotation_present(t *testing.T) {
root := &tree.Node{Name: "root", IsDir: true, Children: map[string]*tree.Node{
".git": {Name: ".git", IsDir: true, Annotation: "ignored (default)"},
}}
if !hasAnyAnnotation(root) {
t.Error("hasAnyAnnotation should be true with annotation")
}
}
func TestHasAnyAnnotation_deep(t *testing.T) {
root := &tree.Node{Name: "root", IsDir: true, Children: map[string]*tree.Node{
"internal": {Name: "internal", IsDir: true, Children: map[string]*tree.Node{
"deep": {Name: "deep", IsDir: true, Annotation: "tests omitted (--omit-test)"},
}},
}}
if !hasAnyAnnotation(root) {
t.Error("hasAnyAnnotation should be true for deep annotation")
}
}
func TestFormatFlags_nil(t *testing.T) {
if FormatFlags(nil) != "" {
t.Error("FormatFlags(nil) should be empty")
}
}
func TestFormatFlags_empty(t *testing.T) {
cfg := &config.Config{
MaxDepth: config.DefaultMaxDepth,
MaxSize: config.DefaultMaxSize,
}
if out := FormatFlags(cfg); out != "" {
t.Errorf("FormatFlags(default config) = %q; want empty", out)
}
}
func TestFormatFlags_set(t *testing.T) {
cfg := &config.Config{
OmitTest: true,
OmitMd: true,
MaxDepth: 10,
}
out := FormatFlags(cfg)
if !strings.Contains(out, "--omit-test") {
t.Error("missing --omit-test")
}
if !strings.Contains(out, "--omit-md") {
t.Error("missing --omit-md")
}
if !strings.Contains(out, "--max-depth 10") {
t.Error("missing --max-depth 10")
}
}
func TestFormatFlags_extra_ignores(t *testing.T) {
cfg := &config.Config{
Ignores: append(config.DefaultIgnores, "mycustomdir"),
}
out := FormatFlags(cfg)
if !strings.Contains(out, "mycustomdir") {
t.Error("missing custom ignore in output")
}
if strings.Contains(out, "node_modules") {
t.Error("default ignore leaked into Ignored line")
}
}
func TestSetMinus(t *testing.T) {
tests := []struct {
name string
haystack []string
defaults []string
want []string
}{
{"empty", nil, []string{"a"}, nil},
{"all_default", []string{"a", "b"}, []string{"a", "b"}, nil},
{"one_extra", []string{"a", "c"}, []string{"a"}, []string{"c"}},
{"duplicates_deduped", []string{"c", "c", "a"}, []string{"a"}, []string{"c"}},
{"no_defaults", []string{"x"}, nil, []string{"x"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := setMinus(tt.haystack, tt.defaults)
if len(got) != len(tt.want) {
t.Errorf("setMinus() length = %d; want %d", len(got), len(tt.want))
return
}
for i := range got {
if got[i] != tt.want[i] {
t.Errorf("setMinus()[%d] = %q; want %q", i, got[i], tt.want[i])
}
}
})
}
}