Files
cheat/internal/cheatpath/cheatpath_test.go
Christopher Allen Lane cc85a4bdb1 chore: bump version to 4.5.0
Bug fixes:
- Fix inverted pager detection logic (returned error instead of path)
- Fix repo.Clone ignoring destination directory parameter
- Fix sheet loading using append on pre-sized slices
- Clean up partial files on copy failure
- Trim whitespace from editor config

Security:
- Add path traversal protection for cheatsheet names

Performance:
- Move regex compilation outside search loop
- Replace string concatenation with strings.Join in search

Build:
- Remove go:generate; embed config and usage as string literals
- Parallelize release builds
- Add fuzz testing infrastructure

Testing:
- Improve test coverage from 38.9% to 50.2%
- Add fuzz tests for search, filter, tags, and validation

Documentation:
- Fix inaccurate code examples in HACKING.md
- Add missing --conf and --all options to man page
- Add ADRs for path traversal, env parsing, and search parallelization
- Update CONTRIBUTING.md to reflect project policy

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 19:56:19 -05:00

114 lines
2.4 KiB
Go

package cheatpath
import (
"strings"
"testing"
)
func TestCheatpathValidate(t *testing.T) {
tests := []struct {
name string
cheatpath Cheatpath
wantErr bool
errMsg string
}{
{
name: "valid cheatpath",
cheatpath: Cheatpath{
Name: "personal",
Path: "/home/user/.config/cheat/personal",
ReadOnly: false,
Tags: []string{"personal"},
},
wantErr: false,
},
{
name: "empty name",
cheatpath: Cheatpath{
Name: "",
Path: "/home/user/.config/cheat/personal",
ReadOnly: false,
Tags: []string{"personal"},
},
wantErr: true,
errMsg: "cheatpath name cannot be empty",
},
{
name: "empty path",
cheatpath: Cheatpath{
Name: "personal",
Path: "",
ReadOnly: false,
Tags: []string{"personal"},
},
wantErr: true,
errMsg: "cheatpath path cannot be empty",
},
{
name: "both empty",
cheatpath: Cheatpath{
Name: "",
Path: "",
ReadOnly: true,
Tags: nil,
},
wantErr: true,
errMsg: "cheatpath name cannot be empty",
},
{
name: "minimal valid",
cheatpath: Cheatpath{
Name: "x",
Path: "/",
},
wantErr: false,
},
{
name: "with readonly and tags",
cheatpath: Cheatpath{
Name: "community",
Path: "/usr/share/cheat",
ReadOnly: true,
Tags: []string{"community", "shared", "readonly"},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.cheatpath.Validate()
if (err != nil) != tt.wantErr {
t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
return
}
if err != nil && tt.errMsg != "" && !strings.Contains(err.Error(), tt.errMsg) {
t.Errorf("Validate() error = %v, want error containing %q", err, tt.errMsg)
}
})
}
}
func TestCheatpathStruct(t *testing.T) {
// Test that the struct fields work as expected
cp := Cheatpath{
Name: "test",
Path: "/test/path",
ReadOnly: true,
Tags: []string{"tag1", "tag2"},
}
if cp.Name != "test" {
t.Errorf("expected Name to be 'test', got %q", cp.Name)
}
if cp.Path != "/test/path" {
t.Errorf("expected Path to be '/test/path', got %q", cp.Path)
}
if !cp.ReadOnly {
t.Error("expected ReadOnly to be true")
}
if len(cp.Tags) != 2 || cp.Tags[0] != "tag1" || cp.Tags[1] != "tag2" {
t.Errorf("expected Tags to be [tag1 tag2], got %v", cp.Tags)
}
}