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: `
`,
Attachments: attachment.Attachments{
{ContentID: "conv_abc123", URL: "https://s3.example.com/photo.png?sig=xxx"},
},
},
rootURL: "",
want: ``,
},
{
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.
` +
`

` +
`

` +
`
`,
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.
` +
`

` +
`

` +
`
`,
},
{
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: `
`,
Attachments: attachment.Attachments{
{ContentID: "img1", URL: "https://s3.example.com/img1.png"},
},
},
rootURL: "",
want: `
`,
},
{
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)
}
})
}
}