From cd03e3d0488e06616d5129cb0d38dc8db950fce5 Mon Sep 17 00:00:00 2001 From: Spiros Raptis Date: Fri, 20 Feb 2026 18:44:27 +0200 Subject: [PATCH 1/4] Ignore cancelled OpenAI dashboard navigations --- .../OpenAIDashboardNavigationDelegate.swift | 11 +++++++++++ ...penAIDashboardNavigationDelegateTests.swift | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 Tests/CodexBarTests/OpenAIDashboardNavigationDelegateTests.swift diff --git a/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift b/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift index 0bf4e24b8..56b821865 100644 --- a/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift +++ b/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift @@ -19,13 +19,24 @@ final class NavigationDelegate: NSObject, WKNavigationDelegate { } func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { + if Self.shouldIgnoreNavigationError(error) { + return + } self.completeOnce(.failure(error)) } func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { + if Self.shouldIgnoreNavigationError(error) { + return + } self.completeOnce(.failure(error)) } + static func shouldIgnoreNavigationError(_ error: Error) -> Bool { + let nsError = error as NSError + return nsError.domain == NSURLErrorDomain && nsError.code == NSURLErrorCancelled + } + private func completeOnce(_ result: Result) { guard !self.hasCompleted else { return } self.hasCompleted = true diff --git a/Tests/CodexBarTests/OpenAIDashboardNavigationDelegateTests.swift b/Tests/CodexBarTests/OpenAIDashboardNavigationDelegateTests.swift new file mode 100644 index 000000000..09bdd0553 --- /dev/null +++ b/Tests/CodexBarTests/OpenAIDashboardNavigationDelegateTests.swift @@ -0,0 +1,18 @@ +import Foundation +import Testing +@testable import CodexBarCore + +@Suite +struct OpenAIDashboardNavigationDelegateTests { + @Test("ignores NSURLErrorCancelled") + func ignoresCancelledNavigationError() { + let error = NSError(domain: NSURLErrorDomain, code: NSURLErrorCancelled) + #expect(NavigationDelegate.shouldIgnoreNavigationError(error)) + } + + @Test("does not ignore non-cancelled URL errors") + func doesNotIgnoreOtherURLErrors() { + let error = NSError(domain: NSURLErrorDomain, code: NSURLErrorTimedOut) + #expect(!NavigationDelegate.shouldIgnoreNavigationError(error)) + } +} From 7e495989c6341532ee879e30b1b5ceb003e17f1a Mon Sep 17 00:00:00 2001 From: Spiros Raptis Date: Fri, 20 Feb 2026 18:46:42 +0200 Subject: [PATCH 2/4] Trigger CI From f91f13a70a4d7540c5fd2a52db1199bd61433601 Mon Sep 17 00:00:00 2001 From: Spiros Raptis Date: Fri, 20 Feb 2026 18:51:37 +0200 Subject: [PATCH 3/4] Mark navigation error helper nonisolated --- .../OpenAIWeb/OpenAIDashboardNavigationDelegate.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift b/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift index 56b821865..e9f6e88e7 100644 --- a/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift +++ b/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift @@ -32,7 +32,7 @@ final class NavigationDelegate: NSObject, WKNavigationDelegate { self.completeOnce(.failure(error)) } - static func shouldIgnoreNavigationError(_ error: Error) -> Bool { + nonisolated static func shouldIgnoreNavigationError(_ error: Error) -> Bool { let nsError = error as NSError return nsError.domain == NSURLErrorDomain && nsError.code == NSURLErrorCancelled } From 375de2247b6098ee76cb3a8f9f50fc64b356e760 Mon Sep 17 00:00:00 2001 From: Spiros Raptis Date: Fri, 20 Feb 2026 19:17:31 +0200 Subject: [PATCH 4/4] Complete continuation on ignored cancelled navigation --- .../OpenAIDashboardNavigationDelegate.swift | 2 ++ ...penAIDashboardNavigationDelegateTests.swift | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift b/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift index e9f6e88e7..52ff42ecb 100644 --- a/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift +++ b/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift @@ -20,6 +20,7 @@ final class NavigationDelegate: NSObject, WKNavigationDelegate { func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { if Self.shouldIgnoreNavigationError(error) { + self.completeOnce(.success(())) return } self.completeOnce(.failure(error)) @@ -27,6 +28,7 @@ final class NavigationDelegate: NSObject, WKNavigationDelegate { func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { if Self.shouldIgnoreNavigationError(error) { + self.completeOnce(.success(())) return } self.completeOnce(.failure(error)) diff --git a/Tests/CodexBarTests/OpenAIDashboardNavigationDelegateTests.swift b/Tests/CodexBarTests/OpenAIDashboardNavigationDelegateTests.swift index 09bdd0553..0f27055f3 100644 --- a/Tests/CodexBarTests/OpenAIDashboardNavigationDelegateTests.swift +++ b/Tests/CodexBarTests/OpenAIDashboardNavigationDelegateTests.swift @@ -1,5 +1,6 @@ import Foundation import Testing +import WebKit @testable import CodexBarCore @Suite @@ -15,4 +16,21 @@ struct OpenAIDashboardNavigationDelegateTests { let error = NSError(domain: NSURLErrorDomain, code: NSURLErrorTimedOut) #expect(!NavigationDelegate.shouldIgnoreNavigationError(error)) } + + @MainActor + @Test("cancelled failures complete with success") + func cancelledFailureCompletesWithSuccess() { + let webView = WKWebView() + var result: Result? + let delegate = NavigationDelegate { result = $0 } + + delegate.webView(webView, didFail: nil, withError: NSError(domain: NSURLErrorDomain, code: NSURLErrorCancelled)) + + switch result { + case .success?: + #expect(Bool(true)) + default: + #expect(Bool(false)) + } + } }