import XCTest
@testable import Physarum
import PhysarumEngine
final class MorphTests: XCTestCase {
private func presetA() -> PresetParams { PresetCatalog.fallbackPreset.params }
private func presetB() -> PresetParams {
var p = PresetCatalog.fallbackPreset.params
for d in ParamRegistry.all { d.set(&p, d.range.upperBound) } // distinct from A
p.spawnPattern = (p.spawnPattern == .ring) ? .random : .ring
p.blendMode = (p.blendMode == .paint) ? .additive : .paint
return p
}
func testEndpointsAreExact() {
let a = presetA(), b = presetB()
XCTAssertTrue(paramsEqual(morphParams(a, b, t: 0), a), "t=0 → A")
XCTAssertTrue(paramsEqual(morphParams(a, b, t: 1), b), "t=1 → B")
}
func testScalarMidpointIsHalfway() {
let a = presetA(), b = presetB()
let mid = morphParams(a, b, t: 0.5)
let d = ParamRegistry.all.first { $0.id == .moveSpeed(0) }!
XCTAssertEqual(d.get(mid), (d.get(a) + d.get(b)) / 2, accuracy: 1e-4)
}
func testDiscreteSwitchesAtHalf() {
let a = presetA(), b = presetB()
XCTAssertEqual(morphParams(a, b, t: 0.49).spawnPattern, a.spawnPattern)
XCTAssertEqual(morphParams(a, b, t: 0.5).spawnPattern, b.spawnPattern)
XCTAssertEqual(morphParams(a, b, t: 0.49).blendMode, a.blendMode)
XCTAssertEqual(morphParams(a, b, t: 0.5).blendMode, b.blendMode)
}
func testColorInterpolates() {
var a = presetA(); a.species[0].color = RGB(0, 0, 0)
var b = presetB(); b.species[0].color = RGB(1, 1, 1)
let mid = morphParams(a, b, t: 0.5)
XCTAssertEqual(mid.species[0].color.x, 0.5, accuracy: 1e-4)
}
func testClampsOutsideUnit() {
let a = presetA(), b = presetB()
XCTAssertTrue(paramsEqual(morphParams(a, b, t: -0.2), a))
XCTAssertTrue(paramsEqual(morphParams(a, b, t: 1.7), b))
}
}