Fall back to System Settings when the Mail consent prompt is the known beta bug
Confirmed via multiple live rounds with Rune this is a macOS 27 beta issue, not a Confab bug — matches an already-documented pattern in this project (Calendar/Contacts requestAccess failing identically). Every failure returns in single-digit milliseconds, ruled out threading, wrong API, build/signing, and notarization; even a fresh notarized build fails identically, while Terminal->Mail (first-party) works with no prompt at all, and the same-style bug already has a drafted Apple Feedback report for a different permission category. Kept the real Apple Event attempt as the primary path (the way this should work once the OS bug is fixed), but now time it: a failure faster than any human could plausibly answer a real dialog (default 300ms) is classified as the platform bug rather than a genuine denial, and the UI falls back to opening System Settings' Automation pane directly with an explanatory note, instead of the button silently doing nothing.
This commit is contained in:
@@ -188,4 +188,29 @@ struct AppleMailServiceTests {
|
||||
#expect(AppleMailService.mapAutomationPermissionStatus(-1744) == .notDetermined)
|
||||
#expect(AppleMailService.mapAutomationPermissionStatus(-9999) == .notDetermined)
|
||||
}
|
||||
|
||||
// MARK: - classifyRequestOutcome
|
||||
|
||||
@Test("classifyRequestOutcome maps success to granted regardless of elapsed time")
|
||||
func classifiesSuccessAsGranted() {
|
||||
#expect(AppleMailService.classifyRequestOutcome(succeeded: true, elapsedSeconds: 0.001) == .granted)
|
||||
#expect(AppleMailService.classifyRequestOutcome(succeeded: true, elapsedSeconds: 5.0) == .granted)
|
||||
}
|
||||
|
||||
@Test("classifyRequestOutcome treats an implausibly fast failure as the suspected platform bug")
|
||||
func classifiesFastFailureAsSuspectedBug() {
|
||||
#expect(AppleMailService.classifyRequestOutcome(succeeded: false, elapsedSeconds: 0.009) == .suspectedPlatformBug)
|
||||
#expect(AppleMailService.classifyRequestOutcome(succeeded: false, elapsedSeconds: 0.0) == .suspectedPlatformBug)
|
||||
}
|
||||
|
||||
@Test("classifyRequestOutcome treats a slower failure as a real denial")
|
||||
func classifiesSlowFailureAsDenied() {
|
||||
#expect(AppleMailService.classifyRequestOutcome(succeeded: false, elapsedSeconds: 1.5) == .denied)
|
||||
}
|
||||
|
||||
@Test("classifyRequestOutcome threshold is right at the boundary")
|
||||
func classifiesThresholdBoundary() {
|
||||
#expect(AppleMailService.classifyRequestOutcome(succeeded: false, elapsedSeconds: AppleMailService.suspectedBugThreseholdSeconds) == .denied)
|
||||
#expect(AppleMailService.classifyRequestOutcome(succeeded: false, elapsedSeconds: AppleMailService.suspectedBugThreseholdSeconds - 0.001) == .suspectedPlatformBug)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user