164 lines
5.4 KiB
Swift
164 lines
5.4 KiB
Swift
import Testing
|
||
import Foundation
|
||
@testable import nahbar
|
||
|
||
// MARK: - SubscriptionTier Tests
|
||
|
||
@Suite("SubscriptionTier – Enum")
|
||
struct SubscriptionTierTests {
|
||
|
||
@Test("Genau 2 Tiers vorhanden")
|
||
func allCasesCount() {
|
||
#expect(SubscriptionTier.allCases.count == 2)
|
||
}
|
||
|
||
@Test("Pro productID ist 'profeatures'")
|
||
func proProductID() {
|
||
#expect(SubscriptionTier.pro.productID == "profeatures")
|
||
}
|
||
|
||
@Test("Max productID ist 'maxfeatures'")
|
||
func maxProductID() {
|
||
#expect(SubscriptionTier.max.productID == "maxfeatures")
|
||
}
|
||
|
||
@Test("Pro displayName ist 'Pro'")
|
||
func proDisplayName() {
|
||
#expect(SubscriptionTier.pro.displayName == "Pro")
|
||
}
|
||
|
||
@Test("Max displayName ist 'Max'")
|
||
func maxDisplayName() {
|
||
#expect(SubscriptionTier.max.displayName == "Max")
|
||
}
|
||
|
||
@Test("productIDs sind einzigartig")
|
||
func productIDsAreUnique() {
|
||
let ids = SubscriptionTier.allCases.map { $0.productID }
|
||
#expect(Set(ids).count == SubscriptionTier.allCases.count)
|
||
}
|
||
|
||
@Test("displayNames sind einzigartig")
|
||
func displayNamesAreUnique() {
|
||
let names = SubscriptionTier.allCases.map { $0.displayName }
|
||
#expect(Set(names).count == SubscriptionTier.allCases.count)
|
||
}
|
||
|
||
@Test("productIDs sind nicht leer")
|
||
func productIDsNotEmpty() {
|
||
for tier in SubscriptionTier.allCases {
|
||
#expect(!tier.productID.isEmpty)
|
||
}
|
||
}
|
||
}
|
||
|
||
// MARK: - AI Free Query Counter Tests
|
||
|
||
// Tests laufen serialisiert, da alle auf UserDefaults.standard mit gleichem Key schreiben
|
||
@Suite("AIAnalysisService – Gratis-Abfragen", .serialized)
|
||
struct AIFreeQueryTests {
|
||
|
||
init() {
|
||
AIAnalysisService.shared.freeQueriesUsed = 0
|
||
}
|
||
|
||
@Test("Limit ist genau 3")
|
||
func limitIsThree() {
|
||
#expect(AIAnalysisService.freeQueryLimit == 3)
|
||
}
|
||
|
||
@Test("Initial: Abfragen verfügbar, remaining = 3")
|
||
func initialState() {
|
||
AIAnalysisService.shared.freeQueriesUsed = 0
|
||
#expect(AIAnalysisService.shared.hasFreeQueriesLeft == true)
|
||
#expect(AIAnalysisService.shared.freeQueriesRemaining == 3)
|
||
}
|
||
|
||
@Test("consumeFreeQuery erhöht Zähler um 1")
|
||
func consumeIncrementsCounter() {
|
||
AIAnalysisService.shared.freeQueriesUsed = 0
|
||
AIAnalysisService.shared.consumeFreeQuery()
|
||
#expect(AIAnalysisService.shared.freeQueriesUsed == 1)
|
||
#expect(AIAnalysisService.shared.freeQueriesRemaining == 2)
|
||
}
|
||
|
||
@Test("Nach 3 Verbrauchungen: hasFreeQueriesLeft == false")
|
||
func afterThreeConsumed() {
|
||
AIAnalysisService.shared.freeQueriesUsed = 0
|
||
AIAnalysisService.shared.consumeFreeQuery()
|
||
AIAnalysisService.shared.consumeFreeQuery()
|
||
AIAnalysisService.shared.consumeFreeQuery()
|
||
#expect(AIAnalysisService.shared.hasFreeQueriesLeft == false)
|
||
#expect(AIAnalysisService.shared.freeQueriesRemaining == 0)
|
||
}
|
||
|
||
@Test("Zähler über Limit: remaining bleibt 0, nicht negativ")
|
||
func remainingNotNegative() {
|
||
AIAnalysisService.shared.freeQueriesUsed = 10
|
||
#expect(AIAnalysisService.shared.freeQueriesRemaining == 0)
|
||
#expect(AIAnalysisService.shared.hasFreeQueriesLeft == false)
|
||
}
|
||
|
||
@Test("Zähler = limit - 1: noch genau 1 Abfrage verfügbar")
|
||
func oneQueryLeft() {
|
||
AIAnalysisService.shared.freeQueriesUsed = AIAnalysisService.freeQueryLimit - 1
|
||
#expect(AIAnalysisService.shared.hasFreeQueriesLeft == true)
|
||
#expect(AIAnalysisService.shared.freeQueriesRemaining == 1)
|
||
}
|
||
|
||
@Test("Zähler = limit: keine Abfragen mehr verfügbar")
|
||
func atLimit() {
|
||
AIAnalysisService.shared.freeQueriesUsed = AIAnalysisService.freeQueryLimit
|
||
#expect(AIAnalysisService.shared.hasFreeQueriesLeft == false)
|
||
}
|
||
|
||
@Test("freeQueriesUsed + freeQueriesRemaining = limit (solange unter limit)")
|
||
func usedPlusRemainingEqualsLimit() {
|
||
for used in 0...AIAnalysisService.freeQueryLimit {
|
||
AIAnalysisService.shared.freeQueriesUsed = used
|
||
let remaining = AIAnalysisService.shared.freeQueriesRemaining
|
||
#expect(used + remaining == AIAnalysisService.freeQueryLimit)
|
||
}
|
||
}
|
||
}
|
||
|
||
// MARK: - AppGroup Pro-Status Tests
|
||
|
||
// Tests laufen serialisiert, da alle dieselbe UserDefaults-Suite nutzen
|
||
@Suite("AppGroup – Pro-Status", .serialized)
|
||
struct AppGroupProStatusTests {
|
||
|
||
private let testDefaults = UserDefaults(suiteName: "nahbar.test.proStatus")!
|
||
|
||
init() {
|
||
testDefaults.removeObject(forKey: "isPro")
|
||
testDefaults.synchronize()
|
||
}
|
||
|
||
@Test("Pro-Status initial false wenn nicht gesetzt")
|
||
func proStatusInitiallyFalse() {
|
||
testDefaults.removeObject(forKey: "isPro")
|
||
#expect(testDefaults.bool(forKey: "isPro") == false)
|
||
}
|
||
|
||
@Test("Pro-Status round-trip: true")
|
||
func proStatusRoundTripTrue() {
|
||
testDefaults.set(true, forKey: "isPro")
|
||
#expect(testDefaults.bool(forKey: "isPro") == true)
|
||
}
|
||
|
||
@Test("Pro-Status round-trip: false")
|
||
func proStatusRoundTripFalse() {
|
||
testDefaults.set(true, forKey: "isPro")
|
||
testDefaults.set(false, forKey: "isPro")
|
||
#expect(testDefaults.bool(forKey: "isPro") == false)
|
||
}
|
||
|
||
@Test("Pro-Status nach removeObject ist false")
|
||
func proStatusAfterRemoveIsFalse() {
|
||
testDefaults.set(true, forKey: "isPro")
|
||
testDefaults.removeObject(forKey: "isPro")
|
||
#expect(testDefaults.bool(forKey: "isPro") == false)
|
||
}
|
||
}
|