Files
letro-ios/UnitTests/Sources/BugReportScreenViewModelTests.swift
Mauro 173b39a07f 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
2026-02-19 16:20:47 +01:00

140 lines
6.2 KiB
Swift

//
// 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.
//
@testable import ElementX
import Testing
import UIKit
@MainActor
@Suite
struct BugReportScreenViewModelTests {
let logFiles: [URL] = [URL(filePath: "/path/to/file1.log"), URL(filePath: "/path/to/file2.log")]
enum TestError: Error {
case testError
}
@Test
func initialState() {
let clientProxy = ClientProxyMock(.init(userID: "@mock.client.com"))
let viewModel = BugReportScreenViewModel(bugReportService: BugReportServiceMock(),
clientProxy: clientProxy,
logFiles: logFiles,
screenshot: nil,
isModallyPresented: false)
let context = viewModel.context
#expect(context.reportText == "")
#expect(context.viewState.screenshot == nil)
#expect(context.sendingLogsEnabled)
}
@Test
func clearScreenshot() {
let clientProxy = ClientProxyMock(.init(userID: "@mock.client.com"))
let viewModel = BugReportScreenViewModel(bugReportService: BugReportServiceMock(),
clientProxy: clientProxy,
logFiles: logFiles,
screenshot: UIImage.actions,
isModallyPresented: false)
let context = viewModel.context
context.send(viewAction: .removeScreenshot)
#expect(context.viewState.screenshot == nil)
}
@Test
func attachScreenshot() {
let clientProxy = ClientProxyMock(.init(userID: "@mock.client.com"))
let viewModel = BugReportScreenViewModel(bugReportService: BugReportServiceMock(),
clientProxy: clientProxy,
logFiles: logFiles,
screenshot: nil,
isModallyPresented: false)
let context = viewModel.context
#expect(context.viewState.screenshot == nil)
context.send(viewAction: .attachScreenshot(UIImage.actions))
#expect(context.viewState.screenshot == UIImage.actions)
}
@Test
func sendReportWithSuccess() async throws {
let mockService = BugReportServiceMock()
mockService.submitBugReportProgressListenerClosure = { _, _ in
await Task.yield()
return .success(SubmitBugReportResponse(reportURL: "https://test.test"))
}
let clientProxy = ClientProxyMock(.init(userID: "@mock.client.com", deviceID: "ABCDEFGH"))
clientProxy.ed25519Base64ReturnValue = "THEEDKEYKEY"
clientProxy.curve25519Base64ReturnValue = "THECURVEKEYKEY"
let viewModel = BugReportScreenViewModel(bugReportService: mockService,
clientProxy: clientProxy,
logFiles: logFiles,
screenshot: nil,
isModallyPresented: false)
let context = viewModel.context
context.reportText = "This will succeed"
let deferred = deferFulfillment(viewModel.actions) { action in
switch action {
case .submitFinished:
return true
default:
return false
}
}
context.send(viewAction: .submit)
try await deferred.fulfill()
#expect(mockService.submitBugReportProgressListenerCallsCount == 1)
#expect(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.userID == "@mock.client.com")
#expect(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.deviceID == "ABCDEFGH")
#expect(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.curve25519 == "THECURVEKEYKEY")
#expect(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.ed25519 == "THEEDKEYKEY")
#expect(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.text == "This will succeed")
#expect(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.logFiles == logFiles)
#expect(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.canContact == false)
#expect(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.githubLabels == [])
#expect(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.files == [])
}
@Test
func sendReportWithError() async throws {
let mockService = BugReportServiceMock()
mockService.submitBugReportProgressListenerClosure = { _, _ in
.failure(.uploadFailure(TestError.testError))
}
let clientProxy = ClientProxyMock(.init(userID: "@mock.client.com"))
let viewModel = BugReportScreenViewModel(bugReportService: mockService,
clientProxy: clientProxy,
screenshot: nil, isModallyPresented: false)
let context = viewModel.context
context.reportText = "This will fail"
let deferred = deferFulfillment(viewModel.actions) { action in
switch action {
case .submitFailed:
return true
default:
return false
}
}
context.send(viewAction: .submit)
try await deferred.fulfill()
#expect(mockService.submitBugReportProgressListenerCallsCount == 1)
#expect(context.reportText == "This will fail", "The bug report should remain in place so the user can retry.")
#expect(!context.viewState.shouldDisableInteraction, "The user should be able to retry.")
}
}