// // AuthModelsTests.swift // suixinkanTests // // Created by Codex on 2026/6/26. // import XCTest @testable import suixinkan /// Auth 模块模型测试,覆盖 v9 登录响应解码和账号转换规则。 final class AuthModelsTests: XCTestCase { /// 测试多账号登录 fixture 能正确解码并合并景区、门店账号。 func testV9AuthResponseDecodesMultiAccountFixture() throws { let response = try TestFixture.payload(V9AuthResponse.self, named: "v9_login_multi_success") XCTAssertEqual(response.token, "person-temp-token") XCTAssertEqual(response.scenicUsers.count, 1) XCTAssertEqual(response.storeUsers.count, 1) XCTAssertEqual(response.accounts.map(\.businessUserId), [101, 201]) } /// 测试景区账号会优先使用 ss_user_id 作为业务账号 ID。 func testV9ScenicUserBusinessUserIdPrefersSsUserId() throws { let json = """ { "account_type": "scenic_user", "id": 1, "user_id": 2, "scenic_user_id": 3, "ss_user_id": 101, "username": "scenic_admin", "real_name": "张三", "nickname": "张三", "phone": "13800138000", "scenic_id": 10, "scenic_name": "示例景区", "is_current": false } """.data(using: .utf8)! let user = try JSONDecoder().decode(V9ScenicUser.self, from: json) XCTAssertEqual(user.businessUserId, 101) XCTAssertEqual(user.toAccountSwitchAccount().accountType, V9ScenicUser.accountTypeValue) XCTAssertEqual(user.toAccountSwitchAccount().toSetUserRequest(), SetUserRequest(ssUserId: 101)) } /// 测试门店账号会优先使用 store_user_id 作为业务账号 ID。 func testV9StoreUserBusinessUserIdPrefersStoreUserId() throws { let json = """ { "account_type": "store_user", "id": 1, "user_id": 2, "store_user_id": 201, "username": "store_admin", "user_name": "store_admin", "real_name": "张三", "phone": "13800138000", "avatar": "", "scenic_id": 10, "scenic_name": "示例景区", "store_id": 20, "store_name": "示例门店", "is_current": false } """.data(using: .utf8)! let user = try JSONDecoder().decode(V9StoreUser.self, from: json) XCTAssertEqual(user.businessUserId, 201) XCTAssertEqual(user.toAccountSwitchAccount().accountType, V9StoreUser.accountTypeValue) XCTAssertEqual(user.toAccountSwitchAccount().toSetUserRequest(), SetUserRequest(storeUserId: 201)) } /// 测试登录响应会派生景区和门店作用域,并去重。 func testV9AuthResponseDerivesScopesFromAccounts() throws { let response = try TestFixture.payload(V9AuthResponse.self, named: "v9_login_multi_success") XCTAssertEqual(response.scenicScopes.map(\.id), [10]) XCTAssertEqual(response.storeScopes.map(\.id), [20]) XCTAssertEqual(response.primaryProfile?.displayName, "示例门店") } /// 测试 LoginRequest 会填充后端要求的默认字段。 func testLoginRequestEncodesExpectedDefaults() throws { let request = LoginRequest(username: "18651857230", password: "secret123") let json = try JSONSerialization.jsonObject(with: JSONEncoder().encode(request)) as? [String: Any] XCTAssertEqual(json?["username"] as? String, "18651857230") XCTAssertEqual(json?["password"] as? String, "secret123") XCTAssertEqual(json?["type"] as? Int, 1) XCTAssertEqual(json?["mobile"] as? String, "") XCTAssertEqual(json?["code"] as? String, "") } }