mirror of
https://github.com/phranck/TUIkit.git
synced 2026-05-21 09:50:35 +00:00
3fb4944472
- Add ServiceEnvironment.swift with 9 EnvironmentKeys for runtime services (stateStorage, lifecycle, keyEventDispatcher, renderCache, preferenceStorage, pulsePhase, cursorTimer, focusIndicatorColor, activeFocusSectionID) - Remove tuiContext, pulsePhase, cursorTimer, focusIndicatorColor, and activeFocusSectionID as direct RenderContext properties - Inject all services through EnvironmentValues in RenderLoop.buildEnvironment() - Add convenience RenderContext init that accepts TUIContext and auto-injects services into the environment - Simplify isolatedForBackground() to only swap environment values - Migrate ~49 access sites in ~25 source files from context.tuiContext.X and context.pulsePhase/cursorTimer to context.environment.X - Update 38 test files to use the new convenience init
206 lines
6.2 KiB
Swift
206 lines
6.2 KiB
Swift
// TUIKit - Terminal UI Kit for Swift
|
|
// FrameModifierTests.swift
|
|
//
|
|
// Created by LAYERED.work
|
|
// License: MIT
|
|
|
|
import Testing
|
|
|
|
@testable import TUIkit
|
|
|
|
// MARK: - Test Helpers
|
|
|
|
/// Creates a default render context for testing.
|
|
private func testContext(width: Int = 40, height: Int = 24) -> RenderContext {
|
|
RenderContext(availableWidth: width, availableHeight: height, tuiContext: TUIContext())
|
|
}
|
|
|
|
// MARK: - FrameModifier Tests
|
|
|
|
@MainActor
|
|
@Suite("FrameModifier Tests")
|
|
struct FrameModifierTests {
|
|
|
|
@Test("FlexibleFrameView with maxWidth infinity fills available width")
|
|
func frameMaxWidthInfinity() {
|
|
let frame = FlexibleFrameView(
|
|
content: Text("Hi"),
|
|
minWidth: nil,
|
|
idealWidth: nil,
|
|
maxWidth: .infinity,
|
|
minHeight: nil,
|
|
idealHeight: nil,
|
|
maxHeight: nil,
|
|
alignment: .center
|
|
)
|
|
let context = testContext(width: 30)
|
|
let buffer = frame.renderToBuffer(context: context)
|
|
|
|
#expect(buffer.width == 30)
|
|
}
|
|
|
|
@Test("FlexibleFrameView with fixed maxWidth constrains")
|
|
func frameFixedMaxWidth() {
|
|
let frame = FlexibleFrameView(
|
|
content: Text("Short"),
|
|
minWidth: nil,
|
|
idealWidth: nil,
|
|
maxWidth: .fixed(10),
|
|
minHeight: nil,
|
|
idealHeight: nil,
|
|
maxHeight: nil,
|
|
alignment: .leading
|
|
)
|
|
let context = testContext(width: 40)
|
|
let buffer = frame.renderToBuffer(context: context)
|
|
|
|
// Content "Short" is 5 chars, no maxWidth expansion without infinity
|
|
#expect(buffer.width <= 10)
|
|
}
|
|
|
|
@Test("FlexibleFrameView with minWidth enforces minimum")
|
|
func frameMinWidth() {
|
|
let frame = FlexibleFrameView(
|
|
content: Text("Hi"),
|
|
minWidth: 10,
|
|
idealWidth: nil,
|
|
maxWidth: nil,
|
|
minHeight: nil,
|
|
idealHeight: nil,
|
|
maxHeight: nil,
|
|
alignment: .leading
|
|
)
|
|
let context = testContext(width: 40)
|
|
let buffer = frame.renderToBuffer(context: context)
|
|
|
|
#expect(buffer.width >= 10)
|
|
}
|
|
|
|
@Test("FlexibleFrameView with minHeight enforces minimum")
|
|
func frameMinHeight() {
|
|
let frame = FlexibleFrameView(
|
|
content: Text("Hi"),
|
|
minWidth: nil,
|
|
idealWidth: nil,
|
|
maxWidth: nil,
|
|
minHeight: 5,
|
|
idealHeight: nil,
|
|
maxHeight: nil,
|
|
alignment: .top
|
|
)
|
|
let context = testContext()
|
|
let buffer = frame.renderToBuffer(context: context)
|
|
|
|
#expect(buffer.height >= 5)
|
|
}
|
|
|
|
@Test("FlexibleFrameView alignment center")
|
|
func frameCenterAlignment() {
|
|
let frame = FlexibleFrameView(
|
|
content: Text("Hi"),
|
|
minWidth: 10,
|
|
idealWidth: nil,
|
|
maxWidth: nil,
|
|
minHeight: 3,
|
|
idealHeight: nil,
|
|
maxHeight: nil,
|
|
alignment: .center
|
|
)
|
|
let context = testContext()
|
|
let buffer = frame.renderToBuffer(context: context)
|
|
|
|
#expect(buffer.width >= 10)
|
|
#expect(buffer.height >= 3)
|
|
// Center vertically: content should be on line 1 (middle of 3)
|
|
let contentLine = buffer.lines[1]
|
|
#expect(contentLine.contains("Hi"))
|
|
// Center horizontally: "Hi" is 2 chars, frame is 10, so 4 spaces on left
|
|
let stripped = contentLine.stripped
|
|
let leadingSpaces = stripped.prefix(while: { $0 == " " }).count
|
|
#expect(leadingSpaces == 4, "Content should be horizontally centered with 4 leading spaces")
|
|
}
|
|
|
|
@Test("FlexibleFrameView alignment trailing")
|
|
func frameTrailingAlignment() {
|
|
let frame = FlexibleFrameView(
|
|
content: Text("Hi"),
|
|
minWidth: 10,
|
|
idealWidth: nil,
|
|
maxWidth: nil,
|
|
minHeight: nil,
|
|
idealHeight: nil,
|
|
maxHeight: nil,
|
|
alignment: .trailing
|
|
)
|
|
let context = testContext()
|
|
let buffer = frame.renderToBuffer(context: context)
|
|
|
|
// "Hi" should be right-aligned within 10 chars
|
|
let line = buffer.lines[0]
|
|
#expect(line.stripped.hasSuffix("Hi"))
|
|
}
|
|
|
|
@Test("FlexibleFrameView alignment bottom")
|
|
func frameBottomAlignment() {
|
|
let frame = FlexibleFrameView(
|
|
content: Text("Hi"),
|
|
minWidth: nil,
|
|
idealWidth: nil,
|
|
maxWidth: nil,
|
|
minHeight: 3,
|
|
idealHeight: nil,
|
|
maxHeight: nil,
|
|
alignment: .bottom
|
|
)
|
|
let context = testContext()
|
|
let buffer = frame.renderToBuffer(context: context)
|
|
|
|
#expect(buffer.height >= 3)
|
|
// Content on last line
|
|
let lastLine = buffer.lines[buffer.height - 1]
|
|
#expect(lastLine.contains("Hi"))
|
|
}
|
|
|
|
@Test("FlexibleFrameView maxHeight constrains available height for content")
|
|
func frameMaxHeight() {
|
|
// maxHeight constrains the availableHeight passed to child rendering,
|
|
// but does not clip content that exceeds constraints. This matches
|
|
// SwiftUI behavior where frame constraints inform layout, not clip.
|
|
let frame = FlexibleFrameView(
|
|
content: Text("Short"),
|
|
minWidth: nil,
|
|
idealWidth: nil,
|
|
maxWidth: nil,
|
|
minHeight: 5,
|
|
idealHeight: nil,
|
|
maxHeight: .fixed(10),
|
|
alignment: .top
|
|
)
|
|
let context = testContext()
|
|
let buffer = frame.renderToBuffer(context: context)
|
|
|
|
// minHeight 5 expands the 1-line content to 5 lines
|
|
#expect(buffer.height == 5)
|
|
}
|
|
|
|
@Test("FlexibleFrameView maxHeight infinity fills available space")
|
|
func frameMaxHeightInfinity() {
|
|
let frame = FlexibleFrameView(
|
|
content: Text("Hi"),
|
|
minWidth: nil,
|
|
idealWidth: nil,
|
|
maxWidth: nil,
|
|
minHeight: nil,
|
|
idealHeight: nil,
|
|
maxHeight: .infinity,
|
|
alignment: .top
|
|
)
|
|
var context = testContext()
|
|
context.availableHeight = 10
|
|
let buffer = frame.renderToBuffer(context: context)
|
|
|
|
// Should expand to fill available height
|
|
#expect(buffer.height == 10)
|
|
}
|
|
}
|