import SwiftUI import Testing import UIKit @testable import WebTerm /// T-iPad-4 · Projects 大屏化的纯布局决策单测。判据是**设备 idiom + 可用宽度** /// (单点,仿 `LayoutPolicy` 先例)——见 `ProjectsLayout` 注释解释为何用 idiom /// 而非 size class(iPad 的 Projects 表单 sheet 内部恒 compact,与 iPhone 横屏 /// 无异,size class 无法在不回归 iPhone 的前提下区分二者)。 /// /// iPhone 零回归的可测护栏:`.phone` 分支必须与「现状」逐字节等价——列数恒 /// 为 1(现有单列 List)、不走网格、sheet detents 恒为 nil(不加修饰符 = 现有 /// 默认全高 sheet)。`.pad` 分支才是新增的大屏行为。 @Suite("ProjectsGridLayout column count (T-iPad-4)") struct ProjectsGridLayoutTests { // MARK: - iPhone → 恒 1 列 / 不走网格(字节级不变) @Test(".phone → 恒 1 列,宽度无关(含横屏宽尺寸,现有单列 List 原样复用)") func phoneIsAlwaysSingleColumn() { #expect(ProjectsGridLayout.columnCount(availableWidth: 320, idiom: .phone) == 1) // iPhone 横屏很宽(~852)也绝不多列 —— 零回归的关键护栏。 #expect(ProjectsGridLayout.columnCount(availableWidth: 852, idiom: .phone) == 1) #expect(ProjectsGridLayout.columnCount(availableWidth: 2000, idiom: .phone) == 1) } @Test(".phone 不走网格;.pad 走网格") func usesGridOnlyOnPad() { #expect(ProjectsGridLayout.usesGrid(idiom: .phone) == false) #expect(ProjectsGridLayout.usesGrid(idiom: .pad) == true) } // MARK: - iPad → 按可用宽度 1/2/3 列 @Test(".pad 且窄于两列阈值 → 1 列(极窄 iPad 多任务,绝不挤压)") func padNarrowIsSingleColumn() { #expect(ProjectsGridLayout.columnCount( availableWidth: ProjectsGridLayout.twoColumnMinWidth - 1, idiom: .pad) == 1) } @Test(".pad 且在 [两列阈值, 三列阈值) → 2 列(表单 sheet 内宽即此档)") func padMediumIsTwoColumns() { #expect(ProjectsGridLayout.columnCount( availableWidth: ProjectsGridLayout.twoColumnMinWidth, idiom: .pad) == 2) #expect(ProjectsGridLayout.columnCount( availableWidth: ProjectsGridLayout.threeColumnMinWidth - 1, idiom: .pad) == 2) } @Test(".pad 且 >= 三列阈值 → 3 列(更宽面板/横屏全宽)") func padWideIsThreeColumns() { #expect(ProjectsGridLayout.columnCount( availableWidth: ProjectsGridLayout.threeColumnMinWidth, idiom: .pad) == 3) #expect(ProjectsGridLayout.columnCount(availableWidth: 1400, idiom: .pad) == 3) } @Test("列数恒 >= 1(任何宽度都不返回 0/负,防空网格崩溃)") func columnCountIsAlwaysPositive() { for width in stride(from: CGFloat(0), through: 2000, by: 137) { #expect(ProjectsGridLayout.columnCount(availableWidth: width, idiom: .pad) >= 1) #expect(ProjectsGridLayout.columnCount(availableWidth: width, idiom: .phone) == 1) } } } @Suite("ProjectsSheetSizing (T-iPad-4)") struct ProjectsSheetSizingTests { @Test(".phone → nil(不加 detent 修饰符 = 现有默认全高 sheet,字节级不变)") func phoneIsNil() { #expect(ProjectsSheetSizing.detents(idiom: .phone) == nil) } @Test(".pad → [.medium, .large](iPad 卡片式,不铺满大屏;仍可上拉到大)") func padIsCardDetents() { #expect(ProjectsSheetSizing.detents(idiom: .pad) == [.medium, .large]) } }