package template import ( "os" "path/filepath" "testing" "time" ) func TestNewCache(t *testing.T) { cache := NewCache("") if cache == nil { t.Fatal("NewCache returned nil") } if cache.templates == nil { t.Fatal("templates map not initialized") } } func TestPositionalReplacement(t *testing.T) { tmpl := &Template{ name: "test", content: "Hello {0}, you are {1} years old!", } result := tmpl.RenderPositional("Alice", 25) expected := "Hello Alice, you are 25 years old!" if result != expected { t.Errorf("Expected %q, got %q", expected, result) } } func TestNamedReplacement(t *testing.T) { tmpl := &Template{ name: "test", content: "Hello {name}, you are {age} years old!", } data := map[string]any{ "name": "Bob", "age": 30, } result := tmpl.RenderNamed(data) expected := "Hello Bob, you are 30 years old!" if result != expected { t.Errorf("Expected %q, got %q", expected, result) } } func TestDotNotationReplacement(t *testing.T) { tmpl := &Template{ name: "test", content: "User: {user.name}, Email: {user.contact.email}", } data := map[string]any{ "user": map[string]any{ "name": "Charlie", "contact": map[string]any{ "email": "charlie@example.com", }, }, } result := tmpl.RenderNamed(data) expected := "User: Charlie, Email: charlie@example.com" if result != expected { t.Errorf("Expected %q, got %q", expected, result) } } func TestTemplateLoadingAndCaching(t *testing.T) { tmpDir, err := os.MkdirTemp("", "template_test") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpDir) templatesDir := filepath.Join(tmpDir, "templates") err = os.MkdirAll(templatesDir, 0755) if err != nil { t.Fatal(err) } templateFile := filepath.Join(templatesDir, "test.html") content := "Hello {name}!" err = os.WriteFile(templateFile, []byte(content), 0644) if err != nil { t.Fatal(err) } cache := NewCache(tmpDir) tmpl, err := cache.Load("test.html") if err != nil { t.Fatal(err) } if tmpl.content != content { t.Errorf("Expected content %q, got %q", content, tmpl.content) } tmpl2, err := cache.Load("test.html") if err != nil { t.Fatal(err) } if tmpl != tmpl2 { t.Error("Template should be cached and return same instance") } } func TestTemplateReloading(t *testing.T) { tmpDir, err := os.MkdirTemp("", "template_test") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpDir) templatesDir := filepath.Join(tmpDir, "templates") err = os.MkdirAll(templatesDir, 0755) if err != nil { t.Fatal(err) } templateFile := filepath.Join(templatesDir, "test.html") content1 := "Hello {name}!" err = os.WriteFile(templateFile, []byte(content1), 0644) if err != nil { t.Fatal(err) } cache := NewCache(tmpDir) tmpl, err := cache.Load("test.html") if err != nil { t.Fatal(err) } if tmpl.content != content1 { t.Errorf("Expected content %q, got %q", content1, tmpl.content) } time.Sleep(10 * time.Millisecond) content2 := "Hi {name}, welcome!" err = os.WriteFile(templateFile, []byte(content2), 0644) if err != nil { t.Fatal(err) } tmpl2, err := cache.Load("test.html") if err != nil { t.Fatal(err) } if tmpl2.content != content2 { t.Errorf("Expected reloaded content %q, got %q", content2, tmpl2.content) } } func TestGetNestedValue(t *testing.T) { tmpl := &Template{} data := map[string]any{ "level1": map[string]any{ "level2": map[string]any{ "value": "found", }, }, } result := tmpl.getNestedValue(data, "level1.level2.value") if result != "found" { t.Errorf("Expected 'found', got %v", result) } result = tmpl.getNestedValue(data, "level1.nonexistent") if result != nil { t.Errorf("Expected nil for nonexistent path, got %v", result) } } func TestMixedReplacementTypes(t *testing.T) { tmpl := &Template{ name: "test", content: "Hello {name}, you have {count} {items.type}s!", } data := map[string]any{ "name": "Dave", "count": 5, "items": map[string]any{ "type": "apple", }, } result := tmpl.RenderNamed(data) expected := "Hello Dave, you have 5 apples!" if result != expected { t.Errorf("Expected %q, got %q", expected, result) } } func TestIncludeSupport(t *testing.T) { tmpDir, err := os.MkdirTemp("", "template_test") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpDir) templatesDir := filepath.Join(tmpDir, "templates") err = os.MkdirAll(templatesDir, 0755) if err != nil { t.Fatal(err) } // Create main template with include mainTemplate := `
{include "header.html"}Hello {name}!` err = os.WriteFile(filepath.Join(templatesDir, "main.html"), []byte(mainTemplate), 0644) if err != nil { t.Fatal(err) } // Create included template headerTemplate := `This is the content block.
{/block}` err = os.WriteFile(filepath.Join(templatesDir, "page.html"), []byte(pageTemplate), 0644) if err != nil { t.Fatal(err) } cache := NewCache(tmpDir) tmpl, err := cache.Load("page.html") if err != nil { t.Fatal(err) } data := map[string]any{ "title": "Test Page", "name": "Bob", } result := tmpl.RenderNamed(data) expected := `This is the content block.
` if result != expected { t.Errorf("Expected %q, got %q", expected, result) } }