// // Copyright 2025 Element Creations Ltd. // Copyright 2022-2025 New Vector Ltd. // // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. // Please see LICENSE files in the repository root for full details. // import Combine @testable import ElementX import Testing @MainActor @Suite struct SecureBackupLogoutConfirmationScreenViewModelTests { private var viewModel: SecureBackupLogoutConfirmationScreenViewModel private var context: SecureBackupLogoutConfirmationScreenViewModel.Context { viewModel.context } private var secureBackupController: SecureBackupControllerMock private var reachabilitySubject: CurrentValueSubject init() { secureBackupController = SecureBackupControllerMock() secureBackupController.underlyingKeyBackupState = CurrentValueSubject(.enabled).asCurrentValuePublisher() reachabilitySubject = CurrentValueSubject(.reachable) viewModel = SecureBackupLogoutConfirmationScreenViewModel(secureBackupController: secureBackupController, homeserverReachabilityPublisher: reachabilitySubject.asCurrentValuePublisher()) } @Test func initialState() { #expect(context.viewState.mode == .saveRecoveryKey) } @Test func ongoingState() async throws { #expect(context.viewState.mode == .saveRecoveryKey) try await confirmation { confirmation in secureBackupController.waitForKeyBackupUploadUploadStateSubjectClosure = { stateSubject in try? await Task.sleep(for: .seconds(4)) stateSubject.send(.uploading(uploadedKeyCount: 50, totalKeyCount: 100)) confirmation() return .success(()) } let deferredWaiting = deferFulfillment(context.observe(\.viewState.mode)) { $0 == .waitingToStart(hasStalled: false) } context.send(viewAction: .logout) _ = try await deferredWaiting.fulfill() // Wait for the 2-second timeout. let deferredHasStalled = deferFulfillment(context.observe(\.viewState.mode)) { $0 == .waitingToStart(hasStalled: true) } _ = try await deferredHasStalled.fulfill() try await deferFulfillment(context.observe(\.viewState.mode)) { $0 == .backupOngoing(progress: 0.5) }.fulfill() } } @Test func offlineState() async throws { #expect(context.viewState.mode == .saveRecoveryKey) try await confirmation { confirmation in secureBackupController.waitForKeyBackupUploadUploadStateSubjectClosure = { stateSubject in try? await Task.sleep(for: .seconds(4)) stateSubject.send(.uploading(uploadedKeyCount: 50, totalKeyCount: 100)) confirmation() return .success(()) } let deferredWaiting = deferFulfillment(context.observe(\.viewState.mode)) { $0 == .waitingToStart(hasStalled: false) } context.send(viewAction: .logout) try await deferredWaiting.fulfill() // Wait for the 2-second timeout. let deferredHasStalled = deferFulfillment(context.observe(\.viewState.mode)) { $0 == .waitingToStart(hasStalled: true) } try await deferredHasStalled.fulfill() try await deferFulfillment(context.observe(\.viewState.mode)) { $0 == .backupOngoing(progress: 0.5) }.fulfill() } let deferred = deferFulfillment(context.observe(\.viewState.mode)) { $0 == .offline } reachabilitySubject.send(.unreachable) try await deferred.fulfill() } }