Files
gochat/backend/internal/repository/article_embedding_repo_test.go
T
2026-08-14 22:40:48 +08:00

151 lines
5.6 KiB
Go

package repository
import (
"context"
"testing"
"github.com/pgvector/pgvector-go"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/gochat/gochat/internal/model"
)
func TestArticleEmbeddingRepo_DB(t *testing.T) {
db := setupTestDB(t, &model.ArticleEmbedding{}, &model.Article{})
repo := NewArticleEmbeddingRepo(db)
assert.NotNil(t, repo.DB())
}
func TestArticleEmbeddingRepo_Upsert_Create(t *testing.T) {
db := setupTestDB(t, &model.ArticleEmbedding{}, &model.Article{})
repo := NewArticleEmbeddingRepo(db)
account := &model.Account{Name: "AEOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
portal := &model.Portal{AccountID: account.ID, Name: "Portal", Slug: "ae-portal"}
require.NoError(t, db.Create(portal).Error)
article := &model.Article{AccountID: account.ID, PortalID: portal.ID, Title: "Art", Slug: "ae-art", Status: "published"}
require.NoError(t, db.Create(article).Error)
emb := &model.ArticleEmbedding{
ArticleID: article.ID,
Term: "test content",
}
err := repo.Upsert(context.Background(), emb)
assert.NoError(t, err)
}
func TestArticleEmbeddingRepo_Upsert_Update(t *testing.T) {
db := setupTestDB(t, &model.ArticleEmbedding{}, &model.Article{})
repo := NewArticleEmbeddingRepo(db)
account := &model.Account{Name: "AEUpdOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
portal := &model.Portal{AccountID: account.ID, Name: "Portal", Slug: "ae-upd"}
require.NoError(t, db.Create(portal).Error)
article := &model.Article{AccountID: account.ID, PortalID: portal.ID, Title: "Art", Slug: "ae-upd-art", Status: "published"}
require.NoError(t, db.Create(article).Error)
// Create first
emb := &model.ArticleEmbedding{ArticleID: article.ID, Term: "original"}
require.NoError(t, repo.Upsert(context.Background(), emb))
// Update
emb2 := &model.ArticleEmbedding{ArticleID: article.ID, Term: "updated"}
err := repo.Upsert(context.Background(), emb2)
assert.NoError(t, err)
found, _ := repo.GetByArticleID(context.Background(), article.ID)
assert.Equal(t, "updated", found.Term)
}
func TestArticleEmbeddingRepo_GetByArticleID(t *testing.T) {
db := setupTestDB(t, &model.ArticleEmbedding{}, &model.Article{})
repo := NewArticleEmbeddingRepo(db)
account := &model.Account{Name: "AEGetOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
portal := &model.Portal{AccountID: account.ID, Name: "Portal", Slug: "ae-get"}
require.NoError(t, db.Create(portal).Error)
article := &model.Article{AccountID: account.ID, PortalID: portal.ID, Title: "Art", Slug: "ae-get-art", Status: "published"}
require.NoError(t, db.Create(article).Error)
emb := &model.ArticleEmbedding{ArticleID: article.ID, Term: "get test"}
require.NoError(t, repo.Upsert(context.Background(), emb))
found, err := repo.GetByArticleID(context.Background(), article.ID)
assert.NoError(t, err)
assert.Equal(t, "get test", found.Term)
}
func TestArticleEmbeddingRepo_GetByArticleID_NotFound(t *testing.T) {
db := setupTestDB(t, &model.ArticleEmbedding{}, &model.Article{})
repo := NewArticleEmbeddingRepo(db)
_, err := repo.GetByArticleID(context.Background(), 9999)
assert.Error(t, err)
}
func TestArticleEmbeddingRepo_DeleteByArticleID(t *testing.T) {
db := setupTestDB(t, &model.ArticleEmbedding{}, &model.Article{})
repo := NewArticleEmbeddingRepo(db)
account := &model.Account{Name: "AEDelOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
portal := &model.Portal{AccountID: account.ID, Name: "Portal", Slug: "ae-del"}
require.NoError(t, db.Create(portal).Error)
article := &model.Article{AccountID: account.ID, PortalID: portal.ID, Title: "Art", Slug: "ae-del-art", Status: "published"}
require.NoError(t, db.Create(article).Error)
emb := &model.ArticleEmbedding{ArticleID: article.ID, Term: "del test"}
require.NoError(t, repo.Upsert(context.Background(), emb))
err := repo.DeleteByArticleID(context.Background(), article.ID)
assert.NoError(t, err)
_, err = repo.GetByArticleID(context.Background(), article.ID)
assert.Error(t, err)
}
func TestArticleEmbeddingRepo_SearchByEmbedding_ExcludesSoftDeletedArticleAndEmbedding(t *testing.T) {
skipIfSQLite(t)
db := setupTestDB(t, &model.ArticleEmbedding{}, &model.Article{}, &model.Portal{})
repo := NewArticleEmbeddingRepo(db)
account := &model.Account{Name: "Soft Delete Search", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
portal := &model.Portal{AccountID: account.ID, Name: "Portal", Slug: "soft-delete-search"}
require.NoError(t, db.Create(portal).Error)
embedding := pgvector.NewVector([]float32{1, 0})
articles := make([]model.Article, 3)
for i, name := range []string{"live", "deleted-article", "deleted-embedding"} {
articles[i] = model.Article{
AccountID: account.ID,
PortalID: portal.ID,
Title: name,
Slug: "soft-delete-search-" + name,
Status: "published",
}
require.NoError(t, db.Create(&articles[i]).Error)
require.NoError(t, repo.Upsert(context.Background(), &model.ArticleEmbedding{
ArticleID: articles[i].ID,
VectorEmbedding: embedding,
Term: name,
}))
}
before, err := repo.SearchByEmbedding(context.Background(), portal.ID, embedding, 10)
require.NoError(t, err)
require.Len(t, before, 3)
require.NotNil(t, before[0].SemanticDistance)
require.NoError(t, db.Delete(&articles[1]).Error)
require.NoError(t, repo.DeleteByArticleID(context.Background(), articles[2].ID))
after, err := repo.SearchByEmbedding(context.Background(), portal.ID, embedding, 10)
require.NoError(t, err)
require.Len(t, after, 1)
assert.Equal(t, articles[0].ID, after[0].ID)
}