Umfassende Erweiterung, Lokalisierung, Besuchsbewertung
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user