mirror of
https://github.com/phranck/TUIkit.git
synced 2026-06-20 09:54:37 +00:00
BREAKING CHANGE: Package name changed due to name collision with existing rensbreur/SwiftTUI package. Changes: - Rename package from SwiftTUI to TUIKit in Package.swift - Rename Sources/SwiftTUI to Sources/TUIKit - Rename Sources/SwiftTUIExample to Sources/TUIKitExample - Rename Tests/SwiftTUITests to Tests/TUIKitTests - Rename SwiftTUI.swift to TUIKit.swift - Update all imports: import SwiftTUI -> import TUIKit - Update all code references: SwiftTUI.renderToBuffer -> TUIKit.renderToBuffer - Update documentation comments - Rename swiftTUIVersion to tuiKitVersion All 181 tests passing.
146 lines
4.8 KiB
Swift
146 lines
4.8 KiB
Swift
//
|
|
// FrameBufferTests.swift
|
|
// TUIKit
|
|
//
|
|
// Tests for FrameBuffer operations and compositing.
|
|
//
|
|
|
|
import Testing
|
|
@testable import TUIKit
|
|
|
|
@Suite("FrameBuffer Tests")
|
|
struct FrameBufferTests {
|
|
|
|
@Test("Empty buffer has zero dimensions")
|
|
func emptyBuffer() {
|
|
let buffer = FrameBuffer()
|
|
#expect(buffer.width == 0)
|
|
#expect(buffer.height == 0)
|
|
#expect(buffer.isEmpty)
|
|
}
|
|
|
|
@Test("Single line buffer has correct dimensions")
|
|
func singleLine() {
|
|
let buffer = FrameBuffer(text: "Hello")
|
|
#expect(buffer.width == 5)
|
|
#expect(buffer.height == 1)
|
|
#expect(buffer.lines == ["Hello"])
|
|
}
|
|
|
|
@Test("Vertical append stacks lines")
|
|
func verticalAppend() {
|
|
var buffer = FrameBuffer(text: "Line 1")
|
|
buffer.appendVertically(FrameBuffer(text: "Line 2"))
|
|
#expect(buffer.height == 2)
|
|
#expect(buffer.lines == ["Line 1", "Line 2"])
|
|
}
|
|
|
|
@Test("Vertical append with spacing")
|
|
func verticalAppendWithSpacing() {
|
|
var buffer = FrameBuffer(text: "Top")
|
|
buffer.appendVertically(FrameBuffer(text: "Bottom"), spacing: 2)
|
|
#expect(buffer.height == 4)
|
|
#expect(buffer.lines == ["Top", "", "", "Bottom"])
|
|
}
|
|
|
|
@Test("Horizontal append places side by side")
|
|
func horizontalAppend() {
|
|
var buffer = FrameBuffer(text: "Left")
|
|
buffer.appendHorizontally(FrameBuffer(text: "Right"), spacing: 1)
|
|
#expect(buffer.height == 1)
|
|
#expect(buffer.lines == ["Left Right"])
|
|
}
|
|
|
|
@Test("Horizontal append with different heights pads correctly")
|
|
func horizontalAppendDifferentHeights() {
|
|
var left = FrameBuffer(lines: ["AB", "CD"])
|
|
let right = FrameBuffer(text: "X")
|
|
left.appendHorizontally(right, spacing: 1)
|
|
#expect(left.height == 2)
|
|
#expect(left.lines[0] == "AB X")
|
|
// Row 1: "CD" padded to width 2, spacing " ", no right content
|
|
#expect(left.lines[1] == "CD ")
|
|
}
|
|
|
|
@Test("ANSI codes are excluded from width calculation")
|
|
func ansiStrippedWidth() {
|
|
let styled = "\u{1B}[1mBold\u{1B}[0m"
|
|
let buffer = FrameBuffer(text: styled)
|
|
#expect(buffer.width == 4) // "Bold" is 4 chars
|
|
}
|
|
|
|
@Test("Horizontal append with ANSI codes pads correctly")
|
|
func horizontalAppendWithAnsi() {
|
|
let styled = "\u{1B}[1mHi\u{1B}[0m"
|
|
var left = FrameBuffer(text: styled)
|
|
left.appendHorizontally(FrameBuffer(text: "There"), spacing: 1)
|
|
#expect(left.height == 1)
|
|
// "Hi" (styled) + " " (spacing) + "There"
|
|
#expect(left.lines[0].stripped == "Hi There")
|
|
}
|
|
}
|
|
|
|
@Suite("Overlay Tests")
|
|
struct OverlayTests {
|
|
|
|
@Test("Overlay modifier renders overlay on top of base")
|
|
func overlayRendering() {
|
|
let view = Text("Base Content")
|
|
.overlay {
|
|
Text("Top")
|
|
}
|
|
let context = RenderContext(availableWidth: 80, availableHeight: 24)
|
|
let buffer = renderToBuffer(view, context: context)
|
|
// The overlay "Top" should be centered on "Base Content"
|
|
#expect(buffer.height >= 1)
|
|
#expect(!buffer.isEmpty)
|
|
}
|
|
|
|
@Test("Dimmed modifier applies dim effect")
|
|
func dimmedRendering() {
|
|
let view = Text("Dimmed text").dimmed()
|
|
let context = RenderContext(availableWidth: 80, availableHeight: 24)
|
|
let buffer = renderToBuffer(view, context: context)
|
|
#expect(buffer.height == 1)
|
|
// Check that the ANSI dim code is present
|
|
#expect(buffer.lines[0].contains("\u{1B}[2m"))
|
|
}
|
|
|
|
@Test("Modal helper combines dimmed and overlay")
|
|
func modalRendering() {
|
|
let view = Text("Background")
|
|
.modal {
|
|
Text("Modal")
|
|
}
|
|
let context = RenderContext(availableWidth: 80, availableHeight: 24)
|
|
let buffer = renderToBuffer(view, context: context)
|
|
// The result should contain both the dimmed background and the modal
|
|
#expect(!buffer.isEmpty)
|
|
}
|
|
|
|
@Test("FrameBuffer compositing places overlay at correct position")
|
|
func frameBufferCompositing() {
|
|
let base = FrameBuffer(lines: ["AAAA", "AAAA", "AAAA"])
|
|
let overlay = FrameBuffer(text: "X")
|
|
|
|
// Place overlay at position (1, 1)
|
|
let result = base.composited(with: overlay, at: (x: 1, y: 1))
|
|
|
|
#expect(result.height == 3)
|
|
#expect(result.lines[0] == "AAAA")
|
|
#expect(result.lines[1].contains("X"))
|
|
#expect(result.lines[2] == "AAAA")
|
|
}
|
|
|
|
@Test("FrameBuffer compositing with offset")
|
|
func frameBufferCompositingOffset() {
|
|
let base = FrameBuffer(lines: ["1234567890"])
|
|
let overlay = FrameBuffer(text: "XXX")
|
|
|
|
// Place overlay at column 3
|
|
let result = base.composited(with: overlay, at: (x: 3, y: 0))
|
|
|
|
#expect(result.lines[0].stripped == "123XXX7890")
|
|
}
|
|
}
|