136 lines
5.3 KiB
Swift
136 lines
5.3 KiB
Swift
//
|
|
// TankCatalogTests.swift
|
|
// GasTankARTests
|
|
//
|
|
// Created by Dennis Nemec on 14.09.26.
|
|
//
|
|
|
|
import Testing
|
|
import Foundation
|
|
@testable import GasTankAR
|
|
|
|
/// Prüft das Laden/Decodieren des Tank-Katalogs aus JSON sowie die abgeleiteten
|
|
/// Abfragen (verfügbare Größen/Farben, Auflösung & Normalisierung der Auswahl).
|
|
struct TankCatalogTests {
|
|
|
|
// Kleiner, in sich konsistenter Beispielkatalog für Query-Tests.
|
|
private static let sampleJSON = """
|
|
{
|
|
"sizeDisplayNames": { "t1_2": "1,2 t", "t2_9": "2,9 t" },
|
|
"colorDisplayNames": { "white": "Weiß", "green": "Hellgrün", "olive": "Olivgrün" },
|
|
"tanks": [
|
|
{ "size": "t1_2", "color": "white", "placement": "aboveGround", "modelPath": "DG-2700_wh.usdz", "domeCenterX": -0.426 },
|
|
{ "size": "t1_2", "color": "green", "placement": "aboveGround", "modelPath": "DG-2700_mi.usdz", "domeCenterX": -0.426 },
|
|
{ "size": "t1_2", "color": "olive", "placement": "belowGround", "modelPath": "DG-2700_ol.usdz", "domeCenterX": -0.498 },
|
|
{ "size": "t2_9", "color": "white", "placement": "aboveGround", "modelPath": "DG-6400_wh.usdz", "domeCenterX": -1.939 },
|
|
{ "size": "t2_9", "color": "olive", "placement": "belowGround", "modelPath": "DG-6400_ol.usdz", "domeCenterX": -2.018 }
|
|
]
|
|
}
|
|
"""
|
|
|
|
private static func sampleCatalog() throws -> TankCatalog {
|
|
let loader = DataTankCatalogLoader(data: Data(sampleJSON.utf8))
|
|
return TankCatalog(file: try loader.load())
|
|
}
|
|
|
|
// MARK: - Decoding
|
|
|
|
@Test func decodesAllFieldsFromJSON() throws {
|
|
let catalog = try Self.sampleCatalog()
|
|
let def = try #require(catalog.definitions.first)
|
|
|
|
#expect(def.size == .t1_2)
|
|
#expect(def.color == .white)
|
|
#expect(def.placement == .aboveGround)
|
|
#expect(def.modelPath == "DG-2700_wh.usdz")
|
|
#expect(def.domeCenterX == -0.426)
|
|
#expect(def.modelResourceName == "DG-2700_wh")
|
|
#expect(def.modelFileExtension == "usdz")
|
|
}
|
|
|
|
@Test func decodesDisplayNameMappings() throws {
|
|
let catalog = try Self.sampleCatalog()
|
|
#expect(catalog.sizeDisplayNames["t1_2"] == "1,2 t")
|
|
#expect(catalog.colorDisplayNames["olive"] == "Olivgrün")
|
|
}
|
|
|
|
@Test func displayNameFallsBackToRawValueWhenMissing() {
|
|
// Katalog ohne Mappings → Anzeigename ist der rawValue.
|
|
let catalog = TankCatalog(definitions: [])
|
|
#expect(catalog.displayName(for: TankSize.t2_1) == "t2_1")
|
|
#expect(catalog.displayName(for: TankColor.green) == "green")
|
|
}
|
|
|
|
@Test func missingResourceThrows() {
|
|
let loader = BundleTankCatalogLoader(
|
|
bundle: .main,
|
|
resourceName: "Datei-die-nicht-existiert",
|
|
resourceExtension: "json"
|
|
)
|
|
#expect(throws: TankCatalogLoaderError.self) {
|
|
_ = try loader.load()
|
|
}
|
|
}
|
|
|
|
@Test func emptyCatalogWhenLoaderFails() {
|
|
let loader = BundleTankCatalogLoader(resourceName: "gibt-es-nicht")
|
|
let catalog = TankCatalog(loader: loader)
|
|
#expect(catalog.definitions.isEmpty)
|
|
}
|
|
|
|
// MARK: - Abgeleitete Abfragen
|
|
|
|
@Test func availableColorsDependOnPlacement() throws {
|
|
let catalog = try Self.sampleCatalog()
|
|
#expect(catalog.colors(for: .t1_2, placement: .aboveGround) == [.white, .green])
|
|
#expect(catalog.colors(for: .t1_2, placement: .belowGround) == [.olive])
|
|
}
|
|
|
|
@Test func availableSizesPerPlacement() throws {
|
|
let catalog = try Self.sampleCatalog()
|
|
#expect(catalog.sizes(for: .aboveGround) == [.t1_2, .t2_9])
|
|
#expect(catalog.sizes(for: .belowGround) == [.t1_2, .t2_9])
|
|
}
|
|
|
|
@Test func placementsPreserveOrder() throws {
|
|
let catalog = try Self.sampleCatalog()
|
|
#expect(catalog.placements == [.aboveGround, .belowGround])
|
|
}
|
|
|
|
@Test func displayNamesResolveFromCatalog() throws {
|
|
let catalog = try Self.sampleCatalog()
|
|
#expect(catalog.displayName(for: TankSize.t2_9) == "2,9 t")
|
|
#expect(catalog.displayName(for: TankColor.olive) == "Olivgrün")
|
|
}
|
|
|
|
// MARK: - Auflösung & Normalisierung
|
|
|
|
@Test func definitionMatchesExactSelection() throws {
|
|
let catalog = try Self.sampleCatalog()
|
|
let tank = Tank(size: .t2_9, color: .olive, placement: .belowGround)
|
|
#expect(catalog.definition(for: tank)?.modelPath == "DG-6400_ol.usdz")
|
|
}
|
|
|
|
@Test func normalizesInconsistentColorForPlacement() throws {
|
|
let catalog = try Self.sampleCatalog()
|
|
// Weiß gibt es unterirdisch nicht → sollte auf Olivgrün korrigiert werden.
|
|
let tank = Tank(size: .t2_9, color: .white, placement: .belowGround)
|
|
let normalized = catalog.normalized(tank)
|
|
#expect(normalized.color == .olive)
|
|
#expect(catalog.definition(for: normalized) != nil)
|
|
}
|
|
|
|
@Test func resolvedDefinitionHealsLegacySelection() throws {
|
|
let catalog = try Self.sampleCatalog()
|
|
// Altdaten: unterirdisch + weiß → muss trotzdem das Olivgrün-Modell liefern.
|
|
let legacy = Tank(size: .t2_9, color: .white, placement: .belowGround)
|
|
#expect(catalog.resolvedDefinition(for: legacy)?.modelPath == "DG-6400_ol.usdz")
|
|
}
|
|
|
|
@Test func validSelectionStaysUnchanged() throws {
|
|
let catalog = try Self.sampleCatalog()
|
|
let tank = Tank(size: .t1_2, color: .green, placement: .aboveGround)
|
|
#expect(catalog.normalized(tank) == tank)
|
|
}
|
|
}
|