forked from mirror/coolify-cli
refactor(output): reorganize table formatter and improve test robustness
- Move empty slice check before table writer creation for early exit - Fix error message typo: "ascii w" → "table" - Enhance boolean test to dynamically locate data rows instead of hardcoded indices
This commit is contained in:
@@ -210,12 +210,23 @@ func TestTableFormatter_BooleanValues(t *testing.T) {
|
||||
|
||||
output := buf.String()
|
||||
|
||||
// Check boolean formatting
|
||||
lines := strings.Split(output, "\n")
|
||||
assert.Contains(t, lines[3], "true")
|
||||
assert.Contains(t, lines[3], "false")
|
||||
assert.Contains(t, lines[4], "false")
|
||||
assert.Contains(t, lines[4], "true")
|
||||
// Check boolean formatting - verify both rows contain expected values
|
||||
// Row 1: test1, true, false
|
||||
assert.Contains(t, output, "test1")
|
||||
assert.Contains(t, output, "test2")
|
||||
|
||||
// Find lines containing test data (not headers/borders)
|
||||
var dataLines []string
|
||||
for _, line := range strings.Split(output, "\n") {
|
||||
if strings.Contains(line, "test1") || strings.Contains(line, "test2") {
|
||||
dataLines = append(dataLines, line)
|
||||
}
|
||||
}
|
||||
require.Len(t, dataLines, 2, "expected exactly 2 data rows")
|
||||
assert.Contains(t, dataLines[0], "true")
|
||||
assert.Contains(t, dataLines[0], "false")
|
||||
assert.Contains(t, dataLines[1], "true")
|
||||
assert.Contains(t, dataLines[1], "false")
|
||||
}
|
||||
|
||||
func TestTableFormatter_NilPointer(t *testing.T) {
|
||||
|
||||
+18
-17
@@ -20,16 +20,6 @@ func NewTableFormatter(opts Options) *TableFormatter {
|
||||
}
|
||||
|
||||
func (f *TableFormatter) Format(data any) (err error) {
|
||||
w := tablewriter.NewWriter(f.opts.Writer)
|
||||
defer func() {
|
||||
if renderErr := w.Render(); renderErr != nil && err == nil {
|
||||
err = fmt.Errorf("failed to render ascii w: %w", renderErr)
|
||||
}
|
||||
}()
|
||||
|
||||
// disable ALL CAPS for column headers
|
||||
w.Options(tablewriter.WithHeaderAutoFormat(tw.Off))
|
||||
|
||||
// Handle different data types
|
||||
val := reflect.ValueOf(data)
|
||||
|
||||
@@ -38,6 +28,24 @@ func (f *TableFormatter) Format(data any) (err error) {
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
// Check for empty slice/array before creating the table writer
|
||||
if (val.Kind() == reflect.Slice || val.Kind() == reflect.Array) && val.Len() == 0 {
|
||||
if _, writeErr := fmt.Fprintln(f.opts.Writer, "No data"); writeErr != nil {
|
||||
return fmt.Errorf("failed to write no data message: %w", writeErr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
w := tablewriter.NewWriter(f.opts.Writer)
|
||||
defer func() {
|
||||
if renderErr := w.Render(); renderErr != nil && err == nil {
|
||||
err = fmt.Errorf("failed to render table: %w", renderErr)
|
||||
}
|
||||
}()
|
||||
|
||||
// disable ALL CAPS for column headers
|
||||
w.Options(tablewriter.WithHeaderAutoFormat(tw.Off))
|
||||
|
||||
switch val.Kind() {
|
||||
case reflect.Slice, reflect.Array:
|
||||
return f.formatSlice(w, val)
|
||||
@@ -52,13 +60,6 @@ func (f *TableFormatter) Format(data any) (err error) {
|
||||
|
||||
// formatSlice formats a slice of structs as a table
|
||||
func (f *TableFormatter) formatSlice(w *tablewriter.Table, val reflect.Value) error {
|
||||
if val.Len() == 0 {
|
||||
if _, err := fmt.Fprintln(f.opts.Writer, "No data"); err != nil {
|
||||
return fmt.Errorf("failed to write no data message: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get the first element to determine columns
|
||||
firstElem := val.Index(0)
|
||||
if firstElem.Kind() == reflect.Ptr {
|
||||
|
||||
Reference in New Issue
Block a user