97 lines
4.1 KiB
Swift
97 lines
4.1 KiB
Swift
import Foundation
|
|
import Testing
|
|
@testable import CodexBarCore
|
|
|
|
#if os(macOS)
|
|
@Suite(.serialized)
|
|
struct ClaudeOAuthKeychainPreAlertGateTests {
|
|
@Test
|
|
func `acknowledgement suppresses repeated presentation until cooldown expires`() {
|
|
let store = ClaudeOAuthKeychainPreAlertGate.StateStore()
|
|
ClaudeOAuthKeychainPreAlertGate.withStateStoreOverrideForTesting(store) {
|
|
let now = Date(timeIntervalSince1970: 1000)
|
|
#expect(ClaudeOAuthKeychainPreAlertGate.presentIfNeeded(now: now, completedAt: now) { true })
|
|
|
|
#expect(
|
|
ClaudeOAuthKeychainPreAlertGate.presentIfNeeded(
|
|
now: now.addingTimeInterval(ClaudeOAuthKeychainPreAlertGate.cooldownInterval - 1),
|
|
completedAt: now,
|
|
present: { true }) == false)
|
|
#expect(
|
|
ClaudeOAuthKeychainPreAlertGate.presentIfNeeded(
|
|
now: now.addingTimeInterval(ClaudeOAuthKeychainPreAlertGate.cooldownInterval + 1),
|
|
completedAt: now,
|
|
present: { true }))
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func `cooldown starts when presentation completes`() {
|
|
let store = ClaudeOAuthKeychainPreAlertGate.StateStore()
|
|
ClaudeOAuthKeychainPreAlertGate.withStateStoreOverrideForTesting(store) {
|
|
let startedAt = Date(timeIntervalSince1970: 1000)
|
|
let completedAt = Date(timeIntervalSince1970: 2000)
|
|
#expect(ClaudeOAuthKeychainPreAlertGate.presentIfNeeded(
|
|
now: startedAt,
|
|
completedAt: completedAt,
|
|
present: { true }))
|
|
|
|
#expect(ClaudeOAuthKeychainPreAlertGate.presentIfNeeded(
|
|
now: startedAt.addingTimeInterval(ClaudeOAuthKeychainPreAlertGate.cooldownInterval + 1),
|
|
completedAt: completedAt,
|
|
present: { true }) == false)
|
|
#expect(ClaudeOAuthKeychainPreAlertGate.presentIfNeeded(
|
|
now: completedAt.addingTimeInterval(ClaudeOAuthKeychainPreAlertGate.cooldownInterval + 1),
|
|
completedAt: completedAt,
|
|
present: { true }))
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func `missing prompt handler does not consume acknowledgement cooldown`() {
|
|
let store = ClaudeOAuthKeychainPreAlertGate.StateStore()
|
|
ClaudeOAuthKeychainPreAlertGate.withStateStoreOverrideForTesting(store) {
|
|
let now = Date(timeIntervalSince1970: 2000)
|
|
#expect(ClaudeOAuthKeychainPreAlertGate.presentIfNeeded(now: now, completedAt: now) { false } == false)
|
|
#expect(ClaudeOAuthKeychainPreAlertGate.presentIfNeeded(now: now, completedAt: now) { true })
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func `duplicate while presentation is in flight is suppressed`() {
|
|
let store = ClaudeOAuthKeychainPreAlertGate.StateStore()
|
|
ClaudeOAuthKeychainPreAlertGate.withStateStoreOverrideForTesting(store) {
|
|
let now = Date(timeIntervalSince1970: 3000)
|
|
var nestedPresentationRan = false
|
|
var nestedResult: Bool?
|
|
let outerResult = ClaudeOAuthKeychainPreAlertGate.presentIfNeeded(now: now, completedAt: now) {
|
|
nestedResult = ClaudeOAuthKeychainPreAlertGate.presentIfNeeded(now: now) {
|
|
nestedPresentationRan = true
|
|
return true
|
|
}
|
|
return true
|
|
}
|
|
#expect(outerResult)
|
|
#expect(nestedResult == false)
|
|
#expect(nestedPresentationRan == false)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func `acknowledgement persists across in memory reset`() {
|
|
ClaudeOAuthKeychainPreAlertGate.resetForTesting()
|
|
defer { ClaudeOAuthKeychainPreAlertGate.resetForTesting() }
|
|
|
|
let now = Date(timeIntervalSince1970: 4000)
|
|
#expect(ClaudeOAuthKeychainPreAlertGate.presentIfNeeded(now: now, completedAt: now) { true })
|
|
ClaudeOAuthKeychainPreAlertGate.resetInMemoryForTesting()
|
|
|
|
#expect(
|
|
ClaudeOAuthKeychainPreAlertGate.presentIfNeeded(
|
|
now: now.addingTimeInterval(ClaudeOAuthKeychainPreAlertGate.cooldownInterval - 1),
|
|
completedAt: now,
|
|
present: { true }) == false)
|
|
}
|
|
}
|
|
#endif
|