feat: add AI retouch before-after comparison
This commit is contained in:
@@ -8,6 +8,40 @@ import XCTest
|
||||
|
||||
/// 旅拍相册模型与展示工具测试。
|
||||
final class TravelAlbumModelsTests: XCTestCase {
|
||||
func testBeforeAfterComparisonMotionMatchesShipSwiftInteractionRange() {
|
||||
XCTAssertEqual(BeforeAfterComparisonMotion.automaticFraction(elapsed: 0), 0.5, accuracy: 0.001)
|
||||
XCTAssertEqual(
|
||||
BeforeAfterComparisonMotion.automaticFraction(
|
||||
elapsed: .pi / (2 * BeforeAfterComparisonMotion.automaticSpeed)
|
||||
),
|
||||
0.8,
|
||||
accuracy: 0.001
|
||||
)
|
||||
XCTAssertEqual(BeforeAfterComparisonMotion.clampedManualFraction(0), 0.05)
|
||||
XCTAssertEqual(BeforeAfterComparisonMotion.clampedManualFraction(1), 0.95)
|
||||
XCTAssertEqual(BeforeAfterComparisonMotion.clampedManualFraction(0.42), 0.42)
|
||||
}
|
||||
|
||||
func testBeforeAfterComparisonLayoutFitsVariableRatiosWithoutCropping() {
|
||||
let landscape = BeforeAfterComparisonLayout.fittedSize(
|
||||
aspectRatio: 16.0 / 9.0,
|
||||
maximumSize: CGSize(width: 358, height: 580)
|
||||
)
|
||||
let portrait = BeforeAfterComparisonLayout.fittedSize(
|
||||
aspectRatio: 2.0 / 3.0,
|
||||
maximumSize: CGSize(width: 358, height: 580)
|
||||
)
|
||||
|
||||
XCTAssertEqual(landscape.width, 358, accuracy: 0.001)
|
||||
XCTAssertEqual(landscape.height, 201.375, accuracy: 0.001)
|
||||
XCTAssertEqual(portrait.width, 358, accuracy: 0.001)
|
||||
XCTAssertEqual(portrait.height, 537, accuracy: 0.001)
|
||||
XCTAssertEqual(
|
||||
BeforeAfterComparisonLayout.aspectRatio(for: CGSize(width: 4000, height: 3000)),
|
||||
4.0 / 3.0
|
||||
)
|
||||
}
|
||||
|
||||
func testPreviewProjectMapsMaterialToOriginalAsset() {
|
||||
let material = TravelAlbumMaterial(
|
||||
id: 8,
|
||||
@@ -68,6 +102,77 @@ final class TravelAlbumModelsTests: XCTestCase {
|
||||
)
|
||||
}
|
||||
|
||||
func testPreviewProjectBuildsComparisonOnlyForValidAIResults() {
|
||||
let project = makePreviewProject(id: 8, kinds: [.original, .retouched, .atmosphere, .cover])
|
||||
|
||||
XCTAssertEqual(
|
||||
project.comparisonContent(for: .retouched),
|
||||
BeforeAfterComparisonContent(
|
||||
beforeURL: "https://cdn.example.com/8-0.jpg",
|
||||
afterURL: "https://cdn.example.com/8-1.jpg"
|
||||
)
|
||||
)
|
||||
XCTAssertNotNil(project.comparisonContent(for: .atmosphere))
|
||||
XCTAssertNil(project.comparisonContent(for: .original))
|
||||
XCTAssertNil(project.comparisonContent(for: .cover))
|
||||
|
||||
let missingResultURL = TravelAlbumPreviewProject(
|
||||
originalMaterialId: 9,
|
||||
assets: [
|
||||
TravelAlbumPreviewAsset(
|
||||
id: "original-9",
|
||||
kind: .original,
|
||||
fileURL: "https://cdn.example.com/original.jpg",
|
||||
coverURL: "",
|
||||
fileName: "原图.jpg",
|
||||
fileSize: 1
|
||||
),
|
||||
TravelAlbumPreviewAsset(
|
||||
id: "retouched-9",
|
||||
kind: .retouched,
|
||||
fileURL: " ",
|
||||
coverURL: "",
|
||||
fileName: "精修.jpg",
|
||||
fileSize: 1
|
||||
),
|
||||
]
|
||||
)
|
||||
XCTAssertNil(missingResultURL.comparisonContent(for: .retouched))
|
||||
}
|
||||
|
||||
func testTemplateComparisonContentRequiresBothURLs() {
|
||||
let valid = TravelAlbumAIRetouchTemplate(
|
||||
id: 1,
|
||||
name: "清透",
|
||||
previewURL: "https://cdn.example.com/preview.jpg",
|
||||
beforeURL: " https://cdn.example.com/before.jpg ",
|
||||
afterURL: "https://cdn.example.com/after.jpg"
|
||||
)
|
||||
let missingAfter = TravelAlbumAIRetouchTemplate(
|
||||
id: 2,
|
||||
name: "暖阳",
|
||||
previewURL: "https://cdn.example.com/preview.jpg",
|
||||
beforeURL: "https://cdn.example.com/before.jpg"
|
||||
)
|
||||
|
||||
XCTAssertEqual(valid.comparisonContent?.beforeURL, "https://cdn.example.com/before.jpg")
|
||||
XCTAssertEqual(valid.comparisonContent?.afterLabel, "效果图")
|
||||
XCTAssertNil(missingAfter.comparisonContent)
|
||||
}
|
||||
|
||||
func testTemplateDecodingDefaultsMissingComparisonURLsToEmptyStrings() throws {
|
||||
let data = Data(
|
||||
#"{"id":3,"name":"旧模板","preview_url":"https://cdn.example.com/preview.jpg"}"#.utf8
|
||||
)
|
||||
|
||||
let template = try JSONDecoder().decode(TravelAlbumAIRetouchTemplate.self, from: data)
|
||||
|
||||
XCTAssertEqual(template.previewURL, "https://cdn.example.com/preview.jpg")
|
||||
XCTAssertEqual(template.beforeURL, "")
|
||||
XCTAssertEqual(template.afterURL, "")
|
||||
XCTAssertNil(template.comparisonContent)
|
||||
}
|
||||
|
||||
func testPreviewAssetFallsBackToAvailableURLForBothQualityLevels() {
|
||||
let missingOriginal = TravelAlbumPreviewAsset(
|
||||
id: "cover-only",
|
||||
|
||||
Reference in New Issue
Block a user