Files
suixinkan_uikit/suixinkanTests/HomeLocationStateStoreTests.swift
汉秋 005349f8e6 模块化 AppStore 并完善素材管理与个人空间设置。
将会话、权限、位置、收款与排队存储拆分为独立模块,同步更新各 ViewModel 与单元测试,并补充素材管理 UI 与个人空间设置交互。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-13 11:01:08 +08:00

152 lines
5.4 KiB
Swift

//
// HomeLocationStateStoreTests.swift
// suixinkanTests
//
import XCTest
@testable import suixinkan
/// 线
final class HomeLocationStateStoreTests: XCTestCase {
private var appStore: AppStore!
private var defaults: UserDefaults!
override func setUp() {
defaults = UserDefaults(suiteName: "HomeLocationStateStoreTests")!
defaults.removePersistentDomain(forName: "HomeLocationStateStoreTests")
appStore = AppStore(defaults: defaults)
appStore.session.userId = "1001"
appStore.session.accountType = .scenicUser
}
override func tearDown() {
appStore.logout()
super.tearDown()
}
func testExpiredOnlineSessionIsClearedOnRestore() {
let expiredTimestamp = Int64(Date().timeIntervalSince1970 * 1000) - HomeLocationStateStore.onlineDurationMillis - 1_000
appStore.location.onlineStatus = true
appStore.location.lastReportTime = expiredTimestamp
let stateStore = HomeLocationStateStore(store: appStore)
stateStore.restoreStateIfNeeded()
XCTAssertFalse(stateStore.isOnline)
XCTAssertFalse(appStore.location.onlineStatus)
XCTAssertEqual(appStore.location.lastReportTime, 0)
}
func testActiveOnlineSessionRestoresCountdown() {
let recentTimestamp = Int64(Date().timeIntervalSince1970 * 1000) - 60_000
appStore.location.onlineStatus = true
appStore.location.lastReportTime = recentTimestamp
let stateStore = HomeLocationStateStore(store: appStore)
stateStore.restoreStateIfNeeded()
XCTAssertTrue(stateStore.isOnline)
XCTAssertGreaterThan(stateStore.nextReportCountdownSeconds, 0)
}
func testFormattedCountdownText() {
let stateStore = HomeLocationStateStore(store: appStore)
XCTAssertEqual(stateStore.formattedCountdown(from: 3661), "01:01:01")
}
func testShouldTriggerTimeoutReminderWithinWindow() {
appStore.location.reminderMinutes = 10
let stateStore = HomeLocationStateStore(store: appStore)
stateStore.startLocationReport(at: Int64(Date().timeIntervalSince1970 * 1000))
stateStore.updateReminderMinutes(10)
// Force countdown into reminder window via reflection of internal state is not available;
// verify helper with manual expectation on threshold logic.
XCTAssertFalse(stateStore.shouldTriggerTimeoutReminder())
}
func testMultipleObserversReceiveStateChanges() {
let stateStore = HomeLocationStateStore(store: appStore)
let firstOwner = StateObserverOwner()
let secondOwner = StateObserverOwner()
var firstChangeCount = 0
var secondChangeCount = 0
stateStore.observe(firstOwner) { firstChangeCount += 1 }
stateStore.observe(secondOwner) { secondChangeCount += 1 }
stateStore.updateReminderMinutes(5)
XCTAssertEqual(firstChangeCount, 1)
XCTAssertEqual(secondChangeCount, 1)
stateStore.removeObserver(firstOwner)
stateStore.updateReminderMinutes(10)
XCTAssertEqual(firstChangeCount, 1)
XCTAssertEqual(secondChangeCount, 2)
}
func testViewModelsShareReminderMinutesWhenUsingSameStateStore() {
let stateStore = HomeLocationStateStore(store: appStore)
let homeViewModel = HomeViewModel(appStore: appStore, locationStateStore: stateStore)
let reportViewModel = LocationReportViewModel(
locationStateStore: stateStore,
locationProvider: MockLocationProvider()
)
homeViewModel.updateReminderMinutes(15)
XCTAssertEqual(reportViewModel.reminderMinutes, 15)
reportViewModel.updateReminderMinutes(5)
XCTAssertEqual(homeViewModel.reminderMinutes, 5)
}
func testViewModelsShareOnlineStateWhenUsingSameStateStore() {
let stateStore = HomeLocationStateStore(store: appStore)
let homeViewModel = HomeViewModel(appStore: appStore, locationStateStore: stateStore)
let reportViewModel = LocationReportViewModel(
locationStateStore: stateStore,
locationProvider: MockLocationProvider()
)
stateStore.startLocationReport(at: Int64(Date().timeIntervalSince1970 * 1000))
XCTAssertTrue(homeViewModel.isOnline)
XCTAssertTrue(reportViewModel.isOnline)
XCTAssertGreaterThan(stateStore.nextReportCountdownSeconds, 0)
stateStore.updateOnlineStatus(false)
XCTAssertFalse(homeViewModel.isOnline)
XCTAssertFalse(reportViewModel.isOnline)
}
func testRestoreClearsOnlineStateWhenStoredLastReportTimeIsMissing() {
appStore.location.onlineStatus = true
appStore.location.lastReportTime = 0
let stateStore = HomeLocationStateStore(store: appStore)
stateStore.restoreStateIfNeeded()
XCTAssertFalse(stateStore.isOnline)
XCTAssertFalse(appStore.location.onlineStatus)
XCTAssertEqual(appStore.location.lastReportTime, 0)
XCTAssertEqual(stateStore.nextReportCountdownSeconds, 0)
}
func testRestoreClearsRuntimeStateWhenPersistedOffline() {
let stateStore = HomeLocationStateStore(store: appStore)
stateStore.startLocationReport(at: Int64(Date().timeIntervalSince1970 * 1000))
appStore.location.onlineStatus = false
stateStore.restoreStateIfNeeded()
XCTAssertFalse(stateStore.isOnline)
XCTAssertEqual(stateStore.nextReportCountdownSeconds, 0)
}
}
private final class StateObserverOwner {}