补充 Auth/Tasks/ScenicPermission/Live 单元测试,并完善 UI Test 登录与会话稳定性。

移除 LoginViewModel 硬编码账号,扩展登录流程测试覆盖;调整 ZLoginSmokeUITests 执行顺序与路由直达逻辑,避免清空 Keychain 影响其它用例。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 12:44:10 +08:00
parent aac8458b04
commit d27438b264
17 changed files with 1104 additions and 36 deletions

View File

@ -293,6 +293,90 @@ final class LiveViewModelTests: XCTestCase {
await XCTAssertThrowsErrorAsync(try await missingURLViewModel.prepare())
XCTAssertEqual(missingURLViewModel.errorMessage, LivePushReadinessError.missingPushURL.localizedDescription)
}
/// RTMP/FLV HTTP
func testLivePlaybackResolverCandidatePriority() {
let live = LiveEntity(
playUrl: "rtmp://pull.example.com/live/1",
pullUrl: "https://cdn.example.com/live/1.flv",
hlsUrl: "https://cdn.example.com/live/1.m3u8",
liveUrl: "https://cdn.example.com/live/1.mp4"
)
XCTAssertEqual(
LivePlaybackURLResolver.playableURL(from: live)?.absoluteString,
"https://cdn.example.com/live/1.m3u8"
)
XCTAssertEqual(
LivePlaybackURLResolver.playableURL(from: ["rtmp://a", "https://cdn.example.com/fallback.mp4"])?.absoluteString,
"https://cdn.example.com/fallback.mp4"
)
}
/// LiveEntity reload
func testLivePlaybackViewModelLoadLiveEntityAndReload() {
let live = LiveEntity(hlsUrl: "https://cdn.example.com/live/1.m3u8")
let viewModel = LivePlaybackViewModel(live: live)
XCTAssertEqual(viewModel.playableURL?.absoluteString, "https://cdn.example.com/live/1.m3u8")
XCTAssertNotNil(viewModel.player)
viewModel.play()
XCTAssertTrue(viewModel.isPlaying)
viewModel.reload()
XCTAssertFalse(viewModel.isPlaying)
XCTAssertNotNil(viewModel.player)
XCTAssertEqual(viewModel.playableURL?.absoluteString, "https://cdn.example.com/live/1.m3u8")
}
///
func testLivePushReadinessInvalidPushURL() {
let viewModel = LivePushReadinessViewModel(
permissionProvider: LivePermissionMock(camera: .granted, microphone: .granted),
networkMonitor: LiveNetworkMock(state: .wifi),
adapter: LivePushAdapterMock(available: true)
)
viewModel.configure(pushURL: "not-a-valid-url")
XCTAssertEqual(viewModel.errorMessage, LivePushReadinessError.invalidPushURL.localizedDescription)
}
/// SDK preparestartstop dispose
func testLivePushReadinessStartStopAndDispose() async throws {
let permissions = LivePermissionMock(camera: .granted, microphone: .granted)
let network = LiveNetworkMock(state: .wifi)
let adapter = LivePushAdapterMock(available: true)
let viewModel = LivePushReadinessViewModel(permissionProvider: permissions, networkMonitor: network, adapter: adapter)
viewModel.configure(pushURL: "rtmp://push.example.com/live/1")
viewModel.startMonitoring()
await viewModel.refreshPermissions()
try viewModel.runDiagnostics()
try await viewModel.prepare()
try await viewModel.startPush()
XCTAssertTrue(adapter.prepareCalled)
XCTAssertTrue(adapter.startCalled)
XCTAssertTrue(viewModel.running)
XCTAssertTrue(viewModel.prepared)
await viewModel.stopPush()
XCTAssertTrue(adapter.stopCalled)
XCTAssertFalse(viewModel.running)
await viewModel.dispose()
XCTAssertFalse(viewModel.prepared)
}
///
func testLivePushStateDisplayText() {
XCTAssertEqual(LivePushPermissionState.granted.displayText, "已授权")
XCTAssertEqual(LivePushNetworkState.wifi.displayText, "Wi-Fi")
XCTAssertEqual(LivePushNetworkState.unavailable.displayText, "网络不可用")
}
}
@MainActor