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) } }