chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,300 @@
|
||||
import AppKit
|
||||
import CodexBarCore
|
||||
import SwiftUI
|
||||
import Testing
|
||||
@testable import CodexBar
|
||||
|
||||
@MainActor
|
||||
@Suite(.serialized)
|
||||
struct StatusMenuOverviewClickTests {
|
||||
@Test
|
||||
func `routes runtime click without gesture recognizer`() {
|
||||
var clicked = false
|
||||
let view = MenuCardItemHostingView(
|
||||
rootView: Text("Overview row"),
|
||||
highlightState: MenuCardHighlightState(),
|
||||
allowsMenuHighlight: true,
|
||||
onClick: { clicked = true })
|
||||
view.frame = NSRect(x: 0, y: 0, width: 320, height: 44)
|
||||
#expect(view._test_simulateRuntimeClick())
|
||||
#expect(clicked)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `routes gpu selection runtime click without gesture recognizer`() {
|
||||
var clicked = false
|
||||
let wrapped = MenuCardSectionContainerView(
|
||||
highlightState: MenuCardHighlightState(),
|
||||
showsSubmenuIndicator: false,
|
||||
submenuIndicatorAlignment: .trailing,
|
||||
submenuIndicatorTopPadding: 0,
|
||||
refreshMonitor: nil)
|
||||
{
|
||||
Text("Overview GPU row")
|
||||
}
|
||||
let view = GPUSelectionHostingView(
|
||||
rootView: wrapped,
|
||||
allowsMenuHighlight: true,
|
||||
onClick: { clicked = true })
|
||||
view.frame = NSRect(x: 0, y: 0, width: 320, height: 44)
|
||||
#expect(view._test_simulateRuntimeClick())
|
||||
#expect(clicked)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `gpu tracking activates only for mouseUp inside row`() {
|
||||
let wrapped = MenuCardSectionContainerView(
|
||||
highlightState: MenuCardHighlightState(),
|
||||
showsSubmenuIndicator: false,
|
||||
submenuIndicatorAlignment: .trailing,
|
||||
submenuIndicatorTopPadding: 0,
|
||||
refreshMonitor: nil)
|
||||
{
|
||||
Text("Overview GPU row")
|
||||
}
|
||||
let view = GPUSelectionHostingView(
|
||||
rootView: wrapped,
|
||||
allowsMenuHighlight: true,
|
||||
onClick: {})
|
||||
view.frame = NSRect(x: 0, y: 0, width: 320, height: 44)
|
||||
let events = Self.mouseClick(at: NSPoint(x: 160, y: 22))
|
||||
|
||||
#expect(view._test_primaryPressDecision(for: events.down) == nil)
|
||||
#expect(view._test_primaryPressDecision(for: events.up) == true)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `gpu tracking cancels when release leaves row`() {
|
||||
let wrapped = MenuCardSectionContainerView(
|
||||
highlightState: MenuCardHighlightState(),
|
||||
showsSubmenuIndicator: true,
|
||||
submenuIndicatorAlignment: .trailing,
|
||||
submenuIndicatorTopPadding: 0,
|
||||
refreshMonitor: nil)
|
||||
{
|
||||
Text("Overview GPU row")
|
||||
}
|
||||
let view = GPUSelectionHostingView(
|
||||
rootView: wrapped,
|
||||
allowsMenuHighlight: true,
|
||||
onClick: {})
|
||||
view.frame = NSRect(x: 0, y: 0, width: 320, height: 44)
|
||||
let outsideUp = Self.mouseClick(at: NSPoint(x: 340, y: 22)).up
|
||||
|
||||
#expect(view._test_primaryPressDecision(for: outsideUp) == false)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `gpu tracking yields an outside drag to native submenu tracking`() {
|
||||
let wrapped = MenuCardSectionContainerView(
|
||||
highlightState: MenuCardHighlightState(),
|
||||
showsSubmenuIndicator: true,
|
||||
submenuIndicatorAlignment: .trailing,
|
||||
submenuIndicatorTopPadding: 0,
|
||||
refreshMonitor: nil)
|
||||
{
|
||||
Text("Overview GPU row")
|
||||
}
|
||||
let view = GPUSelectionHostingView(
|
||||
rootView: wrapped,
|
||||
allowsMenuHighlight: true,
|
||||
onClick: {})
|
||||
view.frame = NSRect(x: 0, y: 0, width: 320, height: 44)
|
||||
|
||||
let insideDrag = Self.mouseDrag(at: NSPoint(x: 160, y: 22))
|
||||
let outsideDrag = Self.mouseDrag(at: NSPoint(x: 340, y: 22))
|
||||
#expect(!view._test_primaryPressShouldYieldToMenu(for: insideDrag))
|
||||
#expect(view._test_primaryPressShouldYieldToMenu(for: outsideDrag))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `hitTest preserves button targets in standard hosting view`() {
|
||||
let view = MenuCardItemHostingView(
|
||||
rootView: Text("Overview row"),
|
||||
highlightState: MenuCardHighlightState(),
|
||||
allowsMenuHighlight: true,
|
||||
onClick: {})
|
||||
view.frame = NSRect(x: 0, y: 0, width: 320, height: 44)
|
||||
let button = NSButton(frame: NSRect(x: 10, y: 10, width: 50, height: 20))
|
||||
view.addSubview(button)
|
||||
|
||||
let hit = view.hitTest(NSPoint(x: 15, y: 15))
|
||||
#expect(hit !== view)
|
||||
#expect(hit === button || hit?.isDescendant(of: button) == true)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `hitTest preserves button targets in gpu selection hosting view`() {
|
||||
let wrapped = MenuCardSectionContainerView(
|
||||
highlightState: MenuCardHighlightState(),
|
||||
showsSubmenuIndicator: false,
|
||||
submenuIndicatorAlignment: .trailing,
|
||||
submenuIndicatorTopPadding: 0,
|
||||
refreshMonitor: nil)
|
||||
{
|
||||
Text("Overview GPU row")
|
||||
}
|
||||
let view = GPUSelectionHostingView(
|
||||
rootView: wrapped,
|
||||
allowsMenuHighlight: true,
|
||||
onClick: {})
|
||||
view.frame = NSRect(x: 0, y: 0, width: 320, height: 44)
|
||||
let button = NSButton(frame: NSRect(x: 10, y: 10, width: 50, height: 20))
|
||||
view.addSubview(button)
|
||||
|
||||
let hit = view.hitTest(NSPoint(x: 15, y: 15))
|
||||
#expect(hit !== view)
|
||||
#expect(hit === button || hit?.isDescendant(of: button) == true)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `gpu hosting preserves nested SwiftUI button target`() {
|
||||
let interactiveRegionStore = MenuCardInteractiveRegionStore()
|
||||
let content = Button("Copy") {}
|
||||
.frame(width: 80, height: 30)
|
||||
.menuCardInteractiveControl()
|
||||
.frame(width: 320, height: 44, alignment: .trailing)
|
||||
let wrapped = MenuCardSectionContainerView(
|
||||
highlightState: MenuCardHighlightState(),
|
||||
showsSubmenuIndicator: false,
|
||||
submenuIndicatorAlignment: .trailing,
|
||||
submenuIndicatorTopPadding: 0,
|
||||
refreshMonitor: nil,
|
||||
interactiveRegionStore: interactiveRegionStore)
|
||||
{
|
||||
content
|
||||
}
|
||||
let view = GPUSelectionHostingView(
|
||||
rootView: wrapped,
|
||||
allowsMenuHighlight: true,
|
||||
containsInteractiveControls: true,
|
||||
interactiveRegionStore: interactiveRegionStore,
|
||||
onClick: {})
|
||||
view.frame = NSRect(x: 0, y: 0, width: 320, height: 51)
|
||||
Self.settleWindowlessLayout(view)
|
||||
let buttonPoint = NSPoint(x: 280, y: 39)
|
||||
|
||||
#expect(view._test_hitsHostedInteractiveControl(at: buttonPoint))
|
||||
#expect(!view._test_hitsHostedInteractiveControl(at: NSPoint(x: 280, y: 8)))
|
||||
#expect(view.hitTest(buttonPoint) !== view)
|
||||
#expect(!view._test_simulateRuntimeClick(at: buttonPoint))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `standard hosting forwards nested SwiftUI control events without invoking row`() {
|
||||
var rowClicked = false
|
||||
let interactiveRegionStore = MenuCardInteractiveRegionStore()
|
||||
let content = Button("Copy") {}
|
||||
.frame(width: 80, height: 30)
|
||||
.menuCardInteractiveControl()
|
||||
.frame(width: 320, height: 44, alignment: .trailing)
|
||||
let wrapped = MenuCardSectionContainerView(
|
||||
highlightState: MenuCardHighlightState(),
|
||||
showsSubmenuIndicator: false,
|
||||
submenuIndicatorAlignment: .trailing,
|
||||
submenuIndicatorTopPadding: 0,
|
||||
refreshMonitor: nil,
|
||||
interactiveRegionStore: interactiveRegionStore)
|
||||
{
|
||||
content
|
||||
}
|
||||
let view = MenuCardItemHostingView(
|
||||
rootView: wrapped,
|
||||
highlightState: MenuCardHighlightState(),
|
||||
allowsMenuHighlight: true,
|
||||
containsInteractiveControls: true,
|
||||
interactiveRegionStore: interactiveRegionStore,
|
||||
onClick: { rowClicked = true })
|
||||
view.frame = NSRect(x: 0, y: 0, width: 320, height: 51)
|
||||
Self.settleWindowlessLayout(view)
|
||||
let buttonPoint = NSPoint(x: 280, y: 39)
|
||||
|
||||
#expect(view._test_hitsHostedInteractiveControl(at: buttonPoint))
|
||||
#expect(!view._test_hitsHostedInteractiveControl(at: NSPoint(x: 280, y: 8)))
|
||||
let events = Self.mouseClick(at: buttonPoint)
|
||||
view.mouseDown(with: events.down)
|
||||
view.mouseUp(with: events.up)
|
||||
let forwarded = view._test_forwardedHostedControlEvents
|
||||
#expect(forwarded.mouseDown)
|
||||
#expect(forwarded.mouseUp)
|
||||
#expect(!rowClicked)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `hidden SwiftUI button region keeps row clickable`() {
|
||||
var rowClicked = false
|
||||
let interactiveRegionStore = MenuCardInteractiveRegionStore()
|
||||
let content = Button("Hidden copy") {}
|
||||
.frame(width: 80, height: 30)
|
||||
.menuCardInteractiveControl(isEnabled: false)
|
||||
.frame(width: 320, height: 44, alignment: .trailing)
|
||||
let wrapped = MenuCardSectionContainerView(
|
||||
highlightState: MenuCardHighlightState(),
|
||||
showsSubmenuIndicator: false,
|
||||
submenuIndicatorAlignment: .trailing,
|
||||
submenuIndicatorTopPadding: 0,
|
||||
refreshMonitor: nil,
|
||||
interactiveRegionStore: interactiveRegionStore)
|
||||
{
|
||||
content
|
||||
}
|
||||
let view = MenuCardItemHostingView(
|
||||
rootView: wrapped,
|
||||
highlightState: MenuCardHighlightState(),
|
||||
allowsMenuHighlight: true,
|
||||
containsInteractiveControls: true,
|
||||
interactiveRegionStore: interactiveRegionStore,
|
||||
onClick: { rowClicked = true })
|
||||
view.frame = NSRect(x: 0, y: 0, width: 320, height: 44)
|
||||
Self.settleWindowlessLayout(view)
|
||||
let buttonPoint = NSPoint(x: 280, y: 22)
|
||||
|
||||
#expect(!view._test_hitsHostedInteractiveControl(at: buttonPoint))
|
||||
#expect(view._test_simulateRuntimeClick(at: buttonPoint))
|
||||
#expect(rowClicked)
|
||||
}
|
||||
|
||||
private static func settleWindowlessLayout(_ view: NSView) {
|
||||
view.needsLayout = true
|
||||
view.layoutSubtreeIfNeeded()
|
||||
RunLoop.current.run(until: Date().addingTimeInterval(0.02))
|
||||
view.layoutSubtreeIfNeeded()
|
||||
}
|
||||
|
||||
private static func mouseClick(at point: NSPoint) -> (down: NSEvent, up: NSEvent) {
|
||||
let down = NSEvent.mouseEvent(
|
||||
with: .leftMouseDown,
|
||||
location: point,
|
||||
modifierFlags: [],
|
||||
timestamp: 0,
|
||||
windowNumber: 0,
|
||||
context: nil,
|
||||
eventNumber: 1,
|
||||
clickCount: 1,
|
||||
pressure: 1)!
|
||||
let up = NSEvent.mouseEvent(
|
||||
with: .leftMouseUp,
|
||||
location: point,
|
||||
modifierFlags: [],
|
||||
timestamp: 0,
|
||||
windowNumber: 0,
|
||||
context: nil,
|
||||
eventNumber: 2,
|
||||
clickCount: 1,
|
||||
pressure: 0)!
|
||||
return (down, up)
|
||||
}
|
||||
|
||||
private static func mouseDrag(at point: NSPoint) -> NSEvent {
|
||||
NSEvent.mouseEvent(
|
||||
with: .leftMouseDragged,
|
||||
location: point,
|
||||
modifierFlags: [],
|
||||
timestamp: 0,
|
||||
windowNumber: 0,
|
||||
context: nil,
|
||||
eventNumber: 3,
|
||||
clickCount: 1,
|
||||
pressure: 1)!
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user