PDF Rendering still fails from WebUI

This commit is contained in:
2025-12-29 08:08:00 +01:00
parent 0d3164d448
commit c5b3034a8a
3 changed files with 178 additions and 16 deletions
+141
View File
@@ -0,0 +1,141 @@
package pdfrender
import (
"bamort/config"
"bamort/database"
"bamort/models"
"bytes"
"os"
"path/filepath"
"testing"
"github.com/pdfcpu/pdfcpu/pkg/api"
)
// TestAPIvsTestOutput_ShouldBeIdentical verifies that the API handler and test produce identical PDFs
func TestAPIvsTestOutput_ShouldBeIdentical(t *testing.T) {
database.SetupTestDB()
// Load character with ID 18 (same as visual inspection test)
char := &models.Char{}
err := char.FirstID("18")
if err != nil {
t.Fatalf("Failed to load character: %v", err)
}
// === PATH 1: Test method (current working) ===
viewModel1, err := MapCharacterToViewModel(char)
if err != nil {
t.Fatalf("Failed to map character (test path): %v", err)
}
loader1 := NewTemplateLoader("../templates/Default_A4_Quer")
if err := loader1.LoadTemplates(); err != nil {
t.Fatalf("Failed to load templates (test path): %v", err)
}
renderer1 := NewPDFRenderer()
testDate := "28.12.2025"
var testPDFs [][]byte
page1PDFs, _ := RenderPageWithContinuations(viewModel1, "page_1.html", 1, testDate, loader1, renderer1)
testPDFs = append(testPDFs, page1PDFs...)
page2PDFs, _ := RenderPageWithContinuations(viewModel1, "page_2.html", 2, testDate, loader1, renderer1)
testPDFs = append(testPDFs, page2PDFs...)
page3PDFs, _ := RenderPageWithContinuations(viewModel1, "page_3.html", 3, testDate, loader1, renderer1)
testPDFs = append(testPDFs, page3PDFs...)
page4PDFs, _ := RenderPageWithContinuations(viewModel1, "page_4.html", 4, testDate, loader1, renderer1)
testPDFs = append(testPDFs, page4PDFs...)
// === PATH 2: API handler method ===
viewModel2, err := MapCharacterToViewModel(char)
if err != nil {
t.Fatalf("Failed to map character (API path): %v", err)
}
// Use same template resolution as API handler
templateID := "Default_A4_Quer"
templateDir := filepath.Join(config.Cfg.TemplatesDir, templateID)
t.Logf("API template dir: %s", templateDir)
loader2 := NewTemplateLoader(templateDir)
if err := loader2.LoadTemplates(); err != nil {
t.Fatalf("Failed to load templates (API path): %v", err)
}
renderer2 := NewPDFRenderer()
currentDate := testDate // Use same date as test for exact comparison
t.Logf("Using date: %s", currentDate)
var apiPDFs [][]byte
page1PDFs, _ = RenderPageWithContinuations(viewModel2, "page_1.html", 1, currentDate, loader2, renderer2)
apiPDFs = append(apiPDFs, page1PDFs...)
page2PDFs, _ = RenderPageWithContinuations(viewModel2, "page_2.html", 2, currentDate, loader2, renderer2)
apiPDFs = append(apiPDFs, page2PDFs...)
page3PDFs, _ = RenderPageWithContinuations(viewModel2, "page_3.html", 3, currentDate, loader2, renderer2)
apiPDFs = append(apiPDFs, page3PDFs...)
page4PDFs, _ = RenderPageWithContinuations(viewModel2, "page_4.html", 4, currentDate, loader2, renderer2)
apiPDFs = append(apiPDFs, page4PDFs...)
// === COMPARISON ===
if len(testPDFs) != len(apiPDFs) {
t.Fatalf("Different number of PDFs: test=%d, api=%d", len(testPDFs), len(apiPDFs))
}
t.Logf("Both methods generated %d page PDFs", len(testPDFs))
// Merge both for final comparison
tmpDir1 := "/tmp/bamort_test_compare"
tmpDir2 := "/tmp/bamort_api_compare"
os.MkdirAll(tmpDir1, 0755)
os.MkdirAll(tmpDir2, 0755)
defer os.RemoveAll(tmpDir1)
defer os.RemoveAll(tmpDir2)
// Save and merge test PDFs
var testPaths []string
for i, pdf := range testPDFs {
path := filepath.Join(tmpDir1, "page_"+string(rune('0'+i))+".pdf")
os.WriteFile(path, pdf, 0644)
testPaths = append(testPaths, path)
}
testMerged := filepath.Join(tmpDir1, "merged.pdf")
api.MergeCreateFile(testPaths, testMerged, false, nil)
// Save and merge API PDFs
var apiPaths []string
for i, pdf := range apiPDFs {
path := filepath.Join(tmpDir2, "page_"+string(rune('0'+i))+".pdf")
os.WriteFile(path, pdf, 0644)
apiPaths = append(apiPaths, path)
}
apiMerged := filepath.Join(tmpDir2, "merged.pdf")
api.MergeCreateFile(apiPaths, apiMerged, false, nil)
// Read merged PDFs
testBytes, _ := os.ReadFile(testMerged)
apiBytes, _ := os.ReadFile(apiMerged)
t.Logf("Test PDF size: %d bytes", len(testBytes))
t.Logf("API PDF size: %d bytes", len(apiBytes))
// Check if identical (excluding date metadata)
if bytes.Equal(testBytes, apiBytes) {
t.Log("✓ PDFs are byte-identical")
} else {
// Save for manual inspection
os.WriteFile("/tmp/test_output.pdf", testBytes, 0644)
os.WriteFile("/tmp/api_output.pdf", apiBytes, 0644)
t.Logf("PDFs differ - saved to /tmp/test_output.pdf and /tmp/api_output.pdf for comparison")
t.Log("Note: Difference might be due to date stamps - checking individual pages...")
// Compare individual pages
for i := 0; i < len(testPDFs); i++ {
if bytes.Equal(testPDFs[i], apiPDFs[i]) {
t.Logf(" Page %d: identical", i+1)
} else {
t.Logf(" Page %d: DIFFERENT (test=%d bytes, api=%d bytes)", i+1, len(testPDFs[i]), len(apiPDFs[i]))
}
}
}
}
+19 -7
View File
@@ -87,7 +87,7 @@ func ExportCharacterToPDF(c *gin.Context) {
renderer := NewPDFRenderer()
currentDate := time.Now().Format("02.01.2006")
// Render all 4 pages with continuations
// Generate all pages with continuations if needed
var allPDFs [][]byte
// Page 1: Stats
@@ -96,7 +96,10 @@ func ExportCharacterToPDF(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to render page 1: " + err.Error()})
return
}
allPDFs = append(allPDFs, page1PDFs...)
//allPDFs = append(allPDFs, page1PDFs...)
for _, pdf := range page1PDFs {
allPDFs = append(allPDFs, pdf)
}
// Page 2: Play
page2PDFs, err := RenderPageWithContinuations(viewModel, "page_2.html", 2, currentDate, loader, renderer)
@@ -104,7 +107,10 @@ func ExportCharacterToPDF(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to render page 2: " + err.Error()})
return
}
allPDFs = append(allPDFs, page2PDFs...)
//allPDFs = append(allPDFs, page2PDFs...)
for _, pdf := range page2PDFs {
allPDFs = append(allPDFs, pdf)
}
// Page 3: Spells
page3PDFs, err := RenderPageWithContinuations(viewModel, "page_3.html", 3, currentDate, loader, renderer)
@@ -112,7 +118,10 @@ func ExportCharacterToPDF(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to render page 3: " + err.Error()})
return
}
allPDFs = append(allPDFs, page3PDFs...)
//allPDFs = append(allPDFs, page3PDFs...)
for _, pdf := range page3PDFs {
allPDFs = append(allPDFs, pdf)
}
// Page 4: Equipment
page4PDFs, err := RenderPageWithContinuations(viewModel, "page_4.html", 4, currentDate, loader, renderer)
@@ -120,7 +129,10 @@ func ExportCharacterToPDF(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to render page 4: " + err.Error()})
return
}
allPDFs = append(allPDFs, page4PDFs...)
//allPDFs = append(allPDFs, page4PDFs...)
for _, pdf := range page4PDFs {
allPDFs = append(allPDFs, pdf)
}
// Merge PDFs if needed
var finalPDF []byte
@@ -128,7 +140,7 @@ func ExportCharacterToPDF(c *gin.Context) {
finalPDF = allPDFs[0]
} else {
// Merge multiple PDFs
tmpDir := "/tmp/bamort_pdf_export"
tmpDir := fmt.Sprintf("/tmp/bamort_pdf_export_%d", time.Now().UnixNano())
if err := os.MkdirAll(tmpDir, 0755); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create temp directory"})
return
@@ -147,7 +159,7 @@ func ExportCharacterToPDF(c *gin.Context) {
}
// Merge PDFs
combinedPath := fmt.Sprintf("%s/combined.pdf", tmpDir)
combinedPath := fmt.Sprintf("%s/combined_%d.pdf", tmpDir, time.Now().UnixNano())
if err := api.MergeCreateFile(filePaths, combinedPath, false, nil); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to merge PDFs: " + err.Error()})
return
+18 -9
View File
@@ -1,6 +1,7 @@
package pdfrender
import (
"bamort/config"
"bamort/database"
"bamort/models"
"fmt"
@@ -8,6 +9,7 @@ import (
"path/filepath"
"strings"
"testing"
"time"
"github.com/pdfcpu/pdfcpu/pkg/api"
)
@@ -519,10 +521,10 @@ func TestVisualInspection_AllPages(t *testing.T) {
database.SetupTestDB()
// Load character Fanjo Vetrani with ID 18 from test database
charID := "18"
char := &models.Char{}
err := char.FirstID("18")
if err != nil {
t.Fatalf("Failed to load character with ID 18 (Fanjo Vetrani): %v", err)
if err := char.FirstID(charID); err != nil {
t.Fatalf("Failed to load character with ID %s (Fanjo Vetrani): %v", charID, err)
}
// Verify we loaded the correct character
@@ -537,25 +539,32 @@ func TestVisualInspection_AllPages(t *testing.T) {
t.Fatalf("Failed to map character: %v", err)
}
templateID := "Default_A4_Quer"
// Load templates
loader := NewTemplateLoader("../templates/Default_A4_Quer")
if err = loader.LoadTemplates(); err != nil {
templateDir := filepath.Join(config.Cfg.TemplatesDir, templateID)
// Load templates
loader := NewTemplateLoader(templateDir)
if err := loader.LoadTemplates(); err != nil {
t.Fatalf("Failed to load templates: %v", err)
}
renderer := NewPDFRenderer()
currentDate := time.Now().Format("02.01.2006")
// Generate all pages with continuations if needed
allPDFs := [][]byte{}
var allPDFs [][]byte
//#####################################
var filePaths []string
outputDir := "/tmp/bamort_pdf_test"
if err := os.MkdirAll(outputDir, 0755); err != nil {
t.Fatalf("Failed to create output directory: %v", err)
}
//#####################################
// Page 1: Stats page with skills (may have continuations)
t.Log("Generating Page 1: Stats...")
page1PDFs, err := RenderPageWithContinuations(viewModel, "page_1.html", 1, "18.12.2025", loader, renderer)
page1PDFs, err := RenderPageWithContinuations(viewModel, "page_1.html", 1, currentDate, loader, renderer)
if err != nil {
t.Fatalf("Failed to generate page1: %v", err)
}
@@ -580,7 +589,7 @@ func TestVisualInspection_AllPages(t *testing.T) {
// Page 2: Play/Adventure page with weapons (may have continuations)
t.Log("Generating Page 2: Play...")
page2PDFs, err := RenderPageWithContinuations(viewModel, "page_2.html", 2, "18.12.2025", loader, renderer)
page2PDFs, err := RenderPageWithContinuations(viewModel, "page_2.html", 2, currentDate, loader, renderer)
if err != nil {
t.Fatalf("Failed to generate page2: %v", err)
}
@@ -605,7 +614,7 @@ func TestVisualInspection_AllPages(t *testing.T) {
// Page 3: Spells page (may have continuations)
t.Log("Generating Page 3: Spells...")
page3PDFs, err := RenderPageWithContinuations(viewModel, "page_3.html", 3, "18.12.2025", loader, renderer)
page3PDFs, err := RenderPageWithContinuations(viewModel, "page_3.html", 3, currentDate, loader, renderer)
if err != nil {
t.Fatalf("Failed to generate page3: %v", err)
}