// // LiveAPITests.swift // suixinkanTests // import XCTest @testable import suixinkan @MainActor /// 直播 API 测试。 final class LiveAPITests: XCTestCase { func testManualLiveListAndDetailBuildAndroidQueries() async throws { let session = MockURLSession(responses: [ envelopeJSON(#"{"page":1,"page_size":10,"total":0,"total_pages":0,"items":[]}"#), envelopeJSON(#"{"id":7,"title":"直播"}"#), ]) let api = LiveAPI(client: APIClient(environment: .testing, session: session)) _ = try await api.liveList(scenicId: "12", page: 2, pageSize: 10) _ = try await api.liveDetail(liveId: 7) XCTAssertEqual(session.requests[0].httpMethod, "GET") XCTAssertEqual(session.requests[0].url?.path, "/api/app/manual-live/list") let listQuery = URLComponents(url: session.requests[0].url!, resolvingAgainstBaseURL: false)?.queryItems XCTAssertEqual(listQuery?.first { $0.name == "scenic_id" }?.value, "12") XCTAssertEqual(listQuery?.first { $0.name == "page" }?.value, "2") XCTAssertEqual(listQuery?.first { $0.name == "page_size" }?.value, "10") XCTAssertEqual(session.requests[1].httpMethod, "GET") XCTAssertEqual(session.requests[1].url?.path, "/api/app/manual-live/detail") let detailQuery = URLComponents(url: session.requests[1].url!, resolvingAgainstBaseURL: false)?.queryItems XCTAssertEqual(detailQuery?.first { $0.name == "live_id" }?.value, "7") } func testManualLiveControlBodies() async throws { let session = MockURLSession(responses: [envelopeJSON("{}"), envelopeJSON("{}"), envelopeJSON("{}"), envelopeJSON("{}")]) let api = LiveAPI(client: APIClient(environment: .testing, session: session)) try await api.createLive(scenicId: "3", title: "直播A", coverImg: "https://cdn/c.jpg") try await api.startLive(liveId: 8) try await api.finishLive(liveId: 8) try await api.setPushMode(liveId: 8, mode: 2) XCTAssertEqual(session.requests[0].url?.path, "/api/app/manual-live/create") let createBody = try JSONSerialization.jsonObject(with: XCTUnwrap(session.requests[0].httpBody)) as? [String: Any] XCTAssertEqual(createBody?["scenic_id"] as? String, "3") XCTAssertEqual(createBody?["title"] as? String, "直播A") XCTAssertEqual(createBody?["cover_img"] as? String, "https://cdn/c.jpg") XCTAssertEqual(session.requests[1].url?.path, "/api/app/manual-live/start") let startBody = try JSONSerialization.jsonObject(with: XCTUnwrap(session.requests[1].httpBody)) as? [String: Any] XCTAssertEqual(startBody?["live_id"] as? Int, 8) XCTAssertEqual(session.requests[2].url?.path, "/api/app/manual-live/finish") XCTAssertEqual(session.requests[3].url?.path, "/api/app/manual-live/set-push-mode") let modeBody = try JSONSerialization.jsonObject(with: XCTUnwrap(session.requests[3].httpBody)) as? [String: Any] XCTAssertEqual(modeBody?["live_id"] as? Int, 8) XCTAssertEqual(modeBody?["manual_push_mode"] as? Int, 2) } func testAlbumRequestsMatchAndroidPaths() async throws { let session = MockURLSession(responses: [ envelopeJSON(#"{"items":[],"page":1,"page_size":10,"total":0,"total_pages":0}"#), envelopeJSON("{}"), envelopeJSON(#"{"id":4,"items":[]}"#), envelopeJSON("{}"), ]) let api = LiveAPI(client: APIClient(environment: .testing, session: session)) _ = try await api.albumList(scenicId: "9", startTime: "2026-07-01", endTime: "2026-07-08", page: 3, pageSize: 10) try await api.createAlbumFolder(scenicId: "9", name: "作品", items: [LiveAlbumFile(url: "https://cdn/a.jpg", type: 2, size: 10)]) _ = try await api.albumFolderDetail(folderId: 4) try await api.deleteAlbumFile(folderId: 4, fileId: 11) XCTAssertEqual(session.requests[0].url?.path, "/api/app/view-album/folders") let query = URLComponents(url: session.requests[0].url!, resolvingAgainstBaseURL: false)?.queryItems XCTAssertEqual(query?.first { $0.name == "scenic_id" }?.value, "9") XCTAssertEqual(query?.first { $0.name == "start_time" }?.value, "2026-07-01") XCTAssertEqual(query?.first { $0.name == "end_time" }?.value, "2026-07-08") XCTAssertEqual(query?.first { $0.name == "page" }?.value, "3") XCTAssertEqual(query?.first { $0.name == "page_size" }?.value, "10") XCTAssertEqual(session.requests[1].url?.path, "/api/app/view-album/create-folder") let createBody = try JSONSerialization.jsonObject(with: XCTUnwrap(session.requests[1].httpBody)) as? [String: Any] XCTAssertEqual(createBody?["scenic_id"] as? String, "9") XCTAssertEqual(createBody?["name"] as? String, "作品") XCTAssertEqual((createBody?["items"] as? [[String: Any]])?.first?["url"] as? String, "https://cdn/a.jpg") XCTAssertEqual(session.requests[2].url?.path, "/api/app/view-album/folder-detail") XCTAssertEqual(session.requests[3].url?.path, "/api/app/view-album/delete-files") let deleteBody = try JSONSerialization.jsonObject(with: XCTUnwrap(session.requests[3].httpBody)) as? [String: Any] XCTAssertEqual(deleteBody?["folder_id"] as? Int, 4) XCTAssertEqual(deleteBody?["file_ids"] as? [Int], [11]) } private func envelopeJSON(_ dataJSON: String) -> Data { """ {"code":100000,"msg":"success","data":\(dataJSON)} """.data(using: .utf8)! } }