Swift Testing for Unit Tests PART 1 (#5119)

* migrated a lot of unit tests to Swift Testing and added a new implementation for deferred fulfillment

more tests migration

Cleaned the code manually to establish some good patterns

more code improvements

some more code improvements

removed empty tests

update project

* more pr suggestions and cleanups

* removed the TestSetup pattern

* fixing claude not reusing tests

* pr suggestion + added indent rule to swiftformat so that we can prevent AIs to change that
This commit is contained in:
Mauro
2026-02-19 16:20:47 +01:00
committed by GitHub
parent fc03e05697
commit 7982aef855
118 changed files with 4630 additions and 4129 deletions
@@ -7,10 +7,12 @@
//
@testable import ElementX
import XCTest
import Foundation
import Testing
@MainActor
class DeactivateAccountScreenViewModelTests: XCTestCase {
@Suite
struct DeactivateAccountScreenViewModelTests {
var clientProxy: ClientProxyMock!
var viewModel: DeactivateAccountScreenViewModelProtocol!
@@ -18,40 +20,34 @@ class DeactivateAccountScreenViewModelTests: XCTestCase {
viewModel.context
}
override func setUpWithError() throws {
init() {
clientProxy = ClientProxyMock(.init())
viewModel = DeactivateAccountScreenViewModel(clientProxy: clientProxy, userIndicatorController: UserIndicatorControllerMock())
}
func testDeactivate() async throws {
@Test
mutating func deactivate() async throws {
try await validateDeactivate(erasingData: false)
}
func testDeactivateAndErase() async throws {
@Test
mutating func deactivateAndErase() async throws {
try await validateDeactivate(erasingData: true)
}
func validateDeactivate(erasingData shouldErase: Bool) async throws {
mutating func validateDeactivate(erasingData shouldErase: Bool) async throws {
let enteredPassword = UUID().uuidString
clientProxy.deactivateAccountPasswordEraseDataClosure = { [weak self] password, eraseData in
guard let self else { return .failure(.sdkError(ClientProxyMockError.generic)) }
clientProxy.deactivateAccountPasswordEraseDataClosure = { [weak clientProxy] password, eraseData in
guard let clientProxy else { return .failure(.sdkError(ClientProxyMockError.generic)) }
if clientProxy.deactivateAccountPasswordEraseDataCallsCount == 1 {
if password != nil {
XCTFail("The password shouldn't be sent first time round.")
}
if eraseData != shouldErase {
XCTFail("The erase parameter is unexpected.")
}
#expect(password == nil, "The password shouldn't be sent first time round.")
#expect(eraseData == shouldErase, "The erase parameter is unexpected.")
return .failure(.sdkError(ClientProxyMockError.generic))
} else {
if password != enteredPassword {
XCTFail("The password should match the user's input on the second call.")
}
if eraseData != shouldErase {
XCTFail("The erase parameter is unexpected.")
}
#expect(password == enteredPassword, "The password should match the user's input on the second call.")
#expect(eraseData == shouldErase, "The erase parameter is unexpected.")
return .success(())
}
}
@@ -59,23 +55,21 @@ class DeactivateAccountScreenViewModelTests: XCTestCase {
context.eraseData = shouldErase
context.password = enteredPassword
XCTAssertNil(context.alertInfo)
#expect(context.alertInfo == nil)
let deferredState = deferFulfillment(context.observe(\.viewState.bindings.alertInfo)) { $0 != nil }
context.send(viewAction: .deactivate)
try await deferredState.fulfill()
guard let confirmationAction = context.alertInfo?.primaryButton.action else {
XCTFail("Couldn't find the confirmation action.")
return
}
let confirmationAction = try #require(context.alertInfo?.primaryButton.action,
"Couldn't find the confirmation action.")
let deferredAction = deferFulfillment(viewModel.actionsPublisher) { $0 == .accountDeactivated }
confirmationAction()
try await deferredAction.fulfill()
XCTAssertEqual(clientProxy.deactivateAccountPasswordEraseDataCallsCount, 2)
XCTAssertEqual(clientProxy.deactivateAccountPasswordEraseDataReceivedArguments?.password, enteredPassword)
XCTAssertEqual(clientProxy.deactivateAccountPasswordEraseDataReceivedArguments?.eraseData, shouldErase)
#expect(clientProxy.deactivateAccountPasswordEraseDataCallsCount == 2)
#expect(clientProxy.deactivateAccountPasswordEraseDataReceivedArguments?.password == enteredPassword)
#expect(clientProxy.deactivateAccountPasswordEraseDataReceivedArguments?.eraseData == shouldErase)
}
}