Skip to content

Commit 60393c7

Browse files
committed
tests, including an attachment (gitea.png) in an issue
1 parent 1d9f2dd commit 60393c7

File tree

5 files changed

+163
-1
lines changed

5 files changed

+163
-1
lines changed

models/fixtures/attachment.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,16 @@
153153
download_count: 0
154154
size: 0
155155
created_unix: 946684800
156+
157+
-
158+
id: 13
159+
uuid: 1b267670-1793-4cd0-abc1-449269b7cff9
160+
repo_id: 1
161+
issue_id: 23
162+
release_id: 0
163+
uploader_id: 0
164+
comment_id: 2
165+
name: gitea.png
166+
download_count: 0
167+
size: 1458
168+
created_unix: 946684800

models/fixtures/issue.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,3 +372,20 @@
372372
created_unix: 1707270422
373373
updated_unix: 1707270422
374374
is_locked: false
375+
376+
-
377+
id: 23
378+
repo_id: 1
379+
index: 6
380+
poster_id: 1
381+
original_author_id: 0
382+
name: issue23
383+
content: 'content including this image: <image alt="gitea.png" src="attachments/1b267670-1793-4cd0-abc1-449269b7cff9" /> with some more content behind it'
384+
milestone_id: 0
385+
priority: 0
386+
is_closed: false
387+
is_pull: false
388+
num_comments: 2
389+
created_unix: 946684800
390+
updated_unix: 978307200
391+
is_locked: false

models/fixtures/repository.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
num_watches: 4
1010
num_stars: 0
1111
num_forks: 0
12-
num_issues: 2
12+
num_issues: 3
1313
num_closed_issues: 1
1414
num_pulls: 3
1515
num_closed_pulls: 0

services/mailer/mail_test.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"html/template"
1111
"io"
1212
"mime/quotedprintable"
13+
"path/filepath"
1314
"regexp"
1415
"strings"
1516
"testing"
@@ -23,6 +24,7 @@ import (
2324
user_model "code.gitea.io/gitea/models/user"
2425
"code.gitea.io/gitea/modules/markup"
2526
"code.gitea.io/gitea/modules/setting"
27+
"code.gitea.io/gitea/modules/storage"
2628

2729
"github.com/stretchr/testify/assert"
2830
)
@@ -58,6 +60,7 @@ func prepareMailerTest(t *testing.T) (doer *user_model.User, repo *repo_model.Re
5860

5961
setting.MailService = &mailService
6062
setting.Domain = "localhost"
63+
setting.AppURL = "https://try.gitea.io/"
6164

6265
doer = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
6366
repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1, Owner: doer})
@@ -451,3 +454,132 @@ func TestFromDisplayName(t *testing.T) {
451454
assert.EqualValues(t, "Mister X (by Code IT on [code.it])", fromDisplayName(&user_model.User{FullName: "Mister X", Name: "tmp"}))
452455
})
453456
}
457+
458+
func PrepareAttachmentsStorage(t testing.TB) { // same as in test_utils.go
459+
// prepare attachments directory and files
460+
assert.NoError(t, storage.Clean(storage.Attachments))
461+
462+
s, err := storage.NewStorage(setting.LocalStorageType, &setting.Storage{
463+
Path: filepath.Join(filepath.Dir(setting.AppPath), "tests", "testdata", "data", "attachments"),
464+
})
465+
assert.NoError(t, err)
466+
assert.NoError(t, s.IterateObjects("", func(p string, obj storage.Object) error {
467+
_, err = storage.Copy(storage.Attachments, p, s, p)
468+
return err
469+
}))
470+
}
471+
472+
func TestEmbedBase64ImagesInEmail(t *testing.T) {
473+
// Fake context setup
474+
doer, repo, _, _ := prepareMailerTest(t)
475+
PrepareAttachmentsStorage(t)
476+
setting.MailService.Base64EmbedImages = true
477+
setting.MailService.Base64EmbedImagesMaxSizePerEmail = 10 * 1024 * 1024
478+
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 23, Repo: repo, Poster: doer})
479+
assert.NoError(t, issue.LoadRepo(db.DefaultContext))
480+
481+
subjectTemplates = texttmpl.Must(texttmpl.New("issue/new").Parse(subjectTpl))
482+
bodyTemplates = template.Must(template.New("issue/new").Parse(bodyTpl))
483+
484+
recipients := []*user_model.User{{Name: "Test", Email: "[email protected]"}}
485+
msgs, err := composeIssueCommentMessages(&mailCommentContext{
486+
Context: context.TODO(), // TODO: use a correct context
487+
Issue: issue, Doer: doer, ActionType: activities_model.ActionCreateIssue,
488+
Content: strings.ReplaceAll(issue.Content, `src="`, `src="`+setting.AppURL),
489+
}, "en-US", recipients, false, "issue create")
490+
491+
mailBody := msgs[0].Body
492+
re := regexp.MustCompile(`(?s)<body>(.*?)</body>`)
493+
matches := re.FindStringSubmatch(mailBody)
494+
if len(matches) > 1 {
495+
mailBody = matches[1]
496+
}
497+
// check if the mail body was correctly generated
498+
assert.NoError(t, err)
499+
assert.Contains(t, mailBody, "content including this image")
500+
501+
// check if an image was embedded
502+
assert.Contains(t, mailBody, "data:image/png;base64,")
503+
504+
// check if the image was embedded only once
505+
assert.Equal(t, 1, strings.Count(mailBody, "data:image/png;base64,"))
506+
507+
img2InternalBase64 := "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAxAQMAAAB3d7wRAAAABlBMVEVgmyF6qkqITHmkAAAAAXRSTlMBN+Ho8AAAAJhJREFUKM+V0DsOwyAQBNCxXLjkCFwk0t7McDQfhS4tpQuEzWc/iaUU2eo1zC4DUMWYF3DxVKzGTXjBGb2RsjJEo6ZhN1Zj+cEgi/9hBQl3YflkkIsbo5IO5glKTuhPpavM3Hp4C7WdjEWYrL5GMkp/R+s4GPlh/CZn4MEwv9aHHiyD3ujm5X22eaMyDa5yAm+O0B1TPa1l3W2qZWMg+KgtAAAAAElFTkSuQmCC"
508+
509+
// check if the image was embedded correctly
510+
assert.Contains(t, mailBody, img2InternalBase64)
511+
}
512+
513+
func TestEmbedBase64Images(t *testing.T) {
514+
user, repo, _, _ := prepareMailerTest(t)
515+
PrepareAttachmentsStorage(t)
516+
setting.MailService.Base64EmbedImages = true
517+
setting.MailService.Base64EmbedImagesMaxSizePerEmail = 10 * 1024 * 1024
518+
519+
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 23, Repo: repo, Poster: user})
520+
521+
attachment := unittest.AssertExistsAndLoadBean(t, &repo_model.Attachment{ID: 13, IssueID: issue.ID, RepoID: repo.ID})
522+
ctx0 := context.Background()
523+
524+
ctx := &mailCommentContext{Context: ctx0 /* TODO: use a correct context */, Issue: issue, Doer: user}
525+
526+
img1ExternalURL := "https://via.placeholder.com/10"
527+
img1ExternalImg := "<img src=\"" + img1ExternalURL + "\"/>"
528+
529+
img2InternalURL := setting.AppURL + repo.Owner.Name + "/" + repo.Name + "/attachments/" + attachment.UUID
530+
img2InternalImg := "<img src=\"" + img2InternalURL + "\"/>"
531+
img2InternalBase64 := "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAxAQMAAAB3d7wRAAAABlBMVEVgmyF6qkqITHmkAAAAAXRSTlMBN+Ho8AAAAJhJREFUKM+V0DsOwyAQBNCxXLjkCFwk0t7McDQfhS4tpQuEzWc/iaUU2eo1zC4DUMWYF3DxVKzGTXjBGb2RsjJEo6ZhN1Zj+cEgi/9hBQl3YflkkIsbo5IO5glKTuhPpavM3Hp4C7WdjEWYrL5GMkp/R+s4GPlh/CZn4MEwv9aHHiyD3ujm5X22eaMyDa5yAm+O0B1TPa1l3W2qZWMg+KgtAAAAAElFTkSuQmCC"
532+
img2InternalBase64Img := "<img src=\"" + img2InternalBase64 + "\"/>"
533+
534+
// 1st Test: convert internal image to base64
535+
t.Run("replaceSpecifiedBase64ImagesInternal", func(t *testing.T) {
536+
totalEmbeddedImagesSize := int64(0)
537+
538+
resultImg1Internal, err := AttachmentSrcToBase64DataURI(img2InternalURL, ctx, &totalEmbeddedImagesSize)
539+
assert.NoError(t, err)
540+
assert.Equal(t, img2InternalBase64, resultImg1Internal) // replace cause internal image
541+
})
542+
543+
// 2nd Test: convert external image to base64 -> abort cause external image
544+
t.Run("replaceSpecifiedBase64ImagesExternal", func(t *testing.T) {
545+
totalEmbeddedImagesSize := int64(0)
546+
547+
resultImg1External, err := AttachmentSrcToBase64DataURI(img1ExternalURL, ctx, &totalEmbeddedImagesSize)
548+
assert.Error(t, err)
549+
assert.Equal(t, "", resultImg1External) // don't replace cause external image
550+
})
551+
552+
// 3rd Test: generate email body with 1 internal and 1 external image, expect the result to have the internal image replaced with base64 data and the external not replaced
553+
t.Run("generateEmailBody", func(t *testing.T) {
554+
mailBody := "<html><head></head><body><p>Test1</p>" + img1ExternalImg + "<p>Test2</p>" + img2InternalImg + "<p>Test3</p></body></html>"
555+
expectedMailBody := "<html><head></head><body><p>Test1</p>" + img1ExternalImg + "<p>Test2</p>" + img2InternalBase64Img + "<p>Test3</p></body></html>"
556+
resultMailBody, err := Base64InlineImages(mailBody, ctx)
557+
558+
assert.NoError(t, err)
559+
assert.Equal(t, expectedMailBody, resultMailBody)
560+
})
561+
562+
// 4th Test, generate email body with 2 internal images, but set Mailer.Base64EmbedImagesMaxSizePerEmail to the size of the first image (+1), expect the first image to be replaced and the second not
563+
t.Run("generateEmailBodyWithMaxSize", func(t *testing.T) {
564+
setting.MailService.Base64EmbedImagesMaxSizePerEmail = int64(len(img2InternalBase64) + 1)
565+
566+
mailBody := "<html><head></head><body><p>Test1</p>" + img2InternalImg + "<p>Test2</p>" + img2InternalImg + "<p>Test3</p></body></html>"
567+
expectedMailBody := "<html><head></head><body><p>Test1</p>" + img2InternalBase64Img + "<p>Test2</p>" + img2InternalImg + "<p>Test3</p></body></html>"
568+
resultMailBody, err := Base64InlineImages(mailBody, ctx)
569+
570+
assert.NoError(t, err)
571+
assert.Equal(t, expectedMailBody, resultMailBody)
572+
})
573+
574+
// 5th Test, generate email body with 3 internal images, but set Mailer.Base64EmbedImagesMaxSizePerEmail to the size of all 3 images (+1), expect all images to be replaced
575+
t.Run("generateEmailBodyWith3Images", func(t *testing.T) {
576+
setting.MailService.Base64EmbedImagesMaxSizePerEmail = int64(len(img2InternalBase64)*3 + 1)
577+
578+
mailBody := "<html><head></head><body><p>Test1</p>" + img2InternalImg + "<p>Test2</p>" + img2InternalImg + "<p>Test3</p>" + img2InternalImg + "</body></html>"
579+
expectedMailBody := "<html><head></head><body><p>Test1</p>" + img2InternalBase64Img + "<p>Test2</p>" + img2InternalBase64Img + "<p>Test3</p>" + img2InternalBase64Img + "</body></html>"
580+
resultMailBody, err := Base64InlineImages(mailBody, ctx)
581+
582+
assert.NoError(t, err)
583+
assert.Equal(t, expectedMailBody, resultMailBody)
584+
})
585+
}
Binary file not shown.

0 commit comments

Comments
 (0)