import AppKit import Testing @testable import Kanban /// Per-board frame memory has one rule that is not "put it back where it was": a frame saved on a /// display that is no longer attached must land somewhere visible (02-architecture.md § Windows). /// That rule is untestable against real hardware — the interesting case *is* the monitor that is not /// plugged in — which is why the decision takes its screens as an argument. @MainActor @Suite("Window placement") struct WindowPlacementTests { private let laptop = NSRect(x: 0, y: 0, width: 1512, height: 916) private let external = NSRect(x: 1512, y: 0, width: 2560, height: 1415) @Test("A frame on an attached screen is restored exactly") func aVisibleFrameIsUntouched() { let saved = WindowFrame(x: 120, y: 80, width: 1200, height: 700) let placed = HostedWindowController.placement(for: saved, onScreens: [laptop, external], fallback: laptop) #expect(placed == NSRect(x: 120, y: 80, width: 1200, height: 700)) } @Test("A frame straddling two screens is still where the user left it") func aStraddlingFrameIsUntouched() { // AppKit's own `constrainFrameRect(_:to:)` nudges the remainder into view when the frame is // set, so intersection — not containment — is the right test: a window hanging slightly off // an edge is a place, not a problem. let saved = WindowFrame(x: 1400, y: 100, width: 900, height: 600) let placed = HostedWindowController.placement(for: saved, onScreens: [laptop, external], fallback: laptop) #expect(placed.origin.x == 1400) } @Test("A frame on a screen that is gone keeps its size and centers on the fallback") func aVanishedScreenRelocates() { let saved = WindowFrame(x: 3000, y: 200, width: 1000, height: 600) let placed = HostedWindowController.placement(for: saved, onScreens: [laptop], fallback: laptop) // Size is a preference and survives; position is a place, and the place stopped existing. #expect(placed.size == NSSize(width: 1000, height: 600)) #expect(placed.midX == laptop.midX) #expect(placed.midY == laptop.midY) #expect(laptop.intersects(placed)) } @Test("With no screens at all the fallback still produces a frame") func noScreensStillPlaces() { // Not a real state, but the accessor's `NSScreen.screens` can be empty during a display // reconfiguration, and returning something sane beats a window at the saved coordinates of a // display nobody has. let saved = WindowFrame(x: 4000, y: 4000, width: 800, height: 500) let placed = HostedWindowController.placement(for: saved, onScreens: [], fallback: laptop) #expect(placed.size == NSSize(width: 800, height: 500)) #expect(laptop.contains(placed.origin)) } }