...

Source file src/github.com/cli/go-gh/v2/pkg/text/text_test.go

Documentation: github.com/cli/go-gh/v2/pkg/text

     1  package text
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  )
     9  
    10  func TestRelativeTimeAgo(t *testing.T) {
    11  	const form = "2006-Jan-02 15:04:05"
    12  	now, _ := time.Parse(form, "2020-Nov-22 14:00:00")
    13  	cases := map[string]string{
    14  		"2020-Nov-22 14:00:00": "less than a minute ago",
    15  		"2020-Nov-22 13:59:30": "less than a minute ago",
    16  		"2020-Nov-22 13:59:00": "about 1 minute ago",
    17  		"2020-Nov-22 13:30:00": "about 30 minutes ago",
    18  		"2020-Nov-22 13:00:00": "about 1 hour ago",
    19  		"2020-Nov-22 02:00:00": "about 12 hours ago",
    20  		"2020-Nov-21 14:00:00": "about 1 day ago",
    21  		"2020-Nov-07 14:00:00": "about 15 days ago",
    22  		"2020-Oct-24 14:00:00": "about 29 days ago",
    23  		"2020-Oct-23 14:00:00": "about 1 month ago",
    24  		"2020-Sep-23 14:00:00": "about 2 months ago",
    25  		"2019-Nov-22 14:00:00": "about 1 year ago",
    26  		"2018-Nov-22 14:00:00": "about 2 years ago",
    27  	}
    28  	for createdAt, expected := range cases {
    29  		d, err := time.Parse(form, createdAt)
    30  		assert.NoError(t, err)
    31  		relative := RelativeTimeAgo(now, d)
    32  		assert.Equal(t, expected, relative)
    33  	}
    34  }
    35  
    36  func TestTruncate(t *testing.T) {
    37  	type args struct {
    38  		max int
    39  		s   string
    40  	}
    41  	tests := []struct {
    42  		name string
    43  		args args
    44  		want string
    45  	}{
    46  		{
    47  			name: "empty",
    48  			args: args{
    49  				s:   "",
    50  				max: 10,
    51  			},
    52  			want: "",
    53  		},
    54  		{
    55  			name: "short",
    56  			args: args{
    57  				s:   "hello",
    58  				max: 3,
    59  			},
    60  			want: "hel",
    61  		},
    62  		{
    63  			name: "long",
    64  			args: args{
    65  				s:   "hello world",
    66  				max: 5,
    67  			},
    68  			want: "he...",
    69  		},
    70  		{
    71  			name: "no truncate",
    72  			args: args{
    73  				s:   "hello world",
    74  				max: 11,
    75  			},
    76  			want: "hello world",
    77  		},
    78  		{
    79  			name: "Short enough",
    80  			args: args{
    81  				max: 5,
    82  				s:   "short",
    83  			},
    84  			want: "short",
    85  		},
    86  		{
    87  			name: "Too short",
    88  			args: args{
    89  				max: 4,
    90  				s:   "short",
    91  			},
    92  			want: "shor",
    93  		},
    94  		{
    95  			name: "Japanese",
    96  			args: args{
    97  				max: 11,
    98  				s:   "テストテストテストテスト",
    99  			},
   100  			want: "テストテ...",
   101  		},
   102  		{
   103  			name: "Japanese filled",
   104  			args: args{
   105  				max: 11,
   106  				s:   "aテストテストテストテスト",
   107  			},
   108  			want: "aテスト... ",
   109  		},
   110  		{
   111  			name: "Chinese",
   112  			args: args{
   113  				max: 11,
   114  				s:   "幫新舉報違章工廠新增編號",
   115  			},
   116  			want: "幫新舉報...",
   117  		},
   118  		{
   119  			name: "Chinese filled",
   120  			args: args{
   121  				max: 11,
   122  				s:   "a幫新舉報違章工廠新增編號",
   123  			},
   124  			want: "a幫新舉... ",
   125  		},
   126  		{
   127  			name: "Korean",
   128  			args: args{
   129  				max: 11,
   130  				s:   "프로젝트 내의",
   131  			},
   132  			want: "프로젝트...",
   133  		},
   134  		{
   135  			name: "Korean filled",
   136  			args: args{
   137  				max: 11,
   138  				s:   "a프로젝트 내의",
   139  			},
   140  			want: "a프로젝... ",
   141  		},
   142  		{
   143  			name: "Emoji",
   144  			args: args{
   145  				max: 11,
   146  				s:   "💡💡💡💡💡💡💡💡💡💡💡💡",
   147  			},
   148  			want: "💡💡💡💡...",
   149  		},
   150  		{
   151  			name: "Accented characters",
   152  			args: args{
   153  				max: 11,
   154  				s:   "é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́",
   155  			},
   156  			want: "é́́é́́é́́é́́é́́é́́é́́é́́...",
   157  		},
   158  		{
   159  			name: "Red accented characters",
   160  			args: args{
   161  				max: 11,
   162  				s:   "\x1b[0;31mé́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́é́́\x1b[0m",
   163  			},
   164  			want: "\x1b[0;31mé́́é́́é́́é́́é́́é́́é́́é́́...\x1b[0m",
   165  		},
   166  	}
   167  	for _, tt := range tests {
   168  		t.Run(tt.name, func(t *testing.T) {
   169  			got := Truncate(tt.args.max, tt.args.s)
   170  			assert.Equal(t, tt.want, got)
   171  		})
   172  	}
   173  }
   174  
   175  func TestPadRight(t *testing.T) {
   176  	type args struct {
   177  		max int
   178  		s   string
   179  	}
   180  	tests := []struct {
   181  		name string
   182  		args args
   183  		want string
   184  	}{
   185  		{
   186  			name: "empty",
   187  			args: args{
   188  				s:   "",
   189  				max: 5,
   190  			},
   191  			want: "     ",
   192  		},
   193  		{
   194  			name: "short",
   195  			args: args{
   196  				s:   "hello",
   197  				max: 7,
   198  			},
   199  			want: "hello  ",
   200  		},
   201  		{
   202  			name: "long",
   203  			args: args{
   204  				s:   "hello world",
   205  				max: 5,
   206  			},
   207  			want: "hello world",
   208  		},
   209  		{
   210  			name: "exact",
   211  			args: args{
   212  				s:   "hello world",
   213  				max: 11,
   214  			},
   215  			want: "hello world",
   216  		},
   217  		{
   218  			name: "Japanese",
   219  			args: args{
   220  				s:   "テストテスト",
   221  				max: 13,
   222  			},
   223  			want: "テストテスト ",
   224  		},
   225  		{
   226  			name: "Japanese filled",
   227  			args: args{
   228  				s:   "aテスト",
   229  				max: 9,
   230  			},
   231  			want: "aテスト  ",
   232  		},
   233  		{
   234  			name: "Chinese",
   235  			args: args{
   236  				s:   "幫新舉報違章工廠新增編號",
   237  				max: 26,
   238  			},
   239  			want: "幫新舉報違章工廠新增編號  ",
   240  		},
   241  		{
   242  			name: "Chinese filled",
   243  			args: args{
   244  				s:   "a幫新舉報違章工廠新增編號",
   245  				max: 26,
   246  			},
   247  			want: "a幫新舉報違章工廠新增編號 ",
   248  		},
   249  		{
   250  			name: "Korean",
   251  			args: args{
   252  				s:   "프로젝트 내의",
   253  				max: 15,
   254  			},
   255  			want: "프로젝트 내의  ",
   256  		},
   257  		{
   258  			name: "Korean filled",
   259  			args: args{
   260  				s:   "a프로젝트 내의",
   261  				max: 15,
   262  			},
   263  			want: "a프로젝트 내의 ",
   264  		},
   265  		{
   266  			name: "Emoji",
   267  			args: args{
   268  				s:   "💡💡💡💡",
   269  				max: 10,
   270  			},
   271  			want: "💡💡💡💡  ",
   272  		},
   273  		{
   274  			name: "Accented characters",
   275  			args: args{
   276  				s:   "é́́é́́é́́é́́é́́",
   277  				max: 7,
   278  			},
   279  			want: "é́́é́́é́́é́́é́́  ",
   280  		},
   281  		{
   282  			name: "Red accented characters",
   283  			args: args{
   284  				s:   "\x1b[0;31mé́́é́́é́́é́́é́́\x1b[0m",
   285  				max: 7,
   286  			},
   287  			want: "\x1b[0;31mé́́é́́é́́é́́é́́\x1b[0m  ",
   288  		},
   289  	}
   290  	for _, tt := range tests {
   291  		t.Run(tt.name, func(t *testing.T) {
   292  			got := PadRight(tt.args.max, tt.args.s)
   293  			assert.Equal(t, tt.want, got)
   294  		})
   295  	}
   296  }
   297  
   298  func TestDisplayWidth(t *testing.T) {
   299  	tests := []struct {
   300  		name string
   301  		text string
   302  		want int
   303  	}{
   304  		{
   305  			name: "check mark",
   306  			text: `✓`,
   307  			want: 1,
   308  		},
   309  		{
   310  			name: "bullet icon",
   311  			text: `•`,
   312  			want: 1,
   313  		},
   314  		{
   315  			name: "middle dot",
   316  			text: `·`,
   317  			want: 1,
   318  		},
   319  		{
   320  			name: "ellipsis",
   321  			text: `…`,
   322  			want: 1,
   323  		},
   324  		{
   325  			name: "right arrow",
   326  			text: `→`,
   327  			want: 1,
   328  		},
   329  		{
   330  			name: "smart double quotes",
   331  			text: `“”`,
   332  			want: 2,
   333  		},
   334  		{
   335  			name: "smart single quotes",
   336  			text: `‘’`,
   337  			want: 2,
   338  		},
   339  		{
   340  			name: "em dash",
   341  			text: `—`,
   342  			want: 1,
   343  		},
   344  		{
   345  			name: "en dash",
   346  			text: `–`,
   347  			want: 1,
   348  		},
   349  		{
   350  			name: "emoji",
   351  			text: `👍`,
   352  			want: 2,
   353  		},
   354  		{
   355  			name: "multi-byte emoji",
   356  			text: `👨‍💻`,
   357  			want: 2,
   358  		},
   359  		{
   360  			name: "accent character",
   361  			text: `é́́`,
   362  			want: 1,
   363  		},
   364  		{
   365  			name: "color codes",
   366  			text: "\x1b[0;31mred\x1b[0m",
   367  			want: 3,
   368  		},
   369  		{
   370  			name: "empty",
   371  			text: "",
   372  			want: 0,
   373  		},
   374  		{
   375  			name: "Latin",
   376  			text: "hello world 123$#!",
   377  			want: 18,
   378  		},
   379  		{
   380  			name: "Asian",
   381  			text: "つのだ☆HIRO",
   382  			want: 11,
   383  		},
   384  	}
   385  	for _, tt := range tests {
   386  		t.Run(tt.name, func(t *testing.T) {
   387  			got := DisplayWidth(tt.text)
   388  			assert.Equal(t, tt.want, got)
   389  		})
   390  	}
   391  }
   392  
   393  func TestIndent(t *testing.T) {
   394  	type args struct {
   395  		s      string
   396  		indent string
   397  	}
   398  	tests := []struct {
   399  		name string
   400  		args args
   401  		want string
   402  	}{
   403  		{
   404  			name: "empty",
   405  			args: args{
   406  				s:      "",
   407  				indent: "--",
   408  			},
   409  			want: "",
   410  		},
   411  		{
   412  			name: "blank",
   413  			args: args{
   414  				s:      "\n",
   415  				indent: "--",
   416  			},
   417  			want: "\n",
   418  		},
   419  		{
   420  			name: "indent",
   421  			args: args{
   422  				s:      "one\ntwo\nthree",
   423  				indent: "--",
   424  			},
   425  			want: "--one\n--two\n--three",
   426  		},
   427  	}
   428  	for _, tt := range tests {
   429  		t.Run(tt.name, func(t *testing.T) {
   430  			got := Indent(tt.args.s, tt.args.indent)
   431  			assert.Equal(t, tt.want, got)
   432  		})
   433  	}
   434  }
   435  
   436  func TestRemoveDiacritics(t *testing.T) {
   437  	tests := [][]string{
   438  		// no diacritics
   439  		{"e", "e"},
   440  		{"و", "و"},
   441  		{"И", "И"},
   442  		{"ж", "ж"},
   443  		{"私", "私"},
   444  		{"万", "万"},
   445  
   446  		// diacritics test sets
   447  		{"à", "a"},
   448  		{"é", "e"},
   449  		{"è", "e"},
   450  		{"ô", "o"},
   451  		{"ᾳ", "α"},
   452  		{"εͅ", "ε"},
   453  		{"ῃ", "η"},
   454  		{"ιͅ", "ι"},
   455  
   456  		{"ؤ", "و"},
   457  
   458  		{"ā", "a"},
   459  		{"č", "c"},
   460  		{"ģ", "g"},
   461  		{"ķ", "k"},
   462  		{"ņ", "n"},
   463  		{"š", "s"},
   464  		{"ž", "z"},
   465  
   466  		{"ŵ", "w"},
   467  		{"ŷ", "y"},
   468  		{"ä", "a"},
   469  		{"ÿ", "y"},
   470  		{"á", "a"},
   471  		{"ẁ", "w"},
   472  		{"ỳ", "y"},
   473  		{"ō", "o"},
   474  
   475  		// full words
   476  		{"Miķelis", "Mikelis"},
   477  		{"François", "Francois"},
   478  		{"žluťoučký", "zlutoucky"},
   479  		{"învățătorița", "invatatorita"},
   480  		{"Kękę przy łóżku", "Keke przy łozku"},
   481  	}
   482  
   483  	for _, tt := range tests {
   484  		t.Run(RemoveDiacritics(tt[0]), func(t *testing.T) {
   485  			assert.Equal(t, tt[1], RemoveDiacritics(tt[0]))
   486  		})
   487  	}
   488  }
   489  

View as plain text