diff --git a/pkg/bot/handlers_test.go b/pkg/bot/handlers_test.go new file mode 100644 index 0000000..62549a7 --- /dev/null +++ b/pkg/bot/handlers_test.go @@ -0,0 +1,96 @@ +package bot + +import ( + "strings" + "testing" + + "github.com/mymmrac/telego" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/salvacybersec/keyhunter/pkg/storage" +) + +func TestExtractArg(t *testing.T) { + tests := []struct { + input string + want string + }{ + {"/help", ""}, + {"/scan /tmp/repo", "/tmp/repo"}, + {"/verify 42", "42"}, + {"/key 99 ", "99"}, + {"/recon --sources=github,gitlab", "--sources=github,gitlab"}, + {"", ""}, + } + for _, tt := range tests { + got := extractArg(tt.input) + assert.Equal(t, tt.want, got, "extractArg(%q)", tt.input) + } +} + +func TestIsPrivateChat(t *testing.T) { + private := &telego.Message{Chat: telego.Chat{Type: "private"}} + group := &telego.Message{Chat: telego.Chat{Type: "group"}} + supergroup := &telego.Message{Chat: telego.Chat{Type: "supergroup"}} + + assert.True(t, isPrivateChat(private)) + assert.False(t, isPrivateChat(group)) + assert.False(t, isPrivateChat(supergroup)) +} + +func TestCommandHelpContainsAllCommands(t *testing.T) { + expectedCommands := []string{"/help", "/scan", "/verify", "/recon", "/status", "/stats", "/providers", "/key"} + + require.Len(t, commandHelp, len(expectedCommands), "commandHelp should have %d entries", len(expectedCommands)) + + for _, expected := range expectedCommands { + found := false + for _, c := range commandHelp { + if strings.HasPrefix(c.Cmd, expected) { + found = true + assert.NotEmpty(t, c.Desc, "command %s should have a description", expected) + break + } + } + assert.True(t, found, "command %s should be in commandHelp", expected) + } +} + +func TestCommandHelpDescriptionsNonEmpty(t *testing.T) { + for _, c := range commandHelp { + assert.NotEmpty(t, c.Desc, "command %s must have a description", c.Cmd) + } +} + +func TestStorageToEngine(t *testing.T) { + sf := storageToEngine(dummyStorageFinding()) + assert.Equal(t, "openai", sf.ProviderName) + assert.Equal(t, "sk-****abcd", sf.KeyMasked) + assert.Equal(t, "test.txt", sf.Source) + assert.Equal(t, "file", sf.SourceType) + assert.Equal(t, 10, sf.LineNumber) +} + +// TestNewBot verifies the constructor wires all dependencies. +func TestNewBot(t *testing.T) { + b := New(nil, Deps{}) + require.NotNil(t, b) + assert.False(t, b.startedAt.IsZero(), "startedAt should be set") + assert.True(t, b.lastScan.IsZero(), "lastScan should be zero initially") +} + +// --- helpers --- + +func dummyStorageFinding() storage.Finding { + return storage.Finding{ + ID: 1, + ProviderName: "openai", + KeyValue: "sk-realkey1234", + KeyMasked: "sk-****abcd", + Confidence: "high", + SourcePath: "test.txt", + SourceType: "file", + LineNumber: 10, + } +}