diff --git a/Sources/Zero/Views/AppState.swift b/Sources/Zero/Views/AppState.swift index 55f5a18..7c86520 100644 --- a/Sources/Zero/Views/AppState.swift +++ b/Sources/Zero/Views/AppState.swift @@ -500,13 +500,11 @@ class AppState: ObservableObject { case let .runtimeCommandFailed(_, debugDetails) = zeroError { let message = "\(prefix): \(debugDetails)" AppLogStore.shared.append(message) - print(message) return } let message = "\(prefix): \(error)" AppLogStore.shared.append(message) - print(message) } } diff --git a/Tests/ZeroTests/AppStateTests.swift b/Tests/ZeroTests/AppStateTests.swift index 5dfca93..e2d705a 100644 --- a/Tests/ZeroTests/AppStateTests.swift +++ b/Tests/ZeroTests/AppStateTests.swift @@ -1,4 +1,5 @@ import XCTest +import Darwin @testable import Zero @MainActor @@ -12,12 +13,14 @@ class AppStateTests: XCTestCase { try? KeychainHelper.standard.delete(service: "com.zero.ide", account: "github_token") UserDefaults.standard.removeObject(forKey: Constants.Preferences.selectedOrgLogin) UserDefaults.standard.removeObject(forKey: Constants.Preferences.telemetryOptIn) + AppLogStore.shared.clear() appState = AppState() } override func tearDown() { UserDefaults.standard.removeObject(forKey: Constants.Preferences.selectedOrgLogin) UserDefaults.standard.removeObject(forKey: Constants.Preferences.telemetryOptIn) + AppLogStore.shared.clear() appState = nil super.tearDown() } @@ -369,6 +372,41 @@ class AppStateTests: XCTestCase { XCTAssertEqual(appState.userFacingError, "Failed to load repositories. Please check your token and network.") } + func testFetchRepositoriesErrorDoesNotPrintToStdout() async { + // Given + appState.isLoggedIn = true + appState.accessToken = "gho_test_token" + appState.gitHubServiceFactory = { _ in + MockGitHubService(fetchReposError: URLError(.timedOut)) + } + + // When + let stdout = await captureStdout { + await appState.fetchRepositories() + } + + // Then + XCTAssertTrue(stdout.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) + } + + func testFetchRepositoriesErrorStillAppendsToAppLogStore() async { + // Given + appState.isLoggedIn = true + appState.accessToken = "gho_test_token" + appState.gitHubServiceFactory = { _ in + MockGitHubService(fetchReposError: URLError(.timedOut)) + } + + // When + await appState.fetchRepositories() + + // Then + let logEntries = AppLogStore.shared.recentEntries() + XCTAssertTrue(logEntries.contains { entry in + entry.contains("Failed to fetch repos") && entry.contains("NSURLErrorDomain") + }) + } + func testFetchOrganizationsAuthErrorForcesLogoutAndClearsSelection() async { // Given appState.isLoggedIn = true @@ -515,6 +553,26 @@ class AppStateTests: XCTestCase { // Then XCTAssertFalse(reloadedAgain.telemetryOptIn) } + + private func captureStdout(_ operation: () async -> Void) async -> String { + fflush(stdout) + + let outputPipe = Pipe() + let originalStdout = dup(STDOUT_FILENO) + dup2(outputPipe.fileHandleForWriting.fileDescriptor, STDOUT_FILENO) + + await operation() + + fflush(stdout) + dup2(originalStdout, STDOUT_FILENO) + close(originalStdout) + + outputPipe.fileHandleForWriting.closeFile() + let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile() + outputPipe.fileHandleForReading.closeFile() + + return String(data: outputData, encoding: .utf8) ?? "" + } } // MARK: - Mocks