Restructure the monorepo into clear top-level directories: - backend/: Go module root (cmd, internal, pkg, configs, migrations, docs/swagger, scripts, tests, go.mod, Makefile, .air.toml) - deploy/: Docker (Dockerfile, docker-compose*), quickstart, fluentd - docs/: project documentation + reports/ (moved from repo root) - AGENTS.md: new AI coding-agent guide at repo root Update all references to the new layout: - Dockerfile: COPY backend/go.mod, COPY backend/ (context = repo root) - docker-compose files: context ../.., dockerfile deploy/docker/Dockerfile, env_file ../../.env, volume mounts ../../backend:/app - deploy/quickstart/compose.yaml: dockerfile deploy/docker/Dockerfile - CI: working-directory: backend for go commands, file deploy/docker/Dockerfile, coverage path backend/coverage.out, health_check backend/scripts/ - backend/Makefile: docker target uses -f ../deploy/docker/Dockerfile ../ - README: architecture tree, quickstart, config paths updated Move root stray scripts (rename_models.*, run_m11_tests.sh, verify_build.sh, gorm_bool_main.go) to backend/scripts/legacy/. All moves via git mv to preserve history. Build, vet, SQLite tests, and docker compose config verified.
117 lines
4.1 KiB
Go
117 lines
4.1 KiB
Go
package pubsub
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/ThreeDotsLabs/watermill"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
// --- Topic Constants Tests ---
|
|
// Verifies that all topic constants follow the expected naming convention.
|
|
|
|
func TestTopicConstants_MessageTopics(t *testing.T) {
|
|
assert.Equal(t, "gochat.message.created", TopicMessageCreated)
|
|
assert.Equal(t, "gochat.message.updated", TopicMessageUpdated)
|
|
assert.Equal(t, "gochat.message.deleted", TopicMessageDeleted)
|
|
}
|
|
|
|
func TestTopicConstants_ConversationTopics(t *testing.T) {
|
|
assert.Equal(t, "gochat.conversation.created", TopicConversationCreated)
|
|
assert.Equal(t, "gochat.conversation.updated", TopicConversationUpdated)
|
|
assert.Equal(t, "gochat.conversation.resolved", TopicConversationResolved)
|
|
assert.Equal(t, "gochat.conversation.assigned", TopicConversationAssigned)
|
|
}
|
|
|
|
func TestTopicConstants_ContactTopics(t *testing.T) {
|
|
assert.Equal(t, "gochat.contact.created", TopicContactCreated)
|
|
assert.Equal(t, "gochat.contact.updated", TopicContactUpdated)
|
|
}
|
|
|
|
func TestTopicConstants_InboxTopics(t *testing.T) {
|
|
assert.Equal(t, "gochat.inbox.created", TopicInboxCreated)
|
|
assert.Equal(t, "gochat.inbox.updated", TopicInboxUpdated)
|
|
assert.Equal(t, "gochat.inbox.deleted", TopicInboxDeleted)
|
|
}
|
|
|
|
func TestTopicConstants_AgentTopics(t *testing.T) {
|
|
assert.Equal(t, "gochat.agent.typing_on", TopicAgentTypingOn)
|
|
assert.Equal(t, "gochat.agent.typing_off", TopicAgentTypingOff)
|
|
}
|
|
|
|
func TestTopicConstants_SystemTopics(t *testing.T) {
|
|
assert.Equal(t, "gochat.webhook.received", TopicWebhookReceived)
|
|
assert.Equal(t, "gochat.system.notification", TopicSystemNotification)
|
|
}
|
|
|
|
func TestTopicConstants_AllFollowNamingConvention(t *testing.T) {
|
|
// All topics must start with "gochat."
|
|
topics := []string{
|
|
TopicMessageCreated, TopicMessageUpdated, TopicMessageDeleted,
|
|
TopicConversationCreated, TopicConversationUpdated, TopicConversationResolved, TopicConversationAssigned,
|
|
TopicContactCreated, TopicContactUpdated,
|
|
TopicInboxCreated, TopicInboxUpdated, TopicInboxDeleted,
|
|
TopicAgentTypingOn, TopicAgentTypingOff,
|
|
TopicWebhookReceived, TopicSystemNotification,
|
|
}
|
|
for _, topic := range topics {
|
|
assert.True(t, len(topic) > 7, "topic should not be empty")
|
|
assert.Equal(t, "gochat.", topic[:7], "topic should start with 'gochat.'")
|
|
}
|
|
}
|
|
|
|
// --- FormatTopic Tests ---
|
|
// Verifies the dynamic topic formatting function.
|
|
|
|
func TestFormatTopic_ChannelEvent(t *testing.T) {
|
|
result := FormatTopic(TopicChannelEvent, "telegram")
|
|
assert.Equal(t, "gochat.channel.event.telegram", result)
|
|
}
|
|
|
|
func TestFormatTopic_WebWidget(t *testing.T) {
|
|
result := FormatTopic(TopicChannelEvent, "web_widget")
|
|
assert.Equal(t, "gochat.channel.event.web_widget", result)
|
|
}
|
|
|
|
func TestFormatTopic_Facebook(t *testing.T) {
|
|
result := FormatTopic(TopicChannelEvent, "facebook")
|
|
assert.Equal(t, "gochat.channel.event.facebook", result)
|
|
}
|
|
|
|
func TestFormatTopic_WhatsApp(t *testing.T) {
|
|
result := FormatTopic(TopicChannelEvent, "whatsapp")
|
|
assert.Equal(t, "gochat.channel.event.whatsapp", result)
|
|
}
|
|
|
|
func TestFormatTopic_TemplateWithoutFormatSpecifier(t *testing.T) {
|
|
// If template has no %s, suffix is ignored
|
|
result := FormatTopic("gochat.fixed.topic", "ignored_suffix")
|
|
assert.Equal(t, "gochat.fixed.topic", result)
|
|
}
|
|
|
|
func TestFormatTopic_EmptySuffix(t *testing.T) {
|
|
result := FormatTopic(TopicChannelEvent, "")
|
|
assert.Equal(t, "gochat.channel.event.", result)
|
|
}
|
|
|
|
func TestFormatTopic_MultipleFormatSpecifiers(t *testing.T) {
|
|
// FormatTopic replaces ALL %s occurrences with the suffix
|
|
result := FormatTopic("gochat.%s.%s", "test")
|
|
assert.Equal(t, "gochat.test.test", result)
|
|
}
|
|
|
|
// --- zapLoggerAdapter Tests ---
|
|
// These verify the logger adapter exists and has the correct interface.
|
|
|
|
func TestZapLoggerAdapter_ImplementsInterface(t *testing.T) {
|
|
// Verify that zapLoggerAdapter satisfies watermill.LoggerAdapter at compile time
|
|
var _ watermill.LoggerAdapter = &zapLoggerAdapter{}
|
|
}
|
|
|
|
func TestZapLoggerAdapter_With_ReturnsSameAdapter(t *testing.T) {
|
|
adapter := &zapLoggerAdapter{}
|
|
result := adapter.With(watermill.LogFields{"key": "value"})
|
|
assert.NotNil(t, result)
|
|
// With() returns the same adapter (no field enrichment)
|
|
assert.Equal(t, adapter, result)
|
|
} |