176 lines
8.0 KiB
Swift
176 lines
8.0 KiB
Swift
import Foundation
|
|
import Testing
|
|
@testable import CodexBar
|
|
@testable import CodexBarCore
|
|
|
|
@MainActor
|
|
struct CommandCodeQuotaTransitionTests {
|
|
@Test
|
|
func `display keeps prior primary only during subscription enrichment failure`() throws {
|
|
let plan = try #require(CommandCodePlanCatalog.plans.first { $0.monthlyCreditsUSD > 0 })
|
|
let availableWithPlan = self.snapshot(remaining: 6, plan: plan)
|
|
let missingSubscription = self.snapshot(
|
|
remaining: 0,
|
|
purchasedCredits: 5,
|
|
plan: nil,
|
|
subscriptionUnavailable: true)
|
|
let freeTier = self.snapshot(remaining: 0, plan: nil)
|
|
let freeTierWithPurchasedCredits = self.snapshot(remaining: 0, purchasedCredits: 5, plan: nil)
|
|
|
|
#expect(missingSubscription.primary?.usedPercent == 0)
|
|
#expect(freeTierWithPurchasedCredits.primary?.usedPercent == 0)
|
|
|
|
let stabilized = UsageStore.commandCodeSnapshotResolvingDepletionOnEnrichmentFailure(
|
|
current: missingSubscription,
|
|
previous: availableWithPlan)
|
|
#expect(stabilized.primary?.usedPercent == 100)
|
|
|
|
let stabilizedAgain = UsageStore.commandCodeSnapshotResolvingDepletionOnEnrichmentFailure(
|
|
current: missingSubscription,
|
|
previous: stabilized)
|
|
#expect(stabilizedAgain.primary?.usedPercent == 100)
|
|
|
|
let startupFailure = UsageStore.commandCodeSnapshotResolvingDepletionOnEnrichmentFailure(
|
|
current: missingSubscription,
|
|
previous: nil)
|
|
#expect(startupFailure.primary?.usedPercent == 0)
|
|
|
|
let freeTierFailure = UsageStore.commandCodeSnapshotResolvingDepletionOnEnrichmentFailure(
|
|
current: missingSubscription,
|
|
previous: freeTierWithPurchasedCredits)
|
|
#expect(freeTierFailure.primary?.usedPercent == 0)
|
|
|
|
let validFreeTier = UsageStore.commandCodeSnapshotResolvingDepletionOnEnrichmentFailure(
|
|
current: freeTier,
|
|
previous: availableWithPlan)
|
|
#expect(validFreeTier.primary == nil)
|
|
}
|
|
|
|
@Test
|
|
func `depleted notification does not refire across missing subscription window`() throws {
|
|
let settings = self.makeSettings(suiteName: "CommandCodeDepletedNoRefire")
|
|
settings.sessionQuotaNotificationsEnabled = true
|
|
let notifier = NotifierSpy()
|
|
let store = self.makeStore(settings: settings, notifier: notifier)
|
|
let plan = try #require(CommandCodePlanCatalog.plans.first { $0.monthlyCreditsUSD > 0 })
|
|
let depletedWithPlan = self.snapshot(remaining: 0, plan: plan)
|
|
let freeTier = self.snapshot(remaining: 0, plan: nil)
|
|
let missingSubscription = self.snapshot(
|
|
remaining: 0,
|
|
purchasedCredits: 5,
|
|
plan: nil,
|
|
subscriptionUnavailable: true)
|
|
|
|
store.handleSessionQuotaTransition(provider: .commandcode, snapshot: freeTier)
|
|
#expect(notifier.posts.isEmpty)
|
|
|
|
store.handleSessionQuotaTransition(provider: .commandcode, snapshot: depletedWithPlan)
|
|
let stabilizedFailure = UsageStore.commandCodeSnapshotResolvingDepletionOnEnrichmentFailure(
|
|
current: missingSubscription,
|
|
previous: depletedWithPlan)
|
|
store.handleSessionQuotaTransition(provider: .commandcode, snapshot: stabilizedFailure)
|
|
let repeatedFailure = UsageStore.commandCodeSnapshotResolvingDepletionOnEnrichmentFailure(
|
|
current: missingSubscription,
|
|
previous: stabilizedFailure)
|
|
store.handleSessionQuotaTransition(provider: .commandcode, snapshot: repeatedFailure)
|
|
store.handleSessionQuotaTransition(provider: .commandcode, snapshot: depletedWithPlan)
|
|
|
|
#expect(notifier.posts.count(where: { $0.transition == .depleted }) == 1)
|
|
|
|
store.handleSessionQuotaTransition(provider: .commandcode, snapshot: freeTier)
|
|
store.handleSessionQuotaTransition(provider: .commandcode, snapshot: depletedWithPlan)
|
|
#expect(notifier.posts.count(where: { $0.transition == .depleted }) == 2)
|
|
}
|
|
|
|
@Test
|
|
func `quota warning does not refire across missing subscription window`() throws {
|
|
let settings = self.makeSettings(suiteName: "CommandCodeWarningNoRefire")
|
|
settings.quotaWarningNotificationsEnabled = true
|
|
settings.quotaWarningThresholds = [50]
|
|
let notifier = NotifierSpy()
|
|
let store = self.makeStore(settings: settings, notifier: notifier)
|
|
let plan = try #require(CommandCodePlanCatalog.plans.first { $0.monthlyCreditsUSD > 0 })
|
|
|
|
store.handleQuotaWarningTransitions(provider: .commandcode, snapshot: self.snapshot(remaining: 6, plan: plan))
|
|
store.handleQuotaWarningTransitions(provider: .commandcode, snapshot: self.snapshot(remaining: 4, plan: plan))
|
|
let availableWithPlan = self.snapshot(remaining: 4, plan: plan)
|
|
let missingSubscription = self.snapshot(
|
|
remaining: 0,
|
|
purchasedCredits: 5,
|
|
plan: nil,
|
|
subscriptionUnavailable: true)
|
|
let stabilizedFailure = UsageStore.commandCodeSnapshotResolvingDepletionOnEnrichmentFailure(
|
|
current: missingSubscription,
|
|
previous: availableWithPlan)
|
|
store.handleQuotaWarningTransitions(provider: .commandcode, snapshot: stabilizedFailure)
|
|
let repeatedFailure = UsageStore.commandCodeSnapshotResolvingDepletionOnEnrichmentFailure(
|
|
current: missingSubscription,
|
|
previous: stabilizedFailure)
|
|
store.handleQuotaWarningTransitions(provider: .commandcode, snapshot: repeatedFailure)
|
|
store.handleQuotaWarningTransitions(provider: .commandcode, snapshot: self.snapshot(remaining: 4, plan: plan))
|
|
|
|
#expect(notifier.quotaWarningPosts.count == 1)
|
|
|
|
store.handleQuotaWarningTransitions(provider: .commandcode, snapshot: self.snapshot(remaining: 0, plan: nil))
|
|
store.handleQuotaWarningTransitions(provider: .commandcode, snapshot: self.snapshot(remaining: 4, plan: plan))
|
|
#expect(notifier.quotaWarningPosts.count == 2)
|
|
}
|
|
|
|
private func makeSettings(suiteName: String) -> SettingsStore {
|
|
let defaults = UserDefaults(suiteName: suiteName)!
|
|
defaults.removePersistentDomain(forName: suiteName)
|
|
let settings = SettingsStore(
|
|
userDefaults: defaults,
|
|
configStore: testConfigStore(suiteName: suiteName),
|
|
zaiTokenStore: NoopZaiTokenStore(),
|
|
syntheticTokenStore: NoopSyntheticTokenStore())
|
|
settings.refreshFrequency = .manual
|
|
settings.statusChecksEnabled = false
|
|
return settings
|
|
}
|
|
|
|
private func makeStore(settings: SettingsStore, notifier: NotifierSpy) -> UsageStore {
|
|
UsageStore(
|
|
fetcher: UsageFetcher(),
|
|
browserDetection: BrowserDetection(cacheTTL: 0),
|
|
settings: settings,
|
|
sessionQuotaNotifier: notifier)
|
|
}
|
|
|
|
private func snapshot(
|
|
remaining: Double,
|
|
purchasedCredits: Double = 0,
|
|
plan: CommandCodePlanCatalog.Plan?,
|
|
subscriptionUnavailable: Bool = false) -> UsageSnapshot
|
|
{
|
|
CommandCodeUsageSnapshot(
|
|
monthlyCreditsRemaining: remaining,
|
|
purchasedCredits: purchasedCredits,
|
|
premiumMonthlyCredits: 0,
|
|
opensourceMonthlyCredits: 0,
|
|
plan: plan,
|
|
billingPeriodEnd: nil,
|
|
subscriptionStatus: plan == nil ? nil : "active",
|
|
subscriptionEnrichmentUnavailable: subscriptionUnavailable)
|
|
.toUsageSnapshot()
|
|
}
|
|
|
|
private final class NotifierSpy: SessionQuotaNotifying {
|
|
private(set) var posts: [(transition: SessionQuotaTransition, provider: UsageProvider)] = []
|
|
private(set) var quotaWarningPosts: [QuotaWarningEvent] = []
|
|
|
|
func post(transition: SessionQuotaTransition, provider: UsageProvider, badge _: NSNumber?) {
|
|
self.posts.append((transition, provider))
|
|
}
|
|
|
|
func postQuotaWarning(
|
|
event: QuotaWarningEvent,
|
|
provider _: UsageProvider,
|
|
soundEnabled _: Bool,
|
|
onScreenAlertEnabled _: Bool)
|
|
{
|
|
self.quotaWarningPosts.append(event)
|
|
}
|
|
}
|
|
}
|