// // yanaAPITests.swift // yanaAPITests // // Created by P on 2025/5/27. // import XCTest @testable import yana final class yanaAPITests: XCTestCase { override func setUpWithError() throws { // Put setup code here. This method is called before the invocation of each test method in the class. } override func tearDownWithError() throws { // Put teardown code here. This method is called after the invocation of each test method in the class. } func testExample() throws { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. // Any test you write for XCTest can be annotated as throws and async. // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. } func testPerformanceExample() throws { // This is an example of a performance test case. measure { // Put the code you want to measure the time of here. } } func testIDLoginRequest_Creation() { // 测试ID登录请求的创建 let userID = "399113" let password = "a123456" let request = LoginHelper.createIDLoginRequest(userID: userID, password: password) XCTAssertNotNil(request, "登录请求应该创建成功") XCTAssertEqual(request?.endpoint, "/oauth/token", "端点应该正确") XCTAssertEqual(request?.method, .POST, "请求方法应该是POST") } func testIDLoginResponse_Success() { // 测试登录响应的成功解析 let successResponse = IDLoginResponse( status: "success", message: "登录成功", code: 200, data: IDLoginData( accessToken: "test_token", refreshToken: "refresh_token", tokenType: "Bearer", expiresIn: 3600, scope: "read write", userInfo: UserInfo( userId: "123", username: "testuser", nickname: "Test User", avatar: nil, email: "test@example.com", phone: "399113", status: "active", createTime: "2024-01-01", updateTime: "2024-01-01" ) ) ) XCTAssertTrue(successResponse.isSuccess, "响应应该标记为成功") XCTAssertEqual(successResponse.data?.accessToken, "test_token", "访问令牌应该正确") } func testAccountModelFlow() { // 测试完整的 AccountModel 流程 // 1. 模拟 oauth/token 响应(基于用户提供的真实数据) let loginData = IDLoginData( accessToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.test", refreshToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.refresh", tokenType: "bearer", expiresIn: 2591999, scope: "read write", userInfo: nil, // 真实API没有返回user_info uid: 3184, netEaseToken: "6fba51065b5e32ad18a935438517a1a9", jti: "d3a82ddb-ea6f-4d2f-8dc7-7bdb3d6b9e87" ) // 2. 从 IDLoginData 创建 AccountModel let accountModel = AccountModel.from(loginData: loginData) XCTAssertNotNil(accountModel, "应该能从IDLoginData创建AccountModel") XCTAssertEqual(accountModel?.uid, "3184", "UID应该正确转换为字符串") XCTAssertEqual(accountModel?.accessToken, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.test", "Access Token应该正确") XCTAssertEqual(accountModel?.tokenType, "bearer", "Token类型应该正确") XCTAssertEqual(accountModel?.netEaseToken, "6fba51065b5e32ad18a935438517a1a9", "网易云Token应该正确") XCTAssertNil(accountModel?.ticket, "初始ticket应该为空") // 3. 检查认证状态 XCTAssertTrue(accountModel?.hasValidAuthentication ?? false, "应该有有效的认证") XCTAssertFalse(accountModel?.hasValidSession ?? true, "没有ticket时不应该有有效会话") // 4. 模拟获取ticket后更新AccountModel let ticketString = "eyJhbGciOiJIUzI1NiJ9.ticket" let updatedAccountModel = accountModel?.withTicket(ticketString) XCTAssertNotNil(updatedAccountModel, "应该能更新ticket") XCTAssertEqual(updatedAccountModel?.ticket, ticketString, "Ticket应该正确设置") XCTAssertTrue(updatedAccountModel?.hasValidSession ?? false, "有ticket时应该有有效会话") // 5. 测试持久化和加载 if let finalAccountModel = updatedAccountModel { UserInfoManager.saveAccountModel(finalAccountModel) let loadedAccountModel = UserInfoManager.getAccountModel() XCTAssertNotNil(loadedAccountModel, "应该能加载保存的AccountModel") XCTAssertEqual(loadedAccountModel?.uid, "3184", "加载的UID应该正确") XCTAssertEqual(loadedAccountModel?.accessToken, finalAccountModel.accessToken, "加载的Access Token应该正确") XCTAssertEqual(loadedAccountModel?.ticket, ticketString, "加载的Ticket应该正确") // 6. 测试向后兼容性 let userId = UserInfoManager.getCurrentUserId() let accessToken = UserInfoManager.getAccessToken() let ticket = UserInfoManager.getCurrentUserTicket() XCTAssertEqual(userId, "3184", "向后兼容的用户ID应该正确") XCTAssertEqual(accessToken, finalAccountModel.accessToken, "向后兼容的Access Token应该正确") XCTAssertEqual(ticket, ticketString, "向后兼容的Ticket应该正确") } // 7. 清理 UserInfoManager.clearAllAuthenticationData() XCTAssertNil(UserInfoManager.getAccountModel(), "清理后AccountModel应该为空") XCTAssertNil(UserInfoManager.getCurrentUserId(), "清理后用户ID应该为空") } func testAccountModelWithRealAPIData() { // 使用用户提供的真实API返回数据进行测试 let realAPIResponseData: [String: Any] = [ "uid": 3184, "jti": "d3a82ddb-ea6f-4d2f-8dc7-7bdb3d6b9e87", "token_type": "bearer", "scope": "read write", "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiIyMzU2ODE0Iiwic2NvcGUiOlsicmVhZCIsIndyaXRlIl0sImF0aSI6ImQzYTgyZGRiLWVhNmYtNGQyZi04ZGM3LTdiZGIzZDZiOWU4NyIsImV4cCI6MTc1NTI0MjY5MiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9hY2NvdW50IiwiUk9MRV9NT0JJTEUiLCJST0xFX1VOSVRZIl0sImp0aSI6ImFiZjhjN2ZjLTllOWEtNDE2Yy04NTk2LTBkMWYxZWQyODU2MiIsImNsaWVudF9pZCI6ImVyYmFuLWNsaWVudCJ9.6i_9FnZvviuWYIoXDv9of7EDRyjRVxNbkiHayNUFxNw", "netEaseToken": "6fba51065b5e32ad18a935438517a1a9", "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NTQ2Mzc4OTIsInVzZXJfbmFtZSI6IjIzNTY4MTQiLCJhdXRob3JpdGllcyI6WyJST0xFX2FjY291bnQiLCJST0xFX01PQklMRSIsIlJPTEVfVU5JVFkiXSwianRpIjoiZDNhODJkZGItZWE2Zi00ZDJmLThkYzctN2JkYjNkNmI5ZTg3IiwiY2xpZW50X2lkIjoiZXJiYW4tY2xpZW50Iiwic2NvcGUiOlsicmVhZCIsIndyaXRlIl19.ynUptBtAoPVXz4J1AO8LbaAhmFRF4UnF4C-Ggj6Izpc", "expires_in": 2591999 ] // 模拟JSON解析 do { let jsonData = try JSONSerialization.data(withJSONObject: realAPIResponseData) let loginData = try JSONDecoder().decode(IDLoginData.self, from: jsonData) // 创建AccountModel let accountModel = AccountModel.from(loginData: loginData) XCTAssertNotNil(accountModel, "应该能从真实API数据创建AccountModel") XCTAssertEqual(accountModel?.uid, "3184", "真实API数据的UID应该正确") XCTAssertTrue(accountModel?.hasValidAuthentication ?? false, "真实API数据应该有有效认证") debugInfoSync("✅ 真实API数据测试通过") debugInfoSync(" UID: \(accountModel?.uid ?? "nil")") debugInfoSync(" Access Token存在: \(accountModel?.accessToken != nil)") debugInfoSync(" Token类型: \(accountModel?.tokenType ?? "nil")") } catch { XCTFail("解析真实API数据失败: \(error)") } } } // MARK: - User Info API Tests extension yanaAPITests { func testGetUserInfoRequest() { // 测试获取用户信息请求创建 let uid = "12345" let request = UserInfoHelper.createGetUserInfoRequest(uid: uid) XCTAssertEqual(request.endpoint, "/user/get", "端点应该正确") XCTAssertEqual(request.method, .GET, "请求方法应该是GET") XCTAssertEqual(request.queryParameters?["uid"], uid, "UID参数应该正确") XCTAssertFalse(request.shouldShowLoading, "不应该显示loading") XCTAssertFalse(request.shouldShowError, "不应该显示错误") } func testGetUserInfoResponse() { // 测试用户信息响应解析 let responseData: [String: Any] = [ "code": 200, "message": "success", "timestamp": 1640995200000, "data": [ "user_id": "12345", "username": "testuser", "nickname": "测试用户", "avatar": "https://example.com/avatar.jpg", "email": "test@example.com", "phone": "13800138000", "status": "active", "create_time": "2024-01-01 00:00:00", "update_time": "2024-01-01 00:00:00" ] ] do { let jsonData = try JSONSerialization.data(withJSONObject: responseData) let response = try JSONDecoder().decode(GetUserInfoResponse.self, from: jsonData) XCTAssertTrue(response.isSuccess, "响应应该成功") XCTAssertEqual(response.code, 200, "状态码应该正确") XCTAssertNotNil(response.data, "用户信息数据应该存在") if let userInfo = response.data { XCTAssertEqual(userInfo.userId, "12345", "用户ID应该正确") XCTAssertEqual(userInfo.username, "testuser", "用户名应该正确") XCTAssertEqual(userInfo.nickname, "测试用户", "昵称应该正确") } debugInfoSync("✅ 用户信息响应解析测试通过") } catch { XCTFail("解析用户信息响应失败: \(error)") } } func testUserInfoHelper() { // 测试UserInfoHelper let uid = "67890" UserInfoHelper.debugGetUserInfoRequest(uid: uid) let request = UserInfoHelper.createGetUserInfoRequest(uid: uid) XCTAssertEqual(request.queryParameters?["uid"], uid, "Helper创建的请求应该正确") } }