github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/internal/table/table_test.go (about) 1 package table 2 3 import ( 4 "reflect" 5 "strings" 6 "testing" 7 8 "github.com/ActiveState/cli/internal/mathutils" 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestTable_colWidths(t1 *testing.T) { 13 type args struct { 14 table *Table 15 maxTotalWidth int 16 } 17 tests := []struct { 18 name string 19 args args 20 want []int 21 }{ 22 { 23 "Under max total", 24 args{ 25 &Table{ 26 []string{"123", "1234", "12345"}, 27 []row{ 28 {[]string{"1", "2", "3"}}, 29 }, 30 false, 31 false, 32 false, 33 }, 34 100, 35 }, 36 []int{7, 8, 9}, 37 }, 38 { 39 "multi-byte characters", 40 args{ 41 &Table{ 42 []string{"12✔", "1234", "12345"}, 43 []row{ 44 {[]string{"1", "2", "3"}}, 45 }, 46 false, 47 false, 48 false, 49 }, 50 100, 51 }, 52 []int{7, 8, 9}, 53 }, 54 { 55 "span row dominates", 56 args{ 57 &Table{ 58 []string{"123", "1234", "12345"}, 59 []row{ 60 {[]string{"1", "2", "3"}}, 61 {[]string{"1", "0123456789012345678901234567890123456789"}}, 62 }, 63 false, 64 false, 65 false, 66 }, 67 100, 68 }, 69 []int{14, 17, 20}, 70 }, 71 { 72 "Rowsize wins cause it's longer", 73 args{ 74 &Table{ 75 []string{"1", "2", "3"}, 76 []row{ 77 {[]string{"123", "1234", "12345"}}, 78 }, 79 false, 80 false, 81 false, 82 }, 83 100, 84 }, 85 []int{7, 8, 9}, 86 }, 87 { 88 "Over max total", 89 args{ 90 &Table{ 91 []string{strings.Repeat("-", 40), strings.Repeat("-", 50), strings.Repeat("-", 60)}, 92 []row{ 93 {[]string{"1", "2", "3"}}, 94 }, 95 false, 96 false, 97 false, 98 }, 99 100, 100 }, 101 []int{28, 33, 39}, 102 }, 103 { 104 "Long multi column", 105 args{ 106 &Table{ 107 []string{"a", "b", "c", "d"}, 108 []row{ 109 {[]string{"1", "1", "12", "12"}}, 110 {[]string{strings.Repeat(" ", 100)}}, 111 }, 112 false, 113 false, 114 false, 115 }, 116 100, 117 }, 118 []int{22, 22, 27, 29}, 119 }, 120 { 121 "Long multi column (over maxWidth)", 122 args{ 123 &Table{ 124 []string{"a", "b", "c", "d"}, 125 []row{ 126 {[]string{"1", "1", "12", "12"}}, 127 {[]string{"1", strings.Repeat(" ", 200)}}, 128 }, 129 false, 130 false, 131 false, 132 }, 133 100, 134 }, 135 []int{22, 22, 27, 29}, 136 }, 137 } 138 for _, tt := range tests { 139 t1.Run(tt.name, func(t1 *testing.T) { 140 got, total := tt.args.table.calculateWidth(tt.args.maxTotalWidth) 141 if !reflect.DeepEqual(got, tt.want) { 142 t1.Errorf("calculateWidth() = %v, want %v", got, tt.want) 143 } 144 145 assert.LessOrEqual(t1, total, tt.args.maxTotalWidth) 146 }) 147 } 148 } 149 150 func Test_renderRow(t *testing.T) { 151 type args struct { 152 providedColumns []string 153 colWidths []int 154 } 155 tests := []struct { 156 name string 157 args args 158 want string 159 }{ 160 { 161 "No breaks", 162 args{ 163 providedColumns: []string{"col1", "col2", "col3"}, 164 colWidths: []int{10, 10, 10}, 165 }, 166 " col1 col2 col3 ", 167 }, 168 { 169 "No breaks with color codes", 170 args{ 171 providedColumns: []string{"[HEADING]col1[/RESET]", "[HEADING]col2[/RESET]", "[HEADING]col3[/RESET]"}, 172 colWidths: []int{10, 10, 10}, 173 }, 174 " [HEADING]col1[/RESET] [HEADING]col2[/RESET] [HEADING]col3[/RESET] ", 175 }, 176 { 177 "Breaks", 178 args{ 179 providedColumns: []string{"col1", "col2", "col3"}, 180 colWidths: []int{6, 6, 6}, 181 }, 182 " co co co \n" + 183 " l1 l2 l3 ", 184 }, 185 { 186 "Breaks with color codes", 187 args{ 188 providedColumns: []string{"[HEADING]col1[/RESET]", "[HEADING]col2[/RESET]", "[HEADING]col3[/RESET]"}, 189 colWidths: []int{6, 6, 6}, 190 }, 191 " [HEADING]co [HEADING]co [HEADING]co \n" + 192 " l1[/RESET] l2[/RESET] l3[/RESET] ", 193 }, 194 { 195 "Breaks for multi-byte characters", 196 args{ 197 providedColumns: []string{"✔ol1", "✔ol2", "✔ol3"}, 198 colWidths: []int{6, 6, 6}, 199 }, 200 " ✔o ✔o ✔o \n" + 201 " l1 l2 l3 ", 202 }, 203 { 204 "Empty column", 205 args{ 206 providedColumns: []string{"col1", "", "col3"}, 207 colWidths: []int{6, 6, 6}, 208 }, 209 " co co \n" + 210 " l1 l3 ", 211 }, 212 { 213 "Mutli column span", 214 args{ 215 providedColumns: []string{"abcdefgh", "jklmnopqrstu"}, 216 colWidths: []int{6, 6, 6}, 217 }, 218 " ab jklmnopq \n" + 219 " cd rstu \n" + 220 " ef \n" + 221 " gh ", 222 }, 223 { 224 "Single row mutli column span", 225 args{ 226 providedColumns: []string{"123456789"}, 227 colWidths: []int{1, 2, 3, 4, 5}, 228 }, 229 " 123456789 ", 230 }, 231 { 232 "Multi line second column", 233 args{ 234 providedColumns: []string{"abcd", "abcdefgh"}, 235 colWidths: []int{8, 8}, 236 }, 237 " abcd abcd \n" + 238 " efgh ", 239 }, 240 { 241 "Multi line second column with line breaks", 242 args{ 243 providedColumns: []string{"abcd", "abcde\nfgh"}, 244 colWidths: []int{8, 8}, 245 }, 246 " abcd abcd \n" + 247 " e \n" + 248 " fgh ", 249 }, 250 } 251 for _, tt := range tests { 252 t.Run(tt.name, func(t *testing.T) { 253 if got := renderRow(tt.args.providedColumns, tt.args.colWidths); got != tt.want { 254 t.Errorf("renderRow() = '%v', want '%v'", renderBreaks(got), renderBreaks(tt.want)) 255 } 256 }) 257 } 258 } 259 260 func renderBreaks(v string) string { 261 return strings.ReplaceAll(v, "\n", `\n`) 262 } 263 264 func Test_equalizeWidths(t *testing.T) { 265 type args struct { 266 colWidths []int 267 percentage int 268 } 269 tests := []struct { 270 name string 271 args args 272 want []int 273 }{ 274 { 275 "Equalize widths", 276 args{ 277 []int{10, 20, 30}, 278 20, 279 }, 280 []int{12, 20, 28}, 281 }, 282 { 283 "Equalize widths, account for floats", 284 args{ 285 []int{1, 1, 5}, 286 40, 287 }, 288 []int{1, 1, 5}, 289 }, 290 { 291 "Zero percentage doesn't panic or break", 292 args{ 293 []int{11, 21, 31}, 294 0, 295 }, 296 []int{11, 21, 31}, 297 }, 298 } 299 for _, tt := range tests { 300 t.Run(tt.name, func(t *testing.T) { 301 originalTotal := mathutils.Total(tt.args.colWidths...) 302 equalizeWidths(tt.args.colWidths, tt.args.percentage) 303 if !reflect.DeepEqual(tt.args.colWidths, tt.want) { 304 t.Errorf("equalizeWidths() got = %v, want %v", tt.args.colWidths, tt.want) 305 } 306 if originalTotal != mathutils.Total(tt.args.colWidths...) { 307 t.Errorf("Output total should be equal to input total, got: %v", tt.args.colWidths) 308 } 309 }) 310 } 311 } 312 313 func Test_rescaleColumns(t *testing.T) { 314 type args struct { 315 colWidths []int 316 targetTotal int 317 } 318 tests := []struct { 319 name string 320 args args 321 want []int 322 }{ 323 { 324 "Rescale widths, bigger", 325 args{ 326 []int{5, 5, 5}, 327 20, 328 }, 329 []int{6, 6, 8}, 330 }, 331 { 332 "Rescale widths, same", 333 args{ 334 []int{5, 5, 5}, 335 15, 336 }, 337 []int{5, 5, 5}, 338 }, 339 { 340 "Rescale widths, smaller", 341 args{ 342 []int{5, 5, 5}, 343 10, 344 }, 345 []int{3, 3, 4}, 346 }, 347 } 348 for _, tt := range tests { 349 t.Run(tt.name, func(t *testing.T) { 350 rescaleColumns(tt.args.colWidths, tt.args.targetTotal, false, tt.args.colWidths[0]) 351 if !reflect.DeepEqual(tt.args.colWidths, tt.want) { 352 t.Errorf("rescaleColumns() got = %v, want %v", tt.args.colWidths, tt.want) 353 } 354 total := mathutils.Total(tt.args.colWidths...) 355 if tt.args.targetTotal != total { 356 t.Errorf("rescaleColumns() got total = %v, want total %v", total, tt.args.targetTotal) 357 } 358 }) 359 } 360 }