205 lines
8.3 KiB
Swift
205 lines
8.3 KiB
Swift
import AppKit
|
|
import SwiftUI
|
|
import XCTest
|
|
import MacToolsPluginKit
|
|
@testable import MacTools
|
|
|
|
final class ComponentPanelLayoutTests: XCTestCase {
|
|
func testComponentCardCornerRadiusMatchesLeftClickPanelCornerRadius() {
|
|
XCTAssertEqual(
|
|
PluginComponentPanelLayoutMetrics.cardCornerRadius,
|
|
MenuBarPanelLayout.cornerRadius
|
|
)
|
|
}
|
|
|
|
func testPanelWidthUsesFourFixedColumnsWithinExistingPanelWidth() {
|
|
XCTAssertEqual(ComponentPanelLayout.columns, 4)
|
|
XCTAssertEqual(ComponentPanelLayout.cellWidth, 70)
|
|
XCTAssertEqual(ComponentPanelLayout.originalCellHeight, 94)
|
|
XCTAssertEqual(ComponentPanelLayout.cellHeight, 8)
|
|
XCTAssertEqual(ComponentPanelLayout.horizontalSpacing, 8)
|
|
XCTAssertEqual(ComponentPanelLayout.verticalSpacing, 6)
|
|
XCTAssertEqual(ComponentPanelLayout.verticalSpacing, ComponentPanelLayout.horizontalPadding)
|
|
XCTAssertEqual(ComponentPanelLayout.horizontalPadding, MenuBarPanelLayout.outerPadding)
|
|
XCTAssertEqual(ComponentPanelLayout.topPadding, MenuBarPanelLayout.contentTopPadding)
|
|
XCTAssertEqual(ComponentPanelLayout.bottomPadding, MenuBarPanelLayout.contentBottomPadding)
|
|
XCTAssertEqual(ComponentPanelLayout.verticalPadding, MenuBarPanelLayout.outerPadding)
|
|
XCTAssertEqual(ComponentPanelLayout.contentVerticalPadding, 10)
|
|
XCTAssertEqual(
|
|
ComponentPanelLayout.panelWidth,
|
|
ComponentPanelLayout.horizontalPadding * 2
|
|
+ ComponentPanelLayout.cellWidth * 4
|
|
+ ComponentPanelLayout.horizontalSpacing * 3
|
|
)
|
|
XCTAssertEqual(ComponentPanelLayout.panelWidth, 316)
|
|
}
|
|
|
|
func testScrollClipCornerRadiusMatchesPanelCornerRadius() {
|
|
XCTAssertEqual(
|
|
ComponentPanelLayout.scrollClipCornerRadius,
|
|
MenuBarPanelLayout.cornerRadius
|
|
)
|
|
}
|
|
|
|
func testGridUsesCompactRowsForDenseComponents() {
|
|
XCTAssertLessThan(ComponentPanelLayout.cellHeight, ComponentPanelLayout.cellWidth)
|
|
XCTAssertEqual(ComponentPanelLayout.itemHeight(for: .oneByOne), ComponentPanelLayout.cellHeight)
|
|
XCTAssertEqual(
|
|
ComponentPanelLayout.yOffset(for: ComponentGridPlacement(
|
|
id: "a",
|
|
row: 1,
|
|
column: 0,
|
|
span: .oneByOne,
|
|
yOffset: ComponentPanelLayout.cellHeight + ComponentPanelLayout.verticalSpacing
|
|
)),
|
|
ComponentPanelLayout.cellHeight + ComponentPanelLayout.verticalSpacing
|
|
)
|
|
}
|
|
|
|
func testExpandedSpansUseCompactRowHeightAndExternalSpacing() throws {
|
|
let oneOriginalRow = try XCTUnwrap(PluginComponentSpan(width: 4, height: 12))
|
|
let twoOriginalRows = try XCTUnwrap(PluginComponentSpan(width: 4, height: 25))
|
|
let threeOriginalRows = try XCTUnwrap(PluginComponentSpan(width: 4, height: 37))
|
|
|
|
XCTAssertEqual(ComponentPanelLayout.itemHeight(for: oneOriginalRow), 96)
|
|
XCTAssertEqual(ComponentPanelLayout.itemHeight(for: twoOriginalRows), 200)
|
|
XCTAssertEqual(ComponentPanelLayout.itemHeight(for: threeOriginalRows), 296)
|
|
|
|
let nextAfterOneCompactRow = ComponentGridPlacement(
|
|
id: "after-compact",
|
|
row: 1,
|
|
column: 0,
|
|
span: .oneByOne,
|
|
yOffset: ComponentPanelLayout.cellHeight + ComponentPanelLayout.verticalSpacing
|
|
)
|
|
let nextAfterOneOriginalRow = ComponentGridPlacement(
|
|
id: "after-original",
|
|
row: 12,
|
|
column: 0,
|
|
span: .oneByOne,
|
|
yOffset: ComponentPanelLayout.itemHeight(for: oneOriginalRow) + ComponentPanelLayout.verticalSpacing
|
|
)
|
|
XCTAssertEqual(
|
|
ComponentPanelLayout.yOffset(for: nextAfterOneCompactRow) - ComponentPanelLayout.itemHeight(for: .oneByOne),
|
|
ComponentPanelLayout.verticalSpacing
|
|
)
|
|
XCTAssertEqual(
|
|
ComponentPanelLayout.yOffset(for: nextAfterOneOriginalRow) - ComponentPanelLayout.itemHeight(for: oneOriginalRow),
|
|
ComponentPanelLayout.verticalSpacing
|
|
)
|
|
}
|
|
|
|
func testPreferredHeightForItemsIncludesSharedToolbarAndVerticalPadding() {
|
|
let item = makeItem(id: "system", span: .fourByTwo)
|
|
|
|
XCTAssertEqual(
|
|
ComponentPanelLayout.preferredContentHeight(for: [item], screen: nil),
|
|
ComponentPanelLayout.itemHeight(for: .fourByTwo) + ComponentPanelLayout.contentVerticalPadding
|
|
)
|
|
XCTAssertEqual(
|
|
ComponentPanelLayout.preferredPanelHeight(for: [item], screen: nil),
|
|
MenuBarPanelLayout.topChromeHeight
|
|
+ ComponentPanelLayout.itemHeight(for: .fourByTwo)
|
|
+ ComponentPanelLayout.contentVerticalPadding
|
|
)
|
|
}
|
|
|
|
func testFirstFitPlacesMixedSpansDeterministically() {
|
|
let placements = ComponentGridPlacementEngine.placements(
|
|
for: [
|
|
makeItem(id: "a", span: .oneByOne),
|
|
makeItem(id: "b", span: .oneByTwo),
|
|
makeItem(id: "c", span: .twoByTwo)
|
|
]
|
|
)
|
|
|
|
XCTAssertEqual(
|
|
placements,
|
|
[
|
|
ComponentGridPlacement(id: "a", row: 0, column: 0, span: .oneByOne, yOffset: 0),
|
|
ComponentGridPlacement(id: "b", row: 0, column: 1, span: .oneByTwo, yOffset: 0),
|
|
ComponentGridPlacement(id: "c", row: 0, column: 2, span: .twoByTwo, yOffset: 0)
|
|
]
|
|
)
|
|
}
|
|
|
|
func testWideSpansOccupyFourColumnGridAndAllowLaterSingleColumnFill() {
|
|
let placements = ComponentGridPlacementEngine.placements(
|
|
for: [
|
|
makeItem(id: "wide", span: .fourByTwo),
|
|
makeItem(id: "left", span: .oneByOne),
|
|
makeItem(id: "right", span: .twoByOne)
|
|
]
|
|
)
|
|
|
|
XCTAssertEqual(
|
|
placements,
|
|
[
|
|
ComponentGridPlacement(id: "wide", row: 0, column: 0, span: .fourByTwo, yOffset: 0),
|
|
ComponentGridPlacement(id: "left", row: 2, column: 0, span: .oneByOne, yOffset: 22),
|
|
ComponentGridPlacement(id: "right", row: 2, column: 1, span: .twoByOne, yOffset: 22)
|
|
]
|
|
)
|
|
}
|
|
|
|
func testStackedCardsHaveOnlyInterCardSpacingAndNoTrailingGap() throws {
|
|
let firstSpan = try XCTUnwrap(PluginComponentSpan(width: 4, height: 12))
|
|
let secondSpan = try XCTUnwrap(PluginComponentSpan(width: 4, height: 25))
|
|
let placements = ComponentGridPlacementEngine.placements(
|
|
for: [
|
|
makeItem(id: "first", span: firstSpan),
|
|
makeItem(id: "second", span: secondSpan)
|
|
]
|
|
)
|
|
|
|
XCTAssertEqual(placements.map(\.yOffset), [0, 102])
|
|
XCTAssertEqual(ComponentPanelLayout.gridContentHeight(for: placements), 302)
|
|
}
|
|
|
|
func testColumnStackingUsesOnlyInterCardSpacingForMixedWidths() {
|
|
let placements = ComponentGridPlacementEngine.placements(
|
|
for: [
|
|
makeItem(id: "left-tall", span: .oneByTwo),
|
|
makeItem(id: "right-short", span: .oneByOne),
|
|
makeItem(id: "left-next", span: .oneByOne)
|
|
]
|
|
)
|
|
|
|
XCTAssertEqual(
|
|
placements,
|
|
[
|
|
ComponentGridPlacement(id: "left-tall", row: 0, column: 0, span: .oneByTwo, yOffset: 0),
|
|
ComponentGridPlacement(id: "right-short", row: 0, column: 1, span: .oneByOne, yOffset: 0),
|
|
ComponentGridPlacement(id: "left-next", row: 0, column: 2, span: .oneByOne, yOffset: 0)
|
|
]
|
|
)
|
|
XCTAssertEqual(ComponentPanelLayout.gridContentHeight(for: placements), 16)
|
|
}
|
|
|
|
func testEmptyLayoutUsesEmptyStateHeight() {
|
|
XCTAssertEqual(
|
|
ComponentPanelLayout.gridContentHeight(for: []),
|
|
ComponentPanelLayout.emptyContentHeight
|
|
)
|
|
XCTAssertGreaterThanOrEqual(
|
|
ComponentPanelLayout.preferredPanelHeight(for: [], screen: nil),
|
|
ComponentPanelLayout.minimumPanelHeight
|
|
)
|
|
}
|
|
|
|
private func makeItem(id: String, span: PluginComponentSpan) -> PluginComponentItem {
|
|
PluginComponentItem(
|
|
id: id,
|
|
title: id,
|
|
iconName: "sparkles",
|
|
iconTint: Color(nsColor: .systemBlue),
|
|
description: id,
|
|
helpText: id,
|
|
descriptionTone: .secondary,
|
|
span: span,
|
|
isActive: false,
|
|
isEnabled: true
|
|
)
|
|
}
|
|
}
|