196 lines
6.6 KiB
Swift
196 lines
6.6 KiB
Swift
import Testing
|
|
import Adw
|
|
@_spi(SGTKInternal) import Gtk
|
|
@_spi(Portico) import Portico
|
|
|
|
@MainActor @Suite(.serialized) struct ViewBuilderSlotTests {
|
|
|
|
// MARK: - Single-slot initializer (Clamp)
|
|
|
|
@Test func clampInitBuilderMountsChild() {
|
|
guard Gtk.initCheck() else { return }
|
|
let w = AnyView(Clamp { Label(str: "hi") }).makeWidget(MountContext())
|
|
guard let clamp = w as? Adw.Clamp else {
|
|
Issue.record("Expected Adw.Clamp, got \(type(of: w))")
|
|
return
|
|
}
|
|
#expect(clamp.getChild() != nil)
|
|
}
|
|
|
|
// MARK: - Single-slot modifier
|
|
|
|
@Test func clampModifierBuilderMountsChild() {
|
|
guard Gtk.initCheck() else { return }
|
|
let w = AnyView(Clamp().child { Label(str: "hi") }).makeWidget(MountContext())
|
|
guard let clamp = w as? Adw.Clamp else {
|
|
Issue.record("Expected Adw.Clamp, got \(type(of: w))")
|
|
return
|
|
}
|
|
#expect(clamp.getChild() != nil)
|
|
}
|
|
|
|
// MARK: - Empty closure leaves slot nil
|
|
|
|
@Test func clampInitBuilderEmptyLeavesChildNil() {
|
|
guard Gtk.initCheck() else { return }
|
|
let w = AnyView(Clamp { }).makeWidget(MountContext())
|
|
guard let clamp = w as? Adw.Clamp else {
|
|
Issue.record("Expected Adw.Clamp, got \(type(of: w))")
|
|
return
|
|
}
|
|
#expect(clamp.getChild() == nil)
|
|
}
|
|
|
|
// MARK: - Multi-slot initializer (CenterBox)
|
|
|
|
@Test func centerBoxInitBuilderMountsAllSlots() {
|
|
guard Gtk.initCheck() else { return }
|
|
let w = AnyView(CenterBox(
|
|
centerWidget: { Label(str: "c") },
|
|
endWidget: { Label(str: "e") },
|
|
startWidget: { Label(str: "s") }
|
|
)).makeWidget(MountContext())
|
|
guard let cb = w as? Gtk.CenterBox else {
|
|
Issue.record("Expected Gtk.CenterBox, got \(type(of: w))")
|
|
return
|
|
}
|
|
#expect(cb.getCenterWidget() != nil)
|
|
#expect(cb.getEndWidget() != nil)
|
|
#expect(cb.getStartWidget() != nil)
|
|
}
|
|
|
|
// MARK: - Multi-slot trailing closure (unlabeled = first in declaration order = centerWidget)
|
|
|
|
@Test func centerBoxTrailingClosureBindsFirstParam() {
|
|
guard Gtk.initCheck() else { return }
|
|
let w = AnyView(CenterBox {
|
|
Label(str: "c")
|
|
} endWidget: {
|
|
Label(str: "e")
|
|
} startWidget: {
|
|
Label(str: "s")
|
|
}).makeWidget(MountContext())
|
|
guard let cb = w as? Gtk.CenterBox else {
|
|
Issue.record("Expected Gtk.CenterBox, got \(type(of: w))")
|
|
return
|
|
}
|
|
#expect(cb.getCenterWidget() != nil)
|
|
}
|
|
|
|
@Test func centerBoxNamedSlotsKeepRequiredValue() {
|
|
guard Gtk.initCheck() else { return }
|
|
let w = AnyView(CenterBox(
|
|
baselinePosition: .top,
|
|
endWidget: { Label(str: "r") },
|
|
startWidget: { Label(str: "l") }
|
|
)).makeWidget(MountContext())
|
|
guard let cb = w as? Gtk.CenterBox else {
|
|
Issue.record("Expected Gtk.CenterBox, got \(type(of: w))")
|
|
return
|
|
}
|
|
#expect(cb.getStartWidget() != nil)
|
|
#expect(cb.getEndWidget() != nil)
|
|
#expect(cb.getBaselinePosition() == .top)
|
|
}
|
|
}
|
|
|
|
@MainActor @Suite(.serialized) struct SequentialContainerInitTests {
|
|
|
|
/// Counts the direct children of a widget by walking the GTK sibling chain.
|
|
private func childCount(of w: Gtk.Widget) -> Int {
|
|
var n = 0
|
|
var child = w.getFirstChild()
|
|
while let c = child {
|
|
n += 1
|
|
child = c.getNextSibling()
|
|
}
|
|
return n
|
|
}
|
|
|
|
// MARK: - No-arg base init (WrapBox)
|
|
|
|
@Test func wrapBoxAppendsAllChildren() {
|
|
guard Gtk.initCheck() else { return }
|
|
let w = AnyView(WrapBox {
|
|
Label(str: "a")
|
|
Label(str: "b")
|
|
Label(str: "c")
|
|
}).makeWidget(MountContext())
|
|
#expect(childCount(of: w) == 3)
|
|
}
|
|
|
|
@Test func wrapBoxEmptyClosureLeavesNoChildren() {
|
|
guard Gtk.initCheck() else { return }
|
|
let w = AnyView(WrapBox { }).makeWidget(MountContext())
|
|
#expect(childCount(of: w) == 0)
|
|
}
|
|
|
|
// MARK: - Base params preserved alongside children (Box)
|
|
|
|
@Test func boxAppendsChildrenAndKeepsBaseParams() {
|
|
guard Gtk.initCheck() else { return }
|
|
let w = AnyView(Box(orientation: .vertical, spacing: 8) {
|
|
Label(str: "a")
|
|
Label(str: "b")
|
|
}).makeWidget(MountContext())
|
|
guard let box = w as? Gtk.Box else {
|
|
Issue.record("Expected Gtk.Box, got \(type(of: w))")
|
|
return
|
|
}
|
|
#expect(box.getSpacing() == 8)
|
|
#expect(box.getOrientation() == .vertical)
|
|
#expect(childCount(of: w) == 2)
|
|
}
|
|
|
|
// MARK: - Ordering is preserved
|
|
|
|
@Test func boxPreservesChildOrder() {
|
|
guard Gtk.initCheck() else { return }
|
|
let w = AnyView(Box(orientation: .horizontal, spacing: 0) {
|
|
Label(str: "first")
|
|
Label(str: "second")
|
|
}).makeWidget(MountContext())
|
|
// getFirstChild returns a base Widget; reconstruct Label from the pointer.
|
|
guard let a = w.getFirstChild(), let b = a.getNextSibling() else {
|
|
Issue.record("Expected two children")
|
|
return
|
|
}
|
|
#expect(Gtk.Label(retaining: a.pointer).getText() == "first")
|
|
#expect(Gtk.Label(retaining: b.pointer).getText() == "second")
|
|
}
|
|
|
|
// MARK: - Value-returning append (Leaflet / TabView)
|
|
|
|
/// `Adw.Leaflet.append` returns a `LeafletPage` and wraps children in internal
|
|
/// structure, so assert the semantic outcome rather than the raw sibling count.
|
|
@Test func leafletAppendsChildrenDespiteReturningPage() {
|
|
guard Gtk.initCheck() else { return }
|
|
let w = AnyView(Leaflet {
|
|
Label(str: "a")
|
|
Label(str: "b")
|
|
}).makeWidget(MountContext())
|
|
guard let leaflet = w as? Adw.Leaflet else {
|
|
Issue.record("Expected Adw.Leaflet, got \(type(of: w))")
|
|
return
|
|
}
|
|
#expect(leaflet.getVisibleChild() != nil)
|
|
|
|
let empty = AnyView(Leaflet { }).makeWidget(MountContext())
|
|
guard let emptyLeaflet = empty as? Adw.Leaflet else {
|
|
Issue.record("Expected Adw.Leaflet, got \(type(of: empty))")
|
|
return
|
|
}
|
|
#expect(emptyLeaflet.getVisibleChild() == nil)
|
|
}
|
|
|
|
// MARK: - ListBox wraps each child in a row, so assert via first child
|
|
|
|
@Test func listBoxAppendsChildren() {
|
|
guard Gtk.initCheck() else { return }
|
|
let w = AnyView(ListBox {
|
|
Label(str: "a")
|
|
Label(str: "b")
|
|
}).makeWidget(MountContext())
|
|
#expect(childCount(of: w) == 2)
|
|
}
|
|
}
|