From eeff72eb3703165d493766ded42220147a18fc20 Mon Sep 17 00:00:00 2001 From: Philip Niedertscheider Date: Sat, 10 Oct 2026 23:25:12 +0200 Subject: [PATCH] test(table): Migrate internal layout specs to Swift Testing --- .../Table/PDFTableMergeUtilTests.swift | 84 ++++ .../Table/PDFTableMergeUtil_Spec.swift | 86 ---- .../Internal/Table/PDFTableObjectSpec.swift | 382 ------------------ .../Internal/Table/PDFTableObjectTests.swift | 82 ++++ 4 files changed, 166 insertions(+), 468 deletions(-) create mode 100644 Tests/TPPDFTests/Internal/Table/PDFTableMergeUtilTests.swift delete mode 100644 Tests/TPPDFTests/Internal/Table/PDFTableMergeUtil_Spec.swift delete mode 100644 Tests/TPPDFTests/Internal/Table/PDFTableObjectSpec.swift create mode 100644 Tests/TPPDFTests/Internal/Table/PDFTableObjectTests.swift diff --git a/Tests/TPPDFTests/Internal/Table/PDFTableMergeUtilTests.swift b/Tests/TPPDFTests/Internal/Table/PDFTableMergeUtilTests.swift new file mode 100644 index 00000000..42b2e757 --- /dev/null +++ b/Tests/TPPDFTests/Internal/Table/PDFTableMergeUtilTests.swift @@ -0,0 +1,84 @@ +// +// PDFTableMergeUtilTests.swift +// TPPDF +// +// Created by Philip Niedertscheider on 22.12.2019. +// Copyright © 2016-2026 techprimate GmbH. All rights reserved. +// + +import Testing +@testable import TPPDF + +struct PDFTableMergeUtilTests { + @Test func unmergedTableReturnsOneNodePerCellWithoutSpans() { + // Arrange + let table = makeTable() + + // Act + let result = PDFTableMergeUtil.calculateMerged(table: table) + + // Assert + #expect(result.count == 10) + for row in 0..<10 { + #expect(result[row].count == 10) + for column in 0..<10 { + let node = result[row][column] + #expect(node.cell === table.cells[row][column]) + #expect(node.moreRowsSpan == 0) + #expect(node.moreColumnsSpan == 0) + } + } + } + + @Test func mergingEachRowReturnsOneNodePerRowSpanningAllColumns() { + // Arrange + let table = makeTable() + for row in 0..<10 { + table[row: row].merge() + } + + // Act + let result = PDFTableMergeUtil.calculateMerged(table: table) + + // Assert + #expect(result.count == 10) + for row in 0..<10 { + #expect(result[row].count == 1) + let node = result[row][0] + #expect(node.cell === table.cells[row][0]) + #expect(node.moreRowsSpan == 0) + #expect(node.moreColumnsSpan == 9) + } + } + + @Test func mergingEachColumnReturnsOneNodePerColumnSpanningAllRows() { + // Arrange + let table = makeTable() + for column in 0..<10 { + table[column: column].merge() + } + + // Act + let result = PDFTableMergeUtil.calculateMerged(table: table) + + // Assert + #expect(result.count == 1) + #expect(result[0].count == 10) + for column in 0..<10 { + let node = result[0][column] + #expect(node.cell === table.cells[0][column]) + #expect(node.moreRowsSpan == 9) + #expect(node.moreColumnsSpan == 0) + } + } + + private func makeTable() -> PDFTable { + let table = PDFTable(rows: 10, columns: 10) + for row in 0..<10 { + for column in 0..<10 { + table[row, column].content = "\(row),\(column)".asTableContent + } + } + return table + } +} diff --git a/Tests/TPPDFTests/Internal/Table/PDFTableMergeUtil_Spec.swift b/Tests/TPPDFTests/Internal/Table/PDFTableMergeUtil_Spec.swift deleted file mode 100644 index 7cf22e2d..00000000 --- a/Tests/TPPDFTests/Internal/Table/PDFTableMergeUtil_Spec.swift +++ /dev/null @@ -1,86 +0,0 @@ -// -// PDFTableMergeUtil_Spec.swift -// TPPDF -// -// Created by Philip Niedertscheider on 22.12.2019. -// Copyright © 2016-2026 techprimate GmbH. All rights reserved. -// - -import Foundation -import Nimble -import Quick -@testable import TPPDF - -class PDFTableMergeUtilSpec: QuickSpec { - // swiftlint:disable closure_body_length function_body_length - override func spec() { - describe("PDFTableMergeUtil") { - let ROWS = 10 - let COLS = 10 - - var table = PDFTable(rows: ROWS, columns: COLS) - - beforeEach { - table = PDFTable(rows: ROWS, columns: COLS) - for row in 0.. PDFTable { - let table = PDFTable(rows: rows, columns: columns) - table.widths = [0.1, 0.3, 0.3, 0.3] - table.margin = 10 - table.padding = 10 - table.shouldSplitCellsOnPageBreak = false - table.style.columnHeaderCount = columnHeaderCount - - for row in 0.. [PDFLocatedRenderObject] { - let container = PDFContainer.contentLeft - let generator = PDFGenerator(document: .init(format: .a4)) - let tableObject = PDFTableObject(table: table) - return try tableObject.calculate(generator: generator, container: container) - } -} -#endif diff --git a/Tests/TPPDFTests/Internal/Table/PDFTableObjectTests.swift b/Tests/TPPDFTests/Internal/Table/PDFTableObjectTests.swift new file mode 100644 index 00000000..6f0af90c --- /dev/null +++ b/Tests/TPPDFTests/Internal/Table/PDFTableObjectTests.swift @@ -0,0 +1,82 @@ +// +// PDFTableObjectTests.swift +// TPPDF +// +// Created by Philip Niedertscheider on 05.12.2020. +// Copyright © 2016-2026 techprimate GmbH. All rights reserved. +// + +import CoreGraphics +import Testing +@testable import TPPDF + +#if os(iOS) || os(tvOS) || os(watchOS) || os(visionOS) +import UIKit + +struct PDFTableObjectTests { + @Test(arguments: [false, true]) + func unmergedRowsAcrossPagesPreserveFramesAndConfiguredHeaderRepetition(repeatHeaders: Bool) throws { + // Arrange + let columns = 4 + let table = makeTable() + table.showHeadersOnEveryPage = repeatHeaders + let generator = PDFGenerator(document: .init(format: .a4)) + let object = PDFTableObject(table: table) + let columnXPositions: [CGFloat] = [70, 117.5, 260, 402.5] + let columnWidths: [CGFloat] = [27.5, 122.5, 122.5, 122.5] + #if targetEnvironment(macCatalyst) + let firstPagePositions: [CGFloat] = [70, 117, 164, 211, 258, 305, 352, 399, 446, 493, 540, 600, 660, 720] + let secondPagePositions: [CGFloat] = repeatHeaders + ? [70, 117, 164, 211, 271, 331, 391, 451, 511] + : [70, 130, 190, 250, 310, 370] + let largeRowHeight: CGFloat = 50 + #else + let firstPagePositions: [CGFloat] = [70, 117, 164, 211, 258, 305, 352, 399, 446, 493, 540, 598, 656, 714] + let secondPagePositions: [CGFloat] = repeatHeaders + ? [70, 117, 164, 211, 269, 327, 385, 443, 501] + : [70, 128, 186, 244, 302, 360] + let largeRowHeight: CGFloat = 48 + #endif + let rowYPositions = firstPagePositions + secondPagePositions + let firstPageHeights = Array(repeating: CGFloat(37), count: 10) + Array(repeating: largeRowHeight, count: 4) + let secondPageHeights = (repeatHeaders ? Array(repeating: CGFloat(37), count: 3) : []) + + Array(repeating: largeRowHeight, count: 6) + let rowHeights = firstPageHeights + secondPageHeights + let expectedCount = 80 + 2 /* Outlines */ + 1 /* Page break */ + (repeatHeaders ? 12 : 0) + + // Act + let result = try object.calculate(generator: generator, container: .contentLeft) + + // Assert + try #require(result.count == expectedCount) + #expect(result[56].1 is PDFRectangleObject) + #expect(result[57].1 is PDFPageBreakObject) + for row in rowYPositions.indices { + for column in columnXPositions.indices { + let offset = row >= 14 ? 2 /* First page outline and page break */ : 0 + let frame = result[row * columns + column + offset].1.frame + #expect(frame.origin.x == columnXPositions[column], "Cell \(row),\(column) has invalid x position") + #expect(frame.origin.y == rowYPositions[row], "Cell \(row),\(column) has invalid y position") + #expect(frame.width == columnWidths[column], "Cell \(row),\(column) has invalid width") + #expect(frame.height == rowHeights[row], "Cell \(row),\(column) has invalid height") + } + } + } + + private func makeTable() -> PDFTable { + let table = PDFTable(rows: 20, columns: 4) + table.widths = [0.1, 0.3, 0.3, 0.3] + table.margin = 10 + table.padding = 10 + table.shouldSplitCellsOnPageBreak = false + table.style.columnHeaderCount = 3 + for row in 0..<20 { + table[row, 0].content = "\(row)".asTableContent + for column in 1..<4 { + table[row, column].content = "\(row),\(column)".asTableContent + } + } + return table + } +} +#endif