package pdfrender import ( "testing" ) func TestPreparePaginatedPageData_Page1Stats(t *testing.T) { // Create test view model with many skills to test pagination viewModel := &CharacterSheetViewModel{ Skills: make([]SkillViewModel, 50), // 50 skills should exceed column capacities } // Fill with test data for i := range viewModel.Skills { viewModel.Skills[i] = SkillViewModel{ Name: "Test Skill", Value: 10, } } pageData, err := PreparePaginatedPageData(viewModel, "page_1.html", 1, "2024-01-01") if err != nil { t.Fatalf("PreparePaginatedPageData failed: %v", err) } // Verify columns are populated if len(pageData.SkillsColumn1) == 0 { t.Error("SkillsColumn1 is empty") } if len(pageData.SkillsColumn2) == 0 { t.Error("SkillsColumn2 is empty") } // Get capacities from template templateSet := DefaultA4QuerTemplateSet() var page1Template *TemplateWithMeta for i := range templateSet.Templates { if templateSet.Templates[i].Metadata.Name == "page_1.html" { page1Template = &templateSet.Templates[i] break } } var col1MaxItems, col2MaxItems int for i := range page1Template.Metadata.Blocks { if page1Template.Metadata.Blocks[i].Name == "skills_column1" { col1MaxItems = page1Template.Metadata.Blocks[i].MaxItems } else if page1Template.Metadata.Blocks[i].Name == "skills_column2" { col2MaxItems = page1Template.Metadata.Blocks[i].MaxItems } } // Check capacities (from template) if len(pageData.SkillsColumn1) > col1MaxItems { t.Errorf("SkillsColumn1 exceeds capacity: got %d, max %d (from template)", len(pageData.SkillsColumn1), col1MaxItems) } if len(pageData.SkillsColumn2) > col2MaxItems { t.Errorf("SkillsColumn2 exceeds capacity: got %d, max %d (from template)", len(pageData.SkillsColumn2), col2MaxItems) } // Verify skills are split correctly totalPaginated := len(pageData.SkillsColumn1) + len(pageData.SkillsColumn2) expectedTotal := col1MaxItems + col2MaxItems if totalPaginated > expectedTotal { t.Errorf("Total paginated skills exceeds capacity: got %d, max %d (from template)", totalPaginated, expectedTotal) } t.Logf("Column1: %d skills, Column2: %d skills (total: %d)", len(pageData.SkillsColumn1), len(pageData.SkillsColumn2), totalPaginated) } func TestSplitSkillsForColumns(t *testing.T) { // Get actual column capacities from template templateSet := DefaultA4QuerTemplateSet() var page1Template *TemplateWithMeta for i := range templateSet.Templates { if templateSet.Templates[i].Metadata.Name == "page_1.html" { page1Template = &templateSet.Templates[i] break } } var col1MaxItems, col2MaxItems int for i := range page1Template.Metadata.Blocks { if page1Template.Metadata.Blocks[i].Name == "skills_column1" { col1MaxItems = page1Template.Metadata.Blocks[i].MaxItems } else if page1Template.Metadata.Blocks[i].Name == "skills_column2" { col2MaxItems = page1Template.Metadata.Blocks[i].MaxItems } } tests := []struct { name string skills int col1Max int col2Max int wantCol1 int wantCol2 int }{ { name: "few skills - only column 1", skills: 3, // Less than col1Max col1Max: col1MaxItems, col2Max: col2MaxItems, wantCol1: 3, wantCol2: 0, }, { name: "exactly column 1 capacity", skills: col1MaxItems, col1Max: col1MaxItems, col2Max: col2MaxItems, wantCol1: col1MaxItems, wantCol2: 0, }, { name: "overflow to column 2", skills: col1MaxItems + 3, // More than col1, but less than col1+col2 col1Max: col1MaxItems, col2Max: col2MaxItems, wantCol1: col1MaxItems, wantCol2: 3, }, { name: "both columns full", skills: col1MaxItems + col2MaxItems, col1Max: col1MaxItems, col2Max: col2MaxItems, wantCol1: col1MaxItems, wantCol2: col2MaxItems, }, { name: "more than both columns - truncate", skills: col1MaxItems + col2MaxItems + 12, col1Max: col1MaxItems, col2Max: col2MaxItems, wantCol1: col1MaxItems, wantCol2: col2MaxItems, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Create test skills skills := make([]SkillViewModel, tt.skills) for i := range skills { skills[i] = SkillViewModel{ Name: "Test Skill", Value: 10, } } col1, col2 := SplitSkillsForColumns(skills, tt.col1Max, tt.col2Max) if len(col1) != tt.wantCol1 { t.Errorf("Column1: got %d skills, want %d", len(col1), tt.wantCol1) } if len(col2) != tt.wantCol2 { t.Errorf("Column2: got %d skills, want %d", len(col2), tt.wantCol2) } }) } } func TestPreparePaginatedPageData_Page2Play(t *testing.T) { // Create 40 weapons to test capacity limiting viewModel := &CharacterSheetViewModel{ Weapons: make([]WeaponViewModel, 40), } for i := range viewModel.Weapons { viewModel.Weapons[i] = WeaponViewModel{ Name: "Test Weapon", } } pageData, err := PreparePaginatedPageData(viewModel, "page_2.html", 2, "2024-01-01") if err != nil { t.Fatalf("PreparePaginatedPageData failed: %v", err) } // Page 2 should have weapons limited to 30 if len(pageData.Weapons) > 30 { t.Errorf("Weapons exceed capacity: got %d, max 30", len(pageData.Weapons)) } t.Logf("Page2: %d weapons", len(pageData.Weapons)) } func TestPreparePaginatedPageData_Page3Spell(t *testing.T) { // Get capacities from template templateSet := DefaultA4QuerTemplateSet() leftCap := GetBlockCapacity(&templateSet, "page_3.html", "spells_column1") rightCap := GetBlockCapacity(&templateSet, "page_3.html", "spells_column2") magicItemsCap := GetBlockCapacity(&templateSet, "page_3.html", "magic_items") // Create test data exceeding capacities viewModel := &CharacterSheetViewModel{ Spells: make([]SpellViewModel, 50), MagicItems: make([]MagicItemViewModel, 20), } for i := range viewModel.Spells { viewModel.Spells[i] = SpellViewModel{ Name: "Test Spell", } } for i := range viewModel.MagicItems { viewModel.MagicItems[i] = MagicItemViewModel{ Name: "Test Item", } } pageData, err := PreparePaginatedPageData(viewModel, "page_3.html", 3, "2024-01-01") if err != nil { t.Fatalf("PreparePaginatedPageData failed: %v", err) } // Verify capacities match template if len(pageData.SpellsLeft) != leftCap { t.Errorf("SpellsLeft should be filled to %d (from template), got %d", leftCap, len(pageData.SpellsLeft)) } if len(pageData.SpellsRight) != rightCap { t.Errorf("SpellsRight should be filled to %d (from template), got %d", rightCap, len(pageData.SpellsRight)) } if len(pageData.MagicItems) != magicItemsCap { t.Errorf("MagicItems should be filled to %d (from template), got %d", magicItemsCap, len(pageData.MagicItems)) } t.Logf("Page3: left=%d, right=%d (total=%d), magic_items=%d (from template)", len(pageData.SpellsLeft), len(pageData.SpellsRight), len(pageData.SpellsLeft)+len(pageData.SpellsRight), len(pageData.MagicItems)) } func TestPreparePaginatedPageData_Page4Equipment(t *testing.T) { // Page 4 equipment page needs ALL equipment (not limited by capacity) // because the template has complex container logic that requires the full equipment list // Create test data viewModel := &CharacterSheetViewModel{ Equipment: make([]EquipmentViewModel, 50), } for i := range viewModel.Equipment { viewModel.Equipment[i] = EquipmentViewModel{ Name: "Test Equipment", } } pageData, err := PreparePaginatedPageData(viewModel, "page_4.html", 4, "2024-01-01") if err != nil { t.Fatalf("PreparePaginatedPageData failed: %v", err) } // Verify all equipment is included (not truncated) if len(pageData.Equipment) != 50 { t.Errorf("Equipment should include all items (50), got %d", len(pageData.Equipment)) } t.Logf("Page4: %d equipment items (all items included for container rendering)", len(pageData.Equipment)) }