File size: 3,622 Bytes
b8370f5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | #if os(macOS)
import AppKit
import SwiftMath
import SwiftUI
import Testing
@testable import OpenClawChatUI
@MainActor
struct ChatMathBlockViewTests {
@Test(arguments: [false, true])
func `display math retains its typeset bounds in transcript layout`(usesSplitView: Bool) throws {
_ = NSApplication.shared
let message = OpenClawChatMessage(
role: "assistant",
content: [OpenClawChatMessageContent(
type: "text",
text: "Before the equation.\n\n$$E = mc^2$$\n\nAfter the equation.",
mimeType: nil,
fileName: nil,
content: nil)],
timestamp: nil)
let content = ScrollView {
LazyVStack(alignment: .leading) {
ChatMessageBubble(
message: message,
style: .standard,
markdownVariant: .standard,
userAccent: nil,
displayOptions: [],
assistantName: "OpenClaw",
assistantAvatarText: "OC",
assistantAvatarTint: nil,
showsAssistantAvatar: usesSplitView,
isClean: true,
contextWindowTokens: nil,
userMessageExpanded: false,
onToggleUserMessageExpanded: {},
inlineWidgetResolverReady: false,
inlineWidgetResourceResolver: { _, _ in nil },
mediaArtifactResolverReady: false,
mediaPlaybackAllowed: { false },
loadMediaArtifact: { _, _, _ in nil })
}
.frame(maxWidth: .infinity)
}
let window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 960, height: 680),
styleMask: [.titled, .closable, .resizable, .fullSizeContentView],
backing: .buffered,
defer: false)
let host: NSView
if usesSplitView {
// Full chat's split-view host can collapse an equation that sizes
// correctly in Quick Chat's direct host. Exercise both containers.
let controller = NSHostingController(rootView: NavigationSplitView {
Text("Sessions")
.navigationSplitViewColumnWidth(min: 200, ideal: 240, max: 340)
} detail: {
content
})
window.contentViewController = controller
controller.sceneBridgingOptions = [.toolbars]
host = controller.view
} else {
host = NSHostingView(rootView: content)
window.contentView = host
}
defer {
window.contentViewController = nil
window.contentView = nil
}
for layoutWidth in [CGFloat(960), CGFloat(620), CGFloat(960)] {
window.setContentSize(NSSize(width: layoutWidth, height: 400))
host.layoutSubtreeIfNeeded()
let label = try #require(Self.mathLabel(in: host))
#expect(label.error == nil)
let typesetSize = label.fittingSize
#expect(typesetSize.width > 0)
#expect(typesetSize.height > 0)
#expect(label.bounds.width + 0.5 >= typesetSize.width)
#expect(label.bounds.height + 0.5 >= typesetSize.height)
}
}
private static func mathLabel(in view: NSView) -> MTMathUILabel? {
if let label = view as? MTMathUILabel { return label }
return view.subviews.lazy.compactMap { Self.mathLabel(in: $0) }.first
}
}
#endif
|