github.com/shohhei1126/hugo@v0.42.2-0.20180623210752-3d5928889ad7/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  }