shad-go/excelwriter/writer_test.go

268 lines
5.9 KiB
Go

package excelwriter_test
import (
"fmt"
"os"
"testing"
"github.com/stretchr/testify/require"
"github.com/xuri/excelize/v2"
"gitlab.com/slon/shad-go/excelwriter"
)
const Sheet = "Sheet1"
type MyInt int
type Basic struct {
I int `xlsx:"i"`
UI uint `xlsx:"ui"`
I16 int16 `xlsx:"i_16"`
UI16 uint16 `xlsx:"ui_16"`
I32 int32 `xlsx:"i_32"`
UI32 uint32 `xlsx:"ui_32"`
I64 int64 `xlsx:"i_64"`
UI64 uint64 `xlsx:"ui_64"`
Float float32 `xlsx:"float"`
Double float64 `xlsx:"double"`
Bool bool `xlsx:"bool"`
String string `xlsx:"string"`
MyInt int `xlsx:"my_int"`
}
type Inner struct {
Name string `xlsx:"name"`
}
type TextInt int
func (i TextInt) MarshalText() ([]byte, error) {
return []byte("__" + fmt.Sprint(i) + "__"), nil
}
type TextStruct struct {
V string
}
func (s TextStruct) MarshalText() (text []byte, err error) {
return []byte("__" + s.V + "__"), nil
}
func TestWriter_basic(t *testing.T) {
f := excelize.NewFile()
_, err := f.NewSheet(Sheet)
require.NoError(t, err)
w := excelwriter.New(f)
b := &Basic{
I: -1,
UI: 1,
I16: -16,
UI16: 16,
I32: -32,
UI32: 32,
I64: -64,
UI64: 64,
Float: -2.5,
Double: 5.5,
Bool: true,
String: "hello",
MyInt: 23,
}
require.NoError(t, w.WriteRow(b))
storeFile(t, f, "basic")
rows := readAll(t, f, true)
require.Equal(t, []string{"i", "ui", "i_16", "ui_16", "i_32", "ui_32", "i_64", "ui_64", "float", "double", "bool", "string", "my_int"}, rows[0])
require.Equal(t, []string{"-1", "1", "-16", "16", "-32", "32", "-64", "64", "-2.5", "5.5", "1", "hello", "23"}, rows[1])
}
func TestWriter_map(t *testing.T) {
f := excelize.NewFile()
_, err := f.NewSheet(Sheet)
require.NoError(t, err)
w := excelwriter.New(f)
require.NoError(t, w.WriteRow(map[string]any{
"id": 29,
"name": "hello",
"title": "yo",
}))
require.NoError(t, w.WriteRow(map[string]any{}))
require.NoError(t, w.WriteRow(map[TextStruct]any{
{"id"}: 18,
{"name"}: "tm",
}))
storeFile(t, f, "map")
rows := readAll(t, f, true)
require.Equal(t, []string{"id", "name", "title", "__id__", "__name__"}, rows[0])
require.Equal(t, []string{"29", "hello", "yo"}, rows[1])
require.Equal(t, []string{"", "", "", "18", "tm"}, rows[2])
}
type E struct {
ID string `xlsx:"id"`
NoTag string
Skipped int `xlsx:"-"`
private float32 `xlsx:"private"`
TextInt TextInt `xlsx:"text-int"`
TextStruct TextStruct `xlsx:"text-struct"`
Struct Inner `xlsx:"inner"`
StructPtr *Inner `xlsx:"inner-ptr"`
Slice []int `xlsx:"slice"`
Array [2]int `xlsx:"arr"`
Map map[string]string `xlsx:"map"`
TMMap map[TextStruct]string `xlsx:"tm-map"`
F func() `xlsx:"func"`
Ch chan int `xlsx:"chan"`
}
func TestWriter_elaborate(t *testing.T) {
f := excelize.NewFile()
_, err := f.NewSheet("Sheet1")
require.NoError(t, err)
w := excelwriter.New(f)
e := &E{
ID: "42",
NoTag: "no-tag",
Skipped: 29,
private: 2,
TextInt: 77,
TextStruct: TextStruct{V: "text-struct"},
Struct: Inner{Name: "inner"},
StructPtr: &Inner{Name: "inner-ptr"},
Slice: []int{1, 2, 3},
Array: [2]int{4, 5},
Map: map[string]string{"foo": "bar"},
TMMap: map[TextStruct]string{{"foo"}: "bar"},
F: func() { fmt.Println("hello") },
Ch: make(chan int, 10),
}
require.NoError(t, w.WriteRow(e))
storeFile(t, f, "elaborate")
rows := readAll(t, f, true)
require.Equal(t, []string{"id", "notag", "private", "text-int", "text-struct", "inner", "inner-ptr", "slice", "arr", "map", "tm-map"}, rows[0])
require.Equal(t, []string{"42", "no-tag", "2", "__77__", "__text-struct__", `{"Name":"inner"}`, `{"Name":"inner-ptr"}`, "[1,2,3]", "[4,5]", `{"foo":"bar"}`, `{"__foo__":"bar"}`}, rows[1])
}
func TestWriter_ptr(t *testing.T) {
f := excelize.NewFile()
_, err := f.NewSheet(Sheet)
require.NoError(t, err)
w := excelwriter.New(f)
require.NoError(t, w.WriteRow(struct{ Name string }{"foo"}))
require.NoError(t, w.WriteRow(&struct{ Name string }{"bar"}))
require.NoError(t, w.WriteRow(map[string]string{"name": "baz"}))
require.NoError(t, w.WriteRow(&map[string]string{"name": "qux"}))
storeFile(t, f, "ptr")
rows := readAll(t, f, true)
require.Equal(t, []string{"name"}, rows[0])
require.Equal(t, []string{"foo"}, rows[1])
require.Equal(t, []string{"bar"}, rows[2])
require.Equal(t, []string{"baz"}, rows[3])
require.Equal(t, []string{"qux"}, rows[4])
}
func TestWriter_unsupported(t *testing.T) {
f := excelize.NewFile()
_, err := f.NewSheet("Sheet1")
require.NoError(t, err)
w := excelwriter.New(f)
require.Error(t, w.WriteRow(2))
require.Error(t, w.WriteRow(nil))
var b *Basic
require.Error(t, w.WriteRow(b))
}
type S struct {
P float64 `xlsx:"percent,numfmt:9"`
D int `xlsx:"date,numfmt:15"`
D2 int `xlsx:",numfmt:15"`
T float64 `xlsx:"time,numfmt:22"`
Y int `xlsx:"jpy,numfmt:194"`
}
func TestWriter_style(t *testing.T) {
f := excelize.NewFile()
_, err := f.NewSheet("Sheet1")
require.NoError(t, err)
w := excelwriter.New(f)
s := &S{
P: 0.5,
D: 100,
D2: 100,
T: 100.5,
Y: 200,
}
require.NoError(t, w.WriteRow(s))
storeFile(t, f, "style")
rows := readAll(t, f, false)
require.Equal(t, []string{"percent", "date", "d2", "time", "jpy"}, rows[0])
require.Equal(t, []string{"50%", "9-Apr-00", "9-Apr-00", "4/9/00 12:00", "¥200.00"}, rows[1])
}
func readAll(t *testing.T, f *excelize.File, raw bool) [][]string {
t.Helper()
var out [][]string
rows, err := f.Rows(Sheet)
require.NoError(t, err)
var opts []excelize.Options
if raw {
opts = append(opts, excelize.Options{RawCellValue: true})
}
for i := 1; rows.Next(); i++ {
row, err := rows.Columns(opts...)
require.NoError(t, err)
out = append(out, row)
}
return out
}
func storeFile(t *testing.T, f *excelize.File, prefix string) {
t.Helper()
out, err := os.CreateTemp("/tmp", prefix+"-*.xlsx")
require.NoError(t, err)
_, err = f.WriteTo(out)
require.NoError(t, err)
t.Logf("stored file in %s", out.Name())
}