@@ -132,3 +132,218 @@ func TestStructTableWithDB(t *testing.T) {
132
132
t .Log (table .Debug ())
133
133
}
134
134
}
135
+
136
+ func TestAutoHeaderScenarios (t * testing.T ) {
137
+ type Basic struct {
138
+ Foo int
139
+ Bar string
140
+ baz bool // unexported
141
+ }
142
+
143
+ type WithTags struct {
144
+ ID int `json:"id"`
145
+ Name string `json:"name,omitempty"`
146
+ Age int `json:"-"`
147
+ City string `json:"location"`
148
+ }
149
+
150
+ type Omitted struct {
151
+ SkipMe string `json:"-"`
152
+ KeepMe string
153
+ }
154
+
155
+ type NoTags struct {
156
+ Field1 string
157
+ field2 int // unexported
158
+ }
159
+
160
+ type Embedded struct {
161
+ WithTags
162
+ Extra string
163
+ }
164
+
165
+ type PointerTest struct {
166
+ Value string
167
+ }
168
+
169
+ tests := []struct {
170
+ name string
171
+ data interface {}
172
+ enable bool
173
+ preHeaders []string
174
+ expected string
175
+ }{
176
+ {
177
+ name : "BasicStruct" ,
178
+ data : []Basic {{1 , "test" , true }, {2 , "test2" , false }},
179
+ enable : true ,
180
+ expected : `
181
+ ┌─────┬───────┐
182
+ │ FOO │ BAR │
183
+ ├─────┼───────┤
184
+ │ 1 │ test │
185
+ │ 2 │ test2 │
186
+ └─────┴───────┘
187
+
188
+ ` ,
189
+ },
190
+ {
191
+ name : "WithTags" ,
192
+ data : []WithTags {{1 , "John" , 30 , "NY" }, {2 , "" , 0 , "LA" }},
193
+ enable : true ,
194
+ expected : `
195
+ ┌────┬──────┬──────────┐
196
+ │ ID │ NAME │ LOCATION │
197
+ ├────┼──────┼──────────┤
198
+ │ 1 │ John │ NY │
199
+ │ 2 │ │ LA │
200
+ └────┴──────┴──────────┘
201
+ ` ,
202
+ },
203
+ {
204
+ name : "OmittedFields" ,
205
+ data : []Omitted {{"skip" , "keep" }, {"skip2" , "keep2" }},
206
+ enable : true ,
207
+ expected : `
208
+ ┌────────┐
209
+ │ KEEPME │
210
+ ├────────┤
211
+ │ keep │
212
+ │ keep2 │
213
+ └────────┘
214
+
215
+ ` ,
216
+ },
217
+ {
218
+ name : "NoTags" ,
219
+ data : []NoTags {{"val1" , 42 }, {"val2" , 43 }},
220
+ enable : true ,
221
+ expected : `
222
+ ┌─────────┐
223
+ │ FIELD 1 │
224
+ ├─────────┤
225
+ │ val1 │
226
+ │ val2 │
227
+ └─────────┘
228
+
229
+ ` ,
230
+ },
231
+ {
232
+ name : "Embedded" ,
233
+ data : []Embedded {{WithTags {1 , "John" , 30 , "NY" }, "Extra" }, {WithTags {2 , "Doe" , 25 , "LA" }, "Value" }},
234
+ enable : true ,
235
+ expected : `
236
+ ┌────┬──────┬──────────┬───────┐
237
+ │ ID │ NAME │ LOCATION │ EXTRA │
238
+ ├────┼──────┼──────────┼───────┤
239
+ │ 1 │ John │ NY │ Extra │
240
+ │ 2 │ Doe │ LA │ Value │
241
+ └────┴──────┴──────────┴───────┘
242
+ ` ,
243
+ },
244
+ {
245
+ name : "PointerToStruct" ,
246
+ data : []* PointerTest {{"Value1" }, {"Value2" }},
247
+ enable : true ,
248
+ expected : `
249
+ ┌────────┐
250
+ │ VALUE │
251
+ ├────────┤
252
+ │ Value1 │
253
+ │ Value2 │
254
+ └────────┘
255
+ ` ,
256
+ },
257
+ {
258
+ name : "SliceOfPointers" ,
259
+ data : []* WithTags {{1 , "John" , 30 , "NY" }, {2 , "Doe" , 25 , "LA" }},
260
+ enable : true ,
261
+ expected : `
262
+ ┌────┬──────┬──────────┐
263
+ │ ID │ NAME │ LOCATION │
264
+ ├────┼──────┼──────────┤
265
+ │ 1 │ John │ NY │
266
+ │ 2 │ Doe │ LA │
267
+ └────┴──────┴──────────┘
268
+ ` ,
269
+ },
270
+ {
271
+ name : "NonStruct" ,
272
+ data : [][]string {{"A" , "B" }, {"C" , "D" }},
273
+ enable : false ,
274
+ expected : `
275
+ ┌───┬───┐
276
+ │ A │ B │
277
+ │ C │ D │
278
+ └───┴───┘
279
+ ` ,
280
+ },
281
+ {
282
+ name : "EmptySlice" ,
283
+ data : []WithTags {},
284
+ expected : `` ,
285
+ },
286
+ {
287
+ name : "enabled" ,
288
+ data : []WithTags {{1 , "John" , 30 , "NY" }},
289
+ enable : true ,
290
+ expected : `
291
+ ┌────┬──────┬──────────┐
292
+ │ ID │ NAME │ LOCATION │
293
+ ├────┼──────┼──────────┤
294
+ │ 1 │ John │ NY │
295
+ └────┴──────┴──────────┘
296
+
297
+
298
+ ` , // No header, falls back to string reps
299
+ },
300
+ {
301
+ name : "Disabled" ,
302
+ data : []WithTags {{1 , "John" , 30 , "NY" }},
303
+ enable : false ,
304
+ expected : `
305
+ ┌───┬──────┬────┐
306
+ │ 1 │ John │ NY │
307
+ └───┴──────┴────┘
308
+
309
+ ` , // No header, falls back to string reps
310
+ },
311
+ {
312
+ name : "PreExistingHeaders" ,
313
+ data : []WithTags {{1 , "John" , 30 , "NY" }},
314
+ preHeaders : []string {"CustomID" , "CustomName" , "CustomCity" },
315
+ enable : true ,
316
+ expected : `
317
+ ┌───────────┬─────────────┬─────────────┐
318
+ │ CUSTOM ID │ CUSTOM NAME │ CUSTOM CITY │
319
+ ├───────────┼─────────────┼─────────────┤
320
+ │ 1 │ John │ NY │
321
+ └───────────┴─────────────┴─────────────┘
322
+
323
+ ` ,
324
+ },
325
+ }
326
+
327
+ for _ , tt := range tests {
328
+ t .Run (tt .name , func (t * testing.T ) {
329
+ var buf bytes.Buffer
330
+ table := tablewriter .NewTable (& buf )
331
+ if tt .enable {
332
+ table .Configure (func (cfg * tablewriter.Config ) {
333
+ cfg .Behavior .Struct .AutoHeader = tw .On
334
+ })
335
+ }
336
+
337
+ if len (tt .preHeaders ) > 0 {
338
+ table .Header (tt .preHeaders )
339
+ }
340
+ err := table .Bulk (tt .data )
341
+ if err != nil {
342
+ t .Fatalf ("Bulk failed: %v" , err )
343
+ }
344
+ table .Render ()
345
+
346
+ visualCheck (t , tt .name , buf .String (), tt .expected )
347
+ })
348
+ }
349
+ }
0 commit comments