The Git tab fills in — the parked postures rehome whole, and the strip's membership is the posture
The popover's third tab settles (03 ▸ Git tab, 2026-08-07): BoardGitTabView takes the parked section — the six-posture matrix, the Pro pointer, the nested/unverifiable prose, the branch controls, the Board Settings… door — with the tab label doing the old "Git" header's naming work, and one new caption for the no-repository posture. BoardInfoTab.available drops the Git tab exactly where BoardGitSection resolves absent, carrying 12's absent-no-placeholder rule up to the tab strip; selection resets to Info per open, now a ruling. Daily face only — the remote block still joins with pro-m2. Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -7,7 +7,10 @@ import Testing
|
||||
/// inert `.git`. The seam
|
||||
/// that decides *whether* to show it — `BoardGitNote.hasGitDirectory(at:)` — is a pure, read-only
|
||||
/// `FileManager` check, pinned here against real bytes on disk. Everything else about the note (its
|
||||
/// wording, its placement in `BoardInfoView`) is SwiftUI rendering and deliberately untested.
|
||||
/// wording, its placement in `BoardGitTabView`) is SwiftUI rendering and deliberately untested.
|
||||
///
|
||||
/// Since the 2026-08-07 tab restructure this same answer decides one thing more: whether the popover
|
||||
/// carries a Git tab at all on a free board (`BoardInfoTabAvailabilityTests` below).
|
||||
struct BoardInfoPopoverTests {
|
||||
|
||||
@Test("A board with a .git at its root reports true")
|
||||
@@ -108,6 +111,67 @@ struct BoardGitSectionTests {
|
||||
}
|
||||
}
|
||||
|
||||
/// **The tab strip's membership** (03-board-ui.md ▸ Board popover, the tabbed-popover paragraph —
|
||||
/// the Git session's ruling, 2026-08-07): the Git tab joins the strip only where the git section has
|
||||
/// something true to say, so a free-tier board with no `.git` shows Info | Theme alone.
|
||||
///
|
||||
/// `BoardInfoTab.available` is pinned here for the reason `BoardGitSection.resolve` is pinned above:
|
||||
/// it is the whole decision, pure in its three inputs, and the segmented `Picker` it feeds is SwiftUI
|
||||
/// and stays untested. What these tests are really about is that membership **is** the posture rather
|
||||
/// than a second reading of it — the last one walks the entire input matrix and asserts the tab's
|
||||
/// presence against `resolve` itself, so the strip cannot drift from the surface it labels.
|
||||
@Suite("Board popover ▸ the tab strip's membership")
|
||||
struct BoardInfoTabAvailabilityTests {
|
||||
|
||||
@Test("A free board with no .git shows Info and Theme alone — never a standing Git tab")
|
||||
func theFreeTierDropsTheGitTab() {
|
||||
// 12-editions.md's "absent, no placeholder" carried up to the tab strip: a Git tab on every
|
||||
// free board would be the standing ad for Pro that 12 forbids.
|
||||
#expect(BoardInfoTab.available(tier: .free, mode: .none, hasGitDirectory: false) == [.info, .theme])
|
||||
}
|
||||
|
||||
@Test("A free board carrying an inert .git earns the tab — it has the Pro pointer to say")
|
||||
func anInertGitEarnsTheTab() {
|
||||
#expect(BoardInfoTab.available(tier: .free, mode: .none, hasGitDirectory: true) == [.info, .theme, .git])
|
||||
}
|
||||
|
||||
@Test("Pro shows the Git tab under every mode — each of the four postures is a tab surface")
|
||||
func proAlwaysShowsTheTab() {
|
||||
for mode in BoardGitMode.allCases {
|
||||
for hasGit in [true, false] {
|
||||
#expect(
|
||||
BoardInfoTab.available(tier: .pro, mode: mode, hasGitDirectory: hasGit)
|
||||
== [.info, .theme, .git],
|
||||
"Pro, mode \(mode): the tab is the posture's home, and Git is always last"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test("The tab is present exactly where the git section is not absent, across the whole matrix")
|
||||
func membershipDelegatesToThePosture() {
|
||||
for tier in Tier.allCases {
|
||||
for mode in BoardGitMode.allCases {
|
||||
for hasGit in [true, false] {
|
||||
let tabs = BoardInfoTab.available(tier: tier, mode: mode, hasGitDirectory: hasGit)
|
||||
let isAbsent =
|
||||
BoardGitSection.resolve(tier: tier, mode: mode, hasGitDirectory: hasGit) == .absent
|
||||
|
||||
#expect(
|
||||
tabs.contains(.git) == !isAbsent,
|
||||
"\(tier)/\(mode)/git=\(hasGit): membership is the posture, not a second reading of it"
|
||||
)
|
||||
#expect(
|
||||
Array(tabs.prefix(2)) == [.info, .theme],
|
||||
"Info and Theme stand on every board, in that order — Info is the board's face"
|
||||
)
|
||||
#expect(tabs.count == Set(tabs).count, "no tab appears twice")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// **The window-title widget's two strings** (03-board-ui.md ▸ Board popover, the card that widened
|
||||
/// the widget from a chevron to the whole board-name area): `BoardInfoTitlebarSummary` is the pure
|
||||
/// function this pins, exactly as `BoardGitSectionTests` above pins the section it shares its
|
||||
|
||||
Reference in New Issue
Block a user