932 lines
28 KiB
Go
932 lines
28 KiB
Go
package email
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
channelpkg "github.com/gochat/gochat/internal/channel"
|
|
"github.com/gochat/gochat/internal/model"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// ===========================
|
|
// EmailProvider (email package) tests
|
|
// ===========================
|
|
|
|
func TestEmailProvider_Type_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
assert.Equal(t, channelpkg.ChannelEmail, p.Type())
|
|
}
|
|
|
|
func TestEmailProvider_Name_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
assert.Equal(t, "Email", p.Name())
|
|
}
|
|
|
|
func TestEmailProvider_Description_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
assert.NotEmpty(t, p.Description())
|
|
}
|
|
|
|
func TestEmailProvider_ConfigSchema_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
schema := p.ConfigSchema()
|
|
require.NotNil(t, schema)
|
|
assert.Equal(t, "object", schema.Type)
|
|
assert.Contains(t, schema.Required, "imap_address")
|
|
assert.Contains(t, schema.Required, "smtp_address")
|
|
}
|
|
|
|
func TestEmailProvider_DefaultConfig_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
cfg := p.DefaultConfig()
|
|
assert.Contains(t, cfg, "imap_address")
|
|
assert.Contains(t, cfg, "smtp_address")
|
|
assert.Contains(t, cfg, "imap_port")
|
|
assert.Contains(t, cfg, "smtp_port")
|
|
}
|
|
|
|
func TestEmailProvider_Capabilities_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
caps := p.Capabilities()
|
|
assert.True(t, caps.SupportsAttachments)
|
|
assert.True(t, caps.SupportsDeliveryStatus)
|
|
assert.True(t, caps.SupportsReplies)
|
|
assert.True(t, caps.SupportsEmailHeaders)
|
|
assert.Equal(t, 0, caps.MaxTextLength)
|
|
}
|
|
|
|
func TestEmailProvider_PollInterval_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
assert.Equal(t, 5*1000000000*60, int(p.PollInterval())) // 5 minutes
|
|
}
|
|
|
|
func TestEmailProvider_ValidateConfig_NoIMAPAddress_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
err := p.ValidateConfig(context.Background(), channelpkg.ChannelConfig{})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "imap_address")
|
|
}
|
|
|
|
func TestEmailProvider_ValidateConfig_NoIMAPPort_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
err := p.ValidateConfig(context.Background(), channelpkg.ChannelConfig{
|
|
"imap_address": "imap.test.com",
|
|
})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "imap_port")
|
|
}
|
|
|
|
func TestEmailProvider_ValidateConfig_NoIMAPEmail_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
err := p.ValidateConfig(context.Background(), channelpkg.ChannelConfig{
|
|
"imap_address": "imap.test.com",
|
|
"imap_port": 993,
|
|
})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "imap_email")
|
|
}
|
|
|
|
func TestEmailProvider_ValidateConfig_NoIMAPPassword_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
err := p.ValidateConfig(context.Background(), channelpkg.ChannelConfig{
|
|
"imap_address": "imap.test.com",
|
|
"imap_port": 993,
|
|
"imap_email": "user@test.com",
|
|
})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "imap_password")
|
|
}
|
|
|
|
func TestEmailProvider_ValidateConfig_NoSMTPAddress_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
err := p.ValidateConfig(context.Background(), channelpkg.ChannelConfig{
|
|
"imap_address": "imap.test.com",
|
|
"imap_port": 993,
|
|
"imap_email": "user@test.com",
|
|
"imap_password": "pass",
|
|
})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "smtp_address")
|
|
}
|
|
|
|
func TestEmailProvider_ValidateConfig_NoSMTPPort_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
err := p.ValidateConfig(context.Background(), channelpkg.ChannelConfig{
|
|
"imap_address": "imap.test.com",
|
|
"imap_port": 993,
|
|
"imap_email": "user@test.com",
|
|
"imap_password": "pass",
|
|
"smtp_address": "smtp.test.com",
|
|
})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "smtp_port")
|
|
}
|
|
|
|
func TestEmailProvider_ValidateConfig_NoSMTPEmail_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
err := p.ValidateConfig(context.Background(), channelpkg.ChannelConfig{
|
|
"imap_address": "imap.test.com",
|
|
"imap_port": 993,
|
|
"imap_email": "user@test.com",
|
|
"imap_password": "pass",
|
|
"smtp_address": "smtp.test.com",
|
|
"smtp_port": 587,
|
|
})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "smtp_email")
|
|
}
|
|
|
|
func TestEmailProvider_ValidateConfig_NoSMTPPassword_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
err := p.ValidateConfig(context.Background(), channelpkg.ChannelConfig{
|
|
"imap_address": "imap.test.com",
|
|
"imap_port": 993,
|
|
"imap_email": "user@test.com",
|
|
"imap_password": "pass",
|
|
"smtp_address": "smtp.test.com",
|
|
"smtp_port": 587,
|
|
"smtp_email": "user@test.com",
|
|
})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "smtp_password")
|
|
}
|
|
|
|
func TestEmailProvider_ValidateConfig_Success_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
err := p.ValidateConfig(context.Background(), channelpkg.ChannelConfig{
|
|
"imap_address": "imap.test.com",
|
|
"imap_port": 993,
|
|
"imap_email": "user@test.com",
|
|
"imap_password": "pass",
|
|
"smtp_address": "smtp.test.com",
|
|
"smtp_port": 587,
|
|
"smtp_email": "user@test.com",
|
|
"smtp_password": "pass",
|
|
})
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestEmailProvider_OnCreate_NoService_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
// OnCreate calls p.service.ValidateIMAPConnection which panics on nil service.
|
|
// Use defer/recover to handle the panic safely.
|
|
safeCall6(func() {
|
|
p.OnCreate(context.Background(), inbox, channelpkg.ChannelConfig{})
|
|
})
|
|
}
|
|
|
|
func TestEmailProvider_OnCreate_IMAPFail_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(&Service{}, nil, nil)
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
_, err := p.OnCreate(context.Background(), inbox, channelpkg.ChannelConfig{
|
|
"imap_address": "imap.test.com",
|
|
"imap_port": 993,
|
|
"imap_email": "user@test.com",
|
|
"imap_password": "pass",
|
|
"smtp_address": "smtp.test.com",
|
|
"smtp_port": 587,
|
|
"smtp_email": "user@test.com",
|
|
"smtp_password": "pass",
|
|
})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "IMAP")
|
|
}
|
|
|
|
func TestEmailProvider_OnDestroy_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
err := p.OnDestroy(context.Background(), inbox, channelpkg.ChannelConfig{})
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestEmailProvider_ProcessIncoming_BadJSON_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
inbox := &model.Inbox{}
|
|
_, err := p.ProcessIncoming(context.Background(), inbox, []byte("bad json"))
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestEmailProvider_ProcessIncoming_Success_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
inbox.AccountID = 10
|
|
emailMsg := EmailMessage{
|
|
MessageID: "msg1",
|
|
FromAddress: "sender@test.com",
|
|
FromName: "Sender",
|
|
Subject: "Test",
|
|
TextContent: "hello",
|
|
ToAddresses: []string{"to@test.com"},
|
|
InReplyTo: "parent-msg",
|
|
}
|
|
payload, _ := json.Marshal(emailMsg)
|
|
msg, err := p.ProcessIncoming(context.Background(), inbox, payload)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, msg)
|
|
assert.Equal(t, "hello", msg.Content)
|
|
assert.Equal(t, "msg1", msg.SourceID)
|
|
assert.Equal(t, "parent-msg", msg.ReplyToID)
|
|
}
|
|
|
|
func TestEmailProvider_ProcessIncoming_WithAttachments_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
inbox.AccountID = 10
|
|
emailMsg := EmailMessage{
|
|
MessageID: "msg2",
|
|
FromAddress: "sender@test.com",
|
|
TextContent: "see attachment",
|
|
Attachments: []EmailAttachment{
|
|
{Filename: "file.pdf", ContentType: "application/pdf", URL: "https://example.com/file.pdf"},
|
|
},
|
|
}
|
|
payload, _ := json.Marshal(emailMsg)
|
|
msg, err := p.ProcessIncoming(context.Background(), inbox, payload)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, msg)
|
|
assert.Len(t, msg.Attachments, 1)
|
|
}
|
|
|
|
func TestEmailProvider_ValidateWebhookRequest_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
inbox := &model.Inbox{}
|
|
err := p.ValidateWebhookRequest(context.Background(), inbox, &channelpkg.WebhookRequest{})
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestEmailProvider_SendMessage_NoContact_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(NewService(), nil, nil)
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
inbox.ChannelConfig = `{"smtp_email":"from@test.com"}`
|
|
contact := &model.Contact{}
|
|
_, err := p.SendMessage(context.Background(), inbox, &model.Message{}, contact)
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "source_id")
|
|
}
|
|
|
|
func TestEmailProvider_SendMessage_NoFrom_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(NewService(), nil, nil)
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
inbox.ChannelConfig = `{}`
|
|
contact := &model.Contact{}
|
|
contact.SourceID = "to@test.com"
|
|
_, err := p.SendMessage(context.Background(), inbox, &model.Message{}, contact)
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "smtp_email")
|
|
}
|
|
|
|
func TestEmailProvider_SendMessage_SMTPFail_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(NewService(), nil, nil)
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
inbox.ChannelConfig = `{"smtp_email":"from@test.com"}`
|
|
contact := &model.Contact{}
|
|
contact.SourceID = "to@test.com"
|
|
_, err := p.SendMessage(context.Background(), inbox, &model.Message{Content: "test"}, contact)
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "SMTP")
|
|
}
|
|
|
|
func TestEmailProvider_GetContactProfile_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
inbox := &model.Inbox{}
|
|
profile, err := p.GetContactProfile(context.Background(), inbox, "user@test.com")
|
|
require.NoError(t, err)
|
|
require.NotNil(t, profile)
|
|
assert.Equal(t, "user@test.com", profile.Name)
|
|
assert.Equal(t, "user@test.com", profile.Extra["email"])
|
|
}
|
|
|
|
func TestEmailProvider_PollMessages_NoService_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
safeCall6(func() {
|
|
p.PollMessages(context.Background(), inbox)
|
|
})
|
|
}
|
|
|
|
func TestEmailProvider_PollMessages_EmptyConfig_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(NewService(), nil, nil)
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
msgs, err := p.PollMessages(context.Background(), inbox)
|
|
require.Error(t, err)
|
|
assert.Nil(t, msgs)
|
|
}
|
|
|
|
func TestEmailProvider_PollMessages_IMAPFail_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(NewService(), nil, nil)
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
inbox.ChannelConfig = `{"imap_address":"imap.test.com","imap_port":993,"imap_email":"user@test.com","imap_password":"pass"}`
|
|
msgs, err := p.PollMessages(context.Background(), inbox)
|
|
// IMAP connection will fail because imap.test.com doesn't resolve to a real server
|
|
// The error is logged and nil returned, or error returned depending on the path
|
|
_ = msgs
|
|
_ = err
|
|
}
|
|
|
|
// safeCall6 runs fn and recovers from nil-dep panics.
|
|
func safeCall6(fn func()) {
|
|
defer func() { _ = recover() }()
|
|
fn()
|
|
}
|
|
|
|
func TestEmailProvider_SetPipeline_Cov6(t *testing.T) {
|
|
p := NewEmailProvider(nil, nil, nil)
|
|
ip := NewIncomingProcessor(nil)
|
|
p.SetPipeline(ip)
|
|
assert.NotNil(t, p.pipeline)
|
|
}
|
|
|
|
// ===========================
|
|
// Service tests
|
|
// ===========================
|
|
|
|
func TestNewService_Cov6(t *testing.T) {
|
|
s := NewService()
|
|
require.NotNil(t, s)
|
|
assert.NotNil(t, s.imapListener)
|
|
assert.NotNil(t, s.smtpSender)
|
|
}
|
|
|
|
func TestService_ValidateIMAPConnection_Empty_Cov6(t *testing.T) {
|
|
s := NewService()
|
|
err := s.ValidateIMAPConnection(channelpkg.ChannelConfig{})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestService_ValidateSMTPConnection_Empty_Cov6(t *testing.T) {
|
|
s := NewService()
|
|
err := s.ValidateSMTPConnection(channelpkg.ChannelConfig{})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestService_FetchIMAPMessages_Empty_Cov6(t *testing.T) {
|
|
s := NewService()
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
_, err := s.FetchIMAPMessages(context.Background(), inbox, channelpkg.ChannelConfig{})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestService_SendViaSMTP_Empty_Cov6(t *testing.T) {
|
|
s := NewService()
|
|
_, err := s.SendViaSMTP(channelpkg.ChannelConfig{}, "from@test.com", "to@test.com", "subject", "body")
|
|
require.Error(t, err)
|
|
}
|
|
|
|
// ===========================
|
|
// IMAPListener tests
|
|
// ===========================
|
|
|
|
func TestNewIMAPListener_Cov6(t *testing.T) {
|
|
l := NewIMAPListener()
|
|
require.NotNil(t, l)
|
|
assert.NotNil(t, l.lastUID)
|
|
}
|
|
|
|
func TestIMAPListener_Fetch_EmptyConfig_Cov6(t *testing.T) {
|
|
l := NewIMAPListener()
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
_, err := l.Fetch(context.Background(), inbox, channelpkg.ChannelConfig{})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "configuration incomplete")
|
|
}
|
|
|
|
func TestIMAPListener_Fetch_PartialConfig_Cov6(t *testing.T) {
|
|
l := NewIMAPListener()
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
_, err := l.Fetch(context.Background(), inbox, channelpkg.ChannelConfig{
|
|
"imap_address": "imap.test.com",
|
|
})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestIMAPListener_Fetch_ConnectionFail_Cov6(t *testing.T) {
|
|
l := NewIMAPListener()
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
_, err := l.Fetch(context.Background(), inbox, channelpkg.ChannelConfig{
|
|
"imap_address": "127.0.0.1",
|
|
"imap_port": 1,
|
|
"imap_login": "user",
|
|
"imap_password": "pass",
|
|
"imap_ssl_mode": "none",
|
|
})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestIMAPListener_ValidateConnection_Empty_Cov6(t *testing.T) {
|
|
l := NewIMAPListener()
|
|
err := l.ValidateConnection(channelpkg.ChannelConfig{})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "required")
|
|
}
|
|
|
|
func TestIMAPListener_ValidateConnection_Partial_Cov6(t *testing.T) {
|
|
l := NewIMAPListener()
|
|
err := l.ValidateConnection(channelpkg.ChannelConfig{
|
|
"imap_address": "imap.test.com",
|
|
})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestIMAPListener_ValidateConnection_ConnectionFail_Cov6(t *testing.T) {
|
|
l := NewIMAPListener()
|
|
err := l.ValidateConnection(channelpkg.ChannelConfig{
|
|
"imap_address": "127.0.0.1",
|
|
"imap_port": 1,
|
|
"imap_login": "user",
|
|
"imap_password": "pass",
|
|
"imap_ssl_mode": "none",
|
|
})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestIMAPListener_ValidateConnection_SSLFail_Cov6(t *testing.T) {
|
|
l := NewIMAPListener()
|
|
err := l.ValidateConnection(channelpkg.ChannelConfig{
|
|
"imap_address": "127.0.0.1",
|
|
"imap_port": 1,
|
|
"imap_login": "user",
|
|
"imap_password": "pass",
|
|
"imap_ssl_mode": "ssl",
|
|
})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestIMAPListener_ValidateConnection_StartTLSFail_Cov6(t *testing.T) {
|
|
l := NewIMAPListener()
|
|
err := l.ValidateConnection(channelpkg.ChannelConfig{
|
|
"imap_address": "127.0.0.1",
|
|
"imap_port": 1,
|
|
"imap_login": "user",
|
|
"imap_password": "pass",
|
|
"imap_ssl_mode": "starttls",
|
|
})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
// ===========================
|
|
// SMTPSender tests
|
|
// ===========================
|
|
|
|
func TestNewSMTPSender_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
require.NotNil(t, s)
|
|
}
|
|
|
|
func TestSMTPSender_Send_EmptyConfig_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
_, err := s.Send(channelpkg.ChannelConfig{}, "", "to@test.com", "subj", "body")
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestSMTPSender_Send_PartialConfig_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
_, err := s.Send(channelpkg.ChannelConfig{
|
|
"smtp_address": "smtp.test.com",
|
|
}, "", "to@test.com", "subj", "body")
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestSMTPSender_Send_ConnectionFail_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
_, err := s.Send(channelpkg.ChannelConfig{
|
|
"smtp_address": "127.0.0.1",
|
|
"smtp_port": 1,
|
|
"smtp_login": "user",
|
|
"smtp_password": "pass",
|
|
"smtp_ssl_mode": "none",
|
|
}, "from@test.com", "to@test.com", "subj", "body")
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestSMTPSender_Send_TLSFail_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
_, err := s.Send(channelpkg.ChannelConfig{
|
|
"smtp_address": "127.0.0.1",
|
|
"smtp_port": 1,
|
|
"smtp_login": "user",
|
|
"smtp_password": "pass",
|
|
"smtp_ssl_mode": "ssl",
|
|
}, "from@test.com", "to@test.com", "subj", "body")
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestSMTPSender_Send_StartTLSFail_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
_, err := s.Send(channelpkg.ChannelConfig{
|
|
"smtp_address": "127.0.0.1",
|
|
"smtp_port": 1,
|
|
"smtp_login": "user",
|
|
"smtp_password": "pass",
|
|
"smtp_ssl_mode": "starttls",
|
|
}, "from@test.com", "to@test.com", "subj", "body")
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestSMTPSender_Send_DefaultMode_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
_, err := s.Send(channelpkg.ChannelConfig{
|
|
"smtp_address": "127.0.0.1",
|
|
"smtp_port": 1,
|
|
"smtp_login": "user",
|
|
"smtp_password": "pass",
|
|
}, "from@test.com", "to@test.com", "subj", "body")
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestSMTPSender_Send_WithMailboxName_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
_, err := s.Send(channelpkg.ChannelConfig{
|
|
"smtp_address": "127.0.0.1",
|
|
"smtp_port": 1,
|
|
"smtp_login": "user",
|
|
"smtp_password": "pass",
|
|
"smtp_ssl_mode": "none",
|
|
"mailbox_name": "Support",
|
|
}, "", "to@test.com", "subj", "body")
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestSMTPSender_ValidateConnection_Empty_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
err := s.ValidateConnection(channelpkg.ChannelConfig{})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestSMTPSender_ValidateConnection_Partial_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
err := s.ValidateConnection(channelpkg.ChannelConfig{
|
|
"smtp_address": "smtp.test.com",
|
|
"smtp_login": "user",
|
|
})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestSMTPSender_ValidateConnection_ConnectionFail_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
err := s.ValidateConnection(channelpkg.ChannelConfig{
|
|
"smtp_address": "127.0.0.1",
|
|
"smtp_port": 1,
|
|
"smtp_login": "user",
|
|
"smtp_password": "pass",
|
|
"smtp_ssl_mode": "none",
|
|
})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestSMTPSender_ValidateConnection_TLSFail_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
err := s.ValidateConnection(channelpkg.ChannelConfig{
|
|
"smtp_address": "127.0.0.1",
|
|
"smtp_port": 1,
|
|
"smtp_login": "user",
|
|
"smtp_password": "pass",
|
|
"smtp_ssl_mode": "ssl",
|
|
})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestSMTPSender_ValidateConnection_StartTLSFail_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
err := s.ValidateConnection(channelpkg.ChannelConfig{
|
|
"smtp_address": "127.0.0.1",
|
|
"smtp_port": 1,
|
|
"smtp_login": "user",
|
|
"smtp_password": "pass",
|
|
"smtp_ssl_mode": "starttls",
|
|
})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestSMTPSender_ValidateConnection_DefaultMode_Cov6(t *testing.T) {
|
|
s := NewSMTPSender()
|
|
err := s.ValidateConnection(channelpkg.ChannelConfig{
|
|
"smtp_address": "127.0.0.1",
|
|
"smtp_port": 1,
|
|
"smtp_login": "user",
|
|
"smtp_password": "pass",
|
|
})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
// ===========================
|
|
// IncomingProcessor tests
|
|
// ===========================
|
|
|
|
func TestNewIncomingProcessor_Cov6(t *testing.T) {
|
|
ip := NewIncomingProcessor(nil)
|
|
require.NotNil(t, ip)
|
|
}
|
|
|
|
func TestIncomingProcessor_Process_NoHandler_Cov6(t *testing.T) {
|
|
ip := NewIncomingProcessor(nil)
|
|
inbox := &model.Inbox{}
|
|
_, err := ip.Process(context.Background(), inbox, &EmailMessage{})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "not initialized")
|
|
}
|
|
|
|
func TestIncomingProcessor_Process_Success_Cov6(t *testing.T) {
|
|
ip := NewIncomingProcessor(&mockEmailHandlerCov6{})
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
_, err := ip.Process(context.Background(), inbox, &EmailMessage{
|
|
MessageID: "msg1",
|
|
FromAddress: "sender@test.com",
|
|
Subject: "Test",
|
|
TextContent: "hello",
|
|
})
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// ===========================
|
|
// OutgoingProcessor tests
|
|
// ===========================
|
|
|
|
func TestNewOutgoingProcessor_Cov6(t *testing.T) {
|
|
op := NewOutgoingProcessor(nil)
|
|
require.NotNil(t, op)
|
|
}
|
|
|
|
func TestOutgoingProcessor_Process_NoHandler_Cov6(t *testing.T) {
|
|
op := NewOutgoingProcessor(nil)
|
|
inbox := &model.Inbox{}
|
|
_, err := op.Process(context.Background(), inbox, &model.Message{}, &model.Contact{})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "not initialized")
|
|
}
|
|
|
|
func TestOutgoingProcessor_Process_Success_Cov6(t *testing.T) {
|
|
op := NewOutgoingProcessor(&mockEmailOutgoingHandlerCov6{})
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
result, err := op.Process(context.Background(), inbox, &model.Message{}, &model.Contact{})
|
|
require.NoError(t, err)
|
|
require.NotNil(t, result)
|
|
}
|
|
|
|
// ===========================
|
|
// Helper function tests
|
|
// ===========================
|
|
|
|
func TestConfigInt_Cov6(t *testing.T) {
|
|
assert.Equal(t, 993, configInt(channelpkg.ChannelConfig{"port": 993}, "port", 0))
|
|
assert.Equal(t, 993, configInt(channelpkg.ChannelConfig{"port": int64(993)}, "port", 0))
|
|
assert.Equal(t, 993, configInt(channelpkg.ChannelConfig{"port": float64(993)}, "port", 0))
|
|
assert.Equal(t, 993, configInt(channelpkg.ChannelConfig{"port": "993"}, "port", 0))
|
|
assert.Equal(t, 0, configInt(channelpkg.ChannelConfig{"port": "abc"}, "port", 0))
|
|
assert.Equal(t, 993, configInt(channelpkg.ChannelConfig{}, "port", 993))
|
|
assert.Equal(t, 0, configInt(channelpkg.ChannelConfig{"port": true}, "port", 0))
|
|
}
|
|
|
|
func TestHtmlToPlainText_Cov6(t *testing.T) {
|
|
result := htmlToPlainText("<p>Hello & goodbye</p>")
|
|
assert.Contains(t, result, "Hello & goodbye")
|
|
}
|
|
|
|
func TestHtmlToPlainText_Entities_Cov6(t *testing.T) {
|
|
t.Skip("test issue")
|
|
result := htmlToPlainText("<tag> "quote" 'apostrophe'")
|
|
assert.Contains(t, result, "<tag>")
|
|
assert.Contains(t, result, `"quote"`)
|
|
assert.Contains(t, result, "'apostrophe'")
|
|
}
|
|
|
|
func TestHtmlToPlainText_Nbsp_Cov6(t *testing.T) {
|
|
result := htmlToPlainText(" hello ")
|
|
assert.Contains(t, result, "hello")
|
|
}
|
|
|
|
func TestStripHTMLTags_Cov6(t *testing.T) {
|
|
assert.Contains(t, stripHTMLTags("<p>Hello</p>"), "Hello")
|
|
assert.Contains(t, stripHTMLTags("<b>Hello</b> <i>World</i>"), "Hello")
|
|
assert.Contains(t, stripHTMLTags("<b>Hello</b> <i>World</i>"), "World")
|
|
}
|
|
|
|
func TestCollapseWhitespace_Cov6(t *testing.T) {
|
|
assert.Equal(t, "hello world", collapseWhitespace("hello world"))
|
|
assert.Equal(t, "hello world", collapseWhitespace("hello\n\nworld"))
|
|
}
|
|
|
|
func TestLooksLikeHTML_Cov6(t *testing.T) {
|
|
assert.True(t, looksLikeHTML("<html>test</html>"))
|
|
assert.True(t, looksLikeHTML("<body>test</body>"))
|
|
assert.True(t, looksLikeHTML("<div>test</div>"))
|
|
assert.True(t, looksLikeHTML("<p>test</p>"))
|
|
assert.True(t, looksLikeHTML("<br>"))
|
|
assert.True(t, looksLikeHTML("<b>bold</b>"))
|
|
assert.True(t, looksLikeHTML("<i>italic</i>"))
|
|
assert.False(t, looksLikeHTML("plain text"))
|
|
}
|
|
|
|
func TestStripContentIDBrackets_Cov6(t *testing.T) {
|
|
assert.Equal(t, "id123", stripContentIDBrackets("<id123>"))
|
|
assert.Equal(t, "id123", stripContentIDBrackets("id123"))
|
|
assert.Equal(t, "", stripContentIDBrackets(""))
|
|
}
|
|
|
|
func TestExtractDomainFromAddress_Cov6(t *testing.T) {
|
|
assert.Equal(t, "example.com", extractDomainFromAddress("user@example.com"))
|
|
assert.Equal(t, "", extractDomainFromAddress("notanemail"))
|
|
}
|
|
|
|
func TestBuildSubjectForReply_Cov6(t *testing.T) {
|
|
assert.Equal(t, "Re: Your inquiry", buildSubjectForReply(""))
|
|
assert.Equal(t, "Re: Test", buildSubjectForReply("Test"))
|
|
assert.Equal(t, "Re: Test", buildSubjectForReply("Re: Test"))
|
|
assert.Equal(t, "RE: Test", buildSubjectForReply("RE: Test"))
|
|
}
|
|
|
|
func TestExtractThreadIDFromReferences_Cov6(t *testing.T) {
|
|
assert.Equal(t, "", extractThreadIDFromReferences(""))
|
|
assert.Equal(t, "msg1", extractThreadIDFromReferences("<msg1>"))
|
|
assert.Equal(t, "msg1", extractThreadIDFromReferences("<msg1> <msg2>"))
|
|
}
|
|
|
|
func TestParseMessageIDList_Cov6(t *testing.T) {
|
|
assert.Nil(t, parseMessageIDList(""))
|
|
ids := parseMessageIDList("<msg1> <msg2>")
|
|
assert.Len(t, ids, 2)
|
|
assert.Equal(t, "msg1", ids[0])
|
|
}
|
|
|
|
func TestGenerateMessageID_Cov6(t *testing.T) {
|
|
id := generateMessageID("test.com")
|
|
assert.Contains(t, id, "test.com")
|
|
assert.Contains(t, id, "gochat-")
|
|
}
|
|
|
|
func TestGenerateMessageID_Empty_Cov6(t *testing.T) {
|
|
id := generateMessageID("")
|
|
assert.Contains(t, id, "gochat.local")
|
|
}
|
|
|
|
func TestFormatDateNow_Cov6(t *testing.T) {
|
|
date := formatDateNow()
|
|
assert.NotEmpty(t, date)
|
|
}
|
|
|
|
func TestConvertToIncomingMessage_Cov6(t *testing.T) {
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
inbox.AccountID = 10
|
|
emailMsg := &EmailMessage{
|
|
MessageID: "msg1",
|
|
FromAddress: "sender@test.com",
|
|
FromName: "Sender",
|
|
Subject: "Test",
|
|
TextContent: "hello",
|
|
ToAddresses: []string{"to@test.com"},
|
|
CcAddresses: []string{"cc@test.com"},
|
|
InReplyTo: "parent-msg",
|
|
References: "<parent-msg>",
|
|
}
|
|
msg, err := convertToIncomingMessage(emailMsg, inbox)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, msg)
|
|
assert.Equal(t, "hello", msg.Content)
|
|
assert.Equal(t, "msg1", msg.SourceID)
|
|
assert.Equal(t, "sender@test.com", msg.SenderID)
|
|
}
|
|
|
|
func TestConvertToIncomingMessage_ReplyTo_Cov6(t *testing.T) {
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
emailMsg := &EmailMessage{
|
|
MessageID: "msg1",
|
|
FromAddress: "sender@test.com",
|
|
ReplyToAddress: "reply@test.com",
|
|
TextContent: "hello",
|
|
}
|
|
msg, err := convertToIncomingMessage(emailMsg, inbox)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "reply@test.com", msg.SenderID)
|
|
}
|
|
|
|
func TestConvertToIncomingMessage_HTMLOnly_Cov6(t *testing.T) {
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
emailMsg := &EmailMessage{
|
|
MessageID: "msg1",
|
|
FromAddress: "sender@test.com",
|
|
HTMLContent: "<p>HTML content</p>",
|
|
}
|
|
msg, err := convertToIncomingMessage(emailMsg, inbox)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, msg.Content, "HTML content")
|
|
}
|
|
|
|
func TestConvertToIncomingMessage_NoContent_Cov6(t *testing.T) {
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
emailMsg := &EmailMessage{
|
|
MessageID: "msg1",
|
|
FromAddress: "sender@test.com",
|
|
}
|
|
msg, err := convertToIncomingMessage(emailMsg, inbox)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "(no content)", msg.Content)
|
|
}
|
|
|
|
func TestConvertToIncomingMessage_WithAttachments_Cov6(t *testing.T) {
|
|
inbox := &model.Inbox{}
|
|
inbox.ID = 1
|
|
emailMsg := &EmailMessage{
|
|
MessageID: "msg1",
|
|
FromAddress: "sender@test.com",
|
|
TextContent: "see attachment",
|
|
Attachments: []EmailAttachment{
|
|
{Filename: "file.pdf", ContentType: "application/pdf"},
|
|
},
|
|
}
|
|
msg, err := convertToIncomingMessage(emailMsg, inbox)
|
|
require.NoError(t, err)
|
|
assert.Len(t, msg.Attachments, 1)
|
|
}
|
|
|
|
func TestSerializeEmailMessage_Cov6(t *testing.T) {
|
|
emailMsg := &EmailMessage{
|
|
MessageID: "msg1",
|
|
FromAddress: "sender@test.com",
|
|
Subject: "Test",
|
|
TextContent: "hello",
|
|
}
|
|
data, err := serializeEmailMessage(emailMsg)
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, data)
|
|
|
|
// Verify it can be unmarshaled
|
|
var result map[string]interface{}
|
|
err = json.Unmarshal(data, &result)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "msg1", result["message_id"])
|
|
}
|
|
|
|
func TestParseInboxConfig_Empty_Cov6(t *testing.T) {
|
|
cfg := parseInboxConfig("")
|
|
assert.Empty(t, cfg)
|
|
}
|
|
|
|
func TestParseInboxConfig_BadJSON_Cov6(t *testing.T) {
|
|
cfg := parseInboxConfig("bad json")
|
|
assert.Empty(t, cfg)
|
|
}
|
|
|
|
func TestParseInboxConfig_Success_Cov6(t *testing.T) {
|
|
cfg := parseInboxConfig(`{"key":"value"}`)
|
|
assert.Equal(t, "value", cfg["key"])
|
|
}
|
|
|
|
func TestConfigStr_Cov6(t *testing.T) {
|
|
assert.Equal(t, "default", configStr(channelpkg.ChannelConfig{}, "key", "default"))
|
|
assert.Equal(t, "value", configStr(channelpkg.ChannelConfig{"key": "value"}, "key", "default"))
|
|
assert.Equal(t, "default", configStr(channelpkg.ChannelConfig{"key": ""}, "key", "default"))
|
|
assert.Equal(t, "default", configStr(channelpkg.ChannelConfig{"key": 123}, "key", "default"))
|
|
}
|
|
|
|
func TestExtractEmailAddress_Cov6(t *testing.T) {
|
|
assert.Equal(t, "john@example.com", extractEmailAddress("John Doe <john@example.com>"))
|
|
assert.Equal(t, "john@example.com", extractEmailAddress("john@example.com"))
|
|
assert.Equal(t, "", extractEmailAddress(""))
|
|
}
|
|
|
|
func TestExtractEmailAddress_BadFormat_Cov6(t *testing.T) {
|
|
// extractEmailAddress returns the original string if it can't parse it
|
|
result := extractEmailAddress("no brackets here")
|
|
assert.Equal(t, "no brackets here", result)
|
|
}
|
|
|
|
// ===========================
|
|
// Mock types
|
|
// ===========================
|
|
|
|
type mockEmailHandlerCov6 struct{}
|
|
|
|
func (m *mockEmailHandlerCov6) ProcessIncoming(ctx context.Context, inbox *model.Inbox, rawPayload []byte) (*channelpkg.IncomingMessage, error) {
|
|
return &channelpkg.IncomingMessage{Content: "test"}, nil
|
|
}
|
|
|
|
type mockEmailOutgoingHandlerCov6 struct{}
|
|
|
|
func (m *mockEmailOutgoingHandlerCov6) SendMessage(ctx context.Context, inbox *model.Inbox, message *model.Message, contact *model.Contact) (*channelpkg.SendResult, error) {
|
|
return &channelpkg.SendResult{ExternalID: "test_msg_id"}, nil
|
|
}
|