diff --git a/pkg/tablewriter/table_output.golden b/pkg/tablewriter/table_output.golden new file mode 100755 index 00000000..dfe3299c --- /dev/null +++ b/pkg/tablewriter/table_output.golden @@ -0,0 +1,3 @@ +Name birthday month first_nested second_nested Age +Tom 12 234-0934 2340-234234 28.12 +Jerry 3 aflfafe-afjlk falj-fjlkjlkadf 36.22 diff --git a/pkg/tablewriter/tablewriter.go b/pkg/tablewriter/tablewriter.go index 22e8e147..36a86bdf 100644 --- a/pkg/tablewriter/tablewriter.go +++ b/pkg/tablewriter/tablewriter.go @@ -2,6 +2,7 @@ package tablewriter import ( "fmt" + "io" "os" "reflect" "strings" @@ -22,7 +23,7 @@ func StructValues(data interface{}) string { continue } if shouldFlatten(v.Type().Field(i)) { - fmt.Fprintf(s, "%v\t", StructValues(v.Field(i).Interface())) + fmt.Fprintf(s, "%v", StructValues(v.Field(i).Interface())) continue } fmt.Fprintf(s, "%v\t", v.Field(i).Interface()) @@ -46,7 +47,7 @@ func StructFieldNames(data interface{}) string { continue } if shouldFlatten(field) { - fmt.Fprintf(s, "%s\t", StructFieldNames(reflect.New(field.Type).Interface())) + fmt.Fprintf(s, "%s", StructFieldNames(reflect.New(field.Type).Interface())) continue } fmt.Fprintf(s, "%s\t", fieldName(field)) @@ -54,6 +55,9 @@ func StructFieldNames(data interface{}) string { return s.String() } +// The output io.Writer for WriteTable. This is globally defined to allow overriding in tests. +var tableOutput io.Writer = os.Stdout + // WriteTable writes the given list elements to stdout in a human readable // tabular format. Headers abide by the `table` struct tag. // @@ -63,7 +67,7 @@ func WriteTable(length int, each func(i int) interface{}) error { if length < 1 { return nil } - w := tabwriter.NewWriter(os.Stdout, 0, 0, 4, ' ', 0) + w := tabwriter.NewWriter(tableOutput, 0, 0, 4, ' ', 0) defer func() { _ = w.Flush() }() // Best effort. for ix := 0; ix < length; ix++ { item := each(ix) diff --git a/pkg/tablewriter/tablewriter_test.go b/pkg/tablewriter/tablewriter_test.go new file mode 100644 index 00000000..5318dd1e --- /dev/null +++ b/pkg/tablewriter/tablewriter_test.go @@ -0,0 +1,68 @@ +package tablewriter + +import ( + "bytes" + "flag" + "io/ioutil" + "testing" + + "cdr.dev/slog/sloggers/slogtest/assert" +) + +var write = flag.Bool("write", false, "write to the golden files") + +func TestTableWriter(t *testing.T) { + type NestedRow struct { + NestedOne string `table:"first_nested"` + NestedTwo string `table:"second_nested"` + } + + type Row struct { + ID string `table:"-"` + Name string + BirthdayMonth int `table:"birthday month"` + Nested NestedRow `table:"_"` + Age float32 + } + + items := []Row{ + { + ID: "13123lkjqlkj-2f323l--f23f", + Name: "Tom", + BirthdayMonth: 12, + Age: 28.12, + Nested: NestedRow{ + NestedOne: "234-0934", + NestedTwo: "2340-234234", + }, + }, + { + ID: "afwaflkj23kl-2f323l--f23f", + Name: "Jerry", + BirthdayMonth: 3, + Age: 36.22, + Nested: NestedRow{ + NestedOne: "aflfafe-afjlk", + NestedTwo: "falj-fjlkjlkadf", + }, + }, + } + + buf := bytes.NewBuffer(nil) + tableOutput = buf + err := WriteTable(len(items), func(i int) interface{} { return items[i] }) + assert.Success(t, "write table", err) + + assertGolden(t, "table_output.golden", buf.Bytes()) +} + +func assertGolden(t *testing.T, path string, output []byte) { + if *write { + err := ioutil.WriteFile(path, output, 0777) + assert.Success(t, "write file", err) + return + } + goldenContent, err := ioutil.ReadFile(path) + assert.Success(t, "read golden file", err) + assert.Equal(t, "golden content matches", string(goldenContent), string(output)) +}