Skip to content

Commit

Permalink
Make WKWebView work again
Browse files Browse the repository at this point in the history
  • Loading branch information
lunij committed Mar 26, 2024
1 parent 71e869e commit 2516698
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 143 deletions.
66 changes: 33 additions & 33 deletions Sources/SnapshotTesting/Common/View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,13 @@
let work = {
if #available(iOS 11.0, macOS 10.13, *) {
inWindow {
guard wkWebView.frame.width != 0, wkWebView.frame.height != 0 else {
callback(Image())
return
}
let configuration = WKSnapshotConfiguration()
if #available(iOS 13, macOS 10.15, *) {
configuration.afterScreenUpdates = false
}
wkWebView.takeSnapshot(with: configuration) { image, _ in
callback(image!)
wkWebView.takeSnapshot(with: nil) { image, error in
guard let image else {
debugPrint("No image taken. Error: \(error.description)")
callback(Image())
return
}
callback(image)
}
}
} else {
Expand Down Expand Up @@ -185,33 +182,26 @@
view: view,
viewController: viewController
)
// NB: Avoid safe area influence.
if config.safeArea == .zero { view.frame.origin = .init(x: offscreen, y: offscreen) }

return
(view.snapshot
?? Async { callback in
addImagesForRenderedViews(view).sequence().run { views in
callback(
renderer(bounds: view.bounds, for: traits).image { ctx in
if drawHierarchyInKeyWindow {
view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
} else {
view.layer.render(in: ctx.cgContext)
}
return Async { callback in
addImagesForRenderedViews(view).sequence().run { views in
callback(
renderer(bounds: view.bounds, for: traits).image { ctx in
if drawHierarchyInKeyWindow {
view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
} else {
view.layer.render(in: ctx.cgContext)
}
)
views.forEach { $0.removeFromSuperview() }
view.frame = initialFrame
}
}).map {
dispose()
return $0
}
)
views.forEach { $0.removeFromSuperview() }
view.frame = initialFrame
}
}.map {
dispose()
return $0
}
}

private let offscreen: CGFloat = 10_000

func renderer(bounds: CGRect, for traits: UITraitCollection) -> UIGraphicsImageRenderer {
let renderer: UIGraphicsImageRenderer
if #available(iOS 11.0, tvOS 11.0, *) {
Expand Down Expand Up @@ -358,3 +348,13 @@ extension Array {
}
}
}

extension Optional {
var description: String {
if let value = self {
return String(describing: value)
} else {
return "nil"
}
}
}
110 changes: 0 additions & 110 deletions Tests/SnapshotTestingTests/SnapshotTestingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1101,27 +1101,6 @@ final class SnapshotTestingTests: XCTestCase {
""".utf8)
}

func testWebView() throws {
#if os(iOS)
XCTExpectFailure("WebView snapshotting needs to be fixed")
#endif
#if os(iOS) || os(macOS)
let fixtureUrl = URL(fileURLWithPath: String(#file), isDirectory: false)
.deletingLastPathComponent()
.appendingPathComponent("__Fixtures__/pointfree.html")
let html = try String(contentsOf: fixtureUrl)
let webView = WKWebView()
webView.loadHTMLString(html, baseURL: nil)
if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
assertSnapshot(
of: webView,
as: .image(size: .init(width: 800, height: 600)),
named: platform
)
}
#endif
}

func testViewWithZeroHeightOrWidth() {
#if os(iOS) || os(tvOS)
var rect = CGRect(x: 0, y: 0, width: 350, height: 0)
Expand Down Expand Up @@ -1152,95 +1131,6 @@ final class SnapshotTestingTests: XCTestCase {
#endif
}

func testEmbeddedWebView() throws {
#if os(iOS)
let label = UILabel()
label.text = "Hello, Blob!"

let fixtureUrl = URL(fileURLWithPath: String(#file), isDirectory: false)
.deletingLastPathComponent()
.appendingPathComponent("__Fixtures__/pointfree.html")
let html = try String(contentsOf: fixtureUrl)
let webView = WKWebView()
webView.loadHTMLString(html, baseURL: nil)
webView.isHidden = true

let stackView = UIStackView(arrangedSubviews: [label, webView])
stackView.axis = .vertical

if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
assertSnapshot(
of: stackView,
as: .image(size: .init(width: 800, height: 600)),
named: platform
)
}
#endif
}

#if os(iOS) || os(macOS)
final class ManipulatingWKWebViewNavigationDelegate: NSObject, WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("document.body.children[0].classList.remove(\"hero\")") // Change layout
}
}
func testWebViewWithManipulatingNavigationDelegate() throws {
#if os(iOS)
XCTExpectFailure("WebView snapshotting needs to be fixed")
#endif
let manipulatingWKWebViewNavigationDelegate = ManipulatingWKWebViewNavigationDelegate()
let webView = WKWebView()
webView.navigationDelegate = manipulatingWKWebViewNavigationDelegate

let fixtureUrl = URL(fileURLWithPath: String(#file), isDirectory: false)
.deletingLastPathComponent()
.appendingPathComponent("__Fixtures__/pointfree.html")
let html = try String(contentsOf: fixtureUrl)
webView.loadHTMLString(html, baseURL: nil)
if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
assertSnapshot(
of: webView,
as: .image(size: .init(width: 800, height: 600)),
named: platform
)
}
_ = manipulatingWKWebViewNavigationDelegate
}

final class CancellingWKWebViewNavigationDelegate: NSObject, WKNavigationDelegate {
func webView(
_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
) {
decisionHandler(.cancel)
}
}

func testWebViewWithCancellingNavigationDelegate() throws {
#if os(iOS)
XCTExpectFailure("WebView snapshotting needs to be fixed")
#endif
let cancellingWKWebViewNavigationDelegate = CancellingWKWebViewNavigationDelegate()
let webView = WKWebView()
webView.navigationDelegate = cancellingWKWebViewNavigationDelegate

let fixtureUrl = URL(fileURLWithPath: String(#file), isDirectory: false)
.deletingLastPathComponent()
.appendingPathComponent("__Fixtures__/pointfree.html")
let html = try String(contentsOf: fixtureUrl)
webView.loadHTMLString(html, baseURL: nil)
if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
assertSnapshot(
of: webView,
as: .image(size: .init(width: 800, height: 600)),
named: platform
)
}
_ = cancellingWKWebViewNavigationDelegate
}
#endif

#if os(iOS)
@available(iOS 13.0, *)
func testSwiftUIView_iOS() {
Expand Down
110 changes: 110 additions & 0 deletions Tests/SnapshotTestingTests/Snapshotting/WKWebViewTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import Foundation
import XCTest

#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

#if canImport(WebKit)
import WebKit
#endif

#if canImport(UIKit)
import UIKit.UIView
#endif

@testable import SnapshotTesting

final class WKWebViewTests: XCTestCase {
override func setUp() {
super.setUp()
diffTool = "ksdiff"
// isRecording = true
}

override func tearDown() {
isRecording = false
super.tearDown()
}

#if os(iOS) || os(macOS)
func testWebView() throws {
let webView = WKWebView()
webView.load(.init(url: .htmlFixture))
assertSnapshot(

Check failure on line 34 in Tests/SnapshotTestingTests/Snapshotting/WKWebViewTests.swift

View workflow job for this annotation

GitHub Actions / iOS 16.4 (Xcode 14.3.1)

testWebView, failed - Snapshot "ios" does not match reference.
of: webView,
as: .image(precision: 0.99, perceptualPrecision: 0.99, size: .init(width: 800, height: 600)),
named: platform
)
}

func testWebViewWithManipulatingNavigationDelegate() throws {
final class ManipulatingWKWebViewNavigationDelegate: NSObject, WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("document.body.children[0].classList.remove(\"hero\")") // Change layout
}
}
let manipulatingWKWebViewNavigationDelegate = ManipulatingWKWebViewNavigationDelegate()
let webView = WKWebView()
webView.navigationDelegate = manipulatingWKWebViewNavigationDelegate
webView.load(.init(url: .htmlFixture))
assertSnapshot(

Check failure on line 51 in Tests/SnapshotTestingTests/Snapshotting/WKWebViewTests.swift

View workflow job for this annotation

GitHub Actions / iOS 16.4 (Xcode 14.3.1)

testWebViewWithManipulatingNavigationDelegate, failed - Snapshot "ios" does not match reference.
of: webView,
as: .image(precision: 0.99, perceptualPrecision: 0.99, size: .init(width: 800, height: 600)),
named: platform
)
_ = manipulatingWKWebViewNavigationDelegate
}

func testWebViewWithCancellingNavigationDelegate() throws {
final class CancellingWKWebViewNavigationDelegate: NSObject, WKNavigationDelegate {
func webView(
_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
) {
decisionHandler(.cancel)
}
}
let cancellingWKWebViewNavigationDelegate = CancellingWKWebViewNavigationDelegate()
let webView = WKWebView()
webView.navigationDelegate = cancellingWKWebViewNavigationDelegate
webView.load(.init(url: .htmlFixture))
assertSnapshot(
of: webView,
as: .image(size: .init(width: 800, height: 600)),
named: platform
)
_ = cancellingWKWebViewNavigationDelegate
}
#endif

#if os(iOS)
func testEmbeddedWebView() throws {
let label = UILabel()
label.text = "Hello, Blob!"

let webView = WKWebView()
webView.load(.init(url: .htmlFixture))
webView.isHidden = true

let stackView = UIStackView(arrangedSubviews: [label, webView])
stackView.axis = .vertical

assertSnapshot(
of: stackView,
as: .image(precision: 0.99, perceptualPrecision: 0.99, size: .init(width: 800, height: 600)),
named: platform
)
}
#endif
}

private extension URL {
static var htmlFixture: URL {
URL(fileURLWithPath: String(#file), isDirectory: false)
.deletingLastPathComponent()
.deletingLastPathComponent()
.appendingPathComponent("__Fixtures__/pointfree.html")
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit 2516698

Please sign in to comment.