BlockGrouperTest.swift
86 lignes · 3891 octets
import XCTest @testable import Card2vcf final class BlockGrouperTest: XCTestCase { private func ligne( _ text: String, top: Int, height: Int = 30, left: Int = 0, right: Int = 300, confidence: Float = 90 ) -> OcrLine { OcrLine(text: text, box: OcrBox(left: left, top: top, right: right, bottom: top + height), confidence: confidence) } func testListeVideAucunBloc() { XCTAssertEqual([], BlockGrouper.group([])) } func testTroisPavesSeparesDonnentTroisBlocs() { let lines = [ ligne("Sonia MARTIN", top: 100, height: 40), ligne("Directrice commerciale", top: 150), ligne("561 allée des Noisetiers", top: 400), ligne("69760 Limonest", top: 440), ligne("Tél. 04 75 35 12 34", top: 700), ] let blocs = BlockGrouper.group(lines) XCTAssertEqual(3, blocs.count) XCTAssertEqual(["Sonia MARTIN", "Directrice commerciale"], blocs[0].lines.map(\.text)) XCTAssertEqual(["561 allée des Noisetiers", "69760 Limonest"], blocs[1].lines.map(\.text)) XCTAssertEqual(["Tél. 04 75 35 12 34"], blocs[2].lines.map(\.text)) } func testLignesAdresseContiguesGroupees() { let blocs = BlockGrouper.group([ ligne("561 allée des Noisetiers", top: 100), ligne("69760 Limonest - France", top: 140), ]) XCTAssertEqual(1, blocs.count) XCTAssertEqual("561 allée des Noisetiers\n69760 Limonest - France", blocs[0].text()) } func testDeuxColonnesNonFusionneesMemeSiEntrelaceesVerticalement() { let gauche1 = ligne("561 allée des Noisetiers", top: 100, left: 0, right: 300) let droite1 = ligne("Tél. 04 75 35 12 34", top: 110, left: 600, right: 900) let gauche2 = ligne("69760 Limonest", top: 140, left: 0, right: 300) let droite2 = ligne("contact@voltea.fr", top: 150, left: 600, right: 900) let blocs = BlockGrouper.group([gauche1, droite1, gauche2, droite2]) XCTAssertEqual(2, blocs.count) let textes = blocs.map { $0.lines.map(\.text) } XCTAssertTrue(textes.contains(["561 allée des Noisetiers", "69760 Limonest"]), "colonne gauche intacte: \(textes)") XCTAssertTrue(textes.contains(["Tél. 04 75 35 12 34", "contact@voltea.fr"]), "colonne droite intacte: \(textes)") } func testHauteurMedianeRobusteAUneLigneGeante() { // Logo géant (h=200) : la médiane reste ~30, donc l'écart de 60 px sous le logo coupe. let blocs = BlockGrouper.group([ ligne("VOLTEA", top: 0, height: 200), ligne("Sonia Martin", top: 260), ligne("Directrice", top: 300), ]) XCTAssertEqual(2, blocs.count) XCTAssertEqual(["VOLTEA"], blocs[0].lines.map(\.text)) XCTAssertEqual(["Sonia Martin", "Directrice"], blocs[1].lines.map(\.text)) } func testBlocsOrdonnesDeHautEnBasPuisDeGaucheADroite() { let basGauche = ligne("bas gauche", top: 500, left: 0, right: 200) let hautDroite = ligne("haut droite", top: 100, left: 600, right: 800) let hautGauche = ligne("haut gauche", top: 100, left: 0, right: 200) let blocs = BlockGrouper.group([basGauche, hautDroite, hautGauche]) XCTAssertEqual(["haut gauche", "haut droite", "bas gauche"], blocs.map { $0.text() }) } func testProprietesDeBloc() { let bloc = OcrBlock(lines: [ OcrLine(text: "a", box: OcrBox(left: 10, top: 100, right: 200, bottom: 130), confidence: 80), OcrLine(text: "b", box: OcrBox(left: 20, top: 140, right: 300, bottom: 170), confidence: 60), ]) XCTAssertEqual(OcrBox(left: 10, top: 100, right: 300, bottom: 170), bloc.box()) XCTAssertEqual(70, bloc.avgConfidence()) XCTAssertEqual("a\nb", bloc.text()) } }
GitRust