286 lines
14 KiB
Swift
286 lines
14 KiB
Swift
//
|
|
// TravelAlbumAPITests.swift
|
|
// suixinkanTests
|
|
//
|
|
|
|
import XCTest
|
|
@testable import suixinkan
|
|
|
|
@MainActor
|
|
/// 旅拍相册 API 测试。
|
|
final class TravelAlbumAPITests: XCTestCase {
|
|
func testListBuildsPathAndQuery() async throws {
|
|
let data = envelopeJSON(#"{"total":1,"list":[]}"#)
|
|
let session = MockURLSession(responses: [data])
|
|
let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))
|
|
|
|
_ = try await api.list(page: 2, pageSize: 30)
|
|
|
|
let request = try XCTUnwrap(session.requests.first)
|
|
XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/travel-album/list")
|
|
let query = try XCTUnwrap(URLComponents(url: try XCTUnwrap(request.url), resolvingAgainstBaseURL: false)?.queryItems)
|
|
XCTAssertEqual(query.first { $0.name == "page" }?.value, "2")
|
|
XCTAssertEqual(query.first { $0.name == "page_size" }?.value, "30")
|
|
}
|
|
|
|
func testCreateEncodesBody() async throws {
|
|
let data = envelopeJSON(#"{"id":8}"#)
|
|
let session = MockURLSession(responses: [data])
|
|
let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))
|
|
|
|
_ = try await api.create(
|
|
TravelAlbumCreateRequest(
|
|
name: "2026-07-07-001",
|
|
type: 1,
|
|
orderNumber: nil,
|
|
materialNum: 2,
|
|
materialPrice: 10.5,
|
|
materialPackagePrice: 88,
|
|
photoPrice: 0
|
|
)
|
|
)
|
|
|
|
let request = try XCTUnwrap(session.requests.first)
|
|
XCTAssertEqual(request.httpMethod, "POST")
|
|
XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/travel-album/create")
|
|
let body = try JSONSerialization.jsonObject(with: try XCTUnwrap(request.httpBody)) as? [String: Any]
|
|
XCTAssertEqual(body?["name"] as? String, "2026-07-07-001")
|
|
XCTAssertEqual(body?["type"] as? Int, 1)
|
|
XCTAssertEqual(body?["material_num"] as? Int, 2)
|
|
XCTAssertEqual(body?["material_price"] as? Double, 10.5)
|
|
}
|
|
|
|
func testMaterialListAndDeleteAndMpCode() async throws {
|
|
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))
|
|
|
|
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
|
|
XCTAssertEqual(query?.first { $0.name == "user_equity_travel_id" }?.value, "3")
|
|
XCTAssertEqual(query?.first { $0.name == "order_by" }?.value, "4")
|
|
XCTAssertEqual(query?.first { $0.name == "is_purchased" }?.value, "1")
|
|
XCTAssertEqual(session.requests[1].url?.path, "/api/yf-handset-app/photog/travel-album/delete")
|
|
let body = try JSONSerialization.jsonObject(with: session.requests[1].httpBody!) as? [String: Any]
|
|
XCTAssertEqual(body?["id"] as? Int, 3)
|
|
XCTAssertEqual(session.requests[2].url?.path, "/api/yf-handset-app/photog/travel-album/mp-code")
|
|
}
|
|
|
|
func testMaterialInfoBuildsQueryAndDecodesMaterial() async throws {
|
|
let data = envelopeJSON(
|
|
#"{"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_retouch_batch_id":60,"ai_refined_url":"https://cdn/refined.jpg","ai_atmosphere_url":"https://cdn/atmosphere.jpg","created_at":"","updated_at":""}"#
|
|
)
|
|
let session = MockURLSession(responses: [data])
|
|
let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))
|
|
|
|
let material = try await api.materialInfo(userEquityTravelId: 3, materialId: 6)
|
|
|
|
XCTAssertEqual(material.id, 6)
|
|
XCTAssertEqual(material.aiRetouchBatchId, 60)
|
|
XCTAssertEqual(material.aiRefinedURL, "https://cdn/refined.jpg")
|
|
let request = try XCTUnwrap(session.requests.first)
|
|
XCTAssertEqual(request.httpMethod, "GET")
|
|
XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/travel-album/material-info")
|
|
let query = URLComponents(url: try XCTUnwrap(request.url), resolvingAgainstBaseURL: false)?.queryItems
|
|
XCTAssertEqual(query?.first { $0.name == "user_equity_travel_id" }?.value, "3")
|
|
XCTAssertEqual(query?.first { $0.name == "material_id" }?.value, "6")
|
|
}
|
|
|
|
func testUploadMaterialBuildsPathAndBody() async throws {
|
|
let material = envelopeJSON(#"{"id":6,"user_equity_travel_id":3,"status":1,"order_number":"","user_id":9,"file_name":"A.JPG","file_type":1,"file_url":"https://cdn/a.jpg","file_size":1024,"cover_url":"","is_purchased":false,"created_at":"2026-07-08 10:00:00","updated_at":"2026-07-08 10:00:00"}"#)
|
|
let session = MockURLSession(responses: [material])
|
|
let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))
|
|
|
|
let response = try await api.uploadMaterial(
|
|
TravelAlbumUploadMaterialRequest(
|
|
userEquityTravelId: 3,
|
|
fileName: "A.JPG",
|
|
fileUrl: "https://cdn/a.jpg",
|
|
clientPhotoId: "2a1d96b1-c0cc-489f-9f42-419ff1439a62"
|
|
)
|
|
)
|
|
|
|
XCTAssertEqual(response.id, 6)
|
|
let request = try XCTUnwrap(session.requests.first)
|
|
XCTAssertEqual(request.httpMethod, "POST")
|
|
XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/travel-album/upload-material")
|
|
let body = try JSONSerialization.jsonObject(with: try XCTUnwrap(request.httpBody)) as? [String: Any]
|
|
XCTAssertEqual(body?["user_equity_travel_id"] as? Int, 3)
|
|
XCTAssertEqual(body?["file_name"] as? String, "A.JPG")
|
|
XCTAssertEqual(body?["file_url"] as? String, "https://cdn/a.jpg")
|
|
XCTAssertEqual(body?["client_photo_id"] as? String, "2a1d96b1-c0cc-489f-9f42-419ff1439a62")
|
|
}
|
|
|
|
func testMaterialClientPhotoIdsBuildsPathQueryAndDecodesResponse() async throws {
|
|
let data = envelopeJSON(#"{"client_photo_ids":["one","two"]}"#)
|
|
let session = MockURLSession(responses: [data])
|
|
let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))
|
|
|
|
let response = try await api.materialClientPhotoIds(userEquityTravelId: 3)
|
|
|
|
XCTAssertEqual(response.clientPhotoIds, ["one", "two"])
|
|
let request = try XCTUnwrap(session.requests.first)
|
|
XCTAssertEqual(request.httpMethod, "GET")
|
|
XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/travel-album/material-client-photo-ids")
|
|
let query = URLComponents(url: request.url!, resolvingAgainstBaseURL: false)?.queryItems
|
|
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"}],"remaining_quota":12}"#
|
|
)
|
|
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")
|
|
XCTAssertEqual(response.remainingQuota, 12)
|
|
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,
|
|
coverTemplateId: 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?["cover_template_id"] as? Int, 31)
|
|
XCTAssertEqual(Set(body?.keys.map { $0 } ?? []), [
|
|
"user_equity_travel_id",
|
|
"material_ids",
|
|
"refined_template_id",
|
|
"atmosphere_template_id",
|
|
"cover_template_id",
|
|
])
|
|
}
|
|
|
|
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,
|
|
coverTemplateId: nil
|
|
)
|
|
)
|
|
|
|
let body = try JSONSerialization.jsonObject(with: try XCTUnwrap(session.requests.first?.httpBody)) as? [String: Any]
|
|
XCTAssertNil(body?["atmosphere_template_id"])
|
|
XCTAssertNil(body?["cover_template_id"])
|
|
XCTAssertEqual(Set(body?.keys.map { $0 } ?? []), [
|
|
"user_equity_travel_id",
|
|
"material_ids",
|
|
"refined_template_id",
|
|
])
|
|
}
|
|
|
|
func testSubmitAIReretouchEncodesOnlyFieldsRequiredByEachType() async throws {
|
|
let session = MockURLSession(responses: [
|
|
envelopeJSON(#"{"accepted":true}"#),
|
|
envelopeJSON(#"{"accepted":true}"#),
|
|
envelopeJSON(#"{"accepted":true}"#),
|
|
])
|
|
let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))
|
|
|
|
try await api.submitAIReretouch(
|
|
TravelAlbumAIReretouchRequest(
|
|
id: 11,
|
|
aiRetouchBatchId: 51,
|
|
type: .refined,
|
|
refinedTemplateId: 21,
|
|
atmosphereTemplateId: nil
|
|
)
|
|
)
|
|
try await api.submitAIReretouch(
|
|
TravelAlbumAIReretouchRequest(
|
|
id: 12,
|
|
aiRetouchBatchId: 52,
|
|
type: .atmosphere,
|
|
refinedTemplateId: nil,
|
|
atmosphereTemplateId: 22
|
|
)
|
|
)
|
|
try await api.submitAIReretouch(
|
|
TravelAlbumAIReretouchRequest(
|
|
id: 13,
|
|
aiRetouchBatchId: 53,
|
|
type: .all,
|
|
refinedTemplateId: 21,
|
|
atmosphereTemplateId: 22
|
|
)
|
|
)
|
|
|
|
let bodies = try session.requests.map { request in
|
|
try JSONSerialization.jsonObject(with: XCTUnwrap(request.httpBody)) as? [String: Any]
|
|
}
|
|
XCTAssertEqual(session.requests.map { $0.url?.path }, Array(
|
|
repeating: "/api/yf-handset-app/photog/travel-album/ai-reretouch",
|
|
count: 3
|
|
))
|
|
XCTAssertEqual(Set(bodies[0]?.keys.map { $0 } ?? []), ["id", "ai_retouch_batch_id", "type", "refined_template_id"])
|
|
XCTAssertEqual(Set(bodies[1]?.keys.map { $0 } ?? []), ["id", "ai_retouch_batch_id", "type", "atmosphere_template_id"])
|
|
XCTAssertEqual(Set(bodies[2]?.keys.map { $0 } ?? []), [
|
|
"id",
|
|
"ai_retouch_batch_id",
|
|
"type",
|
|
"refined_template_id",
|
|
"atmosphere_template_id",
|
|
])
|
|
XCTAssertEqual(bodies[0]?["type"] as? Int, 1)
|
|
XCTAssertEqual(bodies[1]?["type"] as? Int, 2)
|
|
XCTAssertEqual(bodies[2]?["type"] as? Int, 3)
|
|
}
|
|
|
|
private func envelopeJSON(_ dataJSON: String) -> Data {
|
|
"""
|
|
{"code":100000,"msg":"success","data":\(dataJSON)}
|
|
""".data(using: .utf8)!
|
|
}
|
|
}
|