Skip to content

Commit cb1c520

Browse files
authored
refactor(app-state): stop printing fetch errors to stdout (#99)
1 parent 9013d63 commit cb1c520

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

Sources/Zero/Views/AppState.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,13 +500,11 @@ class AppState: ObservableObject {
500500
case let .runtimeCommandFailed(_, debugDetails) = zeroError {
501501
let message = "\(prefix): \(debugDetails)"
502502
AppLogStore.shared.append(message)
503-
print(message)
504503
return
505504
}
506505

507506
let message = "\(prefix): \(error)"
508507
AppLogStore.shared.append(message)
509-
print(message)
510508
}
511509
}
512510

Tests/ZeroTests/AppStateTests.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import XCTest
2+
import Darwin
23
@testable import Zero
34

45
@MainActor
@@ -12,12 +13,14 @@ class AppStateTests: XCTestCase {
1213
try? KeychainHelper.standard.delete(service: "com.zero.ide", account: "github_token")
1314
UserDefaults.standard.removeObject(forKey: Constants.Preferences.selectedOrgLogin)
1415
UserDefaults.standard.removeObject(forKey: Constants.Preferences.telemetryOptIn)
16+
AppLogStore.shared.clear()
1517
appState = AppState()
1618
}
1719

1820
override func tearDown() {
1921
UserDefaults.standard.removeObject(forKey: Constants.Preferences.selectedOrgLogin)
2022
UserDefaults.standard.removeObject(forKey: Constants.Preferences.telemetryOptIn)
23+
AppLogStore.shared.clear()
2124
appState = nil
2225
super.tearDown()
2326
}
@@ -369,6 +372,41 @@ class AppStateTests: XCTestCase {
369372
XCTAssertEqual(appState.userFacingError, "Failed to load repositories. Please check your token and network.")
370373
}
371374

375+
func testFetchRepositoriesErrorDoesNotPrintToStdout() async {
376+
// Given
377+
appState.isLoggedIn = true
378+
appState.accessToken = "gho_test_token"
379+
appState.gitHubServiceFactory = { _ in
380+
MockGitHubService(fetchReposError: URLError(.timedOut))
381+
}
382+
383+
// When
384+
let stdout = await captureStdout {
385+
await appState.fetchRepositories()
386+
}
387+
388+
// Then
389+
XCTAssertTrue(stdout.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
390+
}
391+
392+
func testFetchRepositoriesErrorStillAppendsToAppLogStore() async {
393+
// Given
394+
appState.isLoggedIn = true
395+
appState.accessToken = "gho_test_token"
396+
appState.gitHubServiceFactory = { _ in
397+
MockGitHubService(fetchReposError: URLError(.timedOut))
398+
}
399+
400+
// When
401+
await appState.fetchRepositories()
402+
403+
// Then
404+
let logEntries = AppLogStore.shared.recentEntries()
405+
XCTAssertTrue(logEntries.contains { entry in
406+
entry.contains("Failed to fetch repos") && entry.contains("NSURLErrorDomain")
407+
})
408+
}
409+
372410
func testFetchOrganizationsAuthErrorForcesLogoutAndClearsSelection() async {
373411
// Given
374412
appState.isLoggedIn = true
@@ -515,6 +553,26 @@ class AppStateTests: XCTestCase {
515553
// Then
516554
XCTAssertFalse(reloadedAgain.telemetryOptIn)
517555
}
556+
557+
private func captureStdout(_ operation: () async -> Void) async -> String {
558+
fflush(stdout)
559+
560+
let outputPipe = Pipe()
561+
let originalStdout = dup(STDOUT_FILENO)
562+
dup2(outputPipe.fileHandleForWriting.fileDescriptor, STDOUT_FILENO)
563+
564+
await operation()
565+
566+
fflush(stdout)
567+
dup2(originalStdout, STDOUT_FILENO)
568+
close(originalStdout)
569+
570+
outputPipe.fileHandleForWriting.closeFile()
571+
let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
572+
outputPipe.fileHandleForReading.closeFile()
573+
574+
return String(data: outputData, encoding: .utf8) ?? ""
575+
}
518576
}
519577

520578
// MARK: - Mocks

0 commit comments

Comments
 (0)