Implement freemium model with StoreKit 2: - StoreManager singleton for purchase/restore/entitlements - ProFeature enum defining gated features - PaywallView and OnboardingPaywallView for upsell UI - ProGate view modifier and ProBadge component Feature gating: - Trip saving: 1 free trip, then requires Pro - PDF export: Pro only with badge indicator - Progress tab: Shows ProLockedView for free users - Settings: Subscription management section Also fixes pre-existing test issues with StadiumVisit and ItineraryOption model signature changes. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
37 lines
1.0 KiB
Swift
37 lines
1.0 KiB
Swift
//
|
|
// StoreManagerTests.swift
|
|
// SportsTimeTests
|
|
//
|
|
|
|
import Testing
|
|
import StoreKit
|
|
@testable import SportsTime
|
|
|
|
struct StoreManagerTests {
|
|
@Test func shared_returnsSingletonInstance() async {
|
|
let instance1 = await StoreManager.shared
|
|
let instance2 = await StoreManager.shared
|
|
#expect(instance1 === instance2)
|
|
}
|
|
|
|
@Test func isPro_isAccessible() async {
|
|
let manager = await StoreManager.shared
|
|
// Fresh state should not be Pro
|
|
// Note: In real tests, we'd reset state first
|
|
let _ = await manager.isPro // Just verify it's accessible
|
|
#expect(true)
|
|
}
|
|
|
|
@MainActor
|
|
@Test func proProductIDs_containsExpectedProducts() {
|
|
#expect(StoreManager.proProductIDs.contains("com.sportstime.pro.monthly"))
|
|
#expect(StoreManager.proProductIDs.contains("com.sportstime.pro.annual"))
|
|
#expect(StoreManager.proProductIDs.count == 2)
|
|
}
|
|
|
|
@MainActor
|
|
@Test func freeTripLimit_returnsOne() {
|
|
#expect(StoreManager.freeTripLimit == 1)
|
|
}
|
|
}
|