Files
suixinkan_ios_new/suixinkanTests/ProfileSecondaryPagesTests.swift
2026-06-22 15:35:12 +08:00

202 lines
8.1 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// ProfileSecondaryPagesTests.swift
// suixinkanTests
//
// Created by Codex on 2026/6/22.
//
import XCTest
@testable import suixinkan
@MainActor
///
final class ProfileSecondaryPagesTests: XCTestCase {
///
func testSettingsVersionTextUsesBuildNumberWhenNeeded() {
XCTAssertEqual(
SettingsDisplayPolicy.versionText(infoDictionary: [
"CFBundleShortVersionString": "1.2",
"CFBundleVersion": "45"
]),
"1.2.45"
)
XCTAssertEqual(
SettingsDisplayPolicy.versionText(infoDictionary: [
"CFBundleShortVersionString": "1.2.3",
"CFBundleVersion": "45"
]),
"1.2.3"
)
XCTAssertEqual(SettingsDisplayPolicy.versionText(infoDictionary: nil), "1.0.0")
}
/// H5
func testAgreementPagesUseExpectedPaths() {
let pages: [(AgreementPage, String, String)] = [
(.about, "关于我们", "/h5/app/about-us"),
(.userAgreement, "用户协议", "/h5/app/user-agreement"),
(.privacyPolicy, "隐私政策", "/h5/app/privacy-policy"),
(.walletUserNotice, "钱包用户须知", "/h5/app/wallet-user-notice"),
(.walletPrivacy, "钱包隐私政策", "/h5/app/wallet-privacy")
]
for (page, title, path) in pages {
XCTAssertEqual(page.title, title)
XCTAssertEqual(page.id, title)
XCTAssertEqual(page.url.path, path)
}
}
/// 使 v9 accounts
func testSwitchableAccountsUsesExpectedEndpoint() async throws {
let session = ProfileSecondaryURLSession(responses: [
try TestFixture.data(named: "v9_login_multi_success")
])
let api = ProfileAPI(client: APIClient(session: session))
let response = try await api.switchableAccounts()
XCTAssertEqual(response.accounts.count, 2)
let request = try XCTUnwrap(session.requests.first)
XCTAssertEqual(request.httpMethod, "GET")
XCTAssertEqual(request.url?.path, "/api/app/v9/accounts")
}
/// ViewModel
func testAccountSwitchViewModelLoadsAccounts() async throws {
let session = ProfileSecondaryURLSession(responses: [
try TestFixture.data(named: "v9_login_multi_success")
])
let api = ProfileAPI(client: APIClient(session: session))
let viewModel = AccountSwitchViewModel()
try await viewModel.load(api: api)
XCTAssertEqual(viewModel.accounts.map(\.businessUserId), [101, 201])
XCTAssertEqual(viewModel.selectedAccount?.businessUserId, 101)
XCTAssertFalse(viewModel.loading)
}
/// 使 set-user
func testAccountSwitchViewModelSubmitsSetUser() async throws {
let session = ProfileSecondaryURLSession(responses: [
try TestFixture.data(named: "v9_set_store_user_success")
])
let api = AuthAPI(client: APIClient(session: session))
let account = AccountSwitchAccount(
accountType: V9StoreUser.accountTypeValue,
businessUserId: 201,
title: "示例门店",
subtitle: "示例景区",
phone: "13800138000",
avatar: "",
scenicName: "示例景区",
storeId: 20,
storeName: "示例门店",
scenicId: 10,
isCurrent: false
)
let viewModel = AccountSwitchViewModel()
let response = try await viewModel.switchAccount(account, api: api)
XCTAssertFalse(response.token.isEmpty)
let request = try XCTUnwrap(session.requests.first)
XCTAssertEqual(request.httpMethod, "POST")
XCTAssertEqual(request.url?.path, "/api/app/v9/set-user")
let json = try XCTUnwrap(JSONSerialization.jsonObject(with: XCTUnwrap(request.httpBody)) as? [String: Any])
XCTAssertEqual(json["store_user_id"] as? Int, 201)
XCTAssertNil(json["ss_user_id"] as? Int)
}
///
func testRealNameInfoDecodesLossyFields() async throws {
let session = ProfileSecondaryURLSession(responses: [
try TestFixture.data(named: "real_name_info_success")
])
let api = ProfileAPI(client: APIClient(session: session))
let response = try await api.realNameInfo()
let info = try XCTUnwrap(response.realNameInfo)
XCTAssertEqual(info.realName, "测试摄影师")
XCTAssertEqual(info.idCardNo, "320100********0012")
XCTAssertTrue(info.verified)
XCTAssertFalse(info.isLongValid)
XCTAssertEqual(info.auditStatus, 2)
XCTAssertEqual(info.auditorId, 7)
XCTAssertEqual(info.auditor?.name, "审核员")
XCTAssertEqual(session.requests.first?.url?.path, "/api/yf-handset-app/photog/real-name/info")
}
///
func testRealNameSmsAndSubmitUseExpectedEndpoints() async throws {
let session = ProfileSecondaryURLSession(responses: [
try TestFixture.data(named: "empty_success"),
try TestFixture.data(named: "empty_success")
])
let api = ProfileAPI(client: APIClient(session: session))
try await api.realNameSmsVerifyCode()
try await api.realNameSubmit(
RealNameAuthRequest(
realName: "测试摄影师",
idCardNo: "11010519491231002X",
smsVerifyCode: "123456",
startDate: "2026-01-01",
endDate: "2046-01-01",
isLongValid: 0,
frontUrl: "https://cdn.example.com/front.jpg",
backUrl: "https://cdn.example.com/back.jpg"
)
)
XCTAssertEqual(session.requests.map { $0.url?.path }, [
"/api/yf-handset-app/photog/real-name/sms-verify-code",
"/api/yf-handset-app/photog/real-name/submit"
])
let json = try XCTUnwrap(JSONSerialization.jsonObject(with: XCTUnwrap(session.requests.last?.httpBody)) as? [String: Any])
XCTAssertEqual(json["real_name"] as? String, "测试摄影师")
XCTAssertEqual(json["id_card_no"] as? String, "11010519491231002X")
XCTAssertEqual(json["sms_verify_code"] as? String, "123456")
XCTAssertEqual(json["is_long_valid"] as? Int, 0)
}
///
func testRealNameIDCardValidation() {
XCTAssertTrue(RealNameAuthViewModel.isValidMainlandIDCardNumber("11010519491231002x"))
XCTAssertEqual(RealNameAuthViewModel.normalizedIDCardNumber(" 11010519491231002x "), "11010519491231002X")
XCTAssertFalse(RealNameAuthViewModel.isValidMainlandIDCardNumber("110105194912310021"))
XCTAssertFalse(RealNameAuthViewModel.isValidMainlandIDCardNumber("123"))
}
/// URI
func testHomeSystemSettingsRouteResolvesToSettingsPage() {
XCTAssertEqual(
HomeMenuRouter.resolve(uri: "system_settings", title: "设置中心"),
.destination(.settings)
)
}
}
/// URLSession
private final class ProfileSecondaryURLSession: URLSessionProtocol {
private var responses: [Data]
private(set) var requests: [URLRequest] = []
///
init(responses: [Data]) {
self.responses = responses
}
///
func data(for request: URLRequest) async throws -> (Data, URLResponse) {
requests.append(request)
let data = responses.isEmpty ? Data() : responses.removeFirst()
return (
data,
HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: nil, headerFields: nil)!
)
}
}