Complete native rewrite of the web-based SoliCards game as a SwiftUI multiplatform app targeting iOS 17+, iPadOS 17+, and macOS 14+. Three solitaire variants (Klondike, Spider, FreeCell) with full game rules, drag & drop, smart zoom layout, 6 themes, 4 difficulty levels, SwiftData persistence, VoiceOver accessibility, and 57 unit tests. Key features: - MVVM + Protocol-Oriented Strategy architecture - DragGesture with coordinate-space hit-testing (long press + drag) - Smart zoom: cards auto-size to fit screen based on deepest column - Landscape: 30% bigger cards with scrollable overflow (iOS) - macOS: 120pt card cap, 92% height buffer for window resizing - Auto-save, game resume, statistics tracking via SwiftData - Privacy manifest, app icon, String Catalog, zero dependencies Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
45 lines
1.3 KiB
Swift
45 lines
1.3 KiB
Swift
import Testing
|
|
@testable import SoliCards
|
|
|
|
@Suite("Deck Tests")
|
|
struct DeckTests {
|
|
|
|
@Test("Standard deck has 52 cards")
|
|
func standardDeckCount() {
|
|
let deck = Deck.standard()
|
|
#expect(deck.count == 52)
|
|
}
|
|
|
|
@Test("Double deck has 104 cards")
|
|
func doubleDeckCount() {
|
|
let deck = Deck.double()
|
|
#expect(deck.count == 104)
|
|
}
|
|
|
|
@Test("Standard deck has all suits and ranks")
|
|
func standardDeckCompleteness() {
|
|
let deck = Deck.standard()
|
|
for suit in Suit.allCases {
|
|
for rank in Rank.allCases {
|
|
let count = deck.filter { $0.suit == suit && $0.rank == rank }.count
|
|
#expect(count == 1, "Expected exactly 1 \(rank.displayName) of \(suit.displayName)")
|
|
}
|
|
}
|
|
}
|
|
|
|
@Test("Deck starts with all cards face down")
|
|
func allFaceDown() {
|
|
let deck = Deck.standard()
|
|
#expect(deck.allSatisfy { !$0.isFaceUp })
|
|
}
|
|
|
|
@Test("Shuffle produces different orderings")
|
|
func shuffleRandomness() {
|
|
let deck1 = Deck.standard()
|
|
let deck2 = Deck.standard()
|
|
// Extremely unlikely to be identical after shuffle
|
|
let sameOrder = zip(deck1, deck2).allSatisfy { $0.suit == $1.suit && $0.rank == $1.rank }
|
|
#expect(!sameOrder)
|
|
}
|
|
}
|