- Add dutyCyclePercent and defaultUtilizationFactorPercent to ComponentLibraryItem with normalization logic and backend field fetching - Change default dailyUsageHours from 1h to 24h - Replace goal editor stepper with day/hour/minute wheel pickers - Update app icon colors and remove duplicate icon assets - Move SavedBattery.swift into Batteries/ directory, remove Pods group - Add iPad-only flag and start frame support to screenshot framing scripts - Rework localized App Store screenshot titles across all languages - Add runtime goals and BOM completed items to sample data - Bump version to 1.5.1 (build 41) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
152 lines
4.6 KiB
Swift
152 lines
4.6 KiB
Swift
import Foundation
|
|
import Testing
|
|
@testable import Cable
|
|
|
|
struct ComponentLibraryItemTests {
|
|
|
|
@Test func localizedNameUsesExactLocaleMatch() async throws {
|
|
let item = ComponentLibraryItem(
|
|
id: "component-1",
|
|
name: "Anchor Winch",
|
|
translations: ["de_DE": "Ankerwinde"],
|
|
voltageIn: nil,
|
|
voltageOut: nil,
|
|
watt: nil,
|
|
dutyCyclePercent: nil,
|
|
defaultUtilizationFactorPercent: nil,
|
|
iconURL: nil,
|
|
affiliateLinks: []
|
|
)
|
|
|
|
let german = Foundation.Locale(identifier: "de_DE")
|
|
#expect(item.localizedName(for: german) == "Ankerwinde")
|
|
}
|
|
|
|
@Test func localizedNameFallsBackToBaseName() async throws {
|
|
let item = ComponentLibraryItem(
|
|
id: "component-2",
|
|
name: "Anchor Winch",
|
|
translations: [:],
|
|
voltageIn: nil,
|
|
voltageOut: nil,
|
|
watt: nil,
|
|
dutyCyclePercent: nil,
|
|
defaultUtilizationFactorPercent: nil,
|
|
iconURL: nil,
|
|
affiliateLinks: []
|
|
)
|
|
|
|
let french = Foundation.Locale(identifier: "fr_FR")
|
|
#expect(item.localizedName(for: french) == "Anchor Winch")
|
|
}
|
|
|
|
@Test func localizedNameDoesNotFallbackToSecondaryLanguages() async throws {
|
|
let item = ComponentLibraryItem(
|
|
id: "component-5",
|
|
name: "Anchor Winch",
|
|
translations: [
|
|
"es_ES": "Molinete",
|
|
"de_DE": "Ankerwinde"
|
|
],
|
|
voltageIn: nil,
|
|
voltageOut: nil,
|
|
watt: nil,
|
|
dutyCyclePercent: nil,
|
|
defaultUtilizationFactorPercent: nil,
|
|
iconURL: nil,
|
|
affiliateLinks: []
|
|
)
|
|
|
|
let languages = ["fr-FR", "de-DE", "es-ES"]
|
|
#expect(item.localizedName(usingPreferredLanguages: languages) == nil)
|
|
}
|
|
|
|
@Test func localizedNameUsesLanguageOnlyMatch() async throws {
|
|
let item = ComponentLibraryItem(
|
|
id: "component-3",
|
|
name: "Anchor Winch",
|
|
translations: ["es": "Molinete"],
|
|
voltageIn: nil,
|
|
voltageOut: nil,
|
|
watt: nil,
|
|
dutyCyclePercent: nil,
|
|
defaultUtilizationFactorPercent: nil,
|
|
iconURL: nil,
|
|
affiliateLinks: []
|
|
)
|
|
|
|
let spanishMexico = Foundation.Locale(identifier: "es_MX")
|
|
#expect(item.localizedName(for: spanishMexico) == "Molinete")
|
|
}
|
|
|
|
@Test func localizedNameFallsBackToMatchingLanguageFromRegionalEntry() async throws {
|
|
let item = ComponentLibraryItem(
|
|
id: "component-6",
|
|
name: "Anchor Winch",
|
|
translations: ["de_DE": "Ankerwinde"],
|
|
voltageIn: nil,
|
|
voltageOut: nil,
|
|
watt: nil,
|
|
dutyCyclePercent: nil,
|
|
defaultUtilizationFactorPercent: nil,
|
|
iconURL: nil,
|
|
affiliateLinks: []
|
|
)
|
|
|
|
let germanSwitzerland = Foundation.Locale(identifier: "de_CH")
|
|
#expect(item.localizedName(for: germanSwitzerland) == "Ankerwinde")
|
|
}
|
|
|
|
@Test func localizedNameHandlesHyphenatedKeys() async throws {
|
|
let item = ComponentLibraryItem(
|
|
id: "component-4",
|
|
name: "Anchor Winch",
|
|
translations: ["fr-FR": "Guindeau"],
|
|
voltageIn: nil,
|
|
voltageOut: nil,
|
|
watt: nil,
|
|
dutyCyclePercent: nil,
|
|
defaultUtilizationFactorPercent: nil,
|
|
iconURL: nil,
|
|
affiliateLinks: []
|
|
)
|
|
|
|
let french = Foundation.Locale(identifier: "fr_FR")
|
|
#expect(item.localizedName(for: french) == "Guindeau")
|
|
}
|
|
|
|
@Test func normalizedDutyCycleTreatsZeroAsFullUsage() async throws {
|
|
let item = ComponentLibraryItem(
|
|
id: "component-7",
|
|
name: "Compressor",
|
|
translations: [:],
|
|
voltageIn: nil,
|
|
voltageOut: nil,
|
|
watt: nil,
|
|
dutyCyclePercent: 0,
|
|
defaultUtilizationFactorPercent: nil,
|
|
iconURL: nil,
|
|
affiliateLinks: []
|
|
)
|
|
|
|
#expect(item.normalizedDutyCyclePercent == 100)
|
|
}
|
|
|
|
@Test func defaultDailyUsageHoursConvertsPercentToHours() async throws {
|
|
let item = ComponentLibraryItem(
|
|
id: "component-8",
|
|
name: "Heater",
|
|
translations: [:],
|
|
voltageIn: nil,
|
|
voltageOut: nil,
|
|
watt: nil,
|
|
dutyCyclePercent: nil,
|
|
defaultUtilizationFactorPercent: 50,
|
|
iconURL: nil,
|
|
affiliateLinks: []
|
|
)
|
|
|
|
#expect(item.defaultDailyUsageHours == 12)
|
|
}
|
|
}
|