Fix Kownlege card & Metrics Tests

This commit is contained in:
Kaede Akino committed 2026-09-18 18:26:43 +08:00
1 parent ead82299d8
commit cd765c1200
4 files changed
+74 -6

No files matched your search

@@ -28,6 +28,7 @@ public struct AssistantCompactToolDetails: View {
contentHeight = $0
}
.frame(maxHeight: expanded ? nil : previewHeight, alignment: .top)
.fixedSize(horizontal: false, vertical: true)
.clipped()
if expanded || preview.isShortened || contentHeight > previewHeight {
HStack(spacing: 16) {
@@ -31,18 +31,61 @@ struct MobileKnowledgeToolRenderingTests {
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)
if card.descriptor.name != "skill_install" { #expect(expanded.height > compact.height) }
#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))
@@ -56,6 +99,12 @@ struct MobileKnowledgeToolRenderingTests {
#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)
+14 -2
View File
@@ -34,13 +34,25 @@ struct KnowledgeToolRenderingTests {
try snapshot(
row, width: width, height: compact, name: "mac-\(language.rawValue)-\(card.descriptor.name)")
}
let presenter = try #require(
AgentToolCatalog.builtInPresenters.first { $0.id == card.descriptor.presentation?.presenterID })
let detail = try #require(
AgentToolPresentation.detail(for: card, presenter: presenter, locale: language.locale))
guard AgentToolDetailPreview(detail).isShortened else {
#expect(!state.disclosures.isExpanded(.toolDetail(card.id)))
continue
}
state.disclosures.toggleDisclosure(.toolDetail(card.id))
configure()
let expanded = row.measuredHeight(for: width)
#expect(expanded >= compact)
if card.descriptor.name != "skill_install" { #expect(expanded > compact) }
#expect(expanded > compact, "\(language.rawValue): \(card.descriptor.name)")
configure()
#expect(abs(row.measuredHeight(for: width) - expanded) < 0.5)
#expect(state.disclosures.isExpanded(.toolDetail(card.id)))
state.disclosures.toggleDisclosure(.toolDetail(card.id))
configure()
#expect(abs(row.measuredHeight(for: width) - compact) < 0.5)
#expect(!state.disclosures.isExpanded(.toolDetail(card.id)))
}
}
}
+8 -2
View File
@@ -348,6 +348,9 @@ struct ServerMetricsLifecycleTests {
#expect(fixture.model.servers.count == 1)
#expect(fixture.model.snapshot(for: fixture.host.id)?.state == .live)
#expect(await fixture.sampler.connections == 1)
// Base metrics appear before GPU collection finishes and the sampling sleep is registered.
// Both the maintenance loop and the sampler must be waiting before advancing this clock.
await eventually { fixture.time.pendingSleeps == 2 }
let first = server.point?.date
fixture.time.advance(2)
await eventually { server.point?.date != first }
@@ -534,13 +537,15 @@ struct ServerMetricsLifecycleTests {
await eventually { await fixture.sampler.connections == 2 }
}
private func eventually(_ condition: () async -> Bool) async {
private func eventually(
sourceLocation: SourceLocation = #_sourceLocation, _ condition: () async -> Bool
) async {
for _ in 0..<2000 {
if await condition() { return }
await Task.yield()
try? await Task.sleep(for: .milliseconds(1))
}
#expect(await condition())
#expect(await condition(), sourceLocation: sourceLocation)
}
private struct Fixture {
@@ -659,6 +664,7 @@ private nonisolated final class ManualMetricsTime: @unchecked Sendable {
private var waiters: [UUID: (Date, CheckedContinuation<Void, any Error>)] = [:]
private var requested: [Double] = []
var delays: [Double] { lock.withLock { requested } }
var pendingSleeps: Int { lock.withLock { waiters.count } }
var clock: MetricsClock {
MetricsClock(now: { self.lock.withLock { self.date } }, sleep: { try await self.sleep($0) })
}