hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

strings_test.go (16385B)

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