github.com/status-im/status-go@v1.1.0/server/handlers_test.go (about) 1 package server 2 3 import ( 4 "database/sql" 5 "encoding/json" 6 "image/color" 7 "net/http" 8 "net/http/httptest" 9 "net/url" 10 "path/filepath" 11 "testing" 12 13 "github.com/status-im/status-go/images" 14 15 "github.com/status-im/status-go/eth-node/crypto" 16 17 "github.com/status-im/status-go/common/dbsetup" 18 "github.com/status-im/status-go/multiaccounts" 19 mc "github.com/status-im/status-go/multiaccounts/common" 20 21 "github.com/golang/protobuf/proto" 22 "github.com/stretchr/testify/suite" 23 "go.uber.org/zap" 24 25 "github.com/status-im/status-go/appdatabase" 26 "github.com/status-im/status-go/protocol/common" 27 "github.com/status-im/status-go/protocol/protobuf" 28 "github.com/status-im/status-go/protocol/sqlite" 29 "github.com/status-im/status-go/protocol/tt" 30 "github.com/status-im/status-go/t/helpers" 31 ) 32 33 func TestHandlersSuite(t *testing.T) { 34 suite.Run(t, new(HandlersSuite)) 35 } 36 37 type HandlersSuite struct { 38 suite.Suite 39 db *sql.DB 40 logger *zap.Logger 41 } 42 43 func (s *HandlersSuite) SetupTest() { 44 db, err := helpers.SetupTestMemorySQLDB(appdatabase.DbInitializer{}) 45 s.Require().NoError(err) 46 47 err = sqlite.Migrate(db) 48 s.Require().NoError(err) 49 50 s.logger = tt.MustCreateTestLogger() 51 s.db = db 52 } 53 54 func (s *HandlersSuite) saveUserMessage(msg *common.Message) { 55 whisperTimestamp := 0 56 source := "" 57 text := "" 58 contentType := 0 59 timestamp := 0 60 chatID := "1" 61 localChatID := "1" 62 responseTo := "" 63 clockValue := 0 64 65 stmt, err := s.db.Prepare(` 66 INSERT INTO user_messages ( 67 id, 68 whisper_timestamp, 69 source, 70 text, 71 content_type, 72 timestamp, 73 chat_id, 74 local_chat_id, 75 response_to, 76 clock_value, 77 unfurled_links, 78 unfurled_status_links 79 ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?) 80 `) 81 82 s.Require().NoError(err) 83 84 links := []byte{} 85 statusLinks := []byte{} 86 87 if msg.UnfurledLinks != nil { 88 links, err = json.Marshal(msg.UnfurledLinks) 89 s.Require().NoError(err) 90 } 91 92 if msg.UnfurledStatusLinks != nil { 93 statusLinks, err = proto.Marshal(msg.UnfurledStatusLinks) 94 s.Require().NoError(err) 95 } 96 97 _, err = stmt.Exec( 98 msg.ID, 99 whisperTimestamp, 100 source, 101 text, 102 contentType, 103 timestamp, 104 chatID, 105 localChatID, 106 responseTo, 107 clockValue, 108 links, 109 statusLinks, 110 ) 111 s.Require().NoError(err) 112 } 113 114 func (s *HandlersSuite) httpGetReqRecorder(handler http.HandlerFunc, reqURL string) *httptest.ResponseRecorder { 115 req, err := http.NewRequest("GET", reqURL, nil) 116 s.Require().NoError(err) 117 118 rr := httptest.NewRecorder() 119 handler.ServeHTTP(rr, req) 120 121 return rr 122 } 123 124 func (s *HandlersSuite) verifyHTTPResponseThumbnail(rr *httptest.ResponseRecorder, expectedPayload []byte) { 125 s.Require().Equal(expectedPayload, rr.Body.Bytes()) 126 s.Require().Equal("image/jpeg", rr.HeaderMap.Get("Content-Type")) 127 s.Require().Equal("no-store", rr.HeaderMap.Get("Cache-Control")) 128 } 129 130 func (s *HandlersSuite) TestHandleLinkPreviewThumbnail() { 131 previewURL := "https://github.com" 132 defaultPayload := []byte{0xff, 0xd8, 0xff, 0xdb, 0x0, 0x84, 0x0, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x50} 133 134 msg := common.Message{ 135 ID: "1", 136 ChatMessage: &protobuf.ChatMessage{ 137 UnfurledLinks: []*protobuf.UnfurledLink{ 138 { 139 Type: protobuf.UnfurledLink_LINK, 140 Url: previewURL, 141 ThumbnailWidth: 100, 142 ThumbnailHeight: 200, 143 }, 144 }, 145 }, 146 } 147 s.saveUserMessage(&msg) 148 149 testCases := []struct { 150 Name string 151 ExpectedHTTPStatusCode int 152 ThumbnailPayload []byte 153 Parameters url.Values 154 CheckFunc func(s *HandlersSuite, rr *httptest.ResponseRecorder) 155 }{ 156 { 157 Name: "Test happy path", 158 ExpectedHTTPStatusCode: http.StatusOK, 159 ThumbnailPayload: defaultPayload, 160 Parameters: url.Values{ 161 "message-id": {msg.ID}, 162 "url": {previewURL}, 163 }, 164 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 165 s.verifyHTTPResponseThumbnail(rr, msg.UnfurledLinks[0].ThumbnailPayload) 166 }, 167 }, 168 { 169 Name: "Test request with missing 'url' parameter", 170 ThumbnailPayload: defaultPayload, 171 ExpectedHTTPStatusCode: http.StatusBadRequest, 172 Parameters: url.Values{ 173 "message-id": {msg.ID}, 174 }, 175 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 176 s.Require().Equal("missing query parameter 'url'\n", rr.Body.String()) 177 }, 178 }, 179 { 180 Name: "Test request with missing 'message-id' parameter", 181 ThumbnailPayload: defaultPayload, 182 ExpectedHTTPStatusCode: http.StatusBadRequest, 183 Parameters: url.Values{ 184 "url": {previewURL}, 185 }, 186 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 187 s.Require().Equal("missing query parameter 'message-id'\n", rr.Body.String()) 188 }, 189 }, 190 { 191 Name: "Test mime type not supported", 192 ThumbnailPayload: []byte("unsupported image"), 193 ExpectedHTTPStatusCode: http.StatusNotImplemented, 194 Parameters: url.Values{ 195 "message-id": {msg.ID}, 196 "url": {previewURL}, 197 }, 198 }, 199 } 200 201 handler := handleLinkPreviewThumbnail(s.db, s.logger) 202 203 for _, tc := range testCases { 204 s.Run(tc.Name, func() { 205 msg.UnfurledLinks[0].ThumbnailPayload = tc.ThumbnailPayload 206 s.saveUserMessage(&msg) 207 208 requestURL := "/dummy?" + tc.Parameters.Encode() 209 rr := s.httpGetReqRecorder(handler, requestURL) 210 s.Require().Equal(tc.ExpectedHTTPStatusCode, rr.Code) 211 if tc.CheckFunc != nil { 212 tc.CheckFunc(s, rr) 213 } 214 }) 215 } 216 } 217 218 func (s *HandlersSuite) TestHandleStatusLinkPreviewThumbnail() { 219 contact := &protobuf.UnfurledStatusContactLink{ 220 PublicKey: []byte("PublicKey_1"), 221 Icon: &protobuf.UnfurledLinkThumbnail{ 222 Width: 10, 223 Height: 20, 224 Payload: []byte{0xff, 0xd8, 0xff, 0xdb, 0x0, 0x84, 0x0, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x50}, 225 }, 226 } 227 228 contactWithUnsupportedImage := &protobuf.UnfurledStatusContactLink{ 229 PublicKey: []byte("PublicKey_2"), 230 Icon: &protobuf.UnfurledLinkThumbnail{ 231 Width: 10, 232 Height: 20, 233 Payload: []byte("unsupported image"), 234 }, 235 } 236 237 community := &protobuf.UnfurledStatusCommunityLink{ 238 CommunityId: []byte("CommunityId_1"), 239 Icon: &protobuf.UnfurledLinkThumbnail{ 240 Width: 30, 241 Height: 40, 242 Payload: []byte{0xff, 0xd8, 0xff, 0xdb, 0x0, 0x84, 0x0, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x51}, 243 }, 244 Banner: &protobuf.UnfurledLinkThumbnail{ 245 Width: 50, 246 Height: 60, 247 Payload: []byte{0xff, 0xd8, 0xff, 0xdb, 0x0, 0x84, 0x0, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x52}, 248 }, 249 } 250 251 channel := &protobuf.UnfurledStatusChannelLink{ 252 ChannelUuid: "ChannelUuid_1", 253 Community: &protobuf.UnfurledStatusCommunityLink{ 254 CommunityId: []byte("CommunityId_2"), 255 Icon: &protobuf.UnfurledLinkThumbnail{ 256 Width: 70, 257 Height: 80, 258 Payload: []byte{0xff, 0xd8, 0xff, 0xdb, 0x0, 0x84, 0x0, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x53}, 259 }, 260 Banner: &protobuf.UnfurledLinkThumbnail{ 261 Width: 90, 262 Height: 100, 263 Payload: []byte{0xff, 0xd8, 0xff, 0xdb, 0x0, 0x84, 0x0, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x54}, 264 }, 265 }, 266 } 267 268 unfurledContact := &protobuf.UnfurledStatusLink{ 269 Url: "https://status.app/u/", 270 Payload: &protobuf.UnfurledStatusLink_Contact{ 271 Contact: contact, 272 }, 273 } 274 275 unfurledContactWithUnsupportedImage := &protobuf.UnfurledStatusLink{ 276 Url: "https://status.app/u/", 277 Payload: &protobuf.UnfurledStatusLink_Contact{ 278 Contact: contactWithUnsupportedImage, 279 }, 280 } 281 282 unfurledCommunity := &protobuf.UnfurledStatusLink{ 283 Url: "https://status.app/c/", 284 Payload: &protobuf.UnfurledStatusLink_Community{ 285 Community: community, 286 }, 287 } 288 289 unfurledChannel := &protobuf.UnfurledStatusLink{ 290 Url: "https://status.app/cc/", 291 Payload: &protobuf.UnfurledStatusLink_Channel{ 292 Channel: channel, 293 }, 294 } 295 296 const ( 297 messageIDContactOnly = "1" 298 messageIDCommunityOnly = "2" 299 messageIDChannelOnly = "3" 300 messageIDAllLinks = "4" 301 messageIDUnsupportedImage = "5" 302 ) 303 304 s.saveUserMessage(&common.Message{ 305 ID: messageIDContactOnly, 306 ChatMessage: &protobuf.ChatMessage{ 307 UnfurledStatusLinks: &protobuf.UnfurledStatusLinks{ 308 UnfurledStatusLinks: []*protobuf.UnfurledStatusLink{ 309 unfurledContact, 310 }, 311 }, 312 }, 313 }) 314 315 s.saveUserMessage(&common.Message{ 316 ID: messageIDCommunityOnly, 317 ChatMessage: &protobuf.ChatMessage{ 318 UnfurledStatusLinks: &protobuf.UnfurledStatusLinks{ 319 UnfurledStatusLinks: []*protobuf.UnfurledStatusLink{ 320 unfurledCommunity, 321 }, 322 }, 323 }, 324 }) 325 326 s.saveUserMessage(&common.Message{ 327 ID: messageIDChannelOnly, 328 ChatMessage: &protobuf.ChatMessage{ 329 UnfurledStatusLinks: &protobuf.UnfurledStatusLinks{ 330 UnfurledStatusLinks: []*protobuf.UnfurledStatusLink{ 331 unfurledChannel, 332 }, 333 }, 334 }, 335 }) 336 337 s.saveUserMessage(&common.Message{ 338 ID: messageIDAllLinks, 339 ChatMessage: &protobuf.ChatMessage{ 340 UnfurledStatusLinks: &protobuf.UnfurledStatusLinks{ 341 UnfurledStatusLinks: []*protobuf.UnfurledStatusLink{ 342 unfurledContact, 343 unfurledCommunity, 344 unfurledChannel, 345 }, 346 }, 347 }, 348 }) 349 350 s.saveUserMessage(&common.Message{ 351 ID: messageIDUnsupportedImage, 352 ChatMessage: &protobuf.ChatMessage{ 353 UnfurledStatusLinks: &protobuf.UnfurledStatusLinks{ 354 UnfurledStatusLinks: []*protobuf.UnfurledStatusLink{ 355 unfurledContactWithUnsupportedImage, 356 }, 357 }, 358 }, 359 }) 360 361 testCases := []struct { 362 Name string 363 ExpectedHTTPStatusCode int 364 Parameters url.Values 365 CheckFunc func(s *HandlersSuite, rr *httptest.ResponseRecorder) 366 }{ 367 { 368 Name: "Test valid contact icon link", 369 Parameters: url.Values{ 370 "message-id": {messageIDContactOnly}, 371 "url": {unfurledContact.Url}, 372 "image-id": {string(common.MediaServerContactIcon)}, 373 }, 374 ExpectedHTTPStatusCode: http.StatusOK, 375 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 376 s.verifyHTTPResponseThumbnail(rr, unfurledContact.GetContact().Icon.Payload) 377 }, 378 }, 379 { 380 Name: "Test invalid request for community icon in a contact link", 381 Parameters: url.Values{ 382 "message-id": {messageIDContactOnly}, 383 "url": {unfurledContact.Url}, 384 "image-id": {string(common.MediaServerCommunityIcon)}, 385 }, 386 ExpectedHTTPStatusCode: http.StatusBadRequest, 387 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 388 s.Require().Equal("invalid query parameter 'image-id' value: this is not a community link\n", rr.Body.String()) 389 }, 390 }, 391 { 392 Name: "Test invalid request for cahnnel community banner in a contact link", 393 Parameters: url.Values{ 394 "message-id": {messageIDContactOnly}, 395 "url": {unfurledContact.Url}, 396 "image-id": {string(common.MediaServerChannelCommunityBanner)}, 397 }, 398 ExpectedHTTPStatusCode: http.StatusBadRequest, 399 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 400 s.Require().Equal("invalid query parameter 'image-id' value: this is not a community channel link\n", rr.Body.String()) 401 }, 402 }, 403 { 404 Name: "Test invalid request for channel community banner in a contact link", 405 Parameters: url.Values{ 406 "message-id": {messageIDContactOnly}, 407 "url": {unfurledContact.Url}, 408 "image-id": {"contact-banner"}, 409 }, 410 ExpectedHTTPStatusCode: http.StatusBadRequest, 411 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 412 s.Require().Equal("invalid query parameter 'image-id' value: value not supported\n", rr.Body.String()) 413 }, 414 }, 415 { 416 Name: "Test valid community icon link", 417 Parameters: url.Values{ 418 "message-id": {messageIDCommunityOnly}, 419 "url": {unfurledCommunity.Url}, 420 "image-id": {string(common.MediaServerCommunityIcon)}, 421 }, 422 ExpectedHTTPStatusCode: http.StatusOK, 423 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 424 s.verifyHTTPResponseThumbnail(rr, unfurledCommunity.GetCommunity().Icon.Payload) 425 }, 426 }, 427 { 428 Name: "Test valid community banner link", 429 Parameters: url.Values{ 430 "message-id": {messageIDCommunityOnly}, 431 "url": {unfurledCommunity.Url}, 432 "image-id": {string(common.MediaServerCommunityBanner)}, 433 }, 434 ExpectedHTTPStatusCode: http.StatusOK, 435 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 436 s.verifyHTTPResponseThumbnail(rr, unfurledCommunity.GetCommunity().Banner.Payload) 437 }, 438 }, 439 { 440 Name: "Test valid channel community icon link", 441 Parameters: url.Values{ 442 "message-id": {messageIDChannelOnly}, 443 "url": {unfurledChannel.Url}, 444 "image-id": {string(common.MediaServerChannelCommunityIcon)}, 445 }, 446 ExpectedHTTPStatusCode: http.StatusOK, 447 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 448 s.verifyHTTPResponseThumbnail(rr, unfurledChannel.GetChannel().GetCommunity().Icon.Payload) 449 }, 450 }, 451 { 452 Name: "Test valid channel community banner link", 453 Parameters: url.Values{ 454 "message-id": {messageIDChannelOnly}, 455 "url": {unfurledChannel.Url}, 456 "image-id": {string(common.MediaServerChannelCommunityBanner)}, 457 }, 458 ExpectedHTTPStatusCode: http.StatusOK, 459 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 460 s.verifyHTTPResponseThumbnail(rr, unfurledChannel.GetChannel().GetCommunity().Banner.Payload) 461 }, 462 }, 463 { 464 Name: "Test valid contact icon link in a diverse message", 465 Parameters: url.Values{ 466 "message-id": {messageIDAllLinks}, 467 "url": {unfurledContact.Url}, 468 "image-id": {string(common.MediaServerContactIcon)}, 469 }, 470 ExpectedHTTPStatusCode: http.StatusOK, 471 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 472 s.verifyHTTPResponseThumbnail(rr, unfurledContact.GetContact().Icon.Payload) 473 }, 474 }, 475 { 476 Name: "Test valid community icon link in a diverse message", 477 Parameters: url.Values{ 478 "message-id": {messageIDAllLinks}, 479 "url": {unfurledCommunity.Url}, 480 "image-id": {string(common.MediaServerCommunityIcon)}, 481 }, 482 ExpectedHTTPStatusCode: http.StatusOK, 483 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 484 s.verifyHTTPResponseThumbnail(rr, unfurledCommunity.GetCommunity().Icon.Payload) 485 }, 486 }, 487 { 488 Name: "Test valid channel community icon link in a diverse message", 489 Parameters: url.Values{ 490 "message-id": {messageIDAllLinks}, 491 "url": {unfurledChannel.Url}, 492 "image-id": {string(common.MediaServerChannelCommunityIcon)}, 493 }, 494 ExpectedHTTPStatusCode: http.StatusOK, 495 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 496 s.verifyHTTPResponseThumbnail(rr, unfurledChannel.GetChannel().GetCommunity().Icon.Payload) 497 }, 498 }, 499 { 500 Name: "Test mime type not supported", 501 Parameters: url.Values{ 502 "message-id": {messageIDUnsupportedImage}, 503 "url": {unfurledContactWithUnsupportedImage.Url}, 504 "image-id": {string(common.MediaServerContactIcon)}, 505 }, 506 ExpectedHTTPStatusCode: http.StatusNotImplemented, 507 }, 508 { 509 Name: "Test request with missing 'message-id' parameter", 510 Parameters: url.Values{ 511 "url": {unfurledCommunity.Url}, 512 "image-id": {string(common.MediaServerCommunityIcon)}, 513 }, 514 ExpectedHTTPStatusCode: http.StatusBadRequest, 515 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 516 s.Require().Equal("missing query parameter 'message-id'\n", rr.Body.String()) 517 }, 518 }, 519 { 520 Name: "Test request with missing 'url' parameter", 521 Parameters: url.Values{ 522 "message-id": {messageIDCommunityOnly}, 523 "image-id": {string(common.MediaServerCommunityIcon)}, 524 }, 525 ExpectedHTTPStatusCode: http.StatusBadRequest, 526 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 527 s.Require().Equal("missing query parameter 'url'\n", rr.Body.String()) 528 }, 529 }, 530 { 531 Name: "Test request with missing 'image-id' parameter", 532 Parameters: url.Values{ 533 "message-id": {messageIDCommunityOnly}, 534 "url": {unfurledCommunity.Url}, 535 }, 536 ExpectedHTTPStatusCode: http.StatusBadRequest, 537 CheckFunc: func(s *HandlersSuite, rr *httptest.ResponseRecorder) { 538 s.Require().Equal("missing query parameter 'image-id'\n", rr.Body.String()) 539 }, 540 }, 541 } 542 543 handler := handleStatusLinkPreviewThumbnail(s.db, s.logger) 544 545 for _, tc := range testCases { 546 s.Run(tc.Name, func() { 547 requestURL := "/dummy?" + tc.Parameters.Encode() 548 549 rr := s.httpGetReqRecorder(handler, requestURL) 550 s.Require().Equal(tc.ExpectedHTTPStatusCode, rr.Code) 551 552 if tc.CheckFunc != nil { 553 tc.CheckFunc(s, rr) 554 } 555 }) 556 } 557 } 558 559 func (s *HandlersSuite) validateResponse(w *httptest.ResponseRecorder) { 560 s.Require().Equal(http.StatusOK, w.Code) 561 s.Require().Equal("image/png", w.Header().Get("Content-Type")) 562 n, err := w.Result().Body.Read(make([]byte, 100)) 563 s.Require().NoError(err) 564 s.Require().Greater(n, 0) 565 } 566 567 // TestHandleAccountInitialsImpl tests the handleAccountInitialsImpl function 568 func (s *HandlersSuite) TestHandleAccountInitialsImpl() { 569 // given an account without public key, and request to generate ring with keyUID of the account, 570 // it should still response with a valid image without ring rather than response with empty image 571 dbFile := filepath.Join(s.T().TempDir(), "accounts-tests-") 572 db, err := multiaccounts.InitializeDB(dbFile) 573 s.Require().NoError(err) 574 defer db.Close() 575 keyUID := "0x1" 576 name := "Lopsided Goodnatured Bedbug" 577 expected := multiaccounts.Account{Name: name, KeyUID: keyUID, CustomizationColor: mc.CustomizationColorBlue, ColorHash: nil, ColorID: 10, KDFIterations: dbsetup.ReducedKDFIterationsNumber, Timestamp: 1712856359} 578 s.Require().NoError(db.SaveAccount(expected)) 579 accounts, err := db.GetAccounts() 580 s.Require().NoError(err) 581 s.Require().Len(accounts, 1) 582 s.Require().Equal(expected, accounts[0]) 583 584 w := httptest.NewRecorder() 585 f, err := filepath.Abs("../_assets/tests/UbuntuMono-Regular.ttf") 586 s.Require().NoError(err) 587 p := ImageParams{ 588 Ring: true, 589 RingWidth: 1, 590 KeyUID: keyUID, 591 InitialsLength: 2, 592 BgColor: color.Transparent, 593 Color: color.Transparent, 594 FontFile: f, 595 BgSize: 1, 596 FontSize: 1, 597 UppercaseRatio: 1.0, 598 } 599 handleAccountInitialsImpl(db, s.logger, w, p) 600 s.validateResponse(w) 601 602 // pass a public key to generate ring 603 k, err := crypto.GenerateKey() 604 s.Require().NoError(err) 605 p.PublicKey = common.PubkeyToHex(&k.PublicKey) 606 w = httptest.NewRecorder() 607 handleAccountInitialsImpl(db, s.logger, w, p) 608 s.Require().Equal(http.StatusOK, w.Code) 609 } 610 611 // TestHandleAccountImagesImpl tests the handleAccountImagesImpl function 612 func (s *HandlersSuite) TestHandleAccountImagesImpl() { 613 // given an account with identity images and without public key, and request to generate ring with keyUID of the account, 614 // it should still response with a valid image without ring rather than response with empty image 615 dbFile := filepath.Join(s.T().TempDir(), "accounts-tests-") 616 db, err := multiaccounts.InitializeDB(dbFile) 617 s.Require().NoError(err) 618 defer db.Close() 619 keyUID := "0x1" 620 name := "Lopsided Goodnatured Bedbug" 621 expected := multiaccounts.Account{ 622 Name: name, 623 KeyUID: keyUID, 624 CustomizationColor: mc.CustomizationColorBlue, 625 ColorHash: nil, 626 ColorID: 10, 627 KDFIterations: dbsetup.ReducedKDFIterationsNumber, 628 Timestamp: 1712856359, 629 Images: images.SampleIdentityImageForQRCode(), 630 } 631 s.Require().NoError(db.SaveAccount(expected)) 632 accounts, err := db.GetAccounts() 633 s.Require().NoError(err) 634 s.Require().Len(accounts, 1) 635 s.Require().Equal(expected, accounts[0]) 636 637 w := httptest.NewRecorder() 638 f, err := filepath.Abs("../_assets/tests/UbuntuMono-Regular.ttf") 639 s.Require().NoError(err) 640 p := ImageParams{ 641 Ring: true, 642 RingWidth: 1, 643 KeyUID: keyUID, 644 InitialsLength: 2, 645 BgColor: color.Transparent, 646 Color: color.Transparent, 647 FontFile: f, 648 BgSize: 1, 649 FontSize: 1, 650 UppercaseRatio: 1.0, 651 ImageName: images.LargeDimName, 652 } 653 handleAccountImagesImpl(db, s.logger, w, p) 654 s.validateResponse(w) 655 656 // pass a public key to generate ring 657 k, err := crypto.GenerateKey() 658 s.Require().NoError(err) 659 p.PublicKey = common.PubkeyToHex(&k.PublicKey) 660 w = httptest.NewRecorder() 661 handleAccountImagesImpl(db, s.logger, w, p) 662 s.Require().Equal(http.StatusOK, w.Code) 663 }