369 lines
8.8 KiB
Go
369 lines
8.8 KiB
Go
package wpdf
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
)
|
|
|
|
func newBuilderWithPage(t *testing.T) *WPDFBuilder {
|
|
t.Helper()
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
b.AddPage()
|
|
return b
|
|
}
|
|
|
|
func TestNewPDFBuilderDefaults(t *testing.T) {
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
|
|
if b == nil {
|
|
t.Fatal("expected non-nil builder")
|
|
}
|
|
if b.FPDF() == nil {
|
|
t.Fatal("expected non-nil underlying gofpdf builder")
|
|
}
|
|
|
|
if b.fontName != FontHelvetica {
|
|
t.Errorf("default fontName = %v, want %v", b.fontName, FontHelvetica)
|
|
}
|
|
if b.fontStyle != Normal {
|
|
t.Errorf("default fontStyle = %v, want %v", b.fontStyle, Normal)
|
|
}
|
|
if b.fontSize != 12 {
|
|
t.Errorf("default fontSize = %v, want 12", b.fontSize)
|
|
}
|
|
|
|
left, top, right, _ := b.GetMargins()
|
|
if left != 15 || top != 25 || right != 15 {
|
|
t.Errorf("default margins = (%v, %v, %v), want (15, 25, 15)", left, top, right)
|
|
}
|
|
}
|
|
|
|
func TestNewPDFBuilderUnicode(t *testing.T) {
|
|
b := NewPDFBuilder(Portrait, SizeA4, true)
|
|
if b.tr == nil {
|
|
t.Fatal("expected unicode translator to be set")
|
|
}
|
|
// Translator should not panic on simple ASCII input
|
|
out := b.tr("hello")
|
|
if out == "" {
|
|
t.Errorf("translator returned empty string for non-empty input")
|
|
}
|
|
}
|
|
|
|
func TestNewPDFBuilderNonUnicode(t *testing.T) {
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
if got := b.tr("hello"); got != "hello" {
|
|
t.Errorf("non-unicode translator = %q, want %q", got, "hello")
|
|
}
|
|
}
|
|
|
|
func TestNewPDFBuilderLandscape(t *testing.T) {
|
|
b := NewPDFBuilder(Landscape, SizeA4, false)
|
|
w, h := b.GetPageSize()
|
|
if w <= h {
|
|
t.Errorf("landscape: expected width>height, got w=%v h=%v", w, h)
|
|
}
|
|
}
|
|
|
|
func TestNewPDFBuilderPortrait(t *testing.T) {
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
w, h := b.GetPageSize()
|
|
if h <= w {
|
|
t.Errorf("portrait: expected height>width, got w=%v h=%v", w, h)
|
|
}
|
|
}
|
|
|
|
func TestSetMargins(t *testing.T) {
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
b.SetMargins(PDFMargins{Left: 5, Top: 10, Right: 7})
|
|
|
|
if got := b.GetMarginLeft(); got != 5 {
|
|
t.Errorf("MarginLeft = %v, want 5", got)
|
|
}
|
|
if got := b.GetMarginTop(); got != 10 {
|
|
t.Errorf("MarginTop = %v, want 10", got)
|
|
}
|
|
if got := b.GetMarginRight(); got != 7 {
|
|
t.Errorf("MarginRight = %v, want 7", got)
|
|
}
|
|
// MarginBottom is not set explicitly via SetMargins, just verify accessor doesn't panic.
|
|
_ = b.GetMarginBottom()
|
|
}
|
|
|
|
func TestGetWorkAreaWidth(t *testing.T) {
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
b.SetMargins(PDFMargins{Left: 10, Top: 20, Right: 5})
|
|
pw := b.GetPageWidth()
|
|
want := pw - 10 - 5
|
|
if got := b.GetWorkAreaWidth(); got != want {
|
|
t.Errorf("GetWorkAreaWidth = %v, want %v", got, want)
|
|
}
|
|
}
|
|
|
|
func TestGetPageWidthHeight(t *testing.T) {
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
w, h := b.GetPageSize()
|
|
if got := b.GetPageWidth(); got != w {
|
|
t.Errorf("PageWidth = %v, want %v", got, w)
|
|
}
|
|
if got := b.GetPageHeight(); got != h {
|
|
t.Errorf("PageHeight = %v, want %v", got, h)
|
|
}
|
|
}
|
|
|
|
func TestSetGetTextColor(t *testing.T) {
|
|
b := newBuilderWithPage(t)
|
|
b.SetTextColor(10, 20, 30)
|
|
r, g, bl := b.GetTextColor()
|
|
if r != 10 || g != 20 || bl != 30 {
|
|
t.Errorf("GetTextColor = (%d,%d,%d), want (10,20,30)", r, g, bl)
|
|
}
|
|
}
|
|
|
|
func TestSetGetDrawColor(t *testing.T) {
|
|
b := newBuilderWithPage(t)
|
|
b.SetDrawColor(40, 50, 60)
|
|
r, g, bl := b.GetDrawColor()
|
|
if r != 40 || g != 50 || bl != 60 {
|
|
t.Errorf("GetDrawColor = (%d,%d,%d), want (40,50,60)", r, g, bl)
|
|
}
|
|
}
|
|
|
|
func TestSetGetFillColor(t *testing.T) {
|
|
b := newBuilderWithPage(t)
|
|
b.SetFillColor(70, 80, 90)
|
|
r, g, bl := b.GetFillColor()
|
|
if r != 70 || g != 80 || bl != 90 {
|
|
t.Errorf("GetFillColor = (%d,%d,%d), want (70,80,90)", r, g, bl)
|
|
}
|
|
}
|
|
|
|
func TestSetGetLineWidth(t *testing.T) {
|
|
b := newBuilderWithPage(t)
|
|
b.SetLineWidth(2.5)
|
|
if got := b.GetLineWidth(); got != 2.5 {
|
|
t.Errorf("LineWidth = %v, want 2.5", got)
|
|
}
|
|
}
|
|
|
|
func TestSetFont(t *testing.T) {
|
|
b := newBuilderWithPage(t)
|
|
b.SetFont(FontTimes, Bold, 16)
|
|
if b.fontName != FontTimes {
|
|
t.Errorf("fontName = %v, want %v", b.fontName, FontTimes)
|
|
}
|
|
if b.fontStyle != Bold {
|
|
t.Errorf("fontStyle = %v, want %v", b.fontStyle, Bold)
|
|
}
|
|
if got := b.GetFontSize(); got != 16 {
|
|
t.Errorf("FontSize = %v, want 16", got)
|
|
}
|
|
if b.cellHeight <= 0 {
|
|
t.Errorf("cellHeight must be >0 after SetFont, got %v", b.cellHeight)
|
|
}
|
|
}
|
|
|
|
func TestSetCellSpacing(t *testing.T) {
|
|
b := newBuilderWithPage(t)
|
|
b.SetCellSpacing(3.5)
|
|
if b.cellSpacing != 3.5 {
|
|
t.Errorf("cellSpacing = %v, want 3.5", b.cellSpacing)
|
|
}
|
|
}
|
|
|
|
func TestSetGetXY(t *testing.T) {
|
|
b := newBuilderWithPage(t)
|
|
|
|
b.SetX(50)
|
|
if got := b.GetX(); got != 50 {
|
|
t.Errorf("X = %v, want 50", got)
|
|
}
|
|
|
|
b.SetY(60)
|
|
if got := b.GetY(); got != 60 {
|
|
t.Errorf("Y = %v, want 60", got)
|
|
}
|
|
|
|
b.SetXY(70, 80)
|
|
x, y := b.GetXY()
|
|
if x != 70 || y != 80 {
|
|
t.Errorf("GetXY = (%v,%v), want (70,80)", x, y)
|
|
}
|
|
}
|
|
|
|
func TestIncX(t *testing.T) {
|
|
b := newBuilderWithPage(t)
|
|
b.SetX(10)
|
|
b.IncX(5)
|
|
if got := b.GetX(); got != 15 {
|
|
t.Errorf("after IncX: X = %v, want 15", got)
|
|
}
|
|
}
|
|
|
|
func TestDebug(t *testing.T) {
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
if b.debug != false {
|
|
t.Errorf("default debug = %v, want false", b.debug)
|
|
}
|
|
b.Debug(true)
|
|
if !b.debug {
|
|
t.Errorf("Debug(true) did not enable debug")
|
|
}
|
|
b.Debug(false)
|
|
if b.debug {
|
|
t.Errorf("Debug(false) did not disable debug")
|
|
}
|
|
}
|
|
|
|
func TestPageNo(t *testing.T) {
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
if got := b.PageNo(); got != 0 {
|
|
t.Errorf("PageNo before AddPage = %v, want 0", got)
|
|
}
|
|
b.AddPage()
|
|
if got := b.PageNo(); got != 1 {
|
|
t.Errorf("PageNo after first AddPage = %v, want 1", got)
|
|
}
|
|
b.AddPage()
|
|
if got := b.PageNo(); got != 2 {
|
|
t.Errorf("PageNo after second AddPage = %v, want 2", got)
|
|
}
|
|
}
|
|
|
|
func TestBuildEmpty(t *testing.T) {
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
b.AddPage()
|
|
bin, err := b.Build()
|
|
if err != nil {
|
|
t.Fatalf("Build() error: %v", err)
|
|
}
|
|
if len(bin) == 0 {
|
|
t.Fatal("Build() returned empty bytes")
|
|
}
|
|
// PDFs start with "%PDF-"
|
|
if !bytes.HasPrefix(bin, []byte("%PDF-")) {
|
|
t.Errorf("Build() output does not start with %%PDF- header: %q", bin[:min(10, len(bin))])
|
|
}
|
|
}
|
|
|
|
func TestBuildWithContent(t *testing.T) {
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
b.AddPage()
|
|
b.Cell("Hello", NewPDFCellOpt().Width(50))
|
|
b.Ln(5)
|
|
b.MultiCell("multiline content")
|
|
b.Rect(10, 10, RectFill, NewPDFRectOpt().X(20).Y(20).FillColor(255, 0, 0))
|
|
b.Line(0, 0, 100, 100, NewPDFLineOpt().LineWidth(0.5))
|
|
|
|
bin, err := b.Build()
|
|
if err != nil {
|
|
t.Fatalf("Build() error: %v", err)
|
|
}
|
|
if !bytes.HasPrefix(bin, []byte("%PDF-")) {
|
|
t.Errorf("Build() output does not start with %%PDF- header")
|
|
}
|
|
}
|
|
|
|
func TestGetStringWidth(t *testing.T) {
|
|
b := newBuilderWithPage(t)
|
|
w := b.GetStringWidth("Hello")
|
|
if w <= 0 {
|
|
t.Errorf("GetStringWidth = %v, want >0", w)
|
|
}
|
|
|
|
wLong := b.GetStringWidth("Hello, this is a longer string")
|
|
if wLong <= w {
|
|
t.Errorf("longer string should have wider width: short=%v long=%v", w, wLong)
|
|
}
|
|
}
|
|
|
|
func TestGetStringWidthWithFontOverride(t *testing.T) {
|
|
b := newBuilderWithPage(t)
|
|
b.SetFont(FontHelvetica, Normal, 10)
|
|
|
|
wSmall := b.GetStringWidth("Hello", *NewPDFCellOpt().FontSize(10))
|
|
wLarge := b.GetStringWidth("Hello", *NewPDFCellOpt().FontSize(40))
|
|
|
|
if wLarge <= wSmall {
|
|
t.Errorf("larger font should yield wider string: small=%v large=%v", wSmall, wLarge)
|
|
}
|
|
|
|
// Original font must be restored.
|
|
if b.fontSize != 10 {
|
|
t.Errorf("font size not restored: %v, want 10", b.fontSize)
|
|
}
|
|
}
|
|
|
|
func TestSetAutoPageBreak(t *testing.T) {
|
|
b := newBuilderWithPage(t)
|
|
b.SetAutoPageBreak(true, 10)
|
|
enabled, margin := b.FPDF().GetAutoPageBreak()
|
|
if !enabled || margin != 10 {
|
|
t.Errorf("AutoPageBreak = (%v, %v), want (true, 10)", enabled, margin)
|
|
}
|
|
|
|
b.SetAutoPageBreak(false, 0)
|
|
enabled, _ = b.FPDF().GetAutoPageBreak()
|
|
if enabled {
|
|
t.Errorf("AutoPageBreak should be disabled")
|
|
}
|
|
}
|
|
|
|
func TestSetFooterFunc(t *testing.T) {
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
called := false
|
|
b.SetFooterFunc(func() { called = true })
|
|
b.AddPage()
|
|
_, err := b.Build()
|
|
if err != nil {
|
|
t.Fatalf("Build error: %v", err)
|
|
}
|
|
if !called {
|
|
t.Errorf("footer func was not called")
|
|
}
|
|
}
|
|
|
|
func TestBookmark(t *testing.T) {
|
|
b := newBuilderWithPage(t)
|
|
// Should not panic
|
|
b.Bookmark("section 1", 0, b.GetY())
|
|
|
|
_, err := b.Build()
|
|
if err != nil {
|
|
t.Fatalf("Build error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestLnAdvancesY(t *testing.T) {
|
|
b := newBuilderWithPage(t)
|
|
b.SetXY(20, 50)
|
|
b.Ln(10)
|
|
if y := b.GetY(); y <= 50 {
|
|
t.Errorf("Ln did not advance Y: before=50, after=%v", y)
|
|
}
|
|
}
|
|
|
|
func TestDebugAddPage(t *testing.T) {
|
|
// Test with debug = true to cover that branch
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
b.Debug(true)
|
|
b.AddPage()
|
|
// Just verify Build still works
|
|
_, err := b.Build()
|
|
if err != nil {
|
|
t.Fatalf("Build with debug page error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestDebugLn(t *testing.T) {
|
|
b := NewPDFBuilder(Portrait, SizeA4, false)
|
|
b.AddPage()
|
|
b.Debug(true)
|
|
b.SetXY(20, 50)
|
|
b.Ln(10)
|
|
_, err := b.Build()
|
|
if err != nil {
|
|
t.Fatalf("Build with debug Ln error: %v", err)
|
|
}
|
|
}
|