package main import ( "testing" "github.com/abhinavxd/libredesk/internal/attachment" cmodels "github.com/abhinavxd/libredesk/internal/conversation/models" ) func TestResolveContentCIDs(t *testing.T) { tests := []struct { name string msg cmodels.Message rootURL string want string }{ { name: "replace single cid with attachment url", msg: cmodels.Message{ Content: `
photo.png
`, Attachments: attachment.Attachments{ {ContentID: "conv_abc123", URL: "https://s3.example.com/photo.png?sig=xxx"}, }, }, rootURL: "", want: `
photo.png
`, }, { name: "replace multiple cids", msg: cmodels.Message{ Content: `
`, Attachments: attachment.Attachments{ {ContentID: "img1", URL: "https://s3.example.com/img1.png"}, {ContentID: "img2", URL: "https://s3.example.com/img2.png"}, }, }, rootURL: "", want: `
`, }, { name: "same cid referenced multiple times", msg: cmodels.Message{ Content: `

text

`, Attachments: attachment.Attachments{ {ContentID: "dup1", URL: "https://s3.example.com/dup.png"}, }, }, rootURL: "", want: `

text

`, }, { name: "skip attachment with empty content_id", msg: cmodels.Message{ Content: `
no cids here
`, Attachments: attachment.Attachments{ {ContentID: "", URL: "https://s3.example.com/file.pdf"}, }, }, rootURL: "", want: `
no cids here
`, }, { name: "skip attachment with empty url", msg: cmodels.Message{ Content: `
`, Attachments: attachment.Attachments{ {ContentID: "orphan", URL: ""}, }, }, rootURL: "", want: `
`, }, { name: "no attachments", msg: cmodels.Message{ Content: `
`, Attachments: attachment.Attachments{}, }, rootURL: "", want: `
`, }, { name: "resolve /uploads/ double quotes to absolute url", msg: cmodels.Message{ Content: `
`, }, rootURL: "https://desk.example.com", want: `
`, }, { name: "resolve /uploads/ single quotes to absolute url", msg: cmodels.Message{ Content: `
`, }, rootURL: "https://desk.example.com", want: `
`, }, { name: "skip /uploads/ resolution when rootURL is empty", msg: cmodels.Message{ Content: `
`, }, rootURL: "", want: `
`, }, { name: "cid replacement and /uploads/ resolution together", msg: cmodels.Message{ Content: `
`, Attachments: attachment.Attachments{ {ContentID: "inline1", URL: "https://s3.example.com/inline1.png"}, }, }, rootURL: "https://desk.example.com", want: `
`, }, { name: "does not replace cid in plain text outside src attribute", msg: cmodels.Message{ Content: `
Reference: cid:img1 is the image id
`, Attachments: attachment.Attachments{ {ContentID: "img1", URL: "https://s3.example.com/img1.png"}, }, }, rootURL: "", want: `
Reference: https://s3.example.com/img1.png is the image id
`, }, { name: "rootURL with trailing slash is preserved as-is", msg: cmodels.Message{ Content: ``, }, rootURL: "https://desk.example.com/", want: ``, }, { name: "real email html with cid in nested divs and gmail quote", msg: cmodels.Message{ Content: `
Attachments and inline.

Thanks.
` + `screenshot.png` + `logo.png

` + `


` + `
quoted text
`, Attachments: attachment.Attachments{ {ContentID: "conv_ii_abc1", URL: "https://s3.example.com/screenshot.png?sig=aaa"}, {ContentID: "conv_ii_abc2", URL: "https://s3.example.com/logo.png?sig=bbb"}, }, }, rootURL: "", want: `
Attachments and inline.

Thanks.
` + `screenshot.png` + `logo.png

` + `


` + `
quoted text
`, }, { name: "cid in css background-image inline style", msg: cmodels.Message{ Content: `
content
`, Attachments: attachment.Attachments{ {ContentID: "bg_img", URL: "https://s3.example.com/bg.png"}, }, }, rootURL: "", want: `
content
`, }, { name: "empty content", msg: cmodels.Message{ Content: "", Attachments: attachment.Attachments{ {ContentID: "img1", URL: "https://s3.example.com/img1.png"}, }, }, rootURL: "https://desk.example.com", want: "", }, { name: "content_id with special characters", msg: cmodels.Message{ Content: ``, Attachments: attachment.Attachments{ {ContentID: "conv_uuid_ii_mnoeigle3", URL: "https://s3.example.com/76584918.png"}, }, }, rootURL: "", want: ``, }, { name: "cid reference that does not match any attachment is left as-is", msg: cmodels.Message{ Content: ``, Attachments: attachment.Attachments{ {ContentID: "known_ref", URL: "https://s3.example.com/known.png"}, }, }, rootURL: "", want: ``, }, { name: "mixed /uploads/ in src and in text content", msg: cmodels.Message{ Content: `
See /uploads/readme.txt for details
`, }, rootURL: "https://desk.example.com", want: `
See /uploads/readme.txt for details
`, }, { name: "multiple /uploads/ references with mixed quotes", msg: cmodels.Message{ Content: ``, }, rootURL: "https://desk.example.com", want: ``, }, { name: "attachment url with ampersands in presigned url", msg: cmodels.Message{ Content: ``, Attachments: attachment.Attachments{ {ContentID: "conv_img1", URL: "https://s3.ap-south-1.amazonaws.com/bucket/uuid?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=300&X-Amz-Signature=abc123"}, }, }, rootURL: "", want: ``, }, { name: "cid is case sensitive", msg: cmodels.Message{ Content: ``, Attachments: attachment.Attachments{ {ContentID: "img1", URL: "https://s3.example.com/img1.png"}, }, }, rootURL: "", want: ``, }, { name: "content with html entities around cid", msg: cmodels.Message{ Content: `image & logo`, Attachments: attachment.Attachments{ {ContentID: "img1", URL: "https://s3.example.com/img1.png"}, }, }, rootURL: "", want: `image & logo`, }, { name: "cid in html comment is still replaced", msg: cmodels.Message{ Content: ``, Attachments: attachment.Attachments{ {ContentID: "img1", URL: "https://s3.example.com/img1.png"}, }, }, rootURL: "", want: ``, }, { name: "nil attachments", msg: cmodels.Message{ Content: ``, Attachments: nil, }, rootURL: "https://desk.example.com", want: ``, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { resolveContentCIDs(&tt.msg, tt.rootURL) if tt.msg.Content != tt.want { t.Errorf("resolveContentCIDs()\n got = %s\n want = %s", tt.msg.Content, tt.want) } }) } }