Add unit test for the stream writer to improved line of code coverage (#1898)
- Update dependencies modules - Using the workbook instead of XLSX in the function comments
This commit is contained in:
parent
a64efca31f
commit
5f583549f4
|
@ -409,7 +409,7 @@ func TestDeleteChart(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChartWithLogarithmicBase(t *testing.T) {
|
func TestChartWithLogarithmicBase(t *testing.T) {
|
||||||
// Create test XLSX file with data
|
// Create test workbook with data
|
||||||
f := NewFile()
|
f := NewFile()
|
||||||
sheet1 := f.GetSheetName(0)
|
sheet1 := f.GetSheetName(0)
|
||||||
categories := map[string]float64{
|
categories := map[string]float64{
|
||||||
|
@ -454,14 +454,14 @@ func TestChartWithLogarithmicBase(t *testing.T) {
|
||||||
assert.NoError(t, f.AddChart(sheet1, c.cell, c.opts))
|
assert.NoError(t, f.AddChart(sheet1, c.cell, c.opts))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export XLSX file for human confirmation
|
// Export workbook for human confirmation
|
||||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestChartWithLogarithmicBase10.xlsx")))
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestChartWithLogarithmicBase10.xlsx")))
|
||||||
|
|
||||||
// Write the XLSX file to a buffer
|
// Write the workbook to a buffer
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
assert.NoError(t, f.Write(&buffer))
|
assert.NoError(t, f.Write(&buffer))
|
||||||
|
|
||||||
// Read back the XLSX file from the buffer
|
// Read back the workbook from the buffer
|
||||||
newFile, err := OpenReader(&buffer)
|
newFile, err := OpenReader(&buffer)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
|
@ -228,7 +228,7 @@ func (f *File) getOptions(opts ...Options) *Options {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CharsetTranscoder Set user defined codepage transcoder function for open
|
// CharsetTranscoder Set user defined codepage transcoder function for open
|
||||||
// XLSX from non UTF-8 encoding.
|
// workbook from non UTF-8 encoding.
|
||||||
func (f *File) CharsetTranscoder(fn charsetTranscoderFn) *File { f.CharsetReader = fn; return f }
|
func (f *File) CharsetTranscoder(fn charsetTranscoderFn) *File { f.CharsetReader = fn; return f }
|
||||||
|
|
||||||
// Creates new XML decoder with charset reader.
|
// Creates new XML decoder with charset reader.
|
||||||
|
|
|
@ -365,11 +365,11 @@ func TestNewFile(t *testing.T) {
|
||||||
f := NewFile()
|
f := NewFile()
|
||||||
_, err := f.NewSheet("Sheet1")
|
_, err := f.NewSheet("Sheet1")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
_, err = f.NewSheet("XLSXSheet2")
|
_, err = f.NewSheet("Sheet2")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
_, err = f.NewSheet("XLSXSheet3")
|
_, err = f.NewSheet("Sheet3")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NoError(t, f.SetCellInt("XLSXSheet2", "A23", 56))
|
assert.NoError(t, f.SetCellInt("Sheet2", "A23", 56))
|
||||||
assert.NoError(t, f.SetCellStr("Sheet1", "B20", "42"))
|
assert.NoError(t, f.SetCellStr("Sheet1", "B20", "42"))
|
||||||
f.SetActiveSheet(0)
|
f.SetActiveSheet(0)
|
||||||
|
|
||||||
|
@ -962,7 +962,7 @@ func TestSetDeleteSheet(t *testing.T) {
|
||||||
f, err := prepareTestBook3()
|
f, err := prepareTestBook3()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.NoError(t, f.DeleteSheet("XLSXSheet3"))
|
assert.NoError(t, f.DeleteSheet("Sheet3"))
|
||||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetDeleteSheet.TestBook3.xlsx")))
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetDeleteSheet.TestBook3.xlsx")))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1610,13 +1610,13 @@ func prepareTestBook1() (*File, error) {
|
||||||
|
|
||||||
func prepareTestBook3() (*File, error) {
|
func prepareTestBook3() (*File, error) {
|
||||||
f := NewFile()
|
f := NewFile()
|
||||||
if _, err := f.NewSheet("XLSXSheet2"); err != nil {
|
if _, err := f.NewSheet("Sheet2"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if _, err := f.NewSheet("XLSXSheet3"); err != nil {
|
if _, err := f.NewSheet("Sheet3"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := f.SetCellInt("XLSXSheet2", "A23", 56); err != nil {
|
if err := f.SetCellInt("Sheet2", "A23", 56); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := f.SetCellStr("Sheet1", "B20", "42"); err != nil {
|
if err := f.SetCellStr("Sheet1", "B20", "42"); err != nil {
|
||||||
|
|
6
go.mod
6
go.mod
|
@ -8,10 +8,10 @@ require (
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.8.4
|
||||||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d
|
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d
|
||||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7
|
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7
|
||||||
golang.org/x/crypto v0.22.0
|
golang.org/x/crypto v0.23.0
|
||||||
golang.org/x/image v0.14.0
|
golang.org/x/image v0.14.0
|
||||||
golang.org/x/net v0.24.0
|
golang.org/x/net v0.25.0
|
||||||
golang.org/x/text v0.14.0
|
golang.org/x/text v0.15.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|
12
go.sum
12
go.sum
|
@ -15,14 +15,14 @@ github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7
|
||||||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A=
|
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A=
|
||||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
|
golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
|
||||||
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|
|
@ -359,9 +359,9 @@ var sparklineGroupPresets = []*xlsxX14SparklineGroup{
|
||||||
// AddSparkline provides a function to add sparklines to the worksheet by
|
// AddSparkline provides a function to add sparklines to the worksheet by
|
||||||
// given formatting options. Sparklines are small charts that fit in a single
|
// given formatting options. Sparklines are small charts that fit in a single
|
||||||
// cell and are used to show trends in data. Sparklines are a feature of Excel
|
// cell and are used to show trends in data. Sparklines are a feature of Excel
|
||||||
// 2010 and later only. You can write them to an XLSX file that can be read by
|
// 2010 and later only. You can write them to workbook that can be read by Excel
|
||||||
// Excel 2007, but they won't be displayed. For example, add a grouped
|
// 2007, but they won't be displayed. For example, add a grouped sparkline.
|
||||||
// sparkline. Changes are applied to all three:
|
// Changes are applied to all three:
|
||||||
//
|
//
|
||||||
// err := f.AddSparkline("Sheet1", &excelize.SparklineOptions{
|
// err := f.AddSparkline("Sheet1", &excelize.SparklineOptions{
|
||||||
// Location: []string{"A1", "A2", "A3"},
|
// Location: []string{"A1", "A2", "A3"},
|
||||||
|
|
|
@ -290,7 +290,7 @@ func (sw *StreamWriter) getRowValues(hRow, hCol, vCol int) (res []string, err er
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the token is an XLSX row with the matching row number.
|
// Check if the token is an worksheet row with the matching row number.
|
||||||
func getRowElement(token xml.Token, hRow int) (startElement xml.StartElement, ok bool) {
|
func getRowElement(token xml.Token, hRow int) (startElement xml.StartElement, ok bool) {
|
||||||
startElement, ok = token.(xml.StartElement)
|
startElement, ok = token.(xml.StartElement)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -527,7 +527,7 @@ func (sw *StreamWriter) setCellValFunc(c *xlsxC, val interface{}) error {
|
||||||
var err error
|
var err error
|
||||||
switch val := val.(type) {
|
switch val := val.(type) {
|
||||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
||||||
err = setCellIntFunc(c, val)
|
setCellIntFunc(c, val)
|
||||||
case float32:
|
case float32:
|
||||||
c.T, c.V = setCellFloat(float64(val), -1, 32)
|
c.T, c.V = setCellFloat(float64(val), -1, 32)
|
||||||
case float64:
|
case float64:
|
||||||
|
@ -554,7 +554,7 @@ func (sw *StreamWriter) setCellValFunc(c *xlsxC, val interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// setCellIntFunc is a wrapper of SetCellInt.
|
// setCellIntFunc is a wrapper of SetCellInt.
|
||||||
func setCellIntFunc(c *xlsxC, val interface{}) (err error) {
|
func setCellIntFunc(c *xlsxC, val interface{}) {
|
||||||
switch val := val.(type) {
|
switch val := val.(type) {
|
||||||
case int:
|
case int:
|
||||||
c.T, c.V = setCellInt(val)
|
c.T, c.V = setCellInt(val)
|
||||||
|
@ -576,9 +576,7 @@ func setCellIntFunc(c *xlsxC, val interface{}) (err error) {
|
||||||
c.T, c.V = setCellUint(uint64(val))
|
c.T, c.V = setCellUint(uint64(val))
|
||||||
case uint64:
|
case uint64:
|
||||||
c.T, c.V = setCellUint(val)
|
c.T, c.V = setCellUint(val)
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeCell constructs a cell XML and writes it to the buffer.
|
// writeCell constructs a cell XML and writes it to the buffer.
|
||||||
|
|
|
@ -3,6 +3,7 @@ package excelize
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -224,6 +225,8 @@ func TestStreamTable(t *testing.T) {
|
||||||
assert.Equal(t, newCellNameToCoordinatesError("B", newInvalidCellNameError("B")), streamWriter.AddTable(&Table{Range: "A1:B"}))
|
assert.Equal(t, newCellNameToCoordinatesError("B", newInvalidCellNameError("B")), streamWriter.AddTable(&Table{Range: "A1:B"}))
|
||||||
// Test add table with invalid table name
|
// Test add table with invalid table name
|
||||||
assert.Equal(t, newInvalidNameError("1Table"), streamWriter.AddTable(&Table{Range: "A:B1", Name: "1Table"}))
|
assert.Equal(t, newInvalidNameError("1Table"), streamWriter.AddTable(&Table{Range: "A:B1", Name: "1Table"}))
|
||||||
|
// Test add table with row number exceeds maximum limit
|
||||||
|
assert.Equal(t, ErrMaxRows, streamWriter.AddTable(&Table{Range: "A1048576:C1048576"}))
|
||||||
// Test add table with unsupported charset content types
|
// Test add table with unsupported charset content types
|
||||||
file.ContentTypes = nil
|
file.ContentTypes = nil
|
||||||
file.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
|
file.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
|
||||||
|
@ -332,8 +335,7 @@ func TestStreamSetRowWithStyle(t *testing.T) {
|
||||||
Cell{StyleID: blueStyleID, Value: "value3"},
|
Cell{StyleID: blueStyleID, Value: "value3"},
|
||||||
&Cell{StyleID: blueStyleID, Value: "value3"},
|
&Cell{StyleID: blueStyleID, Value: "value3"},
|
||||||
}, RowOpts{StyleID: grayStyleID}))
|
}, RowOpts{StyleID: grayStyleID}))
|
||||||
err = streamWriter.Flush()
|
assert.NoError(t, streamWriter.Flush())
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
ws, err := file.workSheetReader("Sheet1")
|
ws, err := file.workSheetReader("Sheet1")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -398,3 +400,54 @@ func TestStreamWriterOutlineLevel(t *testing.T) {
|
||||||
}
|
}
|
||||||
assert.NoError(t, file.Close())
|
assert.NoError(t, file.Close())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStreamWriterReader(t *testing.T) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
sw = StreamWriter{
|
||||||
|
rawData: bufferedWriter{},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
sw.rawData.tmp, err = os.CreateTemp(os.TempDir(), "excelize-")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, sw.rawData.tmp.Close())
|
||||||
|
// Test reader stat a closed temp file
|
||||||
|
_, err = sw.rawData.Reader()
|
||||||
|
assert.Error(t, err)
|
||||||
|
_, err = sw.getRowValues(1, 1, 1)
|
||||||
|
assert.Error(t, err)
|
||||||
|
os.Remove(sw.rawData.tmp.Name())
|
||||||
|
|
||||||
|
sw = StreamWriter{
|
||||||
|
file: NewFile(),
|
||||||
|
rawData: bufferedWriter{},
|
||||||
|
}
|
||||||
|
// Test getRowValues without expected row
|
||||||
|
sw.rawData.buf.WriteString("<worksheet><row r=\"1\"><c r=\"B1\"></c></row><worksheet/>")
|
||||||
|
_, err = sw.getRowValues(1, 1, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
sw.rawData.buf.Reset()
|
||||||
|
// Test getRowValues with illegal cell reference
|
||||||
|
sw.rawData.buf.WriteString("<worksheet><row r=\"1\"><c r=\"A\"></c></row><worksheet/>")
|
||||||
|
_, err = sw.getRowValues(1, 1, 1)
|
||||||
|
assert.Equal(t, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")), err)
|
||||||
|
sw.rawData.buf.Reset()
|
||||||
|
// Test getRowValues with invalid c element characters
|
||||||
|
sw.rawData.buf.WriteString("<worksheet><row r=\"1\"><c></row><worksheet/>")
|
||||||
|
_, err = sw.getRowValues(1, 1, 1)
|
||||||
|
assert.EqualError(t, err, "XML syntax error on line 1: element <c> closed by </row>")
|
||||||
|
sw.rawData.buf.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStreamWriterGetRowElement(t *testing.T) {
|
||||||
|
// Test get row element without r attribute
|
||||||
|
dec := xml.NewDecoder(strings.NewReader("<row ht=\"0\" />"))
|
||||||
|
for {
|
||||||
|
token, err := dec.Token()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_, ok := getRowElement(token, 0)
|
||||||
|
assert.False(t, ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue