import Foundation import Testing @testable import FlixyDesign /// Wo die schwebende Videokachel landet. @Suite("Kachel-Platzierung") struct MiniPlayerPlacementTests { /// Ein iPhone im Hochformat, Kachel 180 × 101. private let placement = MiniPlayerPlacement( bounds: CGSize(width: 390, height: 844), tile: CGSize(width: 180, height: 101), inset: 12 ) @Test("Jede Bildschirmhälfte führt in ihre Ecke") func picksTheNearestCorner() { #expect(placement.nearestCorner(toCenter: CGPoint(x: 50, y: 50)) == .topLeading) #expect(placement.nearestCorner(toCenter: CGPoint(x: 340, y: 50)) == .topTrailing) #expect(placement.nearestCorner(toCenter: CGPoint(x: 50, y: 800)) == .bottomLeading) #expect(placement.nearestCorner(toCenter: CGPoint(x: 340, y: 800)) == .bottomTrailing) } @Test("Genau auf der Mitte gewinnt unten rechts") func decidesTheTie() { // Willkürlich, aber festgelegt: ohne eine Regel für den Gleichstand // hinge das Ergebnis an Fließkomma-Zufall, und dieselbe Geste führte // mal hierhin, mal dorthin. let center = CGPoint(x: 195, y: 422) #expect(placement.nearestCorner(toCenter: center) == .bottomTrailing) } @Test("In jeder Ecke bleibt der Sicherheitsabstand") func keepsTheInset() { for corner in MiniPlayerPlacement.Corner.allCases { let start = placement.origin(for: corner) #expect(start.x >= placement.inset) #expect(start.y >= placement.inset) #expect(start.x + placement.tile.width <= 390 - placement.inset) #expect(start.y + placement.tile.height <= 844 - placement.inset) } } @Test("Unten rechts sitzt die Kachel auch wirklich unten rechts") func computesTheFarCorner() { let start = placement.origin(for: .bottomTrailing) #expect(start.x == 198.0) #expect(start.y == 731.0) } @Test("Beim Ziehen rutscht nichts über den Rand") func clampsWhileDragging() { // Ohne diese Grenze zieht man die Kachel hinter den Bildschirmrand, // und dort ist sie mit dem Finger nicht mehr einzuholen. let farOut = placement.clamped(center: CGPoint(x: -500, y: -500)) #expect(farOut.x == 102.0) #expect(farOut.y == 62.5) let alsoFarOut = placement.clamped(center: CGPoint(x: 9_000, y: 9_000)) #expect(alsoFarOut.x == 288.0) #expect(alsoFarOut.y == 781.5) } @Test("Ein Punkt in der Mitte bleibt, wo er ist") func leavesValidPointsAlone() { let inside = CGPoint(x: 195, y: 400) #expect(placement.clamped(center: inside) == inside) } @Test("Ein zu enger Bereich schiebt die Kachel nicht hinaus") func survivesTinyBounds() { // Kommt beim Drehen und in der Übergangsphase vor: der Bereich ist // kurzzeitig schmaler als die Kachel. Ein falsch herum geklammerter // Wert schöbe sie dann dauerhaft aus dem Bild. let narrow = MiniPlayerPlacement( bounds: CGSize(width: 100, height: 80), tile: CGSize(width: 180, height: 101), inset: 12 ) #expect(narrow.origin(for: .bottomTrailing) == CGPoint(x: 12, y: 12)) #expect(narrow.clamped(center: CGPoint(x: 0, y: 0)) == CGPoint(x: 102, y: 62.5)) } }