Files
lanework/KanbanTests/BoardMetricsTests.swift
rzen 71b112d04c Card drag preview renders at the source face's laid-out width
The replica framed to a font-derived nominal width, so faces in wide
lanes' interior masonry columns and narrow lanes dragged a preview of
the wrong size and the cursor could sit over empty space beside it.
CardFaceView's existing onGeometryChange now reports size, not height
alone - height still feeds LaneDropRegistry, width feeds the replica -
and BoardMetrics.cardReplicaWidth(measured:bodyPointSize:) keeps the
old figure as the documented not-yet-laid-out fallback. Same row, same
paddings, same lineLimit at the same width means the same height, so
the preview is now an exact overlay of the face it left.

Manual verification pending alongside the lane grab-point card: 3x vs
1x lanes, interior masonry columns, window re-divide, trash rows,
large text sizes, drag-at-creation fallback.

3 tests. 1661 green on both schemes.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
2026-07-29 13:02:57 -04:00

37 lines
1.7 KiB
Swift

import CoreGraphics
import Testing
@testable import Kanban
/// `BoardMetrics` — the board strip's arithmetic. Most of it is a multiple of the body font and
/// needs no assertion beyond the one every figure already carries (it renders what the board always
/// rendered at 13pt); what is worth pinning is the one figure that is *not* font-derived at all.
private let body: CGFloat = 13
@Suite("BoardMetrics · the card replica's width")
struct CardReplicaWidthTests {
@Test("The measured face's width wins — the replica is the face it was lifted from")
func measuredWidthWins() {
// A face in a wide lane, and one in a narrow three-column lane: neither is the nominal
// figure, and both are what the drag image must be drawn at.
#expect(BoardMetrics.cardReplicaWidth(measured: 340, bodyPointSize: body) == 340)
#expect(BoardMetrics.cardReplicaWidth(measured: 148, bodyPointSize: body) == 148)
}
@Test("A face that has not laid out yet falls back to the representative width")
func unmeasuredFallsBack() {
let fallback = BoardMetrics.cardReplicaWidth(bodyPointSize: body)
#expect(BoardMetrics.cardReplicaWidth(measured: 0, bodyPointSize: body) == fallback)
#expect(BoardMetrics.cardReplicaWidth(measured: -20, bodyPointSize: body) == fallback)
#expect(BoardMetrics.cardReplicaWidth(measured: .nan, bodyPointSize: body) == fallback)
#expect(BoardMetrics.cardReplicaWidth(measured: .infinity, bodyPointSize: body) == fallback)
}
@Test("The fallback scales with the body font, like every other figure here")
func fallbackScales() {
#expect(BoardMetrics.cardReplicaWidth(bodyPointSize: 26)
> BoardMetrics.cardReplicaWidth(bodyPointSize: body))
}
}