import Testing import SwiftUI @testable import bookstax // MARK: - Color Hex Parsing @Suite("Color – Hex Parsing") struct ColorHexParsingTests { // MARK: Valid 6-digit hex @Test("6-digit hex without # prefix parses successfully") func sixDigitNoPound() { #expect(Color(hex: "FF0000") != nil) } @Test("6-digit hex with # prefix parses successfully") func sixDigitWithPound() { #expect(Color(hex: "#FF0000") != nil) } @Test("Black hex #000000 parses successfully") func blackHex() { #expect(Color(hex: "#000000") != nil) } @Test("White hex #FFFFFF parses successfully") func whiteHex() { #expect(Color(hex: "#FFFFFF") != nil) } @Test("Lowercase hex parses successfully") func lowercaseHex() { #expect(Color(hex: "#ff6600") != nil) } // MARK: Valid 3-digit hex @Test("3-digit hex #FFF is valid shorthand") func threeDigitFFF() { #expect(Color(hex: "#FFF") != nil) } @Test("3-digit hex #000 is valid shorthand") func threeDigitZero() { #expect(Color(hex: "#000") != nil) } @Test("3-digit hex #F60 is expanded to #FF6600") func threeDigitExpansion() { let threeDigit = Color(hex: "#F60") let sixDigit = Color(hex: "#FF6600") // Both should parse successfully #expect(threeDigit != nil) #expect(sixDigit != nil) } // MARK: Invalid inputs @Test("5-digit hex returns nil") func fiveDigitInvalid() { #expect(Color(hex: "#FFFFF") == nil) } @Test("7-digit hex returns nil") func sevenDigitInvalid() { #expect(Color(hex: "#FFFFFFF") == nil) } @Test("Empty string returns nil") func emptyStringInvalid() { #expect(Color(hex: "") == nil) } @Test("Non-hex characters return nil") func nonHexCharacters() { #expect(Color(hex: "#GGGGGG") == nil) } @Test("Just # returns nil") func onlyHash() { #expect(Color(hex: "#") == nil) } } // MARK: - Color Hex Round-trip @Suite("Color – Hex Round-trip") struct ColorHexRoundTripTests { @Test("Red #FF0000 round-trips correctly") func redRoundTrip() { let color = Color(hex: "#FF0000")! let hex = color.toHexString() #expect(hex == "#FF0000") } @Test("Green #00FF00 round-trips correctly") func greenRoundTrip() { let color = Color(hex: "#00FF00")! let hex = color.toHexString() #expect(hex == "#00FF00") } @Test("Blue #0000FF round-trips correctly") func blueRoundTrip() { let color = Color(hex: "#0000FF")! let hex = color.toHexString() #expect(hex == "#0000FF") } @Test("Custom color #3A7B55 round-trips correctly") func customColorRoundTrip() { let color = Color(hex: "#3A7B55")! let hex = color.toHexString() #expect(hex == "#3A7B55") } } // MARK: - AccentTheme @Suite("AccentTheme – Properties") struct AccentThemeTests { @Test("All cases are represented in CaseIterable") func allCasesPresent() { #expect(AccentTheme.allCases.count == 8) } @Test("id equals rawValue") func idEqualsRawValue() { for theme in AccentTheme.allCases { #expect(theme.id == theme.rawValue) } } @Test("Every theme has a non-empty displayName") func displayNamesNonEmpty() { for theme in AccentTheme.allCases { #expect(!theme.displayName.isEmpty) } } @Test("accentColor equals shelfColor") func accentColorEqualsShelfColor() { for theme in AccentTheme.allCases { #expect(theme.accentColor == theme.shelfColor) } } @Test("Ocean theme has expected displayName") func oceanDisplayName() { #expect(AccentTheme.ocean.displayName == "Ocean") } @Test("Graphite theme has expected displayName") func graphiteDisplayName() { #expect(AccentTheme.graphite.displayName == "Graphite") } @Test("All themes can be init'd from rawValue") func initFromRawValue() { for theme in AccentTheme.allCases { let reinit = AccentTheme(rawValue: theme.rawValue) #expect(reinit == theme) } } }