package todo import ( "os" "path/filepath" "strings" "testing" ) func TestBootstrapCreatesStructure(t *testing.T) { tmpDir := t.TempDir() origDir, _ := os.Getwd() if err := os.Chdir(tmpDir); err != nil { t.Fatal(err) } defer func() { _ = os.Chdir(origDir) }() if err := Bootstrap(); err != nil { t.Fatalf("Bootstrap failed: %v", err) } // Verify directories for _, dir := range []string{"todo/queued", "todo/doing", "todo/completed"} { info, err := os.Stat(dir) if err != nil { t.Errorf("expected %s to exist: %v", dir, err) continue } if !info.IsDir() { t.Errorf("expected %s to be a directory", dir) } } // Verify README data, err := os.ReadFile("todo/README.md") if err != nil { t.Fatalf("expected todo/README.md to exist: %v", err) } content := string(data) if !strings.Contains(content, "## Queued") { t.Error("README missing ## Queued heading") } if !strings.Contains(content, "## Completed") { t.Error("README missing ## Completed heading") } } func TestBootstrapIdempotent(t *testing.T) { tmpDir := t.TempDir() origDir, _ := os.Getwd() if err := os.Chdir(tmpDir); err != nil { t.Fatal(err) } defer func() { _ = os.Chdir(origDir) }() // Run twice if err := Bootstrap(); err != nil { t.Fatalf("first Bootstrap failed: %v", err) } if err := Bootstrap(); err != nil { t.Fatalf("second Bootstrap failed: %v", err) } // Verify structure still intact for _, dir := range []string{"todo/queued", "todo/doing", "todo/completed"} { if _, err := os.Stat(dir); err != nil { t.Errorf("expected %s to exist after second Bootstrap: %v", dir, err) } } } func TestBootstrapPreservesExistingReadme(t *testing.T) { tmpDir := t.TempDir() origDir, _ := os.Getwd() if err := os.Chdir(tmpDir); err != nil { t.Fatal(err) } defer func() { _ = os.Chdir(origDir) }() // Create structure with custom README if err := os.MkdirAll("todo", 0755); err != nil { t.Fatal(err) } customContent := "# My Custom TODO\n\nCustom content here.\n" if err := os.WriteFile("todo/README.md", []byte(customContent), 0644); err != nil { t.Fatal(err) } if err := Bootstrap(); err != nil { t.Fatalf("Bootstrap failed: %v", err) } // Verify custom README was not overwritten data, err := os.ReadFile("todo/README.md") if err != nil { t.Fatal(err) } if string(data) != customContent { t.Errorf("Bootstrap overwrote existing README.\ngot: %q\nwant: %q", string(data), customContent) } } func TestBootstrapCreatesReadmeWithCorrectPermissions(t *testing.T) { tmpDir := t.TempDir() origDir, _ := os.Getwd() if err := os.Chdir(tmpDir); err != nil { t.Fatal(err) } defer func() { _ = os.Chdir(origDir) }() if err := Bootstrap(); err != nil { t.Fatal(err) } info, err := os.Stat(filepath.Join("todo", "README.md")) if err != nil { t.Fatal(err) } perm := info.Mode().Perm() if perm != 0644 { t.Errorf("README permissions = %o, want 0644", perm) } }