114 lines
3.8 KiB
Go
114 lines
3.8 KiB
Go
package search
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/gochat/gochat/internal/model"
|
|
)
|
|
|
|
func TestLiveMeiliSearchEngineIndexesAndSearchesChatwootShapes(t *testing.T) {
|
|
host := os.Getenv("GOCHAT_LIVE_MEILI_HOST")
|
|
if host == "" {
|
|
t.Skip("set GOCHAT_LIVE_MEILI_HOST to run live Meilisearch gate")
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
|
defer cancel()
|
|
|
|
now := time.Now().UTC()
|
|
token := fmt.Sprintf("gochat-live-%d", now.UnixNano())
|
|
accountID := uint(990001)
|
|
senderID := uint(1234)
|
|
prefix := fmt.Sprintf("gochat_live_%d_", now.UnixNano())
|
|
engine := NewMeiliSearchEngine(EngineConfig{
|
|
Host: host,
|
|
APIKey: os.Getenv("GOCHAT_LIVE_MEILI_API_KEY"),
|
|
IndexPrefix: prefix,
|
|
TimeoutSeconds: 5,
|
|
})
|
|
defer cleanupLiveIndexes(context.Background(), engine)
|
|
|
|
require.NoError(t, engine.Bootstrap(ctx))
|
|
waitForLiveIndex(t, ctx, engine, ResultTypeMessage)
|
|
waitForLiveIndex(t, ctx, engine, ResultTypeContact)
|
|
|
|
require.NoError(t, engine.IndexBatch(ctx, []SearchDocument{
|
|
MessageDocument(model.Message{
|
|
Base: model.Base{ID: 7001, CreatedAt: now, UpdatedAt: now},
|
|
AccountID: accountID,
|
|
InboxID: 77,
|
|
ConversationID: 88,
|
|
SenderType: "contact",
|
|
SenderID: &senderID,
|
|
MessageType: "incoming",
|
|
ContentType: "text",
|
|
Status: "sent",
|
|
Content: token + " message body",
|
|
}),
|
|
ContactDocument(model.Contact{
|
|
Base: model.Base{ID: 7002, CreatedAt: now, UpdatedAt: now},
|
|
AccountID: accountID,
|
|
Name: token + " Contact",
|
|
Email: token + "@example.com",
|
|
}),
|
|
}))
|
|
|
|
messageFilter := &SearchFilter{Page: 1, PerPage: 15, Types: []SearchResultType{ResultTypeMessage}, SenderType: "contact", SenderID: &senderID}
|
|
messageResp := waitForLiveSearchResult(t, ctx, engine, accountID, token, messageFilter, ResultTypeMessage)
|
|
require.Equal(t, int64(1), messageResp.ByType[string(ResultTypeMessage)])
|
|
require.Equal(t, uint(7001), messageResp.Results[0].ID)
|
|
require.Equal(t, accountID, messageResp.Results[0].AccountID)
|
|
|
|
contactFilter := &SearchFilter{Page: 1, PerPage: 15, Types: []SearchResultType{ResultTypeContact}}
|
|
contactResp := waitForLiveSearchResult(t, ctx, engine, accountID, token, contactFilter, ResultTypeContact)
|
|
require.Equal(t, int64(1), contactResp.ByType[string(ResultTypeContact)])
|
|
require.Equal(t, uint(7002), contactResp.Results[0].ID)
|
|
require.Equal(t, accountID, contactResp.Results[0].AccountID)
|
|
}
|
|
|
|
func waitForLiveIndex(t *testing.T, ctx context.Context, engine *MeiliSearchEngine, docType SearchResultType) {
|
|
t.Helper()
|
|
deadline := time.Now().Add(10 * time.Second)
|
|
for {
|
|
resp, err := engine.client.R().SetContext(ctx).Get(fmt.Sprintf("/indexes/%s", engine.indexName(docType)))
|
|
if err == nil && resp.StatusCode() == 200 {
|
|
return
|
|
}
|
|
if time.Now().After(deadline) {
|
|
require.NoError(t, err)
|
|
require.Equal(t, 200, resp.StatusCode())
|
|
}
|
|
time.Sleep(200 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
func waitForLiveSearchResult(t *testing.T, ctx context.Context, engine *MeiliSearchEngine, accountID uint, query string, filter *SearchFilter, resultType SearchResultType) *SearchResponse {
|
|
t.Helper()
|
|
deadline := time.Now().Add(10 * time.Second)
|
|
var lastErr error
|
|
for {
|
|
resp, err := engine.Search(ctx, accountID, query, filter)
|
|
if err == nil && len(resp.Results) > 0 && resp.Results[0].Type == resultType {
|
|
return resp
|
|
}
|
|
lastErr = err
|
|
if time.Now().After(deadline) {
|
|
require.NoError(t, lastErr)
|
|
require.FailNow(t, "timed out waiting for live Meilisearch result")
|
|
}
|
|
time.Sleep(250 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
func cleanupLiveIndexes(ctx context.Context, engine *MeiliSearchEngine) {
|
|
for _, docType := range searchableTypes(nil) {
|
|
_, _ = engine.client.R().SetContext(ctx).Delete(fmt.Sprintf("/indexes/%s", engine.indexName(docType)))
|
|
}
|
|
}
|