From 67c95ca6a8f2efb0853ec50d1a3a57c6beade0ea Mon Sep 17 00:00:00 2001 From: Fuwn Date: Sat, 11 Apr 2026 09:24:53 +0000 Subject: test(collect): add comprehensive test coverage --- internal/collect/collect_test.go | 281 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 internal/collect/collect_test.go diff --git a/internal/collect/collect_test.go b/internal/collect/collect_test.go new file mode 100644 index 0000000..2d73b73 --- /dev/null +++ b/internal/collect/collect_test.go @@ -0,0 +1,281 @@ +package collect_test + +import ( + "os" + "path/filepath" + "strings" + "testing" + "github.com/Fuwn/kivia/internal/collect" +) + +func TestFromPathFindsIdentifiersInFile(testingContext *testing.T) { + filePath := filepath.Join("..", "..", "testdata", "samplepkg", "sample.go") + identifiers, err := collect.FromPath(filePath) + + if err != nil { + testingContext.Fatalf("FromPath returned an error: %v", err) + } + + if len(identifiers) == 0 { + testingContext.Fatalf("Expected identifiers, got none.") + } + + hasFunction := false + hasParameter := false + + for _, identifier := range identifiers { + if identifier.Kind == "function" && identifier.Name == "Handle" { + hasFunction = true + } + + if identifier.Kind == "parameter" { + hasParameter = true + } + } + + if !hasFunction { + testingContext.Fatalf("Expected to find function Handle.") + } + + if !hasParameter { + testingContext.Fatalf("Expected to find parameters.") + } +} + +func TestFromPathFindsIdentifiersInDirectory(testingContext *testing.T) { + rootPath := filepath.Join("..", "..", "testdata", "samplepkg") + identifiers, err := collect.FromPath(rootPath) + + if err != nil { + testingContext.Fatalf("FromPath returned an error: %v", err) + } + + if len(identifiers) == 0 { + testingContext.Fatalf("Expected identifiers, got none.") + } +} + +func TestFromPathFindsIdentifiersRecursively(testingContext *testing.T) { + rootPath := filepath.Join("..", "..", "testdata", "samplepkg", "...") + identifiers, err := collect.FromPath(rootPath) + + if err != nil { + testingContext.Fatalf("FromPath returned an error: %v", err) + } + + if len(identifiers) == 0 { + testingContext.Fatalf("Expected identifiers, got none.") + } +} + +func TestFromPathIncludesContext(testingContext *testing.T) { + filePath := filepath.Join("..", "..", "testdata", "samplepkg", "sample.go") + identifiers, err := collect.FromPath(filePath) + + if err != nil { + testingContext.Fatalf("FromPath returned an error: %v", err) + } + + for _, identifier := range identifiers { + if identifier.File == "" { + testingContext.Fatalf("Expected identifier to have file path.") + } + + if identifier.Line == 0 { + testingContext.Fatalf("Expected identifier to have line number.") + } + } +} + +func TestFromPathIgnoresUnderscore(testingContext *testing.T) { + filePath := filepath.Join("..", "..", "testdata", "samplepkg", "sample.go") + identifiers, err := collect.FromPath(filePath) + + if err != nil { + testingContext.Fatalf("FromPath returned an error: %v", err) + } + + for _, identifier := range identifiers { + if identifier.Name == "_" { + testingContext.Fatalf("Expected underscore identifiers to be ignored.") + } + } +} + +func TestFromPathRejectsNonGoFile(testingContext *testing.T) { + tempDir := testingContext.TempDir() + txtFile := filepath.Join(tempDir, "readme.txt") + + if err := os.WriteFile(txtFile, []byte("hello"), 0o644); err != nil { + testingContext.Fatalf("Failed to write test file: %v", err) + } + + _, err := collect.FromPath(txtFile) + + if err == nil { + testingContext.Fatalf("Expected FromPath to fail for non-Go file.") + } +} + +func TestFromPathSkipsGitVendor(testingContext *testing.T) { + tempDir := testingContext.TempDir() + + for _, dir := range []string{".git", "vendor", "node_modules"} { + if err := os.MkdirAll(filepath.Join(tempDir, dir), 0o755); err != nil { + testingContext.Fatalf("Failed to create directory: %v", err) + } + } + + goFile := filepath.Join(tempDir, "main.go") + + if err := os.WriteFile(goFile, []byte("package main\n"), 0o644); err != nil { + testingContext.Fatalf("Failed to write test file: %v", err) + } + + identifiers, err := collect.FromPath(tempDir) + + if err != nil { + testingContext.Fatalf("FromPath returned an error: %v", err) + } + + if len(identifiers) != 0 { + testingContext.Fatalf("Expected no identifiers from skipped directories.") + } +} + +func TestFromPathReturnsSortedFiles(testingContext *testing.T) { + tempDir := testingContext.TempDir() + + for _, name := range []string{"z.go", "a.go", "m.go"} { + if err := os.WriteFile(filepath.Join(tempDir, name), []byte("package main\n"), 0o644); err != nil { + testingContext.Fatalf("Failed to write test file: %v", err) + } + } + + identifiers, err := collect.FromPath(tempDir) + + if err != nil { + testingContext.Fatalf("FromPath returned an error: %v", err) + } + + if len(identifiers) > 0 { + files := make(map[string]struct{}) + + for _, identifier := range identifiers { + files[identifier.File] = struct{}{} + } + + var fileList []string + + for file := range files { + fileList = append(fileList, filepath.Base(file)) + } + + if !isSorted(fileList) { + testingContext.Fatalf("Expected files to be processed in sorted order.") + } + } +} + +func TestFromPathPreservesEnclosingFunction(testingContext *testing.T) { + filePath := filepath.Join("..", "..", "testdata", "samplepkg", "sample.go") + identifiers, err := collect.FromPath(filePath) + + if err != nil { + testingContext.Fatalf("FromPath returned an error: %v", err) + } + + for _, identifier := range identifiers { + if identifier.Kind == "parameter" || identifier.Kind == "receiver" { + if identifier.Context.EnclosingFunction == "" { + testingContext.Fatalf("Expected %s to have enclosing function.", identifier.Name) + } + } + } +} + +func TestFromPathIncludesTypeInformation(testingContext *testing.T) { + filePath := filepath.Join("..", "..", "testdata", "samplepkg", "sample.go") + identifiers, err := collect.FromPath(filePath) + + if err != nil { + testingContext.Fatalf("FromPath returned an error: %v", err) + } + + hasType := false + + for _, identifier := range identifiers { + if identifier.Context.Type != "" { + hasType = true + + break + } + } + + if !hasType { + testingContext.Fatalf("Expected some identifiers to have type information.") + } +} + +func TestFromPathHandlesParseErrors(testingContext *testing.T) { + tempDir := testingContext.TempDir() + invalidFile := filepath.Join(tempDir, "invalid.go") + validFile := filepath.Join(tempDir, "valid.go") + + if err := os.WriteFile(invalidFile, []byte("this is not valid go"), 0o644); err != nil { + testingContext.Fatalf("Failed to write test file: %v", err) + } + + if err := os.WriteFile(validFile, []byte("package main\nfunc main() {}"), 0o644); err != nil { + testingContext.Fatalf("Failed to write test file: %v", err) + } + + _, err := collect.FromPath(tempDir) + + if err == nil { + testingContext.Fatalf("Expected FromPath to fail when parsing invalid file.") + } +} + +func TestFromPathIgnoresVendorDirectory(testingContext *testing.T) { + tempDir := testingContext.TempDir() + vendorDir := filepath.Join(tempDir, "vendor") + + if err := os.MkdirAll(vendorDir, 0o755); err != nil { + testingContext.Fatalf("Failed to create vendor directory: %v", err) + } + + vendorFile := filepath.Join(vendorDir, "vendor.go") + + if err := os.WriteFile(vendorFile, []byte("package vendor\nfunc VendorFunc() {}"), 0o644); err != nil { + testingContext.Fatalf("Failed to write vendor file: %v", err) + } + + mainFile := filepath.Join(tempDir, "main.go") + + if err := os.WriteFile(mainFile, []byte("package main\nfunc main() {}"), 0o644); err != nil { + testingContext.Fatalf("Failed to write main file: %v", err) + } + + identifiers, err := collect.FromPath(tempDir) + + if err != nil { + testingContext.Fatalf("FromPath returned an error: %v", err) + } + + for _, identifier := range identifiers { + if strings.Contains(identifier.File, "vendor") { + testingContext.Fatalf("Expected vendor directory to be skipped, found %s", identifier.File) + } + } +} + +func isSorted(list []string) bool { + for i := 1; i < len(list); i++ { + if list[i-1] > list[i] { + return false + } + } + + return true +} -- cgit v1.2.3