11package main
22
33import (
4+ "context"
45 "fmt"
56 "net/textproto"
67 "testing"
7- "context"
88)
99
1010const smtpPermanentErr = 530
@@ -15,37 +15,72 @@ type MockEmailQueueRepository struct {
1515 markForRetryCalled bool
1616 id int64
1717 lastError string
18+ getPendingCalled bool
19+ pendingToReturn []EmailQueue
20+ markAsSentCalled bool
1821}
1922
23+ type MockEmailSender struct {
24+ sendCalled bool
25+ subject string
26+ bodyText string
27+ bodyHTML string
28+ to string
29+ }
30+
31+ type MockOrcidService struct {
32+ getEmailCalled bool
33+ orcidReceived string
34+ emailToReturn string
35+ errToReturn error
36+ }
2037
2138func (m * MockEmailQueueRepository ) Enqueue (ctx context.Context , item * EmailQueue ) (* EmailQueue , error ) {
2239 return nil , nil
2340}
2441
2542func (m * MockEmailQueueRepository ) GetPending (ctx context.Context , limit int ) ([]EmailQueue , error ) {
26- return []EmailQueue {}, nil
43+ m .getPendingCalled = true
44+ return m .pendingToReturn , nil
2745}
2846
2947func (m * MockEmailQueueRepository ) MarkAsSent (ctx context.Context , id int64 ) error {
48+ m .markAsSentCalled = true
49+ m .id = id
3050 return nil
3151}
3252
3353func (m * MockEmailQueueRepository ) MarkAsFailed (ctx context.Context , id int64 , errMsg string ) error {
3454 m .markAsFailedCalled = true
35- m .id = id
36- m .lastError = errMsg
55+ m .id = id
56+ m .lastError = errMsg
3757 return nil
3858}
3959
4060func (m * MockEmailQueueRepository ) MarkForRetry (ctx context.Context , id int64 , errMsg string ) error {
4161 m .markForRetryCalled = true
42- m .id = id
43- m .lastError = errMsg
62+ m .id = id
63+ m .lastError = errMsg
4464 return nil
4565}
4666
67+ func (m * MockEmailSender ) Send (to string , subject string , bodyText string , bodyHTML string ) error {
68+ m .sendCalled = true
69+ m .to = to
70+ m .subject = subject
71+ m .bodyText = bodyText
72+ m .bodyHTML = bodyHTML
73+ return nil
74+ }
75+
76+ func (m * MockOrcidService ) GetEmail (ctx context.Context , orcid string ) (string , error ) {
77+ m .getEmailCalled = true
78+ m .orcidReceived = orcid
79+ return m .emailToReturn , m .errToReturn
80+ }
81+
4782func TestIsSMTPPermanentErr (t * testing.T ) {
48- err := fmt .Errorf ("error: %w" , & textproto.Error {
83+ err := fmt .Errorf ("error: %w" , & textproto.Error {
4984 Code : smtpPermanentErr ,
5085 Msg : "authentication required" ,
5186 })
@@ -57,7 +92,7 @@ func TestIsSMTPPermanentErr(t *testing.T) {
5792}
5893
5994func TestIsSMTPTemporaryErr (t * testing.T ) {
60- err := fmt .Errorf ("error: %w" , & textproto.Error {
95+ err := fmt .Errorf ("error: %w" , & textproto.Error {
6196 Code : smtpTemporaryErr ,
6297 Msg : "domain not found" ,
6398 })
@@ -68,77 +103,154 @@ func TestIsSMTPTemporaryErr(t *testing.T) {
68103 }
69104}
70105
71-
72106func TestRetryOrFailSMTPPermanentError (t * testing.T ) {
73- ctx := context .Background ()
107+ ctx := context .Background ()
74108
75- mockRepo := & MockEmailQueueRepository {}
109+ mockRepo := & MockEmailQueueRepository {}
76110
77- worker := & EmailWorker {
78- emailQueueRepo : mockRepo ,
79- }
111+ worker := & EmailWorker {
112+ emailQueueRepo : mockRepo ,
113+ }
80114
81- pending := EmailQueue {
82- Id : 2 ,
83- Attempts : 0 ,
84- }
115+ pending := EmailQueue {
116+ Id : 2 ,
117+ Attempts : 0 ,
118+ }
85119
86- smtpErr := fmt .Errorf ("error: %w" , & textproto.Error {
120+ smtpErr := fmt .Errorf ("error: %w" , & textproto.Error {
87121 Code : smtpPermanentErr ,
88122 Msg : "authentication required" ,
89123 })
90124
91- err := worker .retryOrFail (ctx , pending , "send" , smtpErr )
92- if err != nil {
93- t .Fatalf ("expected retryOrFail to succeed, got error: %v" , err )
94- }
125+ err := worker .retryOrFail (ctx , pending , "send" , smtpErr )
126+ if err != nil {
127+ t .Fatalf ("expected retryOrFail to succeed, got error: %v" , err )
128+ }
95129
96- if ! mockRepo .markAsFailedCalled {
97- t .Fatal ("expected MarkAsFailed to be called" )
98- }
130+ if ! mockRepo .markAsFailedCalled {
131+ t .Fatal ("expected MarkAsFailed to be called" )
132+ }
99133
100- if mockRepo .markForRetryCalled {
101- t .Fatal ("expected MarkForRetry not to be called" )
102- }
134+ if mockRepo .markForRetryCalled {
135+ t .Fatal ("expected MarkForRetry not to be called" )
136+ }
103137
104- if mockRepo .id != pending .Id {
105- t .Fatalf ("expected queue id %d, got %d" , pending .Id , mockRepo .id )
106- }
138+ if mockRepo .id != pending .Id {
139+ t .Fatalf ("expected queue id: %d, got: %d" , pending .Id , mockRepo .id )
140+ }
107141}
108142
109143func TestRetryOrFailSMTPTemporaryError (t * testing.T ) {
110- ctx := context .Background ()
144+ ctx := context .Background ()
111145
112- mockRepo := & MockEmailQueueRepository {}
146+ mockRepo := & MockEmailQueueRepository {}
113147
114- worker := & EmailWorker {
115- emailQueueRepo : mockRepo ,
116- }
148+ worker := & EmailWorker {
149+ emailQueueRepo : mockRepo ,
150+ }
117151
118- pending := EmailQueue {
119- Id : 2 ,
120- Attempts : 0 ,
121- }
152+ pending := EmailQueue {
153+ Id : 2 ,
154+ Attempts : 0 ,
155+ }
122156
123- smtpErr := fmt .Errorf ("error: %w" , & textproto.Error {
157+ smtpErr := fmt .Errorf ("error: %w" , & textproto.Error {
124158 Code : smtpTemporaryErr ,
125159 Msg : "domain not found" ,
126160 })
127161
128- err := worker .retryOrFail (ctx , pending , "send" , smtpErr )
129- if err != nil {
130- t .Fatalf ("expected retryOrFail to succeed, got error: %v" , err )
131- }
162+ err := worker .retryOrFail (ctx , pending , "send" , smtpErr )
163+ if err != nil {
164+ t .Fatalf ("expected retryOrFail to succeed, got error: %v" , err )
165+ }
166+
167+ if ! mockRepo .markForRetryCalled {
168+ t .Fatal ("expected MarkForRetry to be called" )
169+ }
170+
171+ if mockRepo .markAsFailedCalled {
172+ t .Fatal ("expected MarkAsFailed not to be called" )
173+ }
174+
175+ if mockRepo .id != pending .Id {
176+ t .Fatalf ("expected queue id: %d, got: %d" , pending .Id , mockRepo .id )
177+ }
178+ }
132179
133- if ! mockRepo .markForRetryCalled {
134- t .Fatal ("expected MarkForRetry to be called" )
135- }
180+ func TestProcessPendingMarkAsSentWhenSuccess (t * testing.T ) {
181+ ctx := context .Background ()
136182
137- if mockRepo . markAsFailedCalled {
138- t . Fatal ( "expected MarkAsFailed not to be called" )
139- }
183+ mockRepo := & MockEmailQueueRepository {}
184+ mockSender := & MockEmailSender {}
185+ mockOrcid := & MockOrcidService { }
140186
141- if mockRepo .id != pending .Id {
142- t .Fatalf ("expected queue id %d, got %d" , pending .Id , mockRepo .id )
143- }
187+ worker := & EmailWorker {
188+ emailQueueRepo : mockRepo ,
189+ emailSender : mockSender ,
190+ orcidService : mockOrcid ,
191+ }
192+
193+ pending := EmailQueue {
194+ Id : 2 ,
195+ RecipientOrcid : "0000-0000-0000-0000" ,
196+ Subject : "Test" ,
197+ BodyText : "Body test" ,
198+ BodyHTML : "<p>Body test</p>" ,
199+ }
200+
201+ mockRepo .pendingToReturn = []EmailQueue {pending }
202+ mockOrcid .emailToReturn = "test@test.com"
203+
204+ err := worker .ProcessPending (ctx , 1 )
205+ if err != nil {
206+ t .Fatalf ("expected ProcessPending to succeed, got error: %v" , err )
207+ }
208+
209+ if ! mockRepo .getPendingCalled {
210+ t .Fatal ("expected GetPending to be called" )
211+ }
212+
213+ if mockRepo .id != pending .Id {
214+ t .Fatalf ("expected queue id: %d, got: %d" , pending .Id , mockRepo .id )
215+ }
216+
217+ if ! mockOrcid .getEmailCalled {
218+ t .Fatal ("expected getEmail to be called" )
219+ }
220+
221+ if mockOrcid .orcidReceived != pending .RecipientOrcid {
222+ t .Fatalf ("expected orcid: %q, got: %q" , pending .RecipientOrcid , mockOrcid .orcidReceived )
223+ }
224+
225+ if ! mockSender .sendCalled {
226+ t .Fatal ("expected Send to be called" )
227+ }
228+
229+ if mockSender .to != mockOrcid .emailToReturn {
230+ t .Fatalf ("expected email: %q, got: %q" , mockOrcid .emailToReturn , mockSender .to )
231+ }
232+
233+ if mockSender .subject != pending .Subject {
234+ t .Fatalf ("expected subject: %q, got: %q" , pending .Subject , mockSender .subject )
235+ }
236+
237+ if mockSender .bodyText != pending .BodyText {
238+ t .Fatalf ("expected bodyText: %q, got: %q" , pending .BodyText , mockSender .bodyText )
239+ }
240+
241+ if mockSender .bodyHTML != pending .BodyHTML {
242+ t .Fatalf ("expected bodyHTML: %q, got: %q" , pending .BodyHTML , mockSender .bodyHTML )
243+ }
244+
245+ if ! mockRepo .markAsSentCalled {
246+ t .Fatal ("expected MarkAsSent to be called" )
247+ }
248+
249+ if mockRepo .markForRetryCalled {
250+ t .Fatal ("expected MarkForRetry not to be called" )
251+ }
252+
253+ if mockRepo .markAsFailedCalled {
254+ t .Fatal ("expected MarkAsFailed not to be called" )
255+ }
144256}
0 commit comments