github.com/line/line-bot-sdk-go/v7@v7.21.0/linebot/flex_test.go (about) 1 // Copyright 2018 LINE Corporation 2 // 3 // LINE Corporation licenses this file to you under the Apache License, 4 // version 2.0 (the "License"); you may not use this file except in compliance 5 // with the License. You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 package linebot 16 17 import ( 18 "encoding/json" 19 "reflect" 20 "strconv" 21 "testing" 22 ) 23 24 func TestUnmarshalFlexMessageJSON(t *testing.T) { 25 testCases := []struct { 26 JSON []byte 27 Want FlexContainer 28 }{ 29 { 30 JSON: []byte(`{ 31 "type": "bubble", 32 "body": { 33 "type": "box", 34 "layout": "vertical", 35 "borderColor": "#000000", 36 "borderWidth": "2px", 37 "cornerRadius": "20px", 38 "contents": [ 39 { 40 "type": "text", 41 "text": "hello", 42 "lineSpacing": "20px" 43 } 44 ] 45 } 46 }`), 47 Want: &BubbleContainer{ 48 Type: FlexContainerTypeBubble, 49 Body: &BoxComponent{ 50 Type: FlexComponentTypeBox, 51 Layout: FlexBoxLayoutTypeVertical, 52 BorderColor: "#000000", 53 BorderWidth: "2px", 54 CornerRadius: "20px", 55 Contents: []FlexComponent{ 56 &TextComponent{ 57 Type: FlexComponentTypeText, 58 Text: "hello", 59 LineSpacing: "20px", 60 }, 61 }, 62 }, 63 }, 64 }, 65 { 66 JSON: []byte(`{ 67 "type": "bubble", 68 "body": { 69 "type": "box", 70 "layout": "vertical", 71 "contents": [ 72 { 73 "type": "text", 74 "text": "hello" 75 }, 76 { 77 "type": "text", 78 "text": "world" 79 } 80 ] 81 } 82 }`), 83 Want: &BubbleContainer{ 84 Type: FlexContainerTypeBubble, 85 Body: &BoxComponent{ 86 Type: FlexComponentTypeBox, 87 Layout: FlexBoxLayoutTypeVertical, 88 Contents: []FlexComponent{ 89 &TextComponent{ 90 Type: FlexComponentTypeText, 91 Text: "hello", 92 }, 93 &TextComponent{ 94 Type: FlexComponentTypeText, 95 Text: "world", 96 }, 97 }, 98 }, 99 }, 100 }, 101 { 102 JSON: []byte(`{ 103 "type": "carousel", 104 "contents": [ 105 { 106 "type": "bubble", 107 "body": { 108 "type": "box", 109 "layout": "vertical", 110 "contents": [ 111 { 112 "type": "text", 113 "text": "First bubble" 114 } 115 ] 116 } 117 }, 118 { 119 "type": "bubble", 120 "body": { 121 "type": "box", 122 "layout": "vertical", 123 "contents": [ 124 { 125 "type": "text", 126 "text": "Second bubble" 127 } 128 ], 129 "action": { 130 "type": "message", 131 "text": "Second bubble" 132 } 133 } 134 } 135 ] 136 }`), 137 Want: &CarouselContainer{ 138 Type: FlexContainerTypeCarousel, 139 Contents: []*BubbleContainer{ 140 { 141 Type: FlexContainerTypeBubble, 142 Body: &BoxComponent{ 143 Type: FlexComponentTypeBox, 144 Layout: FlexBoxLayoutTypeVertical, 145 Contents: []FlexComponent{ 146 &TextComponent{ 147 Type: FlexComponentTypeText, 148 Text: "First bubble", 149 }, 150 }, 151 }, 152 }, 153 { 154 Type: FlexContainerTypeBubble, 155 Body: &BoxComponent{ 156 Type: FlexComponentTypeBox, 157 Layout: FlexBoxLayoutTypeVertical, 158 Contents: []FlexComponent{ 159 &TextComponent{ 160 Type: FlexComponentTypeText, 161 Text: "Second bubble", 162 }, 163 }, 164 Action: &MessageAction{Text: "Second bubble"}, 165 }, 166 }, 167 }, 168 }, 169 }, 170 { 171 JSON: []byte(`{ 172 "type": "bubble", 173 "size": "nano", 174 "body": { 175 "type": "box", 176 "layout": "vertical", 177 "contents": [ 178 { 179 "type": "text", 180 "text": "hello" 181 }, 182 { 183 "type": "text", 184 "text": "world" 185 } 186 ] 187 } 188 }`), 189 Want: &BubbleContainer{ 190 Type: FlexContainerTypeBubble, 191 Size: FlexBubbleSizeTypeNano, 192 Body: &BoxComponent{ 193 Type: FlexComponentTypeBox, 194 Layout: FlexBoxLayoutTypeVertical, 195 Contents: []FlexComponent{ 196 &TextComponent{ 197 Type: FlexComponentTypeText, 198 Text: "hello", 199 }, 200 &TextComponent{ 201 Type: FlexComponentTypeText, 202 Text: "world", 203 }, 204 }, 205 }, 206 }, 207 }, 208 { 209 JSON: []byte(`{ 210 "type": "bubble", 211 "hero": { 212 "type": "image", 213 "url": "https://scdn.line-apps.com/n/channel_devcenter/img/fx/01_1_cafe.png", 214 "position": "absolute", 215 "size": "full", 216 "aspectRatio": "20:13", 217 "aspectMode": "cover", 218 "action": { 219 "type": "uri", 220 "uri": "https://linecorp.com/" 221 }, 222 "animated": true, 223 "offsetTop": "xs", 224 "offsetBottom": "sm", 225 "offsetStart": "md", 226 "offsetEnd": "lg" 227 }, 228 "body": { 229 "type": "box", 230 "layout": "vertical", 231 "contents": [ 232 { 233 "type": "text", 234 "text": "Brown Cafe", 235 "weight": "bold", 236 "size": "xl" 237 }, 238 { 239 "type": "box", 240 "layout": "baseline", 241 "margin": "md", 242 "contents": [ 243 { 244 "type": "icon", 245 "size": "sm", 246 "url": "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png" 247 }, 248 { 249 "type": "icon", 250 "size": "sm", 251 "url": "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png" 252 }, 253 { 254 "type": "icon", 255 "size": "sm", 256 "url": "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png" 257 }, 258 { 259 "type": "icon", 260 "size": "sm", 261 "url": "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png" 262 }, 263 { 264 "type": "icon", 265 "size": "sm", 266 "url": "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gray_star_28.png" 267 }, 268 { 269 "type": "text", 270 "text": "4.0", 271 "size": "sm", 272 "color": "#999999", 273 "margin": "md", 274 "flex": 0 275 } 276 ] 277 }, 278 { 279 "type": "box", 280 "layout": "vertical", 281 "margin": "lg", 282 "spacing": "sm", 283 "contents": [ 284 { 285 "type": "box", 286 "layout": "baseline", 287 "spacing": "sm", 288 "contents": [ 289 { 290 "type": "text", 291 "text": "Place", 292 "color": "#aaaaaa", 293 "size": "sm", 294 "flex": 1, 295 "maxLines": 0 296 }, 297 { 298 "type": "text", 299 "text": "Miraina Tower, 4-1-6 Shinjuku, Tokyo", 300 "wrap": true, 301 "color": "#666666", 302 "size": "sm", 303 "flex": 5, 304 "maxLines": 1 305 } 306 ] 307 }, 308 { 309 "type": "box", 310 "layout": "baseline", 311 "spacing": "sm", 312 "contents": [ 313 { 314 "type": "text", 315 "text": "Time", 316 "color": "#aaaaaa", 317 "size": "sm", 318 "flex": 1 319 }, 320 { 321 "type": "text", 322 "text": "10:00 - 23:00", 323 "position": "absolute", 324 "wrap": true, 325 "color": "#666666", 326 "size": "sm", 327 "flex": 5, 328 "offsetTop": "xs", 329 "offsetBottom": "sm", 330 "offsetStart": "md", 331 "offsetEnd": "lg" 332 } 333 ] 334 } 335 ] 336 } 337 ] 338 }, 339 "footer": { 340 "type": "box", 341 "layout": "vertical", 342 "position": "absolute", 343 "spacing": "sm", 344 "contents": [ 345 { 346 "type": "button", 347 "style": "link", 348 "height": "sm", 349 "action": { 350 "type": "uri", 351 "label": "CALL", 352 "uri": "https://linecorp.com" 353 }, 354 "position": "absolute", 355 "offsetTop": "xs", 356 "offsetBottom": "sm", 357 "offsetStart": "md", 358 "offsetEnd": "lg" 359 }, 360 { 361 "type": "button", 362 "style": "link", 363 "height": "sm", 364 "action": { 365 "type": "uri", 366 "label": "WEBSITE", 367 "uri": "https://linecorp.com", 368 "altUri": { 369 "desktop": "https://line.me/ja/download" 370 } 371 }, 372 "adjustMode": "shrink-to-fit" 373 }, 374 { 375 "type": "spacer", 376 "size": "sm" 377 }, 378 { 379 "type": "spacer" 380 }, 381 { 382 "type": "spacer", 383 "size": "xs" 384 } 385 ], 386 "flex": 0, 387 "offsetTop": "xs", 388 "offsetBottom": "sm", 389 "offsetStart": "md", 390 "offsetEnd": "lg" 391 } 392 }`), 393 Want: &BubbleContainer{ 394 Type: FlexContainerTypeBubble, 395 Hero: &ImageComponent{ 396 Type: FlexComponentTypeImage, 397 URL: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/01_1_cafe.png", 398 Position: FlexComponentPositionTypeAbsolute, 399 Size: FlexImageSizeTypeFull, 400 AspectRatio: FlexImageAspectRatioType20to13, 401 AspectMode: FlexImageAspectModeTypeCover, 402 Action: &URIAction{URI: "https://linecorp.com/"}, 403 Animated: true, 404 OffsetTop: FlexComponentOffsetTypeXs, 405 OffsetBottom: FlexComponentOffsetTypeSm, 406 OffsetStart: FlexComponentOffsetTypeMd, 407 OffsetEnd: FlexComponentOffsetTypeLg, 408 }, 409 Body: &BoxComponent{ 410 Type: FlexComponentTypeBox, 411 Layout: FlexBoxLayoutTypeVertical, 412 Contents: []FlexComponent{ 413 &TextComponent{ 414 Type: FlexComponentTypeText, 415 Text: "Brown Cafe", 416 Size: FlexTextSizeTypeXl, 417 Weight: FlexTextWeightTypeBold, 418 }, 419 &BoxComponent{ 420 Type: FlexComponentTypeBox, 421 Layout: FlexBoxLayoutTypeBaseline, 422 Contents: []FlexComponent{ 423 &IconComponent{ 424 Type: FlexComponentTypeIcon, 425 URL: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png", 426 Size: FlexIconSizeTypeSm, 427 }, 428 &IconComponent{ 429 Type: FlexComponentTypeIcon, 430 URL: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png", 431 Size: FlexIconSizeTypeSm, 432 }, 433 &IconComponent{ 434 Type: FlexComponentTypeIcon, 435 URL: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png", 436 Size: FlexIconSizeTypeSm, 437 }, 438 &IconComponent{ 439 Type: FlexComponentTypeIcon, 440 URL: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png", 441 Size: FlexIconSizeTypeSm, 442 }, 443 &IconComponent{ 444 Type: FlexComponentTypeIcon, 445 URL: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gray_star_28.png", 446 Size: FlexIconSizeTypeSm, 447 }, 448 &TextComponent{ 449 Type: FlexComponentTypeText, 450 Text: "4.0", 451 Flex: IntPtr(0), 452 Margin: FlexComponentMarginTypeMd, 453 Size: FlexTextSizeTypeSm, 454 Color: "#999999", 455 }, 456 }, 457 Margin: FlexComponentMarginTypeMd, 458 }, 459 &BoxComponent{ 460 Type: FlexComponentTypeBox, 461 Layout: FlexBoxLayoutTypeVertical, 462 Contents: []FlexComponent{ 463 &BoxComponent{ 464 Type: FlexComponentTypeBox, 465 Layout: FlexBoxLayoutTypeBaseline, 466 Contents: []FlexComponent{ 467 &TextComponent{ 468 Type: FlexComponentTypeText, 469 Text: "Place", 470 Flex: IntPtr(1), 471 Size: FlexTextSizeTypeSm, 472 Color: "#aaaaaa", 473 MaxLines: IntPtr(0), 474 }, 475 &TextComponent{ 476 Type: FlexComponentTypeText, 477 Text: "Miraina Tower, 4-1-6 Shinjuku, Tokyo", 478 Flex: IntPtr(5), 479 Size: FlexTextSizeTypeSm, 480 Wrap: true, 481 Color: "#666666", 482 MaxLines: IntPtr(1), 483 }, 484 }, 485 Spacing: FlexComponentSpacingTypeSm, 486 }, 487 &BoxComponent{ 488 Type: FlexComponentTypeBox, 489 Layout: FlexBoxLayoutTypeBaseline, 490 Contents: []FlexComponent{ 491 &TextComponent{ 492 Type: FlexComponentTypeText, 493 Text: "Time", 494 Flex: IntPtr(1), 495 Size: FlexTextSizeTypeSm, 496 Color: "#aaaaaa", 497 }, 498 &TextComponent{ 499 Type: FlexComponentTypeText, 500 Text: "10:00 - 23:00", 501 Position: FlexComponentPositionTypeAbsolute, 502 Flex: IntPtr(5), 503 Size: FlexTextSizeTypeSm, 504 Wrap: true, 505 Color: "#666666", 506 OffsetTop: FlexComponentOffsetTypeXs, 507 OffsetBottom: FlexComponentOffsetTypeSm, 508 OffsetStart: FlexComponentOffsetTypeMd, 509 OffsetEnd: FlexComponentOffsetTypeLg, 510 }, 511 }, 512 Spacing: FlexComponentSpacingTypeSm, 513 }, 514 }, 515 Spacing: FlexComponentSpacingTypeSm, 516 Margin: FlexComponentMarginTypeLg, 517 }, 518 }, 519 }, 520 Footer: &BoxComponent{ 521 Type: FlexComponentTypeBox, 522 Layout: FlexBoxLayoutTypeVertical, 523 Position: FlexComponentPositionTypeAbsolute, 524 Contents: []FlexComponent{ 525 &ButtonComponent{ 526 Type: FlexComponentTypeButton, 527 Action: &URIAction{ 528 Label: "CALL", 529 URI: "https://linecorp.com", 530 }, 531 Position: FlexComponentPositionTypeAbsolute, 532 Height: FlexButtonHeightTypeSm, 533 Style: FlexButtonStyleTypeLink, 534 OffsetTop: FlexComponentOffsetTypeXs, 535 OffsetBottom: FlexComponentOffsetTypeSm, 536 OffsetStart: FlexComponentOffsetTypeMd, 537 OffsetEnd: FlexComponentOffsetTypeLg, 538 }, 539 &ButtonComponent{ 540 Type: FlexComponentTypeButton, 541 Action: &URIAction{ 542 Label: "WEBSITE", 543 URI: "https://linecorp.com", 544 AltURI: &URIActionAltURI{ 545 Desktop: "https://line.me/ja/download", 546 }, 547 }, 548 Height: FlexButtonHeightTypeSm, 549 Style: FlexButtonStyleTypeLink, 550 AdjustMode: FlexComponentAdjustModeTypeShrinkToFit, 551 }, 552 &SpacerComponent{ 553 Type: FlexComponentTypeSpacer, 554 Size: FlexSpacerSizeTypeSm, 555 }, 556 &SpacerComponent{ 557 Type: FlexComponentTypeSpacer, 558 }, 559 &SpacerComponent{ 560 Type: FlexComponentTypeSpacer, 561 Size: FlexSpacerSizeTypeXs, 562 }, 563 }, 564 Spacing: FlexComponentSpacingTypeSm, 565 Flex: IntPtr(0), 566 OffsetTop: FlexComponentOffsetTypeXs, 567 OffsetBottom: FlexComponentOffsetTypeSm, 568 OffsetStart: FlexComponentOffsetTypeMd, 569 OffsetEnd: FlexComponentOffsetTypeLg, 570 }, 571 }, 572 }, 573 { 574 JSON: []byte(`{ 575 "type": "bubble", 576 "body": { 577 "type": "box", 578 "layout": "horizontal", 579 "contents": [ 580 { 581 "type": "text", 582 "text": "hello", 583 "flex": 0 584 }, 585 { 586 "type": "filler", 587 "flex": 4 588 }, 589 { 590 "type": "text", 591 "text": "world", 592 "flex": 2 593 }, 594 { 595 "type": "text", 596 "contents": [ 597 { 598 "type": "span", 599 "text": "hi" 600 }, 601 { 602 "type": "span", 603 "text": "span", 604 "size": "xl", 605 "color": "#29cf5b" 606 } 607 ] 608 } 609 ] 610 } 611 }`), 612 Want: &BubbleContainer{ 613 Type: FlexContainerTypeBubble, 614 Body: &BoxComponent{ 615 Type: FlexComponentTypeBox, 616 Layout: FlexBoxLayoutTypeHorizontal, 617 Contents: []FlexComponent{ 618 &TextComponent{ 619 Type: FlexComponentTypeText, 620 Text: "hello", 621 Flex: IntPtr(0), 622 }, 623 &FillerComponent{ 624 Type: FlexComponentTypeFiller, 625 Flex: IntPtr(4), 626 }, 627 &TextComponent{ 628 Type: FlexComponentTypeText, 629 Text: "world", 630 Flex: IntPtr(2), 631 }, 632 &TextComponent{ 633 Type: FlexComponentTypeText, 634 Contents: []*SpanComponent{ 635 { 636 Type: FlexComponentTypeSpan, 637 Text: "hi", 638 }, 639 { 640 Type: FlexComponentTypeSpan, 641 Text: "span", 642 Size: FlexTextSizeTypeXl, 643 Color: "#29cf5b", 644 }, 645 }, 646 }, 647 }, 648 }, 649 }, 650 }, 651 { 652 JSON: []byte(`{ 653 "type": "bubble", 654 "size": "nano", 655 "hero": { 656 "type": "box", 657 "layout": "vertical", 658 "contents": [ 659 { 660 "type": "text", 661 "text": "hello" 662 }, 663 { 664 "type": "text", 665 "text": "world" 666 } 667 ] 668 } 669 }`), 670 Want: &BubbleContainer{ 671 Type: FlexContainerTypeBubble, 672 Size: FlexBubbleSizeTypeNano, 673 Hero: &BoxComponent{ 674 Type: FlexComponentTypeBox, 675 Layout: FlexBoxLayoutTypeVertical, 676 Contents: []FlexComponent{ 677 &TextComponent{ 678 Type: FlexComponentTypeText, 679 Text: "hello", 680 }, 681 &TextComponent{ 682 Type: FlexComponentTypeText, 683 Text: "world", 684 }, 685 }, 686 }, 687 }, 688 }, 689 { 690 JSON: []byte(`{ 691 "type": "bubble", 692 "body": { 693 "type": "box", 694 "layout": "vertical", 695 "contents": [ 696 { 697 "type": "image", 698 "url": "https://example.com/flex/images/image.jpg", 699 "animated": true 700 }, 701 { 702 "type": "separator" 703 }, 704 { 705 "type": "text", 706 "text": "Text in the box", 707 "adjustMode": "shrink-to-fit" 708 }, 709 { 710 "type": "box", 711 "layout": "vertical", 712 "contents": [], 713 "width": "30px", 714 "maxWidth": "30px", 715 "height": "30px", 716 "maxHeight": "30px", 717 "background": { 718 "type": "linearGradient", 719 "angle": "0deg", 720 "startColor": "#ff0000", 721 "centerColor": "#0000ff", 722 "endColor": "#00ff00", 723 "centerPosition": "10%" 724 } 725 } 726 ], 727 "height": "400px", 728 "justifyContent": "space-evenly", 729 "alignItems": "center" 730 } 731 }`), 732 Want: &BubbleContainer{ 733 Type: FlexContainerTypeBubble, 734 Body: &BoxComponent{ 735 Type: FlexComponentTypeBox, 736 Layout: FlexBoxLayoutTypeVertical, 737 Contents: []FlexComponent{ 738 &ImageComponent{ 739 Type: FlexComponentTypeImage, 740 URL: "https://example.com/flex/images/image.jpg", 741 Animated: true, 742 }, 743 &SeparatorComponent{ 744 Type: FlexComponentTypeSeparator, 745 }, 746 &TextComponent{ 747 Type: FlexComponentTypeText, 748 Text: "Text in the box", 749 AdjustMode: FlexComponentAdjustModeTypeShrinkToFit, 750 }, 751 &BoxComponent{ 752 Type: FlexComponentTypeBox, 753 Layout: FlexBoxLayoutTypeVertical, 754 Contents: []FlexComponent{}, 755 Width: "30px", 756 MaxWidth: "30px", 757 Height: "30px", 758 MaxHeight: "30px", 759 Background: &BoxBackground{ 760 Type: FlexBoxBackgroundTypeLinearGradient, 761 Angle: "0deg", 762 StartColor: "#ff0000", 763 EndColor: "#00ff00", 764 CenterColor: "#0000ff", 765 CenterPosition: "10%", 766 }, 767 }, 768 }, 769 Height: "400px", 770 JustifyContent: FlexComponentJustifyContentTypeSpaceEvenly, 771 AlignItems: FlexComponentAlignItemsTypeCenter, 772 }, 773 }, 774 }, 775 { 776 JSON: []byte(`{ 777 "type": "bubble", 778 "hero": { 779 "type": "video", 780 "url": "https://example.com/video.mp4", 781 "previewUrl": "https://example.com/video_preview.png", 782 "altContent": { 783 "type": "image", 784 "size": "full", 785 "aspectRatio": "20:13", 786 "aspectMode": "cover", 787 "url": "https://example.com/image.png" 788 }, 789 "action": { 790 "type": "uri", 791 "label": "More information", 792 "uri": "http://linecorp.com/" 793 }, 794 "aspectRatio": "20:13" 795 } 796 }`), 797 Want: &BubbleContainer{ 798 Type: FlexContainerTypeBubble, 799 Hero: &VideoComponent{ 800 Type: FlexComponentTypeVideo, 801 URL: "https://example.com/video.mp4", 802 PreviewURL: "https://example.com/video_preview.png", 803 AltContent: &ImageComponent{ 804 Type: FlexComponentTypeImage, 805 URL: "https://example.com/image.png", 806 Size: FlexImageSizeTypeFull, 807 AspectRatio: FlexImageAspectRatioType20to13, 808 AspectMode: FlexImageAspectModeTypeCover, 809 }, 810 Action: &URIAction{ 811 Label: "More information", 812 URI: "http://linecorp.com/", 813 }, 814 AspectRatio: FlexVideoAspectRatioType20to13, 815 }, 816 }, 817 }, 818 } 819 for i, tc := range testCases { 820 t.Run(strconv.Itoa(i), func(t *testing.T) { 821 container, err := UnmarshalFlexMessageJSON(tc.JSON) 822 if err != nil { 823 t.Fatal(err) 824 } 825 if !reflect.DeepEqual(container, tc.Want) { 826 t.Errorf("Container %v, want %v", container, tc.Want) 827 } 828 }) 829 } 830 } 831 832 func TestMarshalJSON(t *testing.T) { 833 testCases := []struct { 834 component FlexComponent 835 want []byte 836 }{ 837 { 838 &FillerComponent{ 839 Type: FlexComponentTypeFiller, 840 Flex: nil, 841 }, 842 []byte(`{"type":"filler"}`), 843 }, 844 { 845 &FillerComponent{ 846 Type: FlexComponentTypeFiller, 847 Flex: IntPtr(4), 848 }, 849 []byte(`{"type":"filler","flex":4}`), 850 }, 851 { 852 &SpanComponent{ 853 Type: FlexComponentTypeSpan, 854 Text: "span", 855 Size: FlexTextSizeTypeMd, 856 Weight: FlexTextWeightTypeRegular, 857 Color: "#0000ff", 858 Style: FlexTextStyleTypeNormal, 859 Decoration: FlexTextDecorationTypeNone, 860 }, 861 []byte(`{"type":"span","text":"span","size":"md","weight":"regular","color":"#0000ff","style":"normal","decoration":"none"}`), 862 }, 863 } 864 865 for i, tc := range testCases { 866 t.Run(strconv.Itoa(i), func(t *testing.T) { 867 got, err := json.Marshal(tc.component) 868 if err != nil { 869 t.Fatal(err) 870 } 871 if !reflect.DeepEqual(got, tc.want) { 872 t.Errorf("got %s, want %s", string(got), string(tc.want)) 873 } 874 }) 875 } 876 } 877 878 func BenchmarkUnmarshalFlexMessageJSON(b *testing.B) { 879 var jsonData = []byte(`{ 880 "type": "bubble", 881 "header": { 882 "type": "box", 883 "layout": "horizontal", 884 "contents": [ 885 { 886 "type": "text", 887 "text": "NEWS DIGEST", 888 "weight": "bold", 889 "color": "#aaaaaa", 890 "size": "sm" 891 } 892 ] 893 }, 894 "hero": { 895 "type": "image", 896 "url": "https://scdn.line-apps.com/n/channel_devcenter/img/fx/01_4_news.png", 897 "size": "full", 898 "aspectRatio": "20:13", 899 "aspectMode": "cover", 900 "action": { 901 "type": "uri", 902 "uri": "https://linecorp.com/" 903 } 904 }, 905 "body": { 906 "type": "box", 907 "layout": "horizontal", 908 "spacing": "md", 909 "contents": [ 910 { 911 "type": "box", 912 "layout": "vertical", 913 "flex": 1, 914 "contents": [ 915 { 916 "type": "image", 917 "url": "https://scdn.line-apps.com/n/channel_devcenter/img/fx/02_1_news_thumbnail_1.png", 918 "aspectMode": "cover", 919 "aspectRatio": "4:3", 920 "size": "sm", 921 "gravity": "bottom" 922 }, 923 { 924 "type": "image", 925 "url": "https://scdn.line-apps.com/n/channel_devcenter/img/fx/02_1_news_thumbnail_2.png", 926 "aspectMode": "cover", 927 "aspectRatio": "4:3", 928 "margin": "md", 929 "size": "sm" 930 } 931 ] 932 }, 933 { 934 "type": "box", 935 "layout": "vertical", 936 "flex": 2, 937 "contents": [ 938 { 939 "type": "text", 940 "text": "7 Things to Know for Today", 941 "gravity": "top", 942 "size": "xs", 943 "flex": 1 944 }, 945 { 946 "type": "separator" 947 }, 948 { 949 "type": "text", 950 "text": "Hay fever goes wild", 951 "gravity": "center", 952 "size": "xs", 953 "flex": 2 954 }, 955 { 956 "type": "separator" 957 }, 958 { 959 "type": "text", 960 "text": "LINE Pay Begins Barcode Payment Service", 961 "gravity": "center", 962 "size": "xs", 963 "flex": 2 964 }, 965 { 966 "type": "separator" 967 }, 968 { 969 "type": "text", 970 "text": "LINE Adds LINE Wallet", 971 "gravity": "bottom", 972 "size": "xs", 973 "flex": 1 974 }, 975 { 976 "type": "text", 977 "contents": [ 978 { 979 "type": "span", 980 "text": "LINE", 981 "size": "xxl", 982 "weight": "bold", 983 "style": "italic", 984 "color": "#4f8f00" 985 }, 986 { 987 "type": "span", 988 "text": "MUSIC", 989 "size": "xxl", 990 "weight": "bold", 991 "style": "italic", 992 "color": "#4f8f00" 993 } 994 ] 995 } 996 ] 997 } 998 ] 999 }, 1000 "footer": { 1001 "type": "box", 1002 "layout": "horizontal", 1003 "contents": [ 1004 { 1005 "type": "button", 1006 "action": { 1007 "type": "uri", 1008 "label": "More", 1009 "uri": "https://linecorp.com" 1010 } 1011 } 1012 ] 1013 } 1014 }`) 1015 b.ResetTimer() 1016 for i := 0; i < b.N; i++ { 1017 _, err := UnmarshalFlexMessageJSON(jsonData) 1018 if err != nil { 1019 b.Fatal(err) 1020 } 1021 } 1022 }