test: expand overlay coverage
This commit is contained in:
@@ -631,3 +631,81 @@ enum CritterIconRenderer {
|
||||
canvas.context.restoreGState()
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
@MainActor
|
||||
extension CritterStatusLabel {
|
||||
static func exerciseForTesting() async {
|
||||
var label = CritterStatusLabel(
|
||||
isPaused: false,
|
||||
isSleeping: false,
|
||||
isWorking: true,
|
||||
earBoostActive: false,
|
||||
blinkTick: 1,
|
||||
sendCelebrationTick: 1,
|
||||
gatewayStatus: .running(details: nil),
|
||||
animationsEnabled: true,
|
||||
iconState: .workingMain(.tool(.bash)))
|
||||
|
||||
_ = label.body
|
||||
_ = label.iconImage
|
||||
_ = label.tickTaskID
|
||||
label.tick(Date())
|
||||
label.resetMotion()
|
||||
label.blink()
|
||||
label.wiggle()
|
||||
label.wiggleLegs()
|
||||
label.wiggleEars()
|
||||
label.scurry()
|
||||
label.scheduleRandomTimers(from: Date())
|
||||
_ = label.gatewayNeedsAttention
|
||||
_ = label.gatewayBadgeColor
|
||||
|
||||
label.isPaused = true
|
||||
_ = label.iconImage
|
||||
|
||||
label.isPaused = false
|
||||
label.isSleeping = true
|
||||
_ = label.iconImage
|
||||
|
||||
label.isSleeping = false
|
||||
label.iconState = .idle
|
||||
_ = label.iconImage
|
||||
|
||||
let failed = CritterStatusLabel(
|
||||
isPaused: false,
|
||||
isSleeping: false,
|
||||
isWorking: false,
|
||||
earBoostActive: false,
|
||||
blinkTick: 0,
|
||||
sendCelebrationTick: 0,
|
||||
gatewayStatus: .failed("boom"),
|
||||
animationsEnabled: false,
|
||||
iconState: .idle)
|
||||
_ = failed.gatewayNeedsAttention
|
||||
_ = failed.gatewayBadgeColor
|
||||
|
||||
let stopped = CritterStatusLabel(
|
||||
isPaused: false,
|
||||
isSleeping: false,
|
||||
isWorking: false,
|
||||
earBoostActive: false,
|
||||
blinkTick: 0,
|
||||
sendCelebrationTick: 0,
|
||||
gatewayStatus: .stopped,
|
||||
animationsEnabled: false,
|
||||
iconState: .idle)
|
||||
_ = stopped.gatewayNeedsAttention
|
||||
_ = stopped.gatewayBadgeColor
|
||||
|
||||
_ = CritterIconRenderer.makeIcon(
|
||||
blink: 0.6,
|
||||
legWiggle: 0.8,
|
||||
earWiggle: 0.4,
|
||||
earScale: 1.4,
|
||||
earHoles: true,
|
||||
eyesClosedLines: true,
|
||||
badge: .init(symbolName: "gearshape.fill", prominence: .secondary))
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -215,6 +215,7 @@ final class HoverHUDController {
|
||||
}
|
||||
|
||||
private func installDismissMonitor() {
|
||||
if ProcessInfo.processInfo.isRunningTests { return }
|
||||
guard self.dismissMonitor == nil, let window else { return }
|
||||
self.dismissMonitor = NSEvent.addGlobalMonitorForEvents(matching: [
|
||||
.leftMouseDown,
|
||||
|
||||
@@ -271,6 +271,9 @@ final class PermissionMonitor {
|
||||
private func startMonitoring() {
|
||||
Task { await self.checkStatus(force: true) }
|
||||
|
||||
if ProcessInfo.processInfo.isRunningTests {
|
||||
return
|
||||
}
|
||||
self.monitorTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
|
||||
guard let self else { return }
|
||||
Task { @MainActor in
|
||||
|
||||
@@ -25,6 +25,7 @@ final class VoicePushToTalkHotkey: @unchecked Sendable {
|
||||
}
|
||||
|
||||
func setEnabled(_ enabled: Bool) {
|
||||
if ProcessInfo.processInfo.isRunningTests { return }
|
||||
self.withMainThread { [weak self] in
|
||||
guard let self else { return }
|
||||
if enabled {
|
||||
|
||||
@@ -855,3 +855,51 @@ private final class TranscriptNSTextView: NSTextView {
|
||||
super.keyDown(with: event)
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
@MainActor
|
||||
extension VoiceWakeOverlayController {
|
||||
static func exerciseForTesting() async {
|
||||
let controller = VoiceWakeOverlayController(enableUI: false)
|
||||
let token = controller.startSession(
|
||||
source: .wakeWord,
|
||||
transcript: "Hello",
|
||||
attributed: nil,
|
||||
forwardEnabled: true,
|
||||
isFinal: false)
|
||||
|
||||
controller.updatePartial(token: token, transcript: "Hello world")
|
||||
controller.presentFinal(token: token, transcript: "Final", autoSendAfter: nil)
|
||||
controller.userBeganEditing()
|
||||
controller.endEditing()
|
||||
controller.updateText("Edited text")
|
||||
|
||||
_ = controller.makeAttributed(from: "Attributed")
|
||||
_ = controller.targetFrame()
|
||||
_ = controller.measuredHeight()
|
||||
_ = controller.dismissTargetFrame(
|
||||
for: NSRect(x: 0, y: 0, width: 120, height: 60),
|
||||
reason: .empty,
|
||||
outcome: .empty)
|
||||
_ = controller.dismissTargetFrame(
|
||||
for: NSRect(x: 0, y: 0, width: 120, height: 60),
|
||||
reason: .explicit,
|
||||
outcome: .sent)
|
||||
_ = controller.dismissTargetFrame(
|
||||
for: NSRect(x: 0, y: 0, width: 120, height: 60),
|
||||
reason: .explicit,
|
||||
outcome: .empty)
|
||||
|
||||
controller.beginSendUI(token: token, sendChime: .none)
|
||||
try? await Task.sleep(nanoseconds: 350_000_000)
|
||||
|
||||
controller.scheduleAutoSend(token: token, after: 10)
|
||||
controller.autoSendTask?.cancel()
|
||||
controller.autoSendTask = nil
|
||||
controller.autoSendToken = nil
|
||||
|
||||
controller.dismiss(token: token, reason: .explicit, outcome: .sent)
|
||||
controller.bringToFrontIfVisible()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -230,6 +230,7 @@ final class WebChatSwiftUIWindowController {
|
||||
}
|
||||
|
||||
private func installDismissMonitor() {
|
||||
if ProcessInfo.processInfo.isRunningTests { return }
|
||||
guard self.dismissMonitor == nil, self.window != nil else { return }
|
||||
self.dismissMonitor = NSEvent.addGlobalMonitorForEvents(
|
||||
matching: [.leftMouseDown, .rightMouseDown, .otherMouseDown])
|
||||
|
||||
@@ -30,5 +30,8 @@ struct CritterIconRendererTests {
|
||||
|
||||
#expect(image.tiffRepresentation != nil)
|
||||
}
|
||||
}
|
||||
|
||||
@Test func critterStatusLabelExercisesHelpers() async {
|
||||
await CritterStatusLabel.exerciseForTesting()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import AppKit
|
||||
import Testing
|
||||
@testable import Clawdis
|
||||
|
||||
@Suite(.serialized)
|
||||
@MainActor
|
||||
struct HoverHUDControllerTests {
|
||||
@Test func hoverHUDControllerPresentsAndDismisses() async {
|
||||
let controller = HoverHUDController()
|
||||
controller.setSuppressed(false)
|
||||
|
||||
controller.statusItemHoverChanged(
|
||||
inside: true,
|
||||
anchorProvider: { NSRect(x: 10, y: 10, width: 24, height: 24) })
|
||||
try? await Task.sleep(nanoseconds: 260_000_000)
|
||||
|
||||
controller.panelHoverChanged(inside: true)
|
||||
controller.panelHoverChanged(inside: false)
|
||||
controller.statusItemHoverChanged(
|
||||
inside: false,
|
||||
anchorProvider: { NSRect(x: 10, y: 10, width: 24, height: 24) })
|
||||
|
||||
controller.dismiss(reason: "test")
|
||||
controller.setSuppressed(true)
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import Testing
|
||||
@Suite(.serialized)
|
||||
@MainActor
|
||||
struct VoiceWakeOverlayControllerTests {
|
||||
@Test func overlayControllerLifecycleWithoutUI() {
|
||||
@Test func overlayControllerLifecycleWithoutUI() async {
|
||||
let controller = VoiceWakeOverlayController(enableUI: false)
|
||||
let token = controller.startSession(
|
||||
source: .wakeWord,
|
||||
@@ -22,6 +22,7 @@ struct VoiceWakeOverlayControllerTests {
|
||||
|
||||
controller.updateLevel(token: token, -0.5)
|
||||
#expect(controller.model.level == 0)
|
||||
try? await Task.sleep(nanoseconds: 120_000_000)
|
||||
controller.updateLevel(token: token, 2.0)
|
||||
#expect(controller.model.level == 1)
|
||||
|
||||
@@ -60,4 +61,8 @@ struct VoiceWakeOverlayControllerTests {
|
||||
controller.updateLevel(token: token, 0.9)
|
||||
#expect(controller.model.level == 0.9)
|
||||
}
|
||||
|
||||
@Test func overlayControllerExercisesHelpers() async {
|
||||
await VoiceWakeOverlayController.exerciseForTesting()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user