github.com/whatlly/hugo@v0.47.1/tpl/strings/strings_test.go (about) 1 // Copyright 2017 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package strings 15 16 import ( 17 "fmt" 18 "html/template" 19 "testing" 20 21 "github.com/gohugoio/hugo/deps" 22 "github.com/spf13/cast" 23 "github.com/spf13/viper" 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/require" 26 ) 27 28 var ns = New(&deps.Deps{Cfg: viper.New()}) 29 30 type tstNoStringer struct{} 31 32 func TestChomp(t *testing.T) { 33 t.Parallel() 34 35 for i, test := range []struct { 36 s interface{} 37 expect interface{} 38 }{ 39 {"\n a\n", "\n a"}, 40 {"\n a\n\n", "\n a"}, 41 {"\n a\r\n", "\n a"}, 42 {"\n a\n\r\n", "\n a"}, 43 {"\n a\r\r", "\n a"}, 44 {"\n a\r", "\n a"}, 45 // errors 46 {tstNoStringer{}, false}, 47 } { 48 errMsg := fmt.Sprintf("[%d] %v", i, test) 49 50 result, err := ns.Chomp(test.s) 51 52 if b, ok := test.expect.(bool); ok && !b { 53 require.Error(t, err, errMsg) 54 continue 55 } 56 57 require.NoError(t, err, errMsg) 58 assert.Equal(t, test.expect, result, errMsg) 59 60 // repeat the check with template.HTML input 61 result, err = ns.Chomp(template.HTML(cast.ToString(test.s))) 62 require.NoError(t, err, errMsg) 63 assert.Equal(t, template.HTML(cast.ToString(test.expect)), result, errMsg) 64 } 65 } 66 67 func TestContains(t *testing.T) { 68 t.Parallel() 69 70 for i, test := range []struct { 71 s interface{} 72 substr interface{} 73 expect bool 74 isErr bool 75 }{ 76 {"", "", true, false}, 77 {"123", "23", true, false}, 78 {"123", "234", false, false}, 79 {"123", "", true, false}, 80 {"", "a", false, false}, 81 {123, "23", true, false}, 82 {123, "234", false, false}, 83 {123, "", true, false}, 84 {template.HTML("123"), []byte("23"), true, false}, 85 {template.HTML("123"), []byte("234"), false, false}, 86 {template.HTML("123"), []byte(""), true, false}, 87 // errors 88 {"", tstNoStringer{}, false, true}, 89 {tstNoStringer{}, "", false, true}, 90 } { 91 errMsg := fmt.Sprintf("[%d] %v", i, test) 92 93 result, err := ns.Contains(test.s, test.substr) 94 95 if test.isErr { 96 require.Error(t, err, errMsg) 97 continue 98 } 99 100 require.NoError(t, err, errMsg) 101 assert.Equal(t, test.expect, result, errMsg) 102 } 103 } 104 105 func TestContainsAny(t *testing.T) { 106 t.Parallel() 107 108 for i, test := range []struct { 109 s interface{} 110 substr interface{} 111 expect bool 112 isErr bool 113 }{ 114 {"", "", false, false}, 115 {"", "1", false, false}, 116 {"", "123", false, false}, 117 {"1", "", false, false}, 118 {"1", "1", true, false}, 119 {"111", "1", true, false}, 120 {"123", "789", false, false}, 121 {"123", "729", true, false}, 122 {"a☺b☻c☹d", "uvw☻xyz", true, false}, 123 {1, "", false, false}, 124 {1, "1", true, false}, 125 {111, "1", true, false}, 126 {123, "789", false, false}, 127 {123, "729", true, false}, 128 {[]byte("123"), template.HTML("789"), false, false}, 129 {[]byte("123"), template.HTML("729"), true, false}, 130 {[]byte("a☺b☻c☹d"), template.HTML("uvw☻xyz"), true, false}, 131 // errors 132 {"", tstNoStringer{}, false, true}, 133 {tstNoStringer{}, "", false, true}, 134 } { 135 errMsg := fmt.Sprintf("[%d] %v", i, test) 136 137 result, err := ns.ContainsAny(test.s, test.substr) 138 139 if test.isErr { 140 require.Error(t, err, errMsg) 141 continue 142 } 143 144 require.NoError(t, err, errMsg) 145 assert.Equal(t, test.expect, result, errMsg) 146 } 147 } 148 149 func TestCountRunes(t *testing.T) { 150 t.Parallel() 151 152 for i, test := range []struct { 153 s interface{} 154 expect interface{} 155 }{ 156 {"foo bar", 6}, 157 {"旁边", 2}, 158 {`<div class="test">旁边</div>`, 2}, 159 // errors 160 {tstNoStringer{}, false}, 161 } { 162 errMsg := fmt.Sprintf("[%d] %v", i, test.s) 163 164 result, err := ns.CountRunes(test.s) 165 166 if b, ok := test.expect.(bool); ok && !b { 167 require.Error(t, err, errMsg) 168 continue 169 } 170 171 require.NoError(t, err, errMsg) 172 assert.Equal(t, test.expect, result, errMsg) 173 } 174 } 175 176 func TestRuneCount(t *testing.T) { 177 t.Parallel() 178 179 for i, test := range []struct { 180 s interface{} 181 expect interface{} 182 }{ 183 {"foo bar", 7}, 184 {"旁边", 2}, 185 {`<div class="test">旁边</div>`, 26}, 186 // errors 187 {tstNoStringer{}, false}, 188 } { 189 errMsg := fmt.Sprintf("[%d] %v", i, test.s) 190 191 result, err := ns.RuneCount(test.s) 192 193 if b, ok := test.expect.(bool); ok && !b { 194 require.Error(t, err, errMsg) 195 continue 196 } 197 198 require.NoError(t, err, errMsg) 199 assert.Equal(t, test.expect, result, errMsg) 200 } 201 } 202 203 func TestCountWords(t *testing.T) { 204 t.Parallel() 205 206 for i, test := range []struct { 207 s interface{} 208 expect interface{} 209 }{ 210 {"Do Be Do Be Do", 5}, 211 {"旁边", 2}, 212 {`<div class="test">旁边</div>`, 2}, 213 // errors 214 {tstNoStringer{}, false}, 215 } { 216 errMsg := fmt.Sprintf("[%d] %v", i, test.s) 217 218 result, err := ns.CountWords(test.s) 219 220 if b, ok := test.expect.(bool); ok && !b { 221 require.Error(t, err, errMsg) 222 continue 223 } 224 225 require.NoError(t, err, errMsg) 226 assert.Equal(t, test.expect, result, errMsg) 227 } 228 } 229 230 func TestHasPrefix(t *testing.T) { 231 t.Parallel() 232 233 for i, test := range []struct { 234 s interface{} 235 prefix interface{} 236 expect interface{} 237 isErr bool 238 }{ 239 {"abcd", "ab", true, false}, 240 {"abcd", "cd", false, false}, 241 {template.HTML("abcd"), "ab", true, false}, 242 {template.HTML("abcd"), "cd", false, false}, 243 {template.HTML("1234"), 12, true, false}, 244 {template.HTML("1234"), 34, false, false}, 245 {[]byte("abcd"), "ab", true, false}, 246 // errors 247 {"", tstNoStringer{}, false, true}, 248 {tstNoStringer{}, "", false, true}, 249 } { 250 errMsg := fmt.Sprintf("[%d] %v", i, test) 251 252 result, err := ns.HasPrefix(test.s, test.prefix) 253 254 if test.isErr { 255 require.Error(t, err, errMsg) 256 continue 257 } 258 259 require.NoError(t, err, errMsg) 260 assert.Equal(t, test.expect, result, errMsg) 261 } 262 } 263 264 func TestHasSuffix(t *testing.T) { 265 t.Parallel() 266 267 for i, test := range []struct { 268 s interface{} 269 suffix interface{} 270 expect interface{} 271 isErr bool 272 }{ 273 {"abcd", "cd", true, false}, 274 {"abcd", "ab", false, false}, 275 {template.HTML("abcd"), "cd", true, false}, 276 {template.HTML("abcd"), "ab", false, false}, 277 {template.HTML("1234"), 34, true, false}, 278 {template.HTML("1234"), 12, false, false}, 279 {[]byte("abcd"), "cd", true, false}, 280 // errors 281 {"", tstNoStringer{}, false, true}, 282 {tstNoStringer{}, "", false, true}, 283 } { 284 errMsg := fmt.Sprintf("[%d] %v", i, test) 285 286 result, err := ns.HasSuffix(test.s, test.suffix) 287 288 if test.isErr { 289 require.Error(t, err, errMsg) 290 continue 291 } 292 293 require.NoError(t, err, errMsg) 294 assert.Equal(t, test.expect, result, errMsg) 295 } 296 } 297 298 func TestReplace(t *testing.T) { 299 t.Parallel() 300 301 for i, test := range []struct { 302 s interface{} 303 old interface{} 304 new interface{} 305 expect interface{} 306 }{ 307 {"aab", "a", "b", "bbb"}, 308 {"11a11", 1, 2, "22a22"}, 309 {12345, 1, 2, "22345"}, 310 // errors 311 {tstNoStringer{}, "a", "b", false}, 312 {"a", tstNoStringer{}, "b", false}, 313 {"a", "b", tstNoStringer{}, false}, 314 } { 315 errMsg := fmt.Sprintf("[%d] %v", i, test) 316 317 result, err := ns.Replace(test.s, test.old, test.new) 318 319 if b, ok := test.expect.(bool); ok && !b { 320 require.Error(t, err, errMsg) 321 continue 322 } 323 324 require.NoError(t, err, errMsg) 325 assert.Equal(t, test.expect, result, errMsg) 326 } 327 } 328 329 func TestSliceString(t *testing.T) { 330 t.Parallel() 331 332 var err error 333 for i, test := range []struct { 334 v1 interface{} 335 v2 interface{} 336 v3 interface{} 337 expect interface{} 338 }{ 339 {"abc", 1, 2, "b"}, 340 {"abc", 1, 3, "bc"}, 341 {"abcdef", 1, int8(3), "bc"}, 342 {"abcdef", 1, int16(3), "bc"}, 343 {"abcdef", 1, int32(3), "bc"}, 344 {"abcdef", 1, int64(3), "bc"}, 345 {"abc", 0, 1, "a"}, 346 {"abcdef", nil, nil, "abcdef"}, 347 {"abcdef", 0, 6, "abcdef"}, 348 {"abcdef", 0, 2, "ab"}, 349 {"abcdef", 2, nil, "cdef"}, 350 {"abcdef", int8(2), nil, "cdef"}, 351 {"abcdef", int16(2), nil, "cdef"}, 352 {"abcdef", int32(2), nil, "cdef"}, 353 {"abcdef", int64(2), nil, "cdef"}, 354 {123, 1, 3, "23"}, 355 {"abcdef", 6, nil, false}, 356 {"abcdef", 4, 7, false}, 357 {"abcdef", -1, nil, false}, 358 {"abcdef", -1, 7, false}, 359 {"abcdef", 1, -1, false}, 360 {tstNoStringer{}, 0, 1, false}, 361 {"ĀĀĀ", 0, 1, "Ā"}, // issue #1333 362 {"a", t, nil, false}, 363 {"a", 1, t, false}, 364 } { 365 errMsg := fmt.Sprintf("[%d] %v", i, test) 366 367 var result string 368 if test.v2 == nil { 369 result, err = ns.SliceString(test.v1) 370 } else if test.v3 == nil { 371 result, err = ns.SliceString(test.v1, test.v2) 372 } else { 373 result, err = ns.SliceString(test.v1, test.v2, test.v3) 374 } 375 376 if b, ok := test.expect.(bool); ok && !b { 377 require.Error(t, err, errMsg) 378 continue 379 } 380 381 require.NoError(t, err, errMsg) 382 assert.Equal(t, test.expect, result, errMsg) 383 } 384 385 // Too many arguments 386 _, err = ns.SliceString("a", 1, 2, 3) 387 if err == nil { 388 t.Errorf("Should have errored") 389 } 390 } 391 392 func TestSplit(t *testing.T) { 393 t.Parallel() 394 395 for i, test := range []struct { 396 v1 interface{} 397 v2 string 398 expect interface{} 399 }{ 400 {"a, b", ", ", []string{"a", "b"}}, 401 {"a & b & c", " & ", []string{"a", "b", "c"}}, 402 {"http://example.com", "http://", []string{"", "example.com"}}, 403 {123, "2", []string{"1", "3"}}, 404 {tstNoStringer{}, ",", false}, 405 } { 406 errMsg := fmt.Sprintf("[%d] %v", i, test) 407 408 result, err := ns.Split(test.v1, test.v2) 409 410 if b, ok := test.expect.(bool); ok && !b { 411 require.Error(t, err, errMsg) 412 continue 413 } 414 415 require.NoError(t, err, errMsg) 416 assert.Equal(t, test.expect, result, errMsg) 417 } 418 } 419 420 func TestSubstr(t *testing.T) { 421 t.Parallel() 422 423 var err error 424 var n int 425 for i, test := range []struct { 426 v1 interface{} 427 v2 interface{} 428 v3 interface{} 429 expect interface{} 430 }{ 431 {"abc", 1, 2, "bc"}, 432 {"abc", 0, 1, "a"}, 433 {"abcdef", -1, 2, "ef"}, 434 {"abcdef", -3, 3, "bcd"}, 435 {"abcdef", 0, -1, "abcde"}, 436 {"abcdef", 2, -1, "cde"}, 437 {"abcdef", 4, -4, false}, 438 {"abcdef", 7, 1, false}, 439 {"abcdef", 1, 100, "bcdef"}, 440 {"abcdef", -100, 3, "abc"}, 441 {"abcdef", -3, -1, "de"}, 442 {"abcdef", 2, nil, "cdef"}, 443 {"abcdef", int8(2), nil, "cdef"}, 444 {"abcdef", int16(2), nil, "cdef"}, 445 {"abcdef", int32(2), nil, "cdef"}, 446 {"abcdef", int64(2), nil, "cdef"}, 447 {"abcdef", 2, int8(3), "cde"}, 448 {"abcdef", 2, int16(3), "cde"}, 449 {"abcdef", 2, int32(3), "cde"}, 450 {"abcdef", 2, int64(3), "cde"}, 451 {123, 1, 3, "23"}, 452 {1.2e3, 0, 4, "1200"}, 453 {tstNoStringer{}, 0, 1, false}, 454 {"abcdef", 2.0, nil, "cdef"}, 455 {"abcdef", 2.0, 2, "cd"}, 456 {"abcdef", 2, 2.0, "cd"}, 457 {"ĀĀĀ", 1, 2, "ĀĀ"}, // # issue 1333 458 {"abcdef", "doo", nil, false}, 459 {"abcdef", "doo", "doo", false}, 460 {"abcdef", 1, "doo", false}, 461 } { 462 errMsg := fmt.Sprintf("[%d] %v", i, test) 463 464 var result string 465 n = i 466 467 if test.v3 == nil { 468 result, err = ns.Substr(test.v1, test.v2) 469 } else { 470 result, err = ns.Substr(test.v1, test.v2, test.v3) 471 } 472 473 if b, ok := test.expect.(bool); ok && !b { 474 require.Error(t, err, errMsg) 475 continue 476 } 477 478 require.NoError(t, err, errMsg) 479 assert.Equal(t, test.expect, result, errMsg) 480 } 481 482 n++ 483 _, err = ns.Substr("abcdef") 484 if err == nil { 485 t.Errorf("[%d] Substr didn't return an expected error", n) 486 } 487 488 n++ 489 _, err = ns.Substr("abcdef", 1, 2, 3) 490 if err == nil { 491 t.Errorf("[%d] Substr didn't return an expected error", n) 492 } 493 } 494 495 func TestTitle(t *testing.T) { 496 t.Parallel() 497 498 for i, test := range []struct { 499 s interface{} 500 expect interface{} 501 }{ 502 {"test", "Test"}, 503 {template.HTML("hypertext"), "Hypertext"}, 504 {[]byte("bytes"), "Bytes"}, 505 // errors 506 {tstNoStringer{}, false}, 507 } { 508 errMsg := fmt.Sprintf("[%d] %v", i, test) 509 510 result, err := ns.Title(test.s) 511 512 if b, ok := test.expect.(bool); ok && !b { 513 require.Error(t, err, errMsg) 514 continue 515 } 516 517 require.NoError(t, err, errMsg) 518 assert.Equal(t, test.expect, result, errMsg) 519 } 520 } 521 522 func TestToLower(t *testing.T) { 523 t.Parallel() 524 525 for i, test := range []struct { 526 s interface{} 527 expect interface{} 528 }{ 529 {"TEST", "test"}, 530 {template.HTML("LoWeR"), "lower"}, 531 {[]byte("BYTES"), "bytes"}, 532 // errors 533 {tstNoStringer{}, false}, 534 } { 535 errMsg := fmt.Sprintf("[%d] %v", i, test) 536 537 result, err := ns.ToLower(test.s) 538 539 if b, ok := test.expect.(bool); ok && !b { 540 require.Error(t, err, errMsg) 541 continue 542 } 543 544 require.NoError(t, err, errMsg) 545 assert.Equal(t, test.expect, result, errMsg) 546 } 547 } 548 549 func TestToUpper(t *testing.T) { 550 t.Parallel() 551 552 for i, test := range []struct { 553 s interface{} 554 expect interface{} 555 }{ 556 {"test", "TEST"}, 557 {template.HTML("UpPeR"), "UPPER"}, 558 {[]byte("bytes"), "BYTES"}, 559 // errors 560 {tstNoStringer{}, false}, 561 } { 562 errMsg := fmt.Sprintf("[%d] %v", i, test) 563 564 result, err := ns.ToUpper(test.s) 565 566 if b, ok := test.expect.(bool); ok && !b { 567 require.Error(t, err, errMsg) 568 continue 569 } 570 571 require.NoError(t, err, errMsg) 572 assert.Equal(t, test.expect, result, errMsg) 573 } 574 } 575 576 func TestTrim(t *testing.T) { 577 t.Parallel() 578 579 for i, test := range []struct { 580 s interface{} 581 cutset interface{} 582 expect interface{} 583 }{ 584 {"abba", "a", "bb"}, 585 {"abba", "ab", ""}, 586 {"<tag>", "<>", "tag"}, 587 {`"quote"`, `"`, "quote"}, 588 {1221, "1", "22"}, 589 {1221, "12", ""}, 590 {template.HTML("<tag>"), "<>", "tag"}, 591 {[]byte("<tag>"), "<>", "tag"}, 592 // errors 593 {"", tstNoStringer{}, false}, 594 {tstNoStringer{}, "", false}, 595 } { 596 errMsg := fmt.Sprintf("[%d] %v", i, test) 597 598 result, err := ns.Trim(test.s, test.cutset) 599 600 if b, ok := test.expect.(bool); ok && !b { 601 require.Error(t, err, errMsg) 602 continue 603 } 604 605 require.NoError(t, err, errMsg) 606 assert.Equal(t, test.expect, result, errMsg) 607 } 608 } 609 610 func TestTrimLeft(t *testing.T) { 611 t.Parallel() 612 613 for i, test := range []struct { 614 s interface{} 615 cutset interface{} 616 expect interface{} 617 }{ 618 {"abba", "a", "bba"}, 619 {"abba", "ab", ""}, 620 {"<tag>", "<>", "tag>"}, 621 {`"quote"`, `"`, `quote"`}, 622 {1221, "1", "221"}, 623 {1221, "12", ""}, 624 {"007", "0", "7"}, 625 {template.HTML("<tag>"), "<>", "tag>"}, 626 {[]byte("<tag>"), "<>", "tag>"}, 627 // errors 628 {"", tstNoStringer{}, false}, 629 {tstNoStringer{}, "", false}, 630 } { 631 errMsg := fmt.Sprintf("[%d] %v", i, test) 632 633 result, err := ns.TrimLeft(test.cutset, test.s) 634 635 if b, ok := test.expect.(bool); ok && !b { 636 require.Error(t, err, errMsg) 637 continue 638 } 639 640 require.NoError(t, err, errMsg) 641 assert.Equal(t, test.expect, result, errMsg) 642 } 643 } 644 645 func TestTrimPrefix(t *testing.T) { 646 t.Parallel() 647 648 for i, test := range []struct { 649 s interface{} 650 prefix interface{} 651 expect interface{} 652 }{ 653 {"aabbaa", "a", "abbaa"}, 654 {"aabb", "b", "aabb"}, 655 {1234, "12", "34"}, 656 {1234, "34", "1234"}, 657 // errors 658 {"", tstNoStringer{}, false}, 659 {tstNoStringer{}, "", false}, 660 } { 661 errMsg := fmt.Sprintf("[%d] %v", i, test) 662 663 result, err := ns.TrimPrefix(test.prefix, test.s) 664 665 if b, ok := test.expect.(bool); ok && !b { 666 require.Error(t, err, errMsg) 667 continue 668 } 669 670 require.NoError(t, err, errMsg) 671 assert.Equal(t, test.expect, result, errMsg) 672 } 673 } 674 675 func TestTrimRight(t *testing.T) { 676 t.Parallel() 677 678 for i, test := range []struct { 679 s interface{} 680 cutset interface{} 681 expect interface{} 682 }{ 683 {"abba", "a", "abb"}, 684 {"abba", "ab", ""}, 685 {"<tag>", "<>", "<tag"}, 686 {`"quote"`, `"`, `"quote`}, 687 {1221, "1", "122"}, 688 {1221, "12", ""}, 689 {"007", "0", "007"}, 690 {template.HTML("<tag>"), "<>", "<tag"}, 691 {[]byte("<tag>"), "<>", "<tag"}, 692 // errors 693 {"", tstNoStringer{}, false}, 694 {tstNoStringer{}, "", false}, 695 } { 696 errMsg := fmt.Sprintf("[%d] %v", i, test) 697 698 result, err := ns.TrimRight(test.cutset, test.s) 699 700 if b, ok := test.expect.(bool); ok && !b { 701 require.Error(t, err, errMsg) 702 continue 703 } 704 705 require.NoError(t, err, errMsg) 706 assert.Equal(t, test.expect, result, errMsg) 707 } 708 } 709 710 func TestTrimSuffix(t *testing.T) { 711 t.Parallel() 712 713 for i, test := range []struct { 714 s interface{} 715 suffix interface{} 716 expect interface{} 717 }{ 718 {"aabbaa", "a", "aabba"}, 719 {"aabb", "b", "aab"}, 720 {1234, "12", "1234"}, 721 {1234, "34", "12"}, 722 // errors 723 {"", tstNoStringer{}, false}, 724 {tstNoStringer{}, "", false}, 725 } { 726 errMsg := fmt.Sprintf("[%d] %v", i, test) 727 728 result, err := ns.TrimSuffix(test.suffix, test.s) 729 730 if b, ok := test.expect.(bool); ok && !b { 731 require.Error(t, err, errMsg) 732 continue 733 } 734 735 require.NoError(t, err, errMsg) 736 assert.Equal(t, test.expect, result, errMsg) 737 } 738 } 739 740 func TestRepeat(t *testing.T) { 741 t.Parallel() 742 743 for i, test := range []struct { 744 s interface{} 745 n interface{} 746 expect interface{} 747 }{ 748 {"yo", "2", "yoyo"}, 749 {"~", "16", "~~~~~~~~~~~~~~~~"}, 750 {"<tag>", "0", ""}, 751 {"yay", "1", "yay"}, 752 {1221, "1", "1221"}, 753 {1221, 2, "12211221"}, 754 {template.HTML("<tag>"), "2", "<tag><tag>"}, 755 {[]byte("<tag>"), 2, "<tag><tag>"}, 756 // errors 757 {"", tstNoStringer{}, false}, 758 {tstNoStringer{}, "", false}, 759 {"ab", -1, false}, 760 } { 761 errMsg := fmt.Sprintf("[%d] %v", i, test) 762 763 result, err := ns.Repeat(test.n, test.s) 764 765 if b, ok := test.expect.(bool); ok && !b { 766 require.Error(t, err, errMsg) 767 continue 768 } 769 770 require.NoError(t, err, errMsg) 771 assert.Equal(t, test.expect, result, errMsg) 772 } 773 }