loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request 'tests(services/mailer): add tooling and coverage for issues/default.tmpl' (#3816) from earl-warren/forgejo:wip-test-mail into forgejo

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3816
Reviewed-by: Otto <otto@codeberg.org>

+166 -64
+1 -1
services/mailer/mail.go
··· 517 517 case issues_model.ReviewTypeReject: 518 518 name = "reject" 519 519 default: 520 - name = "review" 520 + name = "review" // TODO: there is no activities_model.Action* when sending a review comment, this is deadcode and should be removed 521 521 } 522 522 case issues_model.CommentTypeCode: 523 523 name = "code"
+1 -4
services/mailer/mail_admin_new_user.go
··· 19 19 tplNewUserMail base.TplName = "notify/admin_new_user" 20 20 ) 21 21 22 - var sa = SendAsync 23 - 24 22 // MailNewUser sends notification emails on new user registrations to all admins 25 23 func MailNewUser(ctx context.Context, u *user_model.User) { 26 24 if !setting.Admin.SendNotificationEmailOnNewUser { 27 25 return 28 26 } 29 - 30 27 if setting.MailService == nil { 31 28 // No mail service configured 32 29 return ··· 77 74 msg.Info = subject 78 75 msgs = append(msgs, msg) 79 76 } 80 - sa(msgs...) 77 + SendAsync(msgs...) 81 78 }
+28 -45
services/mailer/mail_admin_new_user_test.go
··· 11 11 "code.gitea.io/gitea/models/db" 12 12 user_model "code.gitea.io/gitea/models/user" 13 13 "code.gitea.io/gitea/modules/setting" 14 - "code.gitea.io/gitea/modules/translation" 14 + "code.gitea.io/gitea/modules/test" 15 15 16 16 "github.com/stretchr/testify/assert" 17 17 "github.com/stretchr/testify/require" 18 + 19 + _ "github.com/mattn/go-sqlite3" 18 20 ) 19 21 20 22 func getTestUsers(t *testing.T) []*user_model.User { ··· 45 47 } 46 48 47 49 func TestAdminNotificationMail_test(t *testing.T) { 48 - translation.InitLocales(context.Background()) 49 - locale := translation.NewLocale("") 50 - key := "mail.admin.new_user.user_info" 51 - translatedKey := locale.Tr(key) 52 - require.NotEqualValues(t, key, translatedKey) 53 - 54 - mailService := setting.Mailer{ 55 - From: "test@example.com", 56 - Protocol: "dummy", 57 - } 58 - 59 - setting.MailService = &mailService 60 - 61 - // test with SEND_NOTIFICATION_EMAIL_ON_NEW_USER enabled 62 - setting.Admin.SendNotificationEmailOnNewUser = true 63 - 64 50 ctx := context.Background() 65 - NewContext(ctx) 66 51 67 52 users := getTestUsers(t) 68 - oldSendAsync := sa 69 - defer func() { 70 - sa = oldSendAsync 71 - cleanUpUsers(ctx, users) 72 - }() 53 + 54 + t.Run("SendNotificationEmailOnNewUser_true", func(t *testing.T) { 55 + defer test.MockVariableValue(&setting.Admin.SendNotificationEmailOnNewUser, true)() 73 56 74 - called := false 75 - sa = func(msgs ...*Message) { 76 - assert.Equal(t, len(msgs), 1, "Test provides only one admin user, so only one email must be sent") 77 - assert.Equal(t, msgs[0].To, users[0].Email, "checks if the recipient is the admin of the instance") 78 - manageUserURL := setting.AppURL + "admin/users/" + strconv.FormatInt(users[1].ID, 10) 79 - assert.Contains(t, msgs[0].Body, manageUserURL) 80 - assert.Contains(t, msgs[0].Body, users[1].HTMLURL()) 81 - assert.Contains(t, msgs[0].Body, translatedKey, "the .Locale translates to nothing") 82 - assert.Contains(t, msgs[0].Body, users[1].Name, "user name of the newly created user") 83 - for _, untranslated := range []string{"mail.admin", "admin.users"} { 84 - assert.NotContains(t, msgs[0].Body, untranslated, "this is an untranslated placeholder prefix") 85 - } 86 - called = true 87 - } 88 - MailNewUser(ctx, users[1]) 89 - assert.True(t, called) 57 + called := false 58 + defer mockMailSettings(func(msgs ...*Message) { 59 + assert.Equal(t, len(msgs), 1, "Test provides only one admin user, so only one email must be sent") 60 + assert.Equal(t, msgs[0].To, users[0].Email, "checks if the recipient is the admin of the instance") 61 + manageUserURL := setting.AppURL + "admin/users/" + strconv.FormatInt(users[1].ID, 10) 62 + assert.Contains(t, msgs[0].Body, manageUserURL) 63 + assert.Contains(t, msgs[0].Body, users[1].HTMLURL()) 64 + assert.Contains(t, msgs[0].Body, users[1].Name, "user name of the newly created user") 65 + assertTranslatedLocale(t, msgs[0].Body, "mail.admin", "admin.users") 66 + called = true 67 + })() 68 + MailNewUser(ctx, users[1]) 69 + assert.True(t, called) 70 + }) 90 71 91 - // test with SEND_NOTIFICATION_EMAIL_ON_NEW_USER disabled; emails shouldn't be sent 92 - setting.Admin.SendNotificationEmailOnNewUser = false 93 - sa = func(msgs ...*Message) { 94 - assert.Equal(t, 1, 0, "this shouldn't execute. MailNewUser must exit early since SEND_NOTIFICATION_EMAIL_ON_NEW_USER is disabled") 95 - } 72 + t.Run("SendNotificationEmailOnNewUser_false", func(t *testing.T) { 73 + defer test.MockVariableValue(&setting.Admin.SendNotificationEmailOnNewUser, false)() 74 + defer mockMailSettings(func(msgs ...*Message) { 75 + assert.Equal(t, 1, 0, "this shouldn't execute. MailNewUser must exit early since SEND_NOTIFICATION_EMAIL_ON_NEW_USER is disabled") 76 + })() 77 + MailNewUser(ctx, users[1]) 78 + }) 96 79 97 - MailNewUser(ctx, users[1]) 80 + cleanUpUsers(ctx, users) 98 81 }
+104 -12
services/mailer/mail_test.go
··· 23 23 user_model "code.gitea.io/gitea/models/user" 24 24 "code.gitea.io/gitea/modules/markup" 25 25 "code.gitea.io/gitea/modules/setting" 26 + "code.gitea.io/gitea/modules/test" 26 27 27 28 "github.com/stretchr/testify/assert" 28 29 ) ··· 51 52 52 53 func prepareMailerTest(t *testing.T) (doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment) { 53 54 assert.NoError(t, unittest.PrepareTestDatabase()) 54 - mailService := setting.Mailer{ 55 - From: "test@gitea.com", 56 - } 57 - 58 - setting.MailService = &mailService 59 - setting.Domain = "localhost" 60 55 61 56 doer = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 62 57 repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1, Owner: doer}) ··· 67 62 } 68 63 69 64 func TestComposeIssueCommentMessage(t *testing.T) { 65 + defer mockMailSettings(nil)() 70 66 doer, _, issue, comment := prepareMailerTest(t) 71 67 72 68 markup.Init(&markup.ProcessorHelper{ ··· 75 71 }, 76 72 }) 77 73 78 - setting.IncomingEmail.Enabled = true 79 - defer func() { setting.IncomingEmail.Enabled = false }() 74 + defer test.MockVariableValue(&setting.IncomingEmail.Enabled, true)() 80 75 81 76 subjectTemplates = texttmpl.Must(texttmpl.New("issue/comment").Parse(subjectTpl)) 82 77 bodyTemplates = template.Must(template.New("issue/comment").Parse(bodyTpl)) ··· 122 117 } 123 118 124 119 func TestComposeIssueMessage(t *testing.T) { 120 + defer mockMailSettings(nil)() 125 121 doer, _, issue, _ := prepareMailerTest(t) 126 - 127 - subjectTemplates = texttmpl.Must(texttmpl.New("issue/new").Parse(subjectTpl)) 128 - bodyTemplates = template.Must(template.New("issue/new").Parse(bodyTpl)) 129 122 130 123 recipients := []*user_model.User{{Name: "Test", Email: "test@gitea.com"}, {Name: "Test2", Email: "test2@gitea.com"}} 131 124 msgs, err := composeIssueCommentMessages(&mailCommentContext{ ··· 144 137 references := gomailMsg.GetHeader("References") 145 138 146 139 assert.Len(t, mailto, 1, "exactly one recipient is expected in the To field") 147 - assert.Equal(t, "[user2/repo1] @user2 #1 - issue1", subject[0]) 140 + assert.Equal(t, "[user2/repo1] issue1 (#1)", subject[0]) 148 141 assert.Equal(t, "<user2/repo1/issues/1@localhost>", inReplyTo[0], "In-Reply-To header doesn't match") 149 142 assert.Equal(t, "<user2/repo1/issues/1@localhost>", references[0], "References header doesn't match") 150 143 assert.Equal(t, "<user2/repo1/issues/1@localhost>", messageID[0], "Message-ID header doesn't match") ··· 152 145 assert.Len(t, gomailMsg.GetHeader("List-Unsubscribe"), 1) // url without mailto 153 146 } 154 147 148 + func TestMailerIssueTemplate(t *testing.T) { 149 + defer mockMailSettings(nil)() 150 + assert.NoError(t, unittest.PrepareTestDatabase()) 151 + 152 + doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 153 + 154 + expect := func(t *testing.T, msg *Message, issue *issues_model.Issue, expected ...string) { 155 + subject := msg.ToMessage().GetHeader("Subject") 156 + msgbuf := new(bytes.Buffer) 157 + _, _ = msg.ToMessage().WriteTo(msgbuf) 158 + wholemsg := msgbuf.String() 159 + assert.Contains(t, subject[0], fallbackMailSubject(issue)) 160 + for _, s := range expected { 161 + assert.Contains(t, wholemsg, s) 162 + } 163 + assertTranslatedLocale(t, wholemsg, "mail.issue") 164 + } 165 + 166 + testCompose := func(t *testing.T, ctx *mailCommentContext) *Message { 167 + t.Helper() 168 + recipients := []*user_model.User{{Name: "Test", Email: "test@gitea.com"}} 169 + 170 + ctx.Context = context.Background() 171 + fromMention := false 172 + msgs, err := composeIssueCommentMessages(ctx, "en-US", recipients, fromMention, "TestMailerIssueTemplate") 173 + assert.NoError(t, err) 174 + assert.Len(t, msgs, 1) 175 + return msgs[0] 176 + } 177 + 178 + issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) 179 + assert.NoError(t, issue.LoadRepo(db.DefaultContext)) 180 + 181 + msg := testCompose(t, &mailCommentContext{ 182 + Issue: issue, Doer: doer, ActionType: activities_model.ActionCreateIssue, 183 + Content: issue.Content, 184 + }) 185 + expect(t, msg, issue, issue.Content) 186 + 187 + comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 2, Issue: issue}) 188 + 189 + msg = testCompose(t, &mailCommentContext{ 190 + Issue: issue, Doer: doer, ActionType: activities_model.ActionCommentIssue, 191 + Content: comment.Content, Comment: comment, 192 + }) 193 + expect(t, msg, issue, comment.Content) 194 + 195 + msg = testCompose(t, &mailCommentContext{ 196 + Issue: issue, Doer: doer, ActionType: activities_model.ActionCloseIssue, 197 + Content: comment.Content, Comment: comment, 198 + }) 199 + expect(t, msg, issue, comment.Content) 200 + 201 + msg = testCompose(t, &mailCommentContext{ 202 + Issue: issue, Doer: doer, ActionType: activities_model.ActionReopenIssue, 203 + Content: comment.Content, Comment: comment, 204 + }) 205 + expect(t, msg, issue, comment.Content) 206 + 207 + pull := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) 208 + assert.NoError(t, pull.LoadAttributes(db.DefaultContext)) 209 + pullComment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 4, Issue: pull}) 210 + 211 + msg = testCompose(t, &mailCommentContext{ 212 + Issue: pull, Doer: doer, ActionType: activities_model.ActionCommentPull, 213 + Content: pullComment.Content, Comment: pullComment, 214 + }) 215 + expect(t, msg, pull, pullComment.Content) 216 + 217 + msg = testCompose(t, &mailCommentContext{ 218 + Issue: pull, Doer: doer, ActionType: activities_model.ActionMergePullRequest, 219 + Content: pullComment.Content, Comment: pullComment, 220 + }) 221 + expect(t, msg, pull, pullComment.Content, pull.PullRequest.BaseBranch) 222 + 223 + reviewComment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 9}) 224 + assert.NoError(t, reviewComment.LoadReview(db.DefaultContext)) 225 + 226 + approveComment := reviewComment 227 + approveComment.Review.Type = issues_model.ReviewTypeApprove 228 + msg = testCompose(t, &mailCommentContext{ 229 + Issue: pull, Doer: doer, ActionType: activities_model.ActionApprovePullRequest, 230 + Content: approveComment.Content, Comment: approveComment, 231 + }) 232 + expect(t, msg, pull, approveComment.Content) 233 + 234 + rejectComment := reviewComment 235 + rejectComment.Review.Type = issues_model.ReviewTypeReject 236 + msg = testCompose(t, &mailCommentContext{ 237 + Issue: pull, Doer: doer, ActionType: activities_model.ActionRejectPullRequest, 238 + Content: rejectComment.Content, Comment: rejectComment, 239 + }) 240 + expect(t, msg, pull, rejectComment.Content) 241 + } 242 + 155 243 func TestTemplateSelection(t *testing.T) { 244 + defer mockMailSettings(nil)() 156 245 doer, repo, issue, comment := prepareMailerTest(t) 157 246 recipients := []*user_model.User{{Name: "Test", Email: "test@gitea.com"}} 158 247 ··· 207 296 } 208 297 209 298 func TestTemplateServices(t *testing.T) { 299 + defer mockMailSettings(nil)() 210 300 doer, _, issue, comment := prepareMailerTest(t) 211 301 assert.NoError(t, issue.LoadRepo(db.DefaultContext)) 212 302 ··· 259 349 } 260 350 261 351 func TestGenerateAdditionalHeaders(t *testing.T) { 352 + defer mockMailSettings(nil)() 262 353 doer, _, issue, _ := prepareMailerTest(t) 263 354 264 355 ctx := &mailCommentContext{Context: context.TODO() /* TODO: use a correct context */, Issue: issue, Doer: doer} ··· 288 379 } 289 380 290 381 func Test_createReference(t *testing.T) { 382 + defer mockMailSettings(nil)() 291 383 _, _, issue, comment := prepareMailerTest(t) 292 384 _, _, pullIssue, _ := prepareMailerTest(t) 293 385 pullIssue.IsPull = true
-2
services/mailer/mailer.go
··· 365 365 return waitError 366 366 } 367 367 368 - // Sender sendmail mail sender 369 368 type dummySender struct{} 370 369 371 - // Send send email 372 370 func (s *dummySender) Send(from string, to []string, msg io.WriterTo) error { 373 371 buf := bytes.Buffer{} 374 372 if _, err := msg.WriteTo(&buf); err != nil {
+32
services/mailer/main_test.go
··· 4 4 package mailer 5 5 6 6 import ( 7 + "context" 7 8 "testing" 8 9 9 10 "code.gitea.io/gitea/models/unittest" 11 + "code.gitea.io/gitea/modules/setting" 12 + "code.gitea.io/gitea/modules/templates" 13 + "code.gitea.io/gitea/modules/test" 14 + "code.gitea.io/gitea/modules/translation" 10 15 11 16 _ "code.gitea.io/gitea/models/actions" 17 + 18 + "github.com/stretchr/testify/assert" 12 19 ) 13 20 14 21 func TestMain(m *testing.M) { 15 22 unittest.MainTest(m) 16 23 } 24 + 25 + func assertTranslatedLocale(t *testing.T, message string, prefixes ...string) { 26 + t.Helper() 27 + for _, prefix := range prefixes { 28 + assert.NotContains(t, message, prefix, "there is an untranslated locale prefix") 29 + } 30 + } 31 + 32 + func mockMailSettings(send func(msgs ...*Message)) func() { 33 + translation.InitLocales(context.Background()) 34 + subjectTemplates, bodyTemplates = templates.Mailer(context.Background()) 35 + mailService := setting.Mailer{ 36 + From: "test@gitea.com", 37 + } 38 + cleanups := []func(){ 39 + test.MockVariableValue(&setting.MailService, &mailService), 40 + test.MockVariableValue(&setting.Domain, "localhost"), 41 + test.MockVariableValue(&SendAsync, send), 42 + } 43 + return func() { 44 + for _, cleanup := range cleanups { 45 + cleanup() 46 + } 47 + } 48 + }