713 lines
21 KiB
Go
713 lines
21 KiB
Go
package server
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"image/color"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/status-im/status-go/images"
|
|
|
|
"github.com/status-im/status-go/eth-node/crypto"
|
|
|
|
"github.com/status-im/status-go/common/dbsetup"
|
|
"github.com/status-im/status-go/multiaccounts"
|
|
mc "github.com/status-im/status-go/multiaccounts/common"
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
"github.com/stretchr/testify/suite"
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/status-im/status-go/appdatabase"
|
|
"github.com/status-im/status-go/protocol/common"
|
|
"github.com/status-im/status-go/protocol/protobuf"
|
|
"github.com/status-im/status-go/protocol/sqlite"
|
|
"github.com/status-im/status-go/protocol/tt"
|
|
"github.com/status-im/status-go/t/helpers"
|
|
)
|
|
|
|
func TestHandlersSuite(t *testing.T) {
|
|
suite.Run(t, new(HandlersSuite))
|
|
}
|
|
|
|
type HandlersSuite struct {
|
|
suite.Suite
|
|
db *sql.DB
|
|
logger *zap.Logger
|
|
}
|
|
|
|
func (s *HandlersSuite) SetupTest() {
|
|
db, err := helpers.SetupTestMemorySQLDB(appdatabase.DbInitializer{})
|
|
s.Require().NoError(err)
|
|
|
|
err = sqlite.Migrate(db)
|
|
s.Require().NoError(err)
|
|
|
|
s.logger = tt.MustCreateTestLogger()
|
|
s.db = db
|
|
}
|
|
|
|
func (s *HandlersSuite) saveUserMessage(msg *common.Message) {
|
|
whisperTimestamp := 0
|
|
source := ""
|
|
text := ""
|
|
contentType := 0
|
|
timestamp := 0
|
|
chatID := "1"
|
|
localChatID := "1"
|
|
responseTo := ""
|
|
clockValue := 0
|
|
|
|
stmt, err := s.db.Prepare(`
|
|
INSERT INTO user_messages (
|
|
id,
|
|
whisper_timestamp,
|
|
source,
|
|
text,
|
|
content_type,
|
|
timestamp,
|
|
chat_id,
|
|
local_chat_id,
|
|
response_to,
|
|
clock_value,
|
|
unfurled_links,
|
|
unfurled_status_links
|
|
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
|
|
`)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
links := []byte{}
|
|
statusLinks := []byte{}
|
|
|
|
if msg.UnfurledLinks != nil {
|
|
links, err = json.Marshal(msg.UnfurledLinks)
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
if msg.UnfurledStatusLinks != nil {
|
|
statusLinks, err = proto.Marshal(msg.UnfurledStatusLinks)
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
_, err = stmt.Exec(
|
|
msg.ID,
|
|
whisperTimestamp,
|
|
source,
|
|
text,
|
|
contentType,
|
|
timestamp,
|
|
chatID,
|
|
localChatID,
|
|
responseTo,
|
|
clockValue,
|
|
links,
|
|
statusLinks,
|
|
)
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
func (s *HandlersSuite) httpGetReqRecorder(handler http.HandlerFunc, reqURL string) *httptest.ResponseRecorder {
|
|
req, err := http.NewRequest("GET", reqURL, nil)
|
|
s.Require().NoError(err)
|
|
|
|
rr := httptest.NewRecorder()
|
|
handler.ServeHTTP(rr, req)
|
|
|
|
return rr
|
|
}
|
|
|
|
func (s *HandlersSuite) verifyHTTPResponseThumbnail(rr *httptest.ResponseRecorder, expectedPayload []byte) {
|
|
s.Require().Equal(expectedPayload, rr.Body.Bytes())
|
|
s.Require().Equal("image/jpeg", rr.HeaderMap.Get("Content-Type"))
|
|
s.Require().Equal("no-store", rr.HeaderMap.Get("Cache-Control"))
|
|
}
|
|
|
|
func (s *HandlersSuite) TestHandleLinkPreviewThumbnail() {
|
|
previewURL := "https://github.com"
|
|
defaultPayload := []byte{0xff, 0xd8, 0xff, 0xdb, 0x0, 0x84, 0x0, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x50}
|
|
|
|
msg := common.Message{
|
|
ID: "1",
|
|
ChatMessage: &protobuf.ChatMessage{
|
|
UnfurledLinks: []*protobuf.UnfurledLink{
|
|
{
|
|
Type: protobuf.UnfurledLink_LINK,
|
|
Url: previewURL,
|
|
ThumbnailWidth: 100,
|
|
ThumbnailHeight: 200,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
s.saveUserMessage(&msg)
|
|
|
|
testCases := []struct {
|
|
Name string
|
|
ExpectedHTTPStatusCode int
|
|
ThumbnailPayload []byte
|
|
Parameters url.Values
|
|
CheckFunc func(s *HandlersSuite, rr *httptest.ResponseRecorder)
|
|
}{
|
|
{
|
|
Name: "Test happy path",
|
|
ExpectedHTTPStatusCode: http.StatusOK,
|
|
ThumbnailPayload: defaultPayload,
|
|
Parameters: url.Values{
|
|
"message-id": {msg.ID},
|
|
"url": {previewURL},
|
|
},
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.verifyHTTPResponseThumbnail(rr, msg.UnfurledLinks[0].ThumbnailPayload)
|
|
},
|
|
},
|
|
{
|
|
Name: "Test request with missing 'url' parameter",
|
|
ThumbnailPayload: defaultPayload,
|
|
ExpectedHTTPStatusCode: http.StatusBadRequest,
|
|
Parameters: url.Values{
|
|
"message-id": {msg.ID},
|
|
},
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.Require().Equal("missing query parameter 'url'\n", rr.Body.String())
|
|
},
|
|
},
|
|
{
|
|
Name: "Test request with missing 'message-id' parameter",
|
|
ThumbnailPayload: defaultPayload,
|
|
ExpectedHTTPStatusCode: http.StatusBadRequest,
|
|
Parameters: url.Values{
|
|
"url": {previewURL},
|
|
},
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.Require().Equal("missing query parameter 'message-id'\n", rr.Body.String())
|
|
},
|
|
},
|
|
{
|
|
Name: "Test mime type not supported",
|
|
ThumbnailPayload: []byte("unsupported image"),
|
|
ExpectedHTTPStatusCode: http.StatusNotImplemented,
|
|
Parameters: url.Values{
|
|
"message-id": {msg.ID},
|
|
"url": {previewURL},
|
|
},
|
|
},
|
|
}
|
|
|
|
handler := handleLinkPreviewThumbnail(s.db, s.logger)
|
|
|
|
for _, tc := range testCases {
|
|
s.Run(tc.Name, func() {
|
|
msg.UnfurledLinks[0].ThumbnailPayload = tc.ThumbnailPayload
|
|
s.saveUserMessage(&msg)
|
|
|
|
requestURL := "/dummy?" + tc.Parameters.Encode()
|
|
rr := s.httpGetReqRecorder(handler, requestURL)
|
|
s.Require().Equal(tc.ExpectedHTTPStatusCode, rr.Code)
|
|
if tc.CheckFunc != nil {
|
|
tc.CheckFunc(s, rr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (s *HandlersSuite) TestHandleStatusLinkPreviewThumbnail() {
|
|
contact := &protobuf.UnfurledStatusContactLink{
|
|
PublicKey: []byte("PublicKey_1"),
|
|
Icon: &protobuf.UnfurledLinkThumbnail{
|
|
Width: 10,
|
|
Height: 20,
|
|
Payload: []byte{0xff, 0xd8, 0xff, 0xdb, 0x0, 0x84, 0x0, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x50},
|
|
},
|
|
}
|
|
|
|
contactWithUnsupportedImage := &protobuf.UnfurledStatusContactLink{
|
|
PublicKey: []byte("PublicKey_2"),
|
|
Icon: &protobuf.UnfurledLinkThumbnail{
|
|
Width: 10,
|
|
Height: 20,
|
|
Payload: []byte("unsupported image"),
|
|
},
|
|
}
|
|
|
|
community := &protobuf.UnfurledStatusCommunityLink{
|
|
CommunityId: []byte("CommunityId_1"),
|
|
Icon: &protobuf.UnfurledLinkThumbnail{
|
|
Width: 30,
|
|
Height: 40,
|
|
Payload: []byte{0xff, 0xd8, 0xff, 0xdb, 0x0, 0x84, 0x0, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x51},
|
|
},
|
|
Banner: &protobuf.UnfurledLinkThumbnail{
|
|
Width: 50,
|
|
Height: 60,
|
|
Payload: []byte{0xff, 0xd8, 0xff, 0xdb, 0x0, 0x84, 0x0, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x52},
|
|
},
|
|
}
|
|
|
|
channel := &protobuf.UnfurledStatusChannelLink{
|
|
ChannelUuid: "ChannelUuid_1",
|
|
Community: &protobuf.UnfurledStatusCommunityLink{
|
|
CommunityId: []byte("CommunityId_2"),
|
|
Icon: &protobuf.UnfurledLinkThumbnail{
|
|
Width: 70,
|
|
Height: 80,
|
|
Payload: []byte{0xff, 0xd8, 0xff, 0xdb, 0x0, 0x84, 0x0, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x53},
|
|
},
|
|
Banner: &protobuf.UnfurledLinkThumbnail{
|
|
Width: 90,
|
|
Height: 100,
|
|
Payload: []byte{0xff, 0xd8, 0xff, 0xdb, 0x0, 0x84, 0x0, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x54},
|
|
},
|
|
},
|
|
}
|
|
|
|
transaction := &protobuf.UnfurledStatusTransactionLink{
|
|
TxType: 2,
|
|
Asset: "Asset_1",
|
|
Amount: "Amount_1",
|
|
Address: "Address_1",
|
|
ToAsset: "ToAsset_1",
|
|
ChainId: 11,
|
|
}
|
|
|
|
unfurledContact := &protobuf.UnfurledStatusLink{
|
|
Url: "https://status.app/u/",
|
|
Payload: &protobuf.UnfurledStatusLink_Contact{
|
|
Contact: contact,
|
|
},
|
|
}
|
|
|
|
unfurledContactWithUnsupportedImage := &protobuf.UnfurledStatusLink{
|
|
Url: "https://status.app/u/",
|
|
Payload: &protobuf.UnfurledStatusLink_Contact{
|
|
Contact: contactWithUnsupportedImage,
|
|
},
|
|
}
|
|
|
|
unfurledCommunity := &protobuf.UnfurledStatusLink{
|
|
Url: "https://status.app/c/",
|
|
Payload: &protobuf.UnfurledStatusLink_Community{
|
|
Community: community,
|
|
},
|
|
}
|
|
|
|
unfurledChannel := &protobuf.UnfurledStatusLink{
|
|
Url: "https://status.app/cc/",
|
|
Payload: &protobuf.UnfurledStatusLink_Channel{
|
|
Channel: channel,
|
|
},
|
|
}
|
|
|
|
unfurledTransaction := &protobuf.UnfurledStatusLink{
|
|
Url: "https://status.app/tx/",
|
|
Payload: &protobuf.UnfurledStatusLink_Transaction{
|
|
Transaction: transaction,
|
|
},
|
|
}
|
|
|
|
const (
|
|
messageIDContactOnly = "1"
|
|
messageIDCommunityOnly = "2"
|
|
messageIDChannelOnly = "3"
|
|
messageIDAllLinks = "4"
|
|
messageIDUnsupportedImage = "5"
|
|
messageIDTransactionOnly = "6"
|
|
)
|
|
|
|
s.saveUserMessage(&common.Message{
|
|
ID: messageIDContactOnly,
|
|
ChatMessage: &protobuf.ChatMessage{
|
|
UnfurledStatusLinks: &protobuf.UnfurledStatusLinks{
|
|
UnfurledStatusLinks: []*protobuf.UnfurledStatusLink{
|
|
unfurledContact,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
s.saveUserMessage(&common.Message{
|
|
ID: messageIDCommunityOnly,
|
|
ChatMessage: &protobuf.ChatMessage{
|
|
UnfurledStatusLinks: &protobuf.UnfurledStatusLinks{
|
|
UnfurledStatusLinks: []*protobuf.UnfurledStatusLink{
|
|
unfurledCommunity,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
s.saveUserMessage(&common.Message{
|
|
ID: messageIDChannelOnly,
|
|
ChatMessage: &protobuf.ChatMessage{
|
|
UnfurledStatusLinks: &protobuf.UnfurledStatusLinks{
|
|
UnfurledStatusLinks: []*protobuf.UnfurledStatusLink{
|
|
unfurledChannel,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
s.saveUserMessage(&common.Message{
|
|
ID: messageIDAllLinks,
|
|
ChatMessage: &protobuf.ChatMessage{
|
|
UnfurledStatusLinks: &protobuf.UnfurledStatusLinks{
|
|
UnfurledStatusLinks: []*protobuf.UnfurledStatusLink{
|
|
unfurledContact,
|
|
unfurledCommunity,
|
|
unfurledChannel,
|
|
unfurledTransaction,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
s.saveUserMessage(&common.Message{
|
|
ID: messageIDUnsupportedImage,
|
|
ChatMessage: &protobuf.ChatMessage{
|
|
UnfurledStatusLinks: &protobuf.UnfurledStatusLinks{
|
|
UnfurledStatusLinks: []*protobuf.UnfurledStatusLink{
|
|
unfurledContactWithUnsupportedImage,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
s.saveUserMessage(&common.Message{
|
|
ID: messageIDTransactionOnly,
|
|
ChatMessage: &protobuf.ChatMessage{
|
|
UnfurledStatusLinks: &protobuf.UnfurledStatusLinks{
|
|
UnfurledStatusLinks: []*protobuf.UnfurledStatusLink{
|
|
unfurledTransaction,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
testCases := []struct {
|
|
Name string
|
|
ExpectedHTTPStatusCode int
|
|
Parameters url.Values
|
|
CheckFunc func(s *HandlersSuite, rr *httptest.ResponseRecorder)
|
|
}{
|
|
{
|
|
Name: "Test valid contact icon link",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDContactOnly},
|
|
"url": {unfurledContact.Url},
|
|
"image-id": {string(common.MediaServerContactIcon)},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusOK,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.verifyHTTPResponseThumbnail(rr, unfurledContact.GetContact().Icon.Payload)
|
|
},
|
|
},
|
|
{
|
|
Name: "Test invalid request for community icon in a contact link",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDContactOnly},
|
|
"url": {unfurledContact.Url},
|
|
"image-id": {string(common.MediaServerCommunityIcon)},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusBadRequest,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.Require().Equal("invalid query parameter 'image-id' value: this is not a community link\n", rr.Body.String())
|
|
},
|
|
},
|
|
{
|
|
Name: "Test invalid request for cahnnel community banner in a contact link",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDContactOnly},
|
|
"url": {unfurledContact.Url},
|
|
"image-id": {string(common.MediaServerChannelCommunityBanner)},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusBadRequest,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.Require().Equal("invalid query parameter 'image-id' value: this is not a community channel link\n", rr.Body.String())
|
|
},
|
|
},
|
|
{
|
|
Name: "Test invalid request for channel community banner in a contact link",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDContactOnly},
|
|
"url": {unfurledContact.Url},
|
|
"image-id": {"contact-banner"},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusBadRequest,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.Require().Equal("invalid query parameter 'image-id' value: value not supported\n", rr.Body.String())
|
|
},
|
|
},
|
|
{
|
|
Name: "Test valid community icon link",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDCommunityOnly},
|
|
"url": {unfurledCommunity.Url},
|
|
"image-id": {string(common.MediaServerCommunityIcon)},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusOK,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.verifyHTTPResponseThumbnail(rr, unfurledCommunity.GetCommunity().Icon.Payload)
|
|
},
|
|
},
|
|
{
|
|
Name: "Test valid community banner link",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDCommunityOnly},
|
|
"url": {unfurledCommunity.Url},
|
|
"image-id": {string(common.MediaServerCommunityBanner)},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusOK,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.verifyHTTPResponseThumbnail(rr, unfurledCommunity.GetCommunity().Banner.Payload)
|
|
},
|
|
},
|
|
{
|
|
Name: "Test valid channel community icon link",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDChannelOnly},
|
|
"url": {unfurledChannel.Url},
|
|
"image-id": {string(common.MediaServerChannelCommunityIcon)},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusOK,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.verifyHTTPResponseThumbnail(rr, unfurledChannel.GetChannel().GetCommunity().Icon.Payload)
|
|
},
|
|
},
|
|
{
|
|
Name: "Test valid channel community banner link",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDChannelOnly},
|
|
"url": {unfurledChannel.Url},
|
|
"image-id": {string(common.MediaServerChannelCommunityBanner)},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusOK,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.verifyHTTPResponseThumbnail(rr, unfurledChannel.GetChannel().GetCommunity().Banner.Payload)
|
|
},
|
|
},
|
|
{
|
|
Name: "Test valid contact icon link in a diverse message",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDAllLinks},
|
|
"url": {unfurledContact.Url},
|
|
"image-id": {string(common.MediaServerContactIcon)},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusOK,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.verifyHTTPResponseThumbnail(rr, unfurledContact.GetContact().Icon.Payload)
|
|
},
|
|
},
|
|
{
|
|
Name: "Test valid community icon link in a diverse message",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDAllLinks},
|
|
"url": {unfurledCommunity.Url},
|
|
"image-id": {string(common.MediaServerCommunityIcon)},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusOK,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.verifyHTTPResponseThumbnail(rr, unfurledCommunity.GetCommunity().Icon.Payload)
|
|
},
|
|
},
|
|
{
|
|
Name: "Test valid channel community icon link in a diverse message",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDAllLinks},
|
|
"url": {unfurledChannel.Url},
|
|
"image-id": {string(common.MediaServerChannelCommunityIcon)},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusOK,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.verifyHTTPResponseThumbnail(rr, unfurledChannel.GetChannel().GetCommunity().Icon.Payload)
|
|
},
|
|
},
|
|
{
|
|
Name: "Test mime type not supported",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDUnsupportedImage},
|
|
"url": {unfurledContactWithUnsupportedImage.Url},
|
|
"image-id": {string(common.MediaServerContactIcon)},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusNotImplemented,
|
|
},
|
|
{
|
|
Name: "Test request with missing 'message-id' parameter",
|
|
Parameters: url.Values{
|
|
"url": {unfurledCommunity.Url},
|
|
"image-id": {string(common.MediaServerCommunityIcon)},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusBadRequest,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.Require().Equal("missing query parameter 'message-id'\n", rr.Body.String())
|
|
},
|
|
},
|
|
{
|
|
Name: "Test request with missing 'url' parameter",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDCommunityOnly},
|
|
"image-id": {string(common.MediaServerCommunityIcon)},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusBadRequest,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.Require().Equal("missing query parameter 'url'\n", rr.Body.String())
|
|
},
|
|
},
|
|
{
|
|
Name: "Test request with missing 'image-id' parameter",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDCommunityOnly},
|
|
"url": {unfurledCommunity.Url},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusBadRequest,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.Require().Equal("missing query parameter 'image-id'\n", rr.Body.String())
|
|
},
|
|
},
|
|
{
|
|
Name: "Test request with missing 'message-id' parameter",
|
|
Parameters: url.Values{
|
|
"url": {unfurledTransaction.Url},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusBadRequest,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.Require().Equal("missing query parameter 'message-id'\n", rr.Body.String())
|
|
},
|
|
},
|
|
{
|
|
Name: "Test request with missing 'url' parameter",
|
|
Parameters: url.Values{
|
|
"message-id": {messageIDTransactionOnly},
|
|
},
|
|
ExpectedHTTPStatusCode: http.StatusBadRequest,
|
|
CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) {
|
|
s.Require().Equal("missing query parameter 'url'\n", rr.Body.String())
|
|
},
|
|
},
|
|
}
|
|
|
|
handler := handleStatusLinkPreviewThumbnail(s.db, s.logger)
|
|
|
|
for _, tc := range testCases {
|
|
s.Run(tc.Name, func() {
|
|
requestURL := "/dummy?" + tc.Parameters.Encode()
|
|
|
|
rr := s.httpGetReqRecorder(handler, requestURL)
|
|
s.Require().Equal(tc.ExpectedHTTPStatusCode, rr.Code)
|
|
|
|
if tc.CheckFunc != nil {
|
|
tc.CheckFunc(s, rr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (s *HandlersSuite) validateResponse(w *httptest.ResponseRecorder) {
|
|
s.Require().Equal(http.StatusOK, w.Code)
|
|
s.Require().Equal("image/png", w.Header().Get("Content-Type"))
|
|
n, err := w.Result().Body.Read(make([]byte, 100))
|
|
s.Require().NoError(err)
|
|
s.Require().Greater(n, 0)
|
|
}
|
|
|
|
// TestHandleAccountInitialsImpl tests the handleAccountInitialsImpl function
|
|
func (s *HandlersSuite) TestHandleAccountInitialsImpl() {
|
|
// given an account without public key, and request to generate ring with keyUID of the account,
|
|
// it should still response with a valid image without ring rather than response with empty image
|
|
dbFile := filepath.Join(s.T().TempDir(), "accounts-tests-")
|
|
db, err := multiaccounts.InitializeDB(dbFile)
|
|
s.Require().NoError(err)
|
|
defer db.Close()
|
|
keyUID := "0x1"
|
|
name := "Lopsided Goodnatured Bedbug"
|
|
expected := multiaccounts.Account{Name: name, KeyUID: keyUID, CustomizationColor: mc.CustomizationColorBlue, ColorHash: nil, ColorID: 10, KDFIterations: dbsetup.ReducedKDFIterationsNumber, Timestamp: 1712856359}
|
|
s.Require().NoError(db.SaveAccount(expected))
|
|
accounts, err := db.GetAccounts()
|
|
s.Require().NoError(err)
|
|
s.Require().Len(accounts, 1)
|
|
s.Require().Equal(expected, accounts[0])
|
|
|
|
w := httptest.NewRecorder()
|
|
f, err := filepath.Abs("../_assets/tests/UbuntuMono-Regular.ttf")
|
|
s.Require().NoError(err)
|
|
p := ImageParams{
|
|
Ring: true,
|
|
RingWidth: 1,
|
|
KeyUID: keyUID,
|
|
InitialsLength: 2,
|
|
BgColor: color.Transparent,
|
|
Color: color.Transparent,
|
|
FontFile: f,
|
|
BgSize: 1,
|
|
FontSize: 1,
|
|
UppercaseRatio: 1.0,
|
|
}
|
|
handleAccountInitialsImpl(db, s.logger, w, p)
|
|
s.validateResponse(w)
|
|
|
|
// pass a public key to generate ring
|
|
k, err := crypto.GenerateKey()
|
|
s.Require().NoError(err)
|
|
p.PublicKey = common.PubkeyToHex(&k.PublicKey)
|
|
w = httptest.NewRecorder()
|
|
handleAccountInitialsImpl(db, s.logger, w, p)
|
|
s.Require().Equal(http.StatusOK, w.Code)
|
|
}
|
|
|
|
// TestHandleAccountImagesImpl tests the handleAccountImagesImpl function
|
|
func (s *HandlersSuite) TestHandleAccountImagesImpl() {
|
|
// given an account with identity images and without public key, and request to generate ring with keyUID of the account,
|
|
// it should still response with a valid image without ring rather than response with empty image
|
|
dbFile := filepath.Join(s.T().TempDir(), "accounts-tests-")
|
|
db, err := multiaccounts.InitializeDB(dbFile)
|
|
s.Require().NoError(err)
|
|
defer db.Close()
|
|
keyUID := "0x1"
|
|
name := "Lopsided Goodnatured Bedbug"
|
|
expected := multiaccounts.Account{
|
|
Name: name,
|
|
KeyUID: keyUID,
|
|
CustomizationColor: mc.CustomizationColorBlue,
|
|
ColorHash: nil,
|
|
ColorID: 10,
|
|
KDFIterations: dbsetup.ReducedKDFIterationsNumber,
|
|
Timestamp: 1712856359,
|
|
Images: images.SampleIdentityImageForQRCode(),
|
|
}
|
|
s.Require().NoError(db.SaveAccount(expected))
|
|
accounts, err := db.GetAccounts()
|
|
s.Require().NoError(err)
|
|
s.Require().Len(accounts, 1)
|
|
s.Require().Equal(expected, accounts[0])
|
|
|
|
w := httptest.NewRecorder()
|
|
f, err := filepath.Abs("../_assets/tests/UbuntuMono-Regular.ttf")
|
|
s.Require().NoError(err)
|
|
p := ImageParams{
|
|
Ring: true,
|
|
RingWidth: 1,
|
|
KeyUID: keyUID,
|
|
InitialsLength: 2,
|
|
BgColor: color.Transparent,
|
|
Color: color.Transparent,
|
|
FontFile: f,
|
|
BgSize: 1,
|
|
FontSize: 1,
|
|
UppercaseRatio: 1.0,
|
|
ImageName: images.LargeDimName,
|
|
}
|
|
handleAccountImagesImpl(db, s.logger, w, p)
|
|
s.validateResponse(w)
|
|
|
|
// pass a public key to generate ring
|
|
k, err := crypto.GenerateKey()
|
|
s.Require().NoError(err)
|
|
p.PublicKey = common.PubkeyToHex(&k.PublicKey)
|
|
w = httptest.NewRecorder()
|
|
handleAccountImagesImpl(db, s.logger, w, p)
|
|
s.Require().Equal(http.StatusOK, w.Code)
|
|
}
|