119 lines
6.1 KiB
Swift
119 lines
6.1 KiB
Swift
import AgentKit
|
|
import Foundation
|
|
import SwiftUI
|
|
import TermindApplication
|
|
import TermindPresentation
|
|
import Testing
|
|
import UIKit
|
|
|
|
@testable import TermindIOS
|
|
|
|
@Suite(.serialized) @MainActor
|
|
struct MobileKnowledgeToolRenderingTests {
|
|
@Test func knowledgeRowsStayCompactAtPhoneWidthAndExpandOnDemand() async throws {
|
|
for language in [AppLanguage.english, .simplifiedChinese, .traditionalChinese] {
|
|
for card in AssistantTranscriptPreview.knowledgeCards(language: language) {
|
|
let state = AssistantTranscriptPresentationState()
|
|
state.followDefault(true, for: .tool(card.id))
|
|
let controller = UIHostingController(
|
|
rootView:
|
|
MobileAssistantToolRow(card: card, presentation: state, hostName: { _ in "Unused" })
|
|
.environment(\.locale, language.locale)
|
|
.environment(\.mobileListReduceMotion, true)
|
|
.padding(16)
|
|
.background(Color(uiColor: .systemBackground)))
|
|
let size = CGSize(width: 390, height: 30_000)
|
|
let compact = controller.sizeThatFits(in: size)
|
|
#expect(compact.height <= 360, "\(card.descriptor.name): \(compact.height)")
|
|
#expect(compact.height > 40)
|
|
controller.view.frame = CGRect(origin: .zero, size: compact)
|
|
controller.view.layoutIfNeeded()
|
|
if ProcessInfo.processInfo.environment["TERMIND_KNOWLEDGE_SCREENSHOTS"] == "1" {
|
|
try snapshot(controller.view, name: "ios-\(language.rawValue)-\(card.descriptor.name)")
|
|
}
|
|
let detail = try detail(for: card, language: language)
|
|
guard AgentToolDetailPreview(detail).isShortened else {
|
|
#expect(!state.isExpanded(.toolDetail(card.id)))
|
|
continue
|
|
}
|
|
state.toggleDisclosure(.toolDetail(card.id))
|
|
try await Task.sleep(for: .milliseconds(20))
|
|
controller.view.setNeedsLayout()
|
|
controller.view.layoutIfNeeded()
|
|
let expanded = controller.sizeThatFits(in: size)
|
|
#expect(expanded.height > compact.height, "\(language.rawValue): \(card.descriptor.name)")
|
|
controller.view.setNeedsLayout()
|
|
controller.view.layoutIfNeeded()
|
|
#expect(abs(controller.sizeThatFits(in: size).height - expanded.height) < 0.5)
|
|
#expect(state.isExpanded(.toolDetail(card.id)))
|
|
state.toggleDisclosure(.toolDetail(card.id))
|
|
try await Task.sleep(for: .milliseconds(20))
|
|
controller.view.setNeedsLayout()
|
|
controller.view.layoutIfNeeded()
|
|
#expect(abs(controller.sizeThatFits(in: size).height - compact.height) < 0.5)
|
|
#expect(!state.isExpanded(.toolDetail(card.id)))
|
|
}
|
|
}
|
|
}
|
|
|
|
@Test func shortKnowledgeDetailsKeepTheirNaturalHeight() throws {
|
|
for language in [AppLanguage.english, .simplifiedChinese, .traditionalChinese] {
|
|
var shortCards = 0
|
|
for card in AssistantTranscriptPreview.knowledgeCards(language: language) {
|
|
let detail = try detail(for: card, language: language)
|
|
guard !AgentToolDetailPreview(detail).isShortened else { continue }
|
|
shortCards += 1
|
|
let natural = UIHostingController(
|
|
rootView:
|
|
AssistantToolDetails(items: detail.items)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
.fixedSize(horizontal: false, vertical: true)
|
|
.environment(\.locale, language.locale))
|
|
let compact = UIHostingController(
|
|
rootView:
|
|
AssistantCompactToolDetails(
|
|
detail: detail, isError: false, expanded: .constant(false), copy: { _ in }
|
|
)
|
|
.environment(\.locale, language.locale))
|
|
let proposal = CGSize(width: 334, height: 30_000)
|
|
let naturalHeight = natural.sizeThatFits(in: proposal).height
|
|
#expect(naturalHeight > 0 && naturalHeight < 180)
|
|
#expect(
|
|
abs(compact.sizeThatFits(in: proposal).height - naturalHeight) < 0.5,
|
|
"\(language.rawValue): \(card.descriptor.name)")
|
|
}
|
|
#expect(shortCards > 0)
|
|
}
|
|
}
|
|
|
|
@Test func largerTextScalesThePreviewRatherThanHidingItsControls() {
|
|
let detail = AgentToolDetail(items: [
|
|
.text(.init(text: String(repeating: "Readable memory\n", count: 100), style: .plain))
|
|
])
|
|
let controller = UIHostingController(
|
|
rootView:
|
|
AssistantCompactToolDetails(detail: detail, isError: false, expanded: .constant(false), copy: { _ in })
|
|
.environment(\.dynamicTypeSize, .accessibility2))
|
|
let size = controller.sizeThatFits(in: CGSize(width: 390, height: 30_000))
|
|
#expect(size.height > 180)
|
|
#expect(size.height < 800)
|
|
}
|
|
|
|
private func detail(for card: AgentToolCard, language: AppLanguage) throws -> AgentToolDetail {
|
|
let presenter = try #require(
|
|
AgentToolCatalog.builtInPresenters.first { $0.id == card.descriptor.presentation?.presenterID })
|
|
return try #require(AgentToolPresentation.detail(for: card, presenter: presenter, locale: language.locale))
|
|
}
|
|
|
|
private func snapshot(_ view: UIView, name: String) throws {
|
|
let image = UIGraphicsImageRenderer(bounds: view.bounds).image { context in
|
|
view.layer.render(in: context.cgContext)
|
|
}
|
|
let directory = FileManager.default.temporaryDirectory.appending(path: "knowledge-screenshots")
|
|
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
|
|
let url = directory.appending(path: name + ".png")
|
|
try #require(image.pngData()).write(to: url)
|
|
print("Knowledge snapshot: \(url.path)")
|
|
}
|
|
}
|