199 lines
5.3 KiB
Go
199 lines
5.3 KiB
Go
package mail
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"galaxy/authsession/internal/domain/common"
|
|
"galaxy/authsession/internal/ports"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestStubSenderSendLoginCode(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("zero value defaults to sent", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
sender := &StubSender{}
|
|
|
|
result, err := sender.SendLoginCode(context.Background(), validInput())
|
|
require.NoError(t, err)
|
|
assert.Equal(t, ports.SendLoginCodeOutcomeSent, result.Outcome)
|
|
|
|
attempts := sender.RecordedAttempts()
|
|
require.Len(t, attempts, 1)
|
|
assert.Equal(t, StubModeSent, attempts[0].Mode)
|
|
assert.Equal(t, validInput(), attempts[0].Input)
|
|
})
|
|
|
|
t.Run("default suppressed", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
sender := &StubSender{DefaultMode: StubModeSuppressed}
|
|
|
|
result, err := sender.SendLoginCode(context.Background(), validInput())
|
|
require.NoError(t, err)
|
|
assert.Equal(t, ports.SendLoginCodeOutcomeSuppressed, result.Outcome)
|
|
|
|
attempts := sender.RecordedAttempts()
|
|
require.Len(t, attempts, 1)
|
|
assert.Equal(t, StubModeSuppressed, attempts[0].Mode)
|
|
})
|
|
|
|
t.Run("default failed uses configured error", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
wantErr := errors.New("delivery refused")
|
|
sender := &StubSender{
|
|
DefaultMode: StubModeFailed,
|
|
DefaultError: wantErr,
|
|
}
|
|
|
|
result, err := sender.SendLoginCode(context.Background(), validInput())
|
|
require.Error(t, err)
|
|
assert.ErrorIs(t, err, wantErr)
|
|
assert.Equal(t, ports.SendLoginCodeResult{}, result)
|
|
|
|
attempts := sender.RecordedAttempts()
|
|
require.Len(t, attempts, 1)
|
|
assert.Equal(t, StubModeFailed, attempts[0].Mode)
|
|
})
|
|
|
|
t.Run("default failed uses stable fallback error", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
sender := &StubSender{DefaultMode: StubModeFailed}
|
|
|
|
_, err := sender.SendLoginCode(context.Background(), validInput())
|
|
require.Error(t, err)
|
|
assert.EqualError(t, err, "stub mail sender: forced failure")
|
|
})
|
|
|
|
t.Run("script overrides default and is consumed fifo", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
wantErr := errors.New("step failed")
|
|
sender := &StubSender{
|
|
DefaultMode: StubModeSent,
|
|
Script: []StubStep{
|
|
{Mode: StubModeSuppressed},
|
|
{Mode: StubModeFailed, Err: wantErr},
|
|
},
|
|
}
|
|
|
|
first, err := sender.SendLoginCode(context.Background(), validInput())
|
|
require.NoError(t, err)
|
|
assert.Equal(t, ports.SendLoginCodeOutcomeSuppressed, first.Outcome)
|
|
|
|
second, err := sender.SendLoginCode(context.Background(), validInput())
|
|
require.Error(t, err)
|
|
assert.ErrorIs(t, err, wantErr)
|
|
assert.Equal(t, ports.SendLoginCodeResult{}, second)
|
|
|
|
third, err := sender.SendLoginCode(context.Background(), validInput())
|
|
require.NoError(t, err)
|
|
assert.Equal(t, ports.SendLoginCodeOutcomeSent, third.Outcome)
|
|
|
|
attempts := sender.RecordedAttempts()
|
|
require.Len(t, attempts, 3)
|
|
assert.Equal(t, []StubMode{StubModeSuppressed, StubModeFailed, StubModeSent}, []StubMode{
|
|
attempts[0].Mode,
|
|
attempts[1].Mode,
|
|
attempts[2].Mode,
|
|
})
|
|
assert.Empty(t, sender.Script)
|
|
})
|
|
|
|
t.Run("invalid default mode returns adapter error", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
sender := &StubSender{DefaultMode: StubMode("queued")}
|
|
|
|
_, err := sender.SendLoginCode(context.Background(), validInput())
|
|
require.Error(t, err)
|
|
assert.ErrorContains(t, err, `default mode "queued" is unsupported`)
|
|
assert.Empty(t, sender.RecordedAttempts())
|
|
})
|
|
|
|
t.Run("invalid scripted mode returns adapter error", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
sender := &StubSender{
|
|
Script: []StubStep{
|
|
{Mode: StubMode("queued")},
|
|
},
|
|
}
|
|
|
|
_, err := sender.SendLoginCode(context.Background(), validInput())
|
|
require.Error(t, err)
|
|
assert.ErrorContains(t, err, `mode "queued" is unsupported`)
|
|
assert.Empty(t, sender.RecordedAttempts())
|
|
assert.Empty(t, sender.Script)
|
|
})
|
|
}
|
|
|
|
func TestStubSenderRecordedAttemptsAreDefensive(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
sender := &StubSender{}
|
|
|
|
_, err := sender.SendLoginCode(context.Background(), validInput())
|
|
require.NoError(t, err)
|
|
|
|
attempts := sender.RecordedAttempts()
|
|
require.Len(t, attempts, 1)
|
|
attempts[0].Mode = StubModeFailed
|
|
attempts[0].Input.Code = "000000"
|
|
|
|
again := sender.RecordedAttempts()
|
|
require.Len(t, again, 1)
|
|
assert.Equal(t, StubModeSent, again[0].Mode)
|
|
assert.Equal(t, "654321", again[0].Input.Code)
|
|
}
|
|
|
|
func TestStubSenderSendLoginCodeNilContext(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
sender := &StubSender{}
|
|
|
|
_, err := sender.SendLoginCode(nil, validInput())
|
|
require.Error(t, err)
|
|
assert.ErrorContains(t, err, "nil context")
|
|
assert.Empty(t, sender.RecordedAttempts())
|
|
}
|
|
|
|
func TestStubSenderSendLoginCodeCancelledContext(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
sender := &StubSender{}
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
|
|
_, err := sender.SendLoginCode(ctx, validInput())
|
|
require.Error(t, err)
|
|
assert.ErrorIs(t, err, context.Canceled)
|
|
assert.Empty(t, sender.RecordedAttempts())
|
|
}
|
|
|
|
func TestStubSenderSendLoginCodeInvalidInput(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
sender := &StubSender{}
|
|
|
|
_, err := sender.SendLoginCode(context.Background(), ports.SendLoginCodeInput{})
|
|
require.Error(t, err)
|
|
assert.ErrorContains(t, err, "send login code input email")
|
|
assert.Empty(t, sender.RecordedAttempts())
|
|
}
|
|
|
|
func validInput() ports.SendLoginCodeInput {
|
|
return ports.SendLoginCodeInput{
|
|
Email: common.Email("pilot@example.com"),
|
|
Code: "654321",
|
|
}
|
|
}
|