diff --git a/cmd/commands_test.go b/cmd/commands_test.go new file mode 100644 index 0000000..9a1ba93 --- /dev/null +++ b/cmd/commands_test.go @@ -0,0 +1,151 @@ +package cmd + +import ( + "encoding/json" + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/gusanmaz/onefile/utils" +) + +const testProjectPath = "test_toy_project" + +func setupTestProject(t *testing.T) { + err := os.MkdirAll(testProjectPath, 0755) + if err != nil { + t.Fatalf("Failed to create test project directory: %v", err) + } + + files := map[string]string{ + "main.go": `package main + +import "fmt" + +func main() { + fmt.Println("Hello from toy project!") +}`, + "README.md": `# Toy Project + +This is a simple toy project used for testing the onefile tool.`, + ".gitignore": `# Ignore compiled binaries +*.exe +*.out`, + } + + for name, content := range files { + err := ioutil.WriteFile(filepath.Join(testProjectPath, name), []byte(content), 0644) + if err != nil { + t.Fatalf("Failed to create test file %s: %v", name, err) + } + } +} + +func teardownTestProject(t *testing.T) { + err := os.RemoveAll(testProjectPath) + if err != nil { + t.Fatalf("Failed to remove test project directory: %v", err) + } +} + +func TestDumpCommand(t *testing.T) { + setupTestProject(t) + defer teardownTestProject(t) + + cmd := NewDumpCmd() + cmd.SetArgs([]string{"-p", testProjectPath, "-o", "test_output", "-t", "json"}) + + err := cmd.Execute() + if err != nil { + t.Fatalf("Dump command failed: %v", err) + } + + // Check if the output file exists + _, err = os.Stat("test_output.json") + if os.IsNotExist(err) { + t.Fatalf("Output file was not created") + } + + // Read and parse the JSON output + data, err := ioutil.ReadFile("test_output.json") + if err != nil { + t.Fatalf("Failed to read output file: %v", err) + } + + var projectData utils.ProjectData + err = json.Unmarshal(data, &projectData) + if err != nil { + t.Fatalf("Failed to parse JSON output: %v", err) + } + + // Check if the expected files are present + expectedFiles := []string{"main.go", "README.md", ".gitignore"} + for _, file := range expectedFiles { + found := false + for _, f := range projectData.Files { + if f.Path == file { + found = true + break + } + } + if !found { + t.Errorf("Expected file %s not found in output", file) + } + } + + // Clean up + os.Remove("test_output.json") +} + +func TestReconstructCommand(t *testing.T) { + setupTestProject(t) + defer teardownTestProject(t) + + // First, use the dump command to create a JSON file + dumpCmd := NewDumpCmd() + dumpCmd.SetArgs([]string{"-p", testProjectPath, "-o", "test_dump", "-t", "json"}) + err := dumpCmd.Execute() + if err != nil { + t.Fatalf("Dump command failed: %v", err) + } + + // Now use the reconstruct command + reconstructCmd := NewReconstructCmd() + reconstructCmd.SetArgs([]string{"-j", "test_dump.json", "-o", "test_reconstruct"}) + err = reconstructCmd.Execute() + if err != nil { + t.Fatalf("Reconstruct command failed: %v", err) + } + + // Check if the reconstructed files exist + expectedFiles := []string{"main.go", "README.md", ".gitignore"} + for _, file := range expectedFiles { + path := filepath.Join("test_reconstruct", file) + _, err := os.Stat(path) + if os.IsNotExist(err) { + t.Errorf("Expected file %s not found in reconstructed output", file) + // Print directory contents for debugging + files, _ := ioutil.ReadDir("test_reconstruct") + t.Logf("Contents of test_reconstruct directory:") + for _, f := range files { + t.Logf("- %s", f.Name()) + } + } else if err != nil { + t.Errorf("Error checking file %s: %v", file, err) + } else { + content, err := ioutil.ReadFile(path) + if err != nil { + t.Errorf("Error reading file %s: %v", file, err) + } else { + t.Logf("Content of %s:\n%s", file, string(content)) + } + } + } + + // Clean up + os.RemoveAll("test_reconstruct") + os.Remove("test_dump.json") +} + +// Add more tests for other commands as needed diff --git a/run_tests.sh b/run_tests.sh new file mode 100644 index 0000000..2f0d83a --- /dev/null +++ b/run_tests.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# run_tests.sh + +set -e # Exit immediately if a command exits with a non-zero status. + +echo "Building the project..." +go build -v ./... + +echo "Running all tests..." +go test -v ./... + +echo "Running specific command tests..." +go test -v ./cmd -run TestDumpCommand +go test -v ./cmd -run TestReconstructCommand + +echo "Running utils tests..." +go test -v ./utils -run TestMatchesPatterns + +echo "All tests completed." \ No newline at end of file diff --git a/tests/toy_project/.gitignore b/tests/toy_project/.gitignore new file mode 100644 index 0000000..c43e7ca --- /dev/null +++ b/tests/toy_project/.gitignore @@ -0,0 +1,3 @@ +# Ignore compiled binaries +*.exe +*.out diff --git a/tests/toy_project/README.md b/tests/toy_project/README.md new file mode 100644 index 0000000..1de043b --- /dev/null +++ b/tests/toy_project/README.md @@ -0,0 +1,3 @@ +# Toy Project + +This is a simple toy project used for testing the onefile tool. diff --git a/tests/toy_project/main.go b/tests/toy_project/main.go new file mode 100644 index 0000000..4b45d8c --- /dev/null +++ b/tests/toy_project/main.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("Hello from toy project!") +} diff --git a/utils/file_utils.go b/utils/file_utils.go index 269a577..5e9ece0 100644 --- a/utils/file_utils.go +++ b/utils/file_utils.go @@ -54,16 +54,26 @@ func DumpProject(rootPath string, gitIgnore *ignore.GitIgnore, includeGit, inclu } func ReconstructProject(projectData ProjectData, outputPath string) error { + // First, create all directories for _, dir := range projectData.Directories { - err := os.MkdirAll(filepath.Join(outputPath, dir), 0755) + fullPath := filepath.Join(outputPath, dir) + err := os.MkdirAll(fullPath, 0755) if err != nil { - return fmt.Errorf("error creating directory %s: %v", dir, err) + return fmt.Errorf("error creating directory %s: %v", fullPath, err) } } + // Then, create all files for _, file := range projectData.Files { filePath := filepath.Join(outputPath, file.Path) - err := ioutil.WriteFile(filePath, []byte(file.Content), 0644) + + // Ensure the directory exists (in case it wasn't explicitly listed in Directories) + err := os.MkdirAll(filepath.Dir(filePath), 0755) + if err != nil { + return fmt.Errorf("error creating directory for file %s: %v", filePath, err) + } + + err = ioutil.WriteFile(filePath, []byte(file.Content), 0644) if err != nil { return fmt.Errorf("error writing file %s: %v", file.Path, err) } diff --git a/utils/utils_test.go b/utils/utils_test.go new file mode 100644 index 0000000..2dfde99 --- /dev/null +++ b/utils/utils_test.go @@ -0,0 +1,34 @@ +package utils + +import ( + "testing" + + "github.com/sabhiram/go-gitignore" +) + +func TestMatchesPatterns(t *testing.T) { + patterns := []string{"*.txt", "!important.txt", "temp/"} + gitIgnore := ignore.CompileIgnoreLines(patterns...) + + testCases := []struct { + path string + includeGit bool + includeNonText bool + expected bool + }{ + {"file.txt", true, true, false}, + {"important.txt", true, true, true}, + {"file.go", true, true, true}, + {".git/config", false, true, false}, + {".git/config", true, true, true}, + {"temp/file.go", true, true, false}, + } + + for _, tc := range testCases { + result := MatchesPatterns(tc.path, gitIgnore, tc.includeGit, tc.includeNonText) + if result != tc.expected { + t.Errorf("MatchesPatterns(%q, %v, %v) = %v; want %v", + tc.path, tc.includeGit, tc.includeNonText, result, tc.expected) + } + } +}