| 1 | import XCTest |
| 2 | |
| 3 | @testable import CallsKit |
| 4 | |
| 5 | final class CallBarFitTests: XCTestCase { |
| 6 | private let all = CallBarFit.Control.allCases |
| 7 | |
| 8 | func testEveryWindowTheAppAllowsHasRoomForEverything() { |
| 9 | // 760 is the window's minimum (CallsMac.swift). |
| 10 | for width in stride(from: 760.0, through: 3840, by: 1) { |
| 11 | let fit = CallBarFit.fit(windowWidth: width, controls: all) |
| 12 | XCTAssertEqual(fit.overflow, [], "at \(width)") |
| 13 | XCTAssertEqual(fit.spacing, CallBarFit.roomy, "at \(width)") |
| 14 | XCTAssertLessThanOrEqual(fit.width, CallBarFit.maxWidth) |
| 15 | XCTAssertLessThanOrEqual(fit.width + 2 * CallBarFit.margin, width, "at \(width)") |
| 16 | } |
| 17 | } |
| 18 | |
| 19 | func testNarrowerItTightensThenMovesTheLeastUsedIntoMore() { |
| 20 | var last = CallBarFit.fit(windowWidth: 760, controls: all) |
| 21 | for width in stride(from: 759.0, through: 200, by: -1) { |
| 22 | let fit = CallBarFit.fit(windowWidth: width, controls: all) |
| 23 | // Never the controls that matter most. |
| 24 | for control in all where control.essential { XCTAssertTrue(fit.shows(control), "\(control) at \(width)") } |
| 25 | // Only ever more in ⋯ as it narrows, and in the bar's order. |
| 26 | XCTAssertTrue(Set(last.overflow).isSubset(of: Set(fit.overflow)), "at \(width)") |
| 27 | XCTAssertEqual(fit.overflow, all.filter { fit.overflow.contains($0) }) |
| 28 | // Whatever is shown fits the pane, while the essentials can. |
| 29 | let shown = all.filter(fit.shows) |
| 30 | let needed = CallBarFit.needed(shown, fit.spacing, more: !fit.overflow.isEmpty) |
| 31 | let essentials = CallBarFit.needed(all.filter(\.essential), CallBarFit.tight, more: true) |
| 32 | if width - 2 * CallBarFit.margin >= essentials { |
| 33 | XCTAssertLessThanOrEqual(needed, fit.width + 0.001, "at \(width)") |
| 34 | } |
| 35 | last = fit |
| 36 | } |
| 37 | XCTAssertEqual( |
| 38 | CallBarFit.fit(windowWidth: 300, controls: all).overflow, [.share, .devices, .layout, .link]) |
| 39 | } |
| 40 | |
| 41 | func testTheFirstToGoAreTheLinkThenLayout() { |
| 42 | // ⋯ takes a button's place, so the first time anything moves, two do: |
| 43 | // the link, and the layout (in the bar's order in ⋯). |
| 44 | let tightAll = CallBarFit.needed(all, CallBarFit.tight, more: false) |
| 45 | let fit = CallBarFit.fit(windowWidth: tightAll + 2 * CallBarFit.margin - 1, controls: all) |
| 46 | XCTAssertEqual(fit.overflow, [.layout, .link]) |
| 47 | // A guest has no link: the layout and Devices go first instead. |
| 48 | let guest = all.filter { $0 != .link } |
| 49 | let tightGuest = CallBarFit.needed(guest, CallBarFit.tight, more: false) |
| 50 | XCTAssertEqual( |
| 51 | CallBarFit.fit(windowWidth: tightGuest + 2 * CallBarFit.margin - 1, controls: guest).overflow, |
| 52 | [.devices, .layout]) |
| 53 | } |
| 54 | } |
| 55 | |