package cmd import ( "os" "path/filepath" "testing" "time" "github.com/stretchr/testify/require" "github.com/salvacybersec/keyhunter/pkg/engine/sources" ) func TestSelectSource_Directory(t *testing.T) { dir := t.TempDir() src, err := selectSource([]string{dir}, sourceFlags{}) require.NoError(t, err) _, ok := src.(*sources.DirSource) require.True(t, ok, "expected *DirSource, got %T", src) } func TestSelectSource_File(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "a.txt") require.NoError(t, os.WriteFile(f, []byte("x"), 0o644)) src, err := selectSource([]string{f}, sourceFlags{}) require.NoError(t, err) _, ok := src.(*sources.FileSource) require.True(t, ok, "expected *FileSource, got %T", src) } func TestSelectSource_Git(t *testing.T) { src, err := selectSource([]string{"./some-repo"}, sourceFlags{Git: true}) require.NoError(t, err) gs, ok := src.(*sources.GitSource) require.True(t, ok, "expected *GitSource, got %T", src) require.Equal(t, "./some-repo", gs.RepoPath) } func TestSelectSource_GitSince(t *testing.T) { src, err := selectSource([]string{"./repo"}, sourceFlags{Git: true, Since: "2024-01-15"}) require.NoError(t, err) gs := src.(*sources.GitSource) want, _ := time.Parse("2006-01-02", "2024-01-15") require.Equal(t, want, gs.Since) } func TestSelectSource_GitSinceBadFormat(t *testing.T) { _, err := selectSource([]string{"./repo"}, sourceFlags{Git: true, Since: "15/01/2024"}) require.Error(t, err) require.Contains(t, err.Error(), "YYYY-MM-DD") } func TestSelectSource_URL(t *testing.T) { src, err := selectSource(nil, sourceFlags{URL: "https://example.com/a.js"}) require.NoError(t, err) _, ok := src.(*sources.URLSource) require.True(t, ok) } func TestSelectSource_URLRejectsPositional(t *testing.T) { _, err := selectSource([]string{"./foo"}, sourceFlags{URL: "https://x"}) require.Error(t, err) } func TestSelectSource_Clipboard(t *testing.T) { src, err := selectSource(nil, sourceFlags{Clipboard: true}) require.NoError(t, err) _, ok := src.(*sources.ClipboardSource) require.True(t, ok) } func TestSelectSource_ClipboardRejectsPositional(t *testing.T) { _, err := selectSource([]string{"./foo"}, sourceFlags{Clipboard: true}) require.Error(t, err) } func TestSelectSource_Stdin(t *testing.T) { for _, tok := range []string{"stdin", "-"} { src, err := selectSource([]string{tok}, sourceFlags{}) require.NoError(t, err) _, ok := src.(*sources.StdinSource) require.True(t, ok, "token %q: expected *StdinSource, got %T", tok, src) } } func TestSelectSource_MutuallyExclusive(t *testing.T) { _, err := selectSource(nil, sourceFlags{Git: true, URL: "https://x"}) require.Error(t, err) require.Contains(t, err.Error(), "mutually exclusive") } func TestSelectSource_MissingTarget(t *testing.T) { _, err := selectSource(nil, sourceFlags{}) require.Error(t, err) require.Contains(t, err.Error(), "missing target") } func TestSelectSource_DirForwardsExcludes(t *testing.T) { dir := t.TempDir() src, err := selectSource([]string{dir}, sourceFlags{Excludes: []string{"*.log", "tmp/**"}}) require.NoError(t, err) ds := src.(*sources.DirSource) // NewDirSource merges DefaultExcludes with extras, so user patterns must be present. found := 0 for _, e := range ds.Excludes { if e == "*.log" || e == "tmp/**" { found++ } } require.Equal(t, 2, found, "user excludes not forwarded, got %v", ds.Excludes) }