Files
claude-mnemonic/internal/worker/sdk/dedup_test.go
T
2026-03-06 15:39:52 +00:00

144 lines
3.4 KiB
Go

package sdk
import (
"testing"
"github.com/lukaszraczylo/claude-mnemonic/internal/vector/sqlitevec"
"github.com/lukaszraczylo/claude-mnemonic/pkg/models"
)
func TestBuildObservationSearchText(t *testing.T) {
tests := []struct {
name string
obs *models.ParsedObservation
expected string
}{
{
name: "empty observation",
obs: &models.ParsedObservation{},
expected: "",
},
{
name: "title only",
obs: &models.ParsedObservation{
Title: "Fix database connection",
},
expected: "Fix database connection",
},
{
name: "all fields",
obs: &models.ParsedObservation{
Title: "Fix database connection",
Subtitle: "Connection pooling issue",
Narrative: "The database connection pool was exhausted due to leaked connections.",
},
expected: "Fix database connection Connection pooling issue The database connection pool was exhausted due to leaked connections.",
},
{
name: "truncates long text",
obs: &models.ParsedObservation{
Narrative: string(make([]byte, 3000)),
},
expected: string(make([]byte, 2000)),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := buildObservationSearchText(tt.obs)
if result != tt.expected {
t.Errorf("got %q, want %q", result, tt.expected)
}
})
}
}
func TestExtractObservationIDFromVectorDoc(t *testing.T) {
tests := []struct {
name string
result sqlitevec.QueryResult
expected int64
}{
{
name: "from sqlite_id metadata (float64)",
result: sqlitevec.QueryResult{
ID: "obs_42_narrative",
Metadata: map[string]any{"sqlite_id": float64(42)},
},
expected: 42,
},
{
name: "from sqlite_id metadata (int64)",
result: sqlitevec.QueryResult{
ID: "obs_42_narrative",
Metadata: map[string]any{"sqlite_id": int64(42)},
},
expected: 42,
},
{
name: "fallback to doc_id parsing",
result: sqlitevec.QueryResult{
ID: "obs_99_composite",
Metadata: map[string]any{},
},
expected: 99,
},
{
name: "non-observation doc_id",
result: sqlitevec.QueryResult{
ID: "summary_5_text",
Metadata: map[string]any{},
},
expected: 0,
},
{
name: "zero sqlite_id falls back to doc_id",
result: sqlitevec.QueryResult{
ID: "obs_123_narrative",
Metadata: map[string]any{"sqlite_id": float64(0)},
},
expected: 123,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := extractObservationIDFromVectorDoc(tt.result)
if result != tt.expected {
t.Errorf("got %d, want %d", result, tt.expected)
}
})
}
}
func TestCheckVectorDeduplication_NilClient(t *testing.T) {
p := &Processor{
// No vectorClient set
}
obs := &models.ParsedObservation{
Title: "Test observation",
Narrative: "Some narrative text",
}
result := p.checkVectorDeduplication(nil, obs, "test-project")
if result.Action != "insert" {
t.Errorf("expected Action='insert' when vectorClient is nil, got %q", result.Action)
}
}
func TestCheckVectorDeduplication_EmptySearchText(t *testing.T) {
p := &Processor{
// vectorClient would be set but obs is empty
}
obs := &models.ParsedObservation{
// All empty fields
}
result := p.checkVectorDeduplication(nil, obs, "test-project")
if result.Action != "insert" {
t.Errorf("expected Action='insert' for empty observation, got %q", result.Action)
}
}