fx build fix
This commit is contained in:
@@ -0,0 +1,541 @@
|
||||
package notificationimp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/tech/sendico/notification/interface/api/localizer"
|
||||
mmail "github.com/tech/sendico/notification/internal/server/notificationimp/mail/messagebuilder"
|
||||
"github.com/tech/sendico/pkg/db/storable"
|
||||
"github.com/tech/sendico/pkg/domainprovider"
|
||||
"github.com/tech/sendico/pkg/model"
|
||||
"github.com/tech/sendico/pkg/mlogger/factory"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// Mock implementations
|
||||
|
||||
type mockMailClient struct {
|
||||
sendFunc func(r mmail.MailBuilder) error
|
||||
mailBuilderFunc func() mmail.MailBuilder
|
||||
sentMessages []mockSentMessage
|
||||
}
|
||||
|
||||
type mockSentMessage struct {
|
||||
accountID string
|
||||
templateID string
|
||||
locale string
|
||||
recipients []string
|
||||
data map[string]string
|
||||
buttonLink string
|
||||
}
|
||||
|
||||
func (m *mockMailClient) Send(r mmail.MailBuilder) error {
|
||||
if m.sendFunc != nil {
|
||||
return m.sendFunc(r)
|
||||
}
|
||||
// Record the message for verification
|
||||
msg, _ := r.Build()
|
||||
if msg != nil {
|
||||
sent := mockSentMessage{
|
||||
accountID: msg.AccountID(),
|
||||
templateID: msg.TemplateID(),
|
||||
locale: msg.Locale(),
|
||||
recipients: msg.Recipients(),
|
||||
data: make(map[string]string),
|
||||
}
|
||||
// Extract string parameters
|
||||
for k, v := range msg.Parameters() {
|
||||
if str, ok := v.(string); ok {
|
||||
sent.data[k] = str
|
||||
}
|
||||
}
|
||||
m.sentMessages = append(m.sentMessages, sent)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockMailClient) MailBuilder() mmail.MailBuilder {
|
||||
if m.mailBuilderFunc != nil {
|
||||
return m.mailBuilderFunc()
|
||||
}
|
||||
return &mockMailBuilder{
|
||||
accountID: "",
|
||||
templateID: "",
|
||||
locale: "",
|
||||
recipients: []string{},
|
||||
data: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
type mockMailBuilder struct {
|
||||
accountID string
|
||||
templateID string
|
||||
locale string
|
||||
recipients []string
|
||||
buttonLink string
|
||||
data map[string]string
|
||||
}
|
||||
|
||||
func (m *mockMailBuilder) SetAccountID(accountID string) mmail.MailBuilder {
|
||||
m.accountID = accountID
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *mockMailBuilder) SetTemplateID(templateID string) mmail.MailBuilder {
|
||||
m.templateID = templateID
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *mockMailBuilder) SetLocale(locale string) mmail.MailBuilder {
|
||||
m.locale = locale
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *mockMailBuilder) AddRecipient(recipientName, recipient string) mmail.MailBuilder {
|
||||
m.recipients = append(m.recipients, recipient)
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *mockMailBuilder) AddButton(link string) mmail.MailBuilder {
|
||||
m.buttonLink = link
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *mockMailBuilder) AddData(key, value string) mmail.MailBuilder {
|
||||
m.data[key] = value
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *mockMailBuilder) Build() (mmail.Message, error) {
|
||||
if len(m.recipients) == 0 {
|
||||
return nil, errors.New("recipient not set")
|
||||
}
|
||||
return &mockMessage{
|
||||
accountID: m.accountID,
|
||||
templateID: m.templateID,
|
||||
locale: m.locale,
|
||||
recipients: m.recipients,
|
||||
parameters: convertToAnyMap(m.data),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type mockMessage struct {
|
||||
accountID string
|
||||
templateID string
|
||||
locale string
|
||||
recipients []string
|
||||
parameters map[string]any
|
||||
}
|
||||
|
||||
func (m *mockMessage) AccountID() string { return m.accountID }
|
||||
func (m *mockMessage) TemplateID() string { return m.templateID }
|
||||
func (m *mockMessage) Locale() string { return m.locale }
|
||||
func (m *mockMessage) Recipients() []string { return m.recipients }
|
||||
func (m *mockMessage) Parameters() map[string]any { return m.parameters }
|
||||
func (m *mockMessage) Body(l localizer.Localizer, dp domainprovider.DomainProvider) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func convertToAnyMap(m map[string]string) map[string]any {
|
||||
result := make(map[string]any)
|
||||
for k, v := range m {
|
||||
result[k] = v
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
type mockDomainProvider struct {
|
||||
getFullLinkFunc func(linkElem ...string) (string, error)
|
||||
}
|
||||
|
||||
func (m *mockDomainProvider) GetFullLink(linkElem ...string) (string, error) {
|
||||
if m.getFullLinkFunc != nil {
|
||||
return m.getFullLinkFunc(linkElem...)
|
||||
}
|
||||
return "https://example.com/link", nil
|
||||
}
|
||||
|
||||
func (m *mockDomainProvider) GetAPILink(linkElem ...string) (string, error) {
|
||||
return "https://api.example.com/link", nil
|
||||
}
|
||||
|
||||
// Tests for onAccount handler
|
||||
|
||||
func TestOnAccount_ValidAccount_SendsWelcomeEmail(t *testing.T) {
|
||||
mockClient := &mockMailClient{}
|
||||
mockDP := &mockDomainProvider{}
|
||||
|
||||
api := &NotificationAPI{
|
||||
logger: mlogger.NewLogger(true),
|
||||
client: mockClient,
|
||||
dp: mockDP,
|
||||
}
|
||||
|
||||
account := &model.Account{
|
||||
AccountPublic: model.AccountPublic{
|
||||
AccountBase: model.AccountBase{
|
||||
Base: storable.Base{
|
||||
ID: primitive.NewObjectID(),
|
||||
},
|
||||
Describable: model.Describable{
|
||||
Name: "Test User",
|
||||
},
|
||||
},
|
||||
UserDataBase: model.UserDataBase{
|
||||
Login: "user@example.com",
|
||||
Locale: "en-US",
|
||||
},
|
||||
},
|
||||
VerifyToken: "test-verify-token",
|
||||
}
|
||||
|
||||
err := api.onAccount(context.Background(), account)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if len(mockClient.sentMessages) != 1 {
|
||||
t.Fatalf("Expected 1 message sent, got %d", len(mockClient.sentMessages))
|
||||
}
|
||||
|
||||
sent := mockClient.sentMessages[0]
|
||||
if sent.templateID != "welcome" {
|
||||
t.Errorf("Expected template 'welcome', got '%s'", sent.templateID)
|
||||
}
|
||||
if sent.locale != "en-US" {
|
||||
t.Errorf("Expected locale 'en-US', got '%s'", sent.locale)
|
||||
}
|
||||
if len(sent.recipients) != 1 || sent.recipients[0] != "user@example.com" {
|
||||
t.Errorf("Expected recipient 'user@example.com', got %v", sent.recipients)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnAccount_LinkGenerationFails_ReturnsError(t *testing.T) {
|
||||
mockClient := &mockMailClient{}
|
||||
mockDP := &mockDomainProvider{
|
||||
getFullLinkFunc: func(linkElem ...string) (string, error) {
|
||||
return "", errors.New("link generation failed")
|
||||
},
|
||||
}
|
||||
|
||||
api := &NotificationAPI{
|
||||
logger: mlogger.NewLogger(true),
|
||||
client: mockClient,
|
||||
dp: mockDP,
|
||||
}
|
||||
|
||||
account := &model.Account{
|
||||
AccountPublic: model.AccountPublic{
|
||||
AccountBase: model.AccountBase{
|
||||
Base: storable.Base{
|
||||
ID: primitive.NewObjectID(),
|
||||
},
|
||||
Describable: model.Describable{
|
||||
Name: "Test User",
|
||||
},
|
||||
},
|
||||
UserDataBase: model.UserDataBase{
|
||||
Login: "user@example.com",
|
||||
Locale: "en-US",
|
||||
},
|
||||
},
|
||||
VerifyToken: "test-verify-token",
|
||||
}
|
||||
|
||||
err := api.onAccount(context.Background(), account)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("Expected error from link generation failure")
|
||||
}
|
||||
|
||||
if len(mockClient.sentMessages) != 0 {
|
||||
t.Error("No message should be sent when link generation fails")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnAccount_SendFails_ReturnsError(t *testing.T) {
|
||||
mockClient := &mockMailClient{
|
||||
sendFunc: func(r mmail.MailBuilder) error {
|
||||
return errors.New("send failed")
|
||||
},
|
||||
}
|
||||
mockDP := &mockDomainProvider{}
|
||||
|
||||
api := &NotificationAPI{
|
||||
logger: mlogger.NewLogger(true),
|
||||
client: mockClient,
|
||||
dp: mockDP,
|
||||
}
|
||||
|
||||
account := &model.Account{
|
||||
AccountPublic: model.AccountPublic{
|
||||
AccountBase: model.AccountBase{
|
||||
Base: storable.Base{
|
||||
ID: primitive.NewObjectID(),
|
||||
},
|
||||
Describable: model.Describable{
|
||||
Name: "Test User",
|
||||
},
|
||||
},
|
||||
UserDataBase: model.UserDataBase{
|
||||
Login: "user@example.com",
|
||||
Locale: "en-US",
|
||||
},
|
||||
},
|
||||
VerifyToken: "test-verify-token",
|
||||
}
|
||||
|
||||
err := api.onAccount(context.Background(), account)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("Expected error from send failure")
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for onInvitation handler
|
||||
|
||||
func TestOnInvitation_ValidInvitation_SendsInvitationEmail(t *testing.T) {
|
||||
mockClient := &mockMailClient{}
|
||||
mockDP := &mockDomainProvider{}
|
||||
|
||||
api := &NotificationAPI{
|
||||
logger: mlogger.NewLogger(true),
|
||||
client: mockClient,
|
||||
dp: mockDP,
|
||||
}
|
||||
|
||||
account := &model.Account{
|
||||
AccountPublic: model.AccountPublic{
|
||||
AccountBase: model.AccountBase{
|
||||
Base: storable.Base{
|
||||
ID: primitive.NewObjectID(),
|
||||
},
|
||||
Describable: model.Describable{
|
||||
Name: "Inviter User",
|
||||
},
|
||||
},
|
||||
UserDataBase: model.UserDataBase{
|
||||
Locale: "en-US",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
invitationID := primitive.NewObjectID()
|
||||
invitation := &model.Invitation{}
|
||||
invitation.ID = invitationID
|
||||
invitation.Content.Email = "invitee@example.com"
|
||||
invitation.Content.Name = "Invitee Name"
|
||||
|
||||
err := api.onInvitation(context.Background(), account, invitation)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if len(mockClient.sentMessages) != 1 {
|
||||
t.Fatalf("Expected 1 message sent, got %d", len(mockClient.sentMessages))
|
||||
}
|
||||
|
||||
sent := mockClient.sentMessages[0]
|
||||
if sent.templateID != "invitation" {
|
||||
t.Errorf("Expected template 'invitation', got '%s'", sent.templateID)
|
||||
}
|
||||
if sent.locale != "en-US" {
|
||||
t.Errorf("Expected locale 'en-US', got '%s'", sent.locale)
|
||||
}
|
||||
if len(sent.recipients) != 1 || sent.recipients[0] != "invitee@example.com" {
|
||||
t.Errorf("Expected recipient 'invitee@example.com', got %v", sent.recipients)
|
||||
}
|
||||
if sent.data["InviterName"] != "Inviter User" {
|
||||
t.Errorf("Expected InviterName 'Inviter User', got '%s'", sent.data["InviterName"])
|
||||
}
|
||||
if sent.data["Name"] != "Invitee Name" {
|
||||
t.Errorf("Expected Name 'Invitee Name', got '%s'", sent.data["Name"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnInvitation_LinkGenerationFails_ReturnsError(t *testing.T) {
|
||||
mockClient := &mockMailClient{}
|
||||
mockDP := &mockDomainProvider{
|
||||
getFullLinkFunc: func(linkElem ...string) (string, error) {
|
||||
return "", errors.New("link generation failed")
|
||||
},
|
||||
}
|
||||
|
||||
api := &NotificationAPI{
|
||||
logger: mlogger.NewLogger(true),
|
||||
client: mockClient,
|
||||
dp: mockDP,
|
||||
}
|
||||
|
||||
account := &model.Account{
|
||||
AccountPublic: model.AccountPublic{
|
||||
AccountBase: model.AccountBase{
|
||||
Base: storable.Base{
|
||||
ID: primitive.NewObjectID(),
|
||||
},
|
||||
Describable: model.Describable{
|
||||
Name: "Inviter User",
|
||||
},
|
||||
},
|
||||
UserDataBase: model.UserDataBase{
|
||||
Locale: "en-US",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
invitationID := primitive.NewObjectID()
|
||||
invitation := &model.Invitation{}
|
||||
invitation.ID = invitationID
|
||||
invitation.Content.Email = "invitee@example.com"
|
||||
invitation.Content.Name = "Invitee Name"
|
||||
|
||||
err := api.onInvitation(context.Background(), account, invitation)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("Expected error from link generation failure")
|
||||
}
|
||||
|
||||
if len(mockClient.sentMessages) != 0 {
|
||||
t.Error("No message should be sent when link generation fails")
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for onPasswordReset handler
|
||||
|
||||
func TestOnPasswordReset_ValidReset_SendsResetEmail(t *testing.T) {
|
||||
mockClient := &mockMailClient{}
|
||||
mockDP := &mockDomainProvider{}
|
||||
|
||||
api := &NotificationAPI{
|
||||
logger: mlogger.NewLogger(true),
|
||||
client: mockClient,
|
||||
dp: mockDP,
|
||||
}
|
||||
|
||||
account := &model.Account{
|
||||
AccountPublic: model.AccountPublic{
|
||||
AccountBase: model.AccountBase{
|
||||
Base: storable.Base{
|
||||
ID: primitive.NewObjectID(),
|
||||
},
|
||||
Describable: model.Describable{
|
||||
Name: "Test User",
|
||||
},
|
||||
},
|
||||
UserDataBase: model.UserDataBase{
|
||||
Login: "user@example.com",
|
||||
Locale: "en-US",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resetToken := "reset-token-123"
|
||||
|
||||
err := api.onPasswordReset(context.Background(), account, resetToken)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if len(mockClient.sentMessages) != 1 {
|
||||
t.Fatalf("Expected 1 message sent, got %d", len(mockClient.sentMessages))
|
||||
}
|
||||
|
||||
sent := mockClient.sentMessages[0]
|
||||
if sent.templateID != "reset-password" {
|
||||
t.Errorf("Expected template 'reset-password', got '%s'", sent.templateID)
|
||||
}
|
||||
if sent.locale != "en-US" {
|
||||
t.Errorf("Expected locale 'en-US', got '%s'", sent.locale)
|
||||
}
|
||||
if len(sent.recipients) != 1 || sent.recipients[0] != "user@example.com" {
|
||||
t.Errorf("Expected recipient 'user@example.com', got %v", sent.recipients)
|
||||
}
|
||||
if sent.data["URL"] == "" {
|
||||
t.Error("Expected URL parameter to be set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnPasswordReset_LinkGenerationFails_ReturnsError(t *testing.T) {
|
||||
mockClient := &mockMailClient{}
|
||||
mockDP := &mockDomainProvider{
|
||||
getFullLinkFunc: func(linkElem ...string) (string, error) {
|
||||
return "", errors.New("link generation failed")
|
||||
},
|
||||
}
|
||||
|
||||
api := &NotificationAPI{
|
||||
logger: mlogger.NewLogger(true),
|
||||
client: mockClient,
|
||||
dp: mockDP,
|
||||
}
|
||||
|
||||
account := &model.Account{
|
||||
AccountPublic: model.AccountPublic{
|
||||
AccountBase: model.AccountBase{
|
||||
Base: storable.Base{
|
||||
ID: primitive.NewObjectID(),
|
||||
},
|
||||
Describable: model.Describable{
|
||||
Name: "Test User",
|
||||
},
|
||||
},
|
||||
UserDataBase: model.UserDataBase{
|
||||
Login: "user@example.com",
|
||||
Locale: "en-US",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err := api.onPasswordReset(context.Background(), account, "reset-token")
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("Expected error from link generation failure")
|
||||
}
|
||||
|
||||
if len(mockClient.sentMessages) != 0 {
|
||||
t.Error("No message should be sent when link generation fails")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnPasswordReset_SendFails_ReturnsError(t *testing.T) {
|
||||
mockClient := &mockMailClient{
|
||||
sendFunc: func(r mmail.MailBuilder) error {
|
||||
return errors.New("send failed")
|
||||
},
|
||||
}
|
||||
mockDP := &mockDomainProvider{}
|
||||
|
||||
api := &NotificationAPI{
|
||||
logger: mlogger.NewLogger(true),
|
||||
client: mockClient,
|
||||
dp: mockDP,
|
||||
}
|
||||
|
||||
account := &model.Account{
|
||||
AccountPublic: model.AccountPublic{
|
||||
AccountBase: model.AccountBase{
|
||||
Base: storable.Base{
|
||||
ID: primitive.NewObjectID(),
|
||||
},
|
||||
Describable: model.Describable{
|
||||
Name: "Test User",
|
||||
},
|
||||
},
|
||||
UserDataBase: model.UserDataBase{
|
||||
Login: "user@example.com",
|
||||
Locale: "en-US",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err := api.onPasswordReset(context.Background(), account, "reset-token")
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("Expected error from send failure")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user