移除 LoginViewModel 硬编码账号,扩展登录流程测试覆盖;调整 ZLoginSmokeUITests 执行顺序与路由直达逻辑,避免清空 Keychain 影响其它用例。 Co-authored-by: Cursor <cursoragent@cursor.com>
96 lines
3.7 KiB
Swift
96 lines
3.7 KiB
Swift
//
|
||
// 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, "")
|
||
}
|
||
}
|