Files
steipete--codexbar/Tests/CodexBarTests/UsageMenuCardLayoutTests.swift
2026-07-13 12:22:33 +08:00

117 lines
4.5 KiB
Swift

import AppKit
import CodexBarCore
import SwiftUI
import Testing
@testable import CodexBar
@MainActor
struct UsageMenuCardLayoutTests {
private static let heightTolerance: CGFloat = 1
@Test
func `header only menu card keeps comfortable padding`() {
let model = Self.model()
let width: CGFloat = 296
let headerSize = NSHostingController(rootView: UsageMenuCardHeaderSectionView(
model: model,
showDivider: false,
width: width))
.sizeThatFits(in: CGSize(width: width, height: .greatestFiniteMagnitude))
let cardSize = NSHostingController(rootView: UsageMenuCardView(model: model, width: width))
.sizeThatFits(in: CGSize(width: width, height: .greatestFiniteMagnitude))
#expect(headerSize.height > 0)
#expect(abs(cardSize.height - headerSize.height) < Self.heightTolerance)
}
@Test
func `full provider card matches overview height`() {
let model = Self.model(metrics: [
UsageMenuCardView.Model.Metric(
id: "session",
title: "Session",
percent: 37,
percentStyle: .left,
resetText: "Resets in 41m",
detailText: nil,
detailLeftText: "24% in reserve",
detailRightText: "Lasts until reset",
pacePercent: nil,
paceOnTop: true),
])
let width: CGFloat = 296
let fullCardSize = NSHostingController(rootView: UsageMenuCardView(model: model, width: width))
.sizeThatFits(in: CGSize(width: width, height: .greatestFiniteMagnitude))
let overviewStyleSize = NSHostingController(rootView: UsageMenuCardHeaderAndUsageSectionView(
model: model,
layoutModel: model,
bottomPadding: UsageMenuCardLayout.sectionBottomPadding,
width: width))
.sizeThatFits(in: CGSize(width: width, height: .greatestFiniteMagnitude))
#expect(UsageMenuCardLayout.postHeaderDividerContentSpacing == 16)
#expect(UsageMenuCardLayout.headerOnlyVerticalPadding == 6)
#expect(UsageMenuCardLayout.sectionTopPadding == 6)
#expect(UsageMenuCardLayout.sectionBottomPadding == 6)
#expect(abs(fullCardSize.height - overviewStyleSize.height) < Self.heightTolerance)
}
@Test
func `detail card keeps compact divider gap without usage section`() {
let metricsModel = Self.model(metrics: [
UsageMenuCardView.Model.Metric(
id: "session",
title: "Session",
percent: 37,
percentStyle: .left,
resetText: "Resets in 41m",
detailText: nil,
detailLeftText: "24% in reserve",
detailRightText: "Lasts until reset",
pacePercent: nil,
paceOnTop: true),
])
#expect(UsageMenuCardView.dividerBottomPadding(for: metricsModel) ==
UsageMenuCardLayout.postHeaderDividerContentSpacing)
#expect(UsageMenuCardView.dividerBottomPadding(for: Self.model(creditsText: "$12.34 remaining")) ==
UsageMenuCardLayout.sectionBottomPadding)
#expect(UsageMenuCardView.dividerBottomPadding(for: Self.model(usageNotes: ["Waiting for data"])) ==
UsageMenuCardLayout.sectionBottomPadding)
#expect(UsageMenuCardView.dividerBottomPadding(for: Self.model(placeholder: "No usage yet")) ==
UsageMenuCardLayout.sectionBottomPadding)
}
private static func model(
metrics: [UsageMenuCardView.Model.Metric] = [],
usageNotes: [String] = [],
creditsText: String? = nil,
placeholder: String? = nil) -> UsageMenuCardView.Model
{
UsageMenuCardView.Model(
provider: .codex,
providerName: "Codex",
email: "steipete@gmail.com",
subtitleText: "Not fetched yet",
subtitleStyle: .info,
planText: "Pro 20x",
metrics: metrics,
usageNotes: usageNotes,
openAIAPIUsage: nil,
inlineUsageDashboard: nil,
creditsText: creditsText,
creditsRemaining: nil,
creditsProgressPercent: nil,
creditsScaleText: nil,
creditsHintText: nil,
creditsHintCopyText: nil,
providerCost: nil,
tokenUsage: nil,
placeholder: placeholder,
progressColor: .blue)
}
}