fix: align AI retouch template rules

This commit is contained in:
2026-08-19 10:06:50 +08:00
parent 1757ba5e36
commit 8cd6c0aac8
8 changed files with 117 additions and 46 deletions
@@ -102,7 +102,7 @@ final class TravelAlbumAIRetouchTemplateViewModelTests: XCTestCase {
)
}
func testReretouchWorkflowShowsAndSubmitsOnlyRequiredCategories() async {
func testReretouchWorkflowAllowsAtmosphereOnlyFromOriginalTab() async {
let api = makeAPI()
let refined = TravelAlbumAIRetouchTemplateViewModel(
scenicId: 18,
@@ -133,9 +133,19 @@ final class TravelAlbumAIRetouchTemplateViewModelTests: XCTestCase {
)
await all.loadTemplates(api: api)
XCTAssertEqual(all.visibleCategories, [.refined, .atmosphere])
XCTAssertEqual(all.selectedRefinedTemplateId, 11)
XCTAssertNil(all.selectedRefinedTemplateId)
XCTAssertNil(all.selectedAtmosphereTemplateId)
XCTAssertTrue(all.isOptional(.refined))
XCTAssertTrue(all.isOptional(.atmosphere))
XCTAssertEqual(all.requiredQuota, 0)
XCTAssertFalse(all.canSubmit)
XCTAssertEqual(all.validationMessage, "请至少选择一个修图模板")
all.toggleTemplate(id: 11, category: .refined)
XCTAssertEqual(all.selectedRefinedTemplateId, 11)
all.toggleTemplate(id: 11, category: .refined)
XCTAssertNil(all.selectedRefinedTemplateId)
all.toggleTemplate(id: 21, category: .atmosphere)
XCTAssertEqual(all.requiredQuota, 1)
XCTAssertTrue(all.canSubmit)
await all.submit(api: api)
@@ -159,8 +169,8 @@ final class TravelAlbumAIRetouchTemplateViewModelTests: XCTestCase {
id: 9,
aiRetouchBatchId: 90,
type: .all,
refinedTemplateId: 11,
atmosphereTemplateId: nil
refinedTemplateId: nil,
atmosphereTemplateId: 21
),
])
}
@@ -183,7 +193,7 @@ final class TravelAlbumAIRetouchTemplateViewModelTests: XCTestCase {
XCTAssertTrue(api.aiReretouchRequests.isEmpty)
}
func testMissingOptionalAtmosphereDoesNotDisableAllReretouchWorkflow() async {
func testMissingOptionalAtmosphereStillAllowsSelectingRefinedInAllReretouchWorkflow() async {
let api = makeAPI()
api.aiRetouchTemplatesResponse = TravelAlbumAIRetouchTemplatesResponse(
refinedTemplates: [template(11, "清透")],
@@ -198,6 +208,8 @@ final class TravelAlbumAIRetouchTemplateViewModelTests: XCTestCase {
await viewModel.loadTemplates(api: api)
XCTAssertFalse(viewModel.canSubmit)
viewModel.toggleTemplate(id: 11, category: .refined)
XCTAssertTrue(viewModel.canSubmit)
XCTAssertNil(viewModel.validationMessage)
XCTAssertEqual(viewModel.requiredQuota, 1)
@@ -213,7 +225,7 @@ final class TravelAlbumAIRetouchTemplateViewModelTests: XCTestCase {
)
let reretouch = TravelAlbumAIRetouchTemplateViewModel(
scenicId: 18,
workflow: .reretouch(materialId: 7, batchId: 70, type: .all)
workflow: .reretouch(materialId: 7, batchId: 70, type: .refined)
)
await reretouch.loadTemplates(api: refinedAPI)
XCTAssertFalse(reretouch.canSubmit)
@@ -918,6 +918,43 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase {
XCTAssertEqual(quotaLabel.accessibilityLabel, "剩余8张修图额度")
}
func testOriginalTabReretouchSheetShowsBothTemplateGroupsAsOptional() async throws {
let api = TravelAlbumMockAPI()
api.aiRetouchTemplatesResponse = TravelAlbumAIRetouchTemplatesResponse(
refinedTemplates: [TravelAlbumAIRetouchTemplate(id: 1, name: "清透", previewURL: "")],
atmosphereTemplates: [TravelAlbumAIRetouchTemplate(id: 2, name: "暖阳", previewURL: "")],
remainingQuota: 8
)
let viewModel = TravelAlbumAIRetouchTemplateViewModel(
scenicId: 18,
workflow: .reretouch(materialId: 7, batchId: 70, type: .all)
)
let controller = TravelAlbumAIRetouchTemplateViewController(
viewModel: viewModel,
api: api,
onSubmitted: { _ in }
)
controller.loadViewIfNeeded()
controller.view.frame = CGRect(x: 0, y: 0, width: 390, height: 844)
await waitUntil { !viewModel.isLoading && api.aiRetouchTemplateScenicIds.count == 1 }
controller.view.layoutIfNeeded()
let confirmButton = try XCTUnwrap(
controller.view.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchConfirmButton"
} as? UIButton
)
let accessibleLabels = controller.view.allAccessibilityLabels()
XCTAssertTrue(accessibleLabels.contains("原图精修,选填"))
XCTAssertTrue(accessibleLabels.contains("氛围感修图,选填"))
XCTAssertFalse(confirmButton.isEnabled)
viewModel.toggleTemplate(id: 2, category: .atmosphere)
await waitUntil { confirmButton.isEnabled }
XCTAssertNil(viewModel.selectedRefinedTemplateId)
XCTAssertEqual(viewModel.selectedAtmosphereTemplateId, 2)
}
func testAIRetouchTemplateCellExposesSelectedState() {
let cell = TravelAlbumAIRetouchTemplateCell(frame: .zero)
let template = TravelAlbumAIRetouchTemplate(id: 1, name: "清透", previewURL: "")
@@ -1039,7 +1076,7 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase {
XCTAssertEqual(comparisonButton.bounds.size, CGSize(width: 48, height: 48))
}
func testPreviewAIRetouchUsesSelectedRetouchedTabWorkflowAndNotifiesSubmission() async throws {
func testPreviewAIRetouchFromRetouchedTabAllowsBothOptionalTemplates() async throws {
UIView.setAnimationsEnabled(false)
defer { UIView.setAnimationsEnabled(true) }
let api = TravelAlbumMockAPI()
@@ -1106,7 +1143,16 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchConfirmButton"
} as? UIButton
)
await waitUntil { api.aiRetouchTemplateScenicIds.count == 1 && confirmButton.isEnabled }
let collectionView = try XCTUnwrap(
sheet.view.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchTemplateCollection"
} as? UICollectionView
)
await waitUntil {
api.aiRetouchTemplateScenicIds.count == 1 &&
collectionView.numberOfSections > 2 &&
collectionView.numberOfItems(inSection: 2) == 1
}
sheet.view.frame = CGRect(x: 0, y: 0, width: 390, height: 844)
sheet.view.layoutIfNeeded()
@@ -1114,7 +1160,11 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase {
label.isHidden ? nil : label.text
}
XCTAssertTrue(visibleLabelTexts.contains("原图精修"))
XCTAssertFalse(visibleLabelTexts.contains { $0.contains("氛围感修图") })
XCTAssertTrue(visibleLabelTexts.contains("氛围感修图"))
let accessibleLabels = sheet.view.allAccessibilityLabels()
XCTAssertTrue(accessibleLabels.contains("原图精修,选填"))
XCTAssertTrue(accessibleLabels.contains("氛围感修图,选填"))
XCTAssertFalse(confirmButton.isEnabled)
let selectionCountLabel = try XCTUnwrap(
sheet.view.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchSelectionCountLabel"
@@ -1133,11 +1183,25 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase {
XCTAssertEqual(selectionCountLabel.text, "已选择 1 张照片")
XCTAssertTrue(tipsContainer.isHidden)
XCTAssertTrue(tipsLabel.isHidden)
collectionView.delegate?.collectionView?(
collectionView,
didSelectItemAt: IndexPath(item: 0, section: 2)
)
await waitUntil { confirmButton.isEnabled }
confirmButton.sendActions(for: .touchUpInside)
await waitUntil { api.aiReretouchRequests.count == 1 }
await waitUntil { submissionNotified }
XCTAssertEqual(api.aiReretouchRequests.first?.type, .refined)
XCTAssertEqual(
api.aiReretouchRequests.first,
TravelAlbumAIReretouchRequest(
id: 7,
aiRetouchBatchId: 70,
type: .all,
refinedTemplateId: nil,
atmosphereTemplateId: 21
)
)
XCTAssertTrue(submissionNotified)
XCTAssertTrue(window.rootViewController === controller)
}
+3 -3
View File
@@ -268,7 +268,7 @@ final class TravelAlbumModelsTests: XCTestCase {
)
}
func testPreviewProjectMapsCurrentTabToMinimalAIRetouchWorkflow() {
func testPreviewProjectUsesAllReretouchWorkflowForEveryVisibleVariantTab() {
let originalOnly = makePreviewProject(id: 9, kinds: [.original])
let variants = TravelAlbumPreviewProject(
originalMaterialId: 10,
@@ -286,11 +286,11 @@ final class TravelAlbumModelsTests: XCTestCase {
)
XCTAssertEqual(
variants.aiRetouchWorkflow(albumId: 7, selectedKind: .retouched),
.reretouch(materialId: 10, batchId: 88, type: .refined)
.reretouch(materialId: 10, batchId: 88, type: .all)
)
XCTAssertEqual(
variants.aiRetouchWorkflow(albumId: 7, selectedKind: .atmosphere),
.reretouch(materialId: 10, batchId: 88, type: .atmosphere)
.reretouch(materialId: 10, batchId: 88, type: .all)
)
XCTAssertNil(variants.aiRetouchWorkflow(albumId: 7, selectedKind: .cover))
}