Files
s3-genindex/internal/indexgen/indexgen_test.go
2025-12-03 12:32:36 +01:00

450 lines
10 KiB
Go

package indexgen
import (
"bytes"
"os"
"path/filepath"
"regexp"
"testing"
"time"
)
func TestPrettySize(t *testing.T) {
tests := []struct {
input int64
expected string
}{
{0, "0 bytes"},
{1, "1 byte"},
{2, "2 bytes"},
{1023, "1023 bytes"},
{1024, "1 KB"},
{1536, "1 KB"},
{2048, "2 KB"},
{1024 * 1024, "1 MB"},
{1024 * 1024 * 1024, "1 GB"},
{1024 * 1024 * 1024 * 1024, "1 TB"},
{1024 * 1024 * 1024 * 1024 * 1024, "1 PB"},
}
for _, tt := range tests {
result := PrettySize(tt.input)
if result != tt.expected {
t.Errorf("PrettySize(%d) = %s, want %s", tt.input, result, tt.expected)
}
}
}
func TestGetIconType(t *testing.T) {
tests := []struct {
filename string
expected string
}{
{"test.go", "go"},
{"test.py", "py"},
{"test.js", "js"},
{"test.html", "html"},
{"test.css", "css"},
{"test.json", "json"},
{"test.md", "md"},
{"test.pdf", "pdf"},
{"test.jpg", "image"},
{"test.png", "image"},
{"test.mp4", "video"},
{"test.mp3", "audio"},
{"test.zip", "archive"},
{"test.txt", "doc"},
{"README", "license"},
{"LICENSE", "license"},
{"unknown.ext", "generic"},
{"noext", "generic"},
}
for _, tt := range tests {
result := GetIconType(tt.filename)
if result != tt.expected {
t.Errorf("GetIconType(%s) = %s, want %s", tt.filename, result, tt.expected)
}
}
}
func TestGetIconTypeCaseInsensitive(t *testing.T) {
tests := []struct {
filename string
expected string
}{
{"test.GO", "go"},
{"test.Py", "py"},
{"test.JPG", "image"},
{"test.PNG", "image"},
{"test.MP4", "video"},
{"test.MP3", "audio"},
}
for _, tt := range tests {
result := GetIconType(tt.filename)
if result != tt.expected {
t.Errorf("GetIconType(%s) = %s, want %s", tt.filename, result, tt.expected)
}
}
}
func TestHTMLTemplate(t *testing.T) {
tmpl := GetHTMLTemplate()
if tmpl == nil {
t.Fatal("GetHTMLTemplate() returned nil")
}
// Test template execution with sample data
data := struct {
DirName string
Entries []FileEntry
DirAppend bool
OutputFile string
IsRoot bool
WatermarkURL string
}{
DirName: "test-dir",
Entries: []FileEntry{},
DirAppend: false,
OutputFile: "index.html",
IsRoot: false,
WatermarkURL: "",
}
var buf bytes.Buffer
err := tmpl.Execute(&buf, data)
if err != nil {
t.Fatalf("Template execution failed: %v", err)
}
output := buf.String()
if !bytes.Contains([]byte(output), []byte("test-dir")) {
t.Error("Template output should contain directory name")
}
if !bytes.Contains([]byte(output), []byte("<!DOCTYPE html>")) {
t.Error("Template output should contain HTML doctype")
}
}
func TestHTMLTemplateWithEntries(t *testing.T) {
tmpl := GetHTMLTemplate()
entries := []FileEntry{
{
Name: "test.go",
Path: "test.go",
IsDir: false,
IsSymlink: false,
Size: 1024,
ModTime: time.Now(),
IconType: "go",
CSSClass: "",
SizePretty: "1 KB",
ModTimeISO: "2023-01-01T12:00:00Z",
ModTimeHuman: "01 Jan 23 12:00 UTC",
},
{
Name: "subfolder",
Path: "subfolder/",
IsDir: true,
IsSymlink: false,
Size: -1,
ModTime: time.Now(),
IconType: "folder",
CSSClass: "folder_filled",
SizePretty: "&mdash;",
ModTimeISO: "2023-01-01T12:00:00Z",
ModTimeHuman: "01 Jan 23 12:00 UTC",
},
}
data := struct {
DirName string
Entries []FileEntry
DirAppend bool
OutputFile string
IsRoot bool
WatermarkURL string
}{
DirName: "test-dir",
Entries: entries,
DirAppend: false,
OutputFile: "index.html",
IsRoot: false,
WatermarkURL: "",
}
var buf bytes.Buffer
err := tmpl.Execute(&buf, data)
if err != nil {
t.Fatalf("Template execution with entries failed: %v", err)
}
output := buf.String()
if !bytes.Contains([]byte(output), []byte("test.go")) {
t.Error("Template output should contain file name")
}
if !bytes.Contains([]byte(output), []byte("subfolder")) {
t.Error("Template output should contain folder name")
}
if !bytes.Contains([]byte(output), []byte("#go")) {
t.Error("Template output should contain Go icon reference")
}
if !bytes.Contains([]byte(output), []byte("#folder")) {
t.Error("Template output should contain folder icon reference")
}
}
func TestHTMLTemplateWithWatermark(t *testing.T) {
tmpl := GetHTMLTemplate()
if tmpl == nil {
t.Fatal("GetHTMLTemplate() returned nil")
}
// Test template execution with watermark
data := struct {
DirName string
Entries []FileEntry
DirAppend bool
OutputFile string
IsRoot bool
WatermarkURL string
}{
DirName: "test-dir",
Entries: []FileEntry{},
DirAppend: false,
OutputFile: "index.html",
IsRoot: false,
WatermarkURL: "https://example.com/logo.svg",
}
var buf bytes.Buffer
err := tmpl.Execute(&buf, data)
if err != nil {
t.Fatalf("Template execution with watermark failed: %v", err)
}
output := buf.String()
// Check that watermark image is included
if !bytes.Contains([]byte(output), []byte(`src="https://example.com/logo.svg"`)) {
t.Error("Template output should contain watermark image URL")
}
if !bytes.Contains([]byte(output), []byte(`class="watermark"`)) {
t.Error("Template output should contain watermark CSS class")
}
// Test without watermark
data.WatermarkURL = ""
buf.Reset()
err = tmpl.Execute(&buf, data)
if err != nil {
t.Fatalf("Template execution without watermark failed: %v", err)
}
outputNoWatermark := buf.String()
// Check that watermark image is NOT included when URL is empty
if bytes.Contains([]byte(outputNoWatermark), []byte(`class="watermark"`)) {
t.Error("Template output should not contain watermark when URL is empty")
}
}
func TestReadDirEntries(t *testing.T) {
// Create a temporary directory with test files
tempDir := t.TempDir()
// Create test files
testFiles := []string{"test.go", "test.py", "README.md", ".hidden"}
for _, file := range testFiles {
f, err := os.Create(filepath.Join(tempDir, file))
if err != nil {
t.Fatalf("Failed to create test file %s: %v", file, err)
}
_, err = f.WriteString("test content")
if err != nil {
t.Fatalf("Failed to write to file: %v", err)
}
f.Close()
}
// Create a subdirectory
subDir := filepath.Join(tempDir, "subdir")
err := os.Mkdir(subDir, 0755)
if err != nil {
t.Fatalf("Failed to create subdirectory: %v", err)
}
opts := &Options{
OutputFile: "index.html",
IncludeHidden: false,
Verbose: false,
}
entries, err := ReadDirEntries(tempDir, opts)
if err != nil {
t.Fatalf("ReadDirEntries failed: %v", err)
}
// Should have 4 entries (3 visible files + 1 directory), .hidden should be excluded
expectedCount := 4
if len(entries) != expectedCount {
t.Errorf("Expected %d entries, got %d", expectedCount, len(entries))
}
// Check that we have the expected files (ReadDirEntries doesn't sort, ProcessDir does)
foundDir := false
for _, entry := range entries {
if entry.IsDir && entry.Name == "subdir" {
foundDir = true
break
}
}
if !foundDir {
t.Error("Expected to find subdirectory 'subdir'")
}
// Check that hidden file is excluded
for _, entry := range entries {
if entry.Name == ".hidden" {
t.Error("Hidden file should be excluded when IncludeHidden is false")
}
}
}
func TestReadDirEntriesWithHidden(t *testing.T) {
tempDir := t.TempDir()
// Create test files including hidden
testFiles := []string{"test.go", ".hidden"}
for _, file := range testFiles {
f, err := os.Create(filepath.Join(tempDir, file))
if err != nil {
t.Fatalf("Failed to create test file %s: %v", file, err)
}
f.Close()
}
opts := &Options{
OutputFile: "index.html",
IncludeHidden: true,
Verbose: false,
}
entries, err := ReadDirEntries(tempDir, opts)
if err != nil {
t.Fatalf("ReadDirEntries failed: %v", err)
}
// Should include hidden file
found := false
for _, entry := range entries {
if entry.Name == ".hidden" {
found = true
break
}
}
if !found {
t.Error("Hidden file should be included when IncludeHidden is true")
}
}
func TestReadDirEntriesWithRegexExclusion(t *testing.T) {
tempDir := t.TempDir()
// Create test files
testFiles := []string{"test.go", "test.py", "build.log", "node_modules.txt"}
for _, file := range testFiles {
f, err := os.Create(filepath.Join(tempDir, file))
if err != nil {
t.Fatalf("Failed to create test file %s: %v", file, err)
}
f.Close()
}
regex := regexp.MustCompile("(build|node_modules)")
opts := &Options{
OutputFile: "index.html",
IncludeHidden: false,
ExcludeRegex: regex,
Verbose: false,
}
entries, err := ReadDirEntries(tempDir, opts)
if err != nil {
t.Fatalf("ReadDirEntries failed: %v", err)
}
// Check that excluded files are not present
for _, entry := range entries {
if entry.Name == "build.log" || entry.Name == "node_modules.txt" {
t.Errorf("File %s should be excluded by regex", entry.Name)
}
}
// Should have 2 entries (test.go, test.py)
if len(entries) != 2 {
t.Errorf("Expected 2 entries after regex exclusion, got %d", len(entries))
}
}
func TestFileEntryProperties(t *testing.T) {
tempDir := t.TempDir()
// Create a test file with known content
testFile := filepath.Join(tempDir, "test.go")
content := "package main\nfunc main() {}\n"
err := os.WriteFile(testFile, []byte(content), 0644)
if err != nil {
t.Fatalf("Failed to create test file: %v", err)
}
opts := &Options{
OutputFile: "index.html",
IncludeHidden: false,
Verbose: false,
}
entries, err := ReadDirEntries(tempDir, opts)
if err != nil {
t.Fatalf("ReadDirEntries failed: %v", err)
}
if len(entries) != 1 {
t.Fatalf("Expected 1 entry, got %d", len(entries))
}
entry := entries[0]
// Verify properties
if entry.Name != "test.go" {
t.Errorf("Expected name 'test.go', got '%s'", entry.Name)
}
if entry.IsDir {
t.Error("Expected file to not be a directory")
}
if entry.IsSymlink {
t.Error("Expected file to not be a symlink")
}
if entry.IconType != "go" {
t.Errorf("Expected icon type 'go', got '%s'", entry.IconType)
}
if entry.Size != int64(len(content)) {
t.Errorf("Expected size %d, got %d", len(content), entry.Size)
}
if entry.SizePretty != PrettySize(int64(len(content))) {
t.Errorf("Size pretty mismatch")
}
}