feat: add AI retouch and album preview actions

This commit is contained in:
2026-08-10 16:00:32 +08:00
parent 24fa66281c
commit 439edf827c
14 changed files with 2110 additions and 118 deletions
+76 -2
View File
@@ -51,16 +51,27 @@ final class TravelAlbumAPITests: XCTestCase {
}
func testMaterialListAndDeleteAndMpCode() async throws {
let materialList = envelopeJSON(#"{"total":0,"list":[]}"#)
let materialList = envelopeJSON(
#"{"total":1,"list":[{"id":6,"user_equity_travel_id":3,"status":1,"order_number":"","user_id":9,"file_name":"A.JPG","file_type":2,"file_url":"https://cdn/a.jpg","file_size":1024,"cover_url":"","is_purchased":false,"ai_retouch_status":3,"ai_retouch_status_name":"AI已修","ai_refined_url":"https://cdn/refined.jpg","ai_atmosphere_url":"https://cdn/atmosphere.jpg","created_at":"","updated_at":""}]}"#
)
let empty = envelopeJSON("{}")
let code = envelopeJSON(#"{"mp_code_oss_url":"https://cdn/qr.png"}"#)
let session = MockURLSession(responses: [materialList, empty, code])
let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))
_ = try await api.materialList(userEquityTravelId: 3, page: 1, pageSize: 30, orderBy: 4, isPurchased: 1)
let materials = try await api.materialList(
userEquityTravelId: 3,
page: 1,
pageSize: 30,
orderBy: 4,
isPurchased: 1
)
try await api.deleteAlbum(id: 3)
let response = try await api.mpCode(id: 3)
XCTAssertEqual(materials.list.first?.aiRetouchStatus, 3)
XCTAssertEqual(materials.list.first?.aiRefinedURL, "https://cdn/refined.jpg")
XCTAssertEqual(materials.list.first?.aiAtmosphereURL, "https://cdn/atmosphere.jpg")
XCTAssertEqual(response.mpCodeOssUrl, "https://cdn/qr.png")
XCTAssertEqual(session.requests[0].url?.path, "/api/yf-handset-app/photog/travel-album/material-list")
let query = URLComponents(url: session.requests[0].url!, resolvingAgainstBaseURL: false)?.queryItems
@@ -113,6 +124,69 @@ final class TravelAlbumAPITests: XCTestCase {
XCTAssertEqual(query?.first { $0.name == "user_equity_travel_id" }?.value, "3")
}
func testAIRetouchTemplatesBuildsQueryAndDecodesGroups() async throws {
let data = envelopeJSON(
#"{"refined_templates":[{"id":1,"name":"清透","preview_url":"https://cdn/refined.jpg"}],"atmosphere_templates":[{"id":2,"name":"暖阳","preview_url":"https://cdn/atmosphere.jpg"}],"cover_templates":[{"id":3,"name":"杂志","preview_url":"https://cdn/cover.jpg"}]}"#
)
let session = MockURLSession(responses: [data])
let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))
let response = try await api.aiRetouchTemplates(scenicId: 18)
XCTAssertEqual(response.refinedTemplates.first?.name, "清透")
XCTAssertEqual(response.atmosphereTemplates.first?.id, 2)
XCTAssertEqual(response.coverTemplates.first?.previewURL, "https://cdn/cover.jpg")
let request = try XCTUnwrap(session.requests.first)
XCTAssertEqual(request.httpMethod, "GET")
XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/travel-album/ai-retouch-templates")
let query = URLComponents(url: try XCTUnwrap(request.url), resolvingAgainstBaseURL: false)?.queryItems
XCTAssertEqual(query?.first { $0.name == "scenic_id" }?.value, "18")
}
func testSubmitAIRetouchEncodesRequiredAndSelectedOptionalTemplates() async throws {
let session = MockURLSession(responses: [envelopeJSON(#"{"task_id":9}"#)])
let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))
try await api.submitAIRetouch(
TravelAlbumAIRetouchRequest(
userEquityTravelId: 6,
materialIds: [11, 12, 13, 14],
refinedTemplateId: 21,
atmosphereTemplateId: 22,
aiPreviewTabs: 31
)
)
let request = try XCTUnwrap(session.requests.first)
XCTAssertEqual(request.httpMethod, "POST")
XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/travel-album/ai-retouch")
let body = try JSONSerialization.jsonObject(with: try XCTUnwrap(request.httpBody)) as? [String: Any]
XCTAssertEqual(body?["user_equity_travel_id"] as? Int, 6)
XCTAssertEqual(body?["material_ids"] as? [Int], [11, 12, 13, 14])
XCTAssertEqual(body?["refined_template_id"] as? Int, 21)
XCTAssertEqual(body?["atmosphere_template_id"] as? Int, 22)
XCTAssertEqual(body?["ai_preview_tabs"] as? Int, 31)
}
func testSubmitAIRetouchOmitsAllOptionalTemplatesWhenAbsent() async throws {
let session = MockURLSession(responses: [envelopeJSON(#"{"accepted":true}"#)])
let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))
try await api.submitAIRetouch(
TravelAlbumAIRetouchRequest(
userEquityTravelId: 6,
materialIds: [11],
refinedTemplateId: 21,
atmosphereTemplateId: nil,
aiPreviewTabs: nil
)
)
let body = try JSONSerialization.jsonObject(with: try XCTUnwrap(session.requests.first?.httpBody)) as? [String: Any]
XCTAssertNil(body?["atmosphere_template_id"])
XCTAssertNil(body?["ai_preview_tabs"])
}
private func envelopeJSON(_ dataJSON: String) -> Data {
"""
{"code":100000,"msg":"success","data":\(dataJSON)}