diff --git a/HammerTests.podspec b/HammerTests.podspec index 1616c0d..b6caaa5 100644 --- a/HammerTests.podspec +++ b/HammerTests.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = "HammerTests" - spec.version = "0.13.3" + spec.version = "0.14.0" spec.summary = "iOS touch and keyboard syntheis library for unit tests." spec.description = "Hammer is a touch and keyboard synthesis library for emulating user interaction events. It enables new ways of triggering UI actions in unit tests, replicating a real world environment as much as possible." spec.homepage = "https://github.com/lyft/Hammer" diff --git a/Sources/Hammer/EventGenerator/EventGenerator.swift b/Sources/Hammer/EventGenerator/EventGenerator.swift index 0e75fea..cbd2e24 100644 --- a/Sources/Hammer/EventGenerator/EventGenerator.swift +++ b/Sources/Hammer/EventGenerator/EventGenerator.swift @@ -59,11 +59,12 @@ public final class EventGenerator { /// Initialize an event generator for a specified UIViewController. /// - /// Event Generator will temporarily create a wrapper UIWindow to send touches. + /// If the view controller's view does not have a window, this will temporarily create a wrapper + /// UIWindow to send touches. /// /// - parameter viewController: The viewController to receive events. public convenience init(viewController: UIViewController) throws { - let window = UIWindow(wrapping: viewController) + let window = viewController.view.window ?? UIWindow(wrapping: viewController) if #available(iOS 13.0, *) { window.backgroundColor = .systemBackground @@ -81,12 +82,17 @@ public final class EventGenerator { /// Initialize an event generator for a specified UIView. /// - /// Event Generator will temporarily create a wrapper UIWindow to send touches. + /// If the view does not have a window, this will temporarily create a wrapper UIWindow to send touches. /// /// - parameter view: The view to receive events. /// - parameter alignment: The wrapping alignment to use. public convenience init(view: UIView, alignment: WrappingAlignment = .center) throws { - try self.init(viewController: UIViewController(wrapping: view, alignment: alignment)) + if let window = view.window { + try self.init(window: window) + } else { + try self.init(viewController: UIViewController(wrapping: view.topLevelView, alignment: alignment)) + } + self.mainView = view } diff --git a/Sources/Hammer/Utilties/HammerError.swift b/Sources/Hammer/Utilties/HammerError.swift index 9add251..64e8529 100644 --- a/Sources/Hammer/Utilties/HammerError.swift +++ b/Sources/Hammer/Utilties/HammerError.swift @@ -72,11 +72,11 @@ extension HammerError: CustomStringConvertible { case .viewIsNotInHierarchy(let view): return "View is not in hierarchy: \(view.shortDescription)" case .viewIsNotVisible(let view): - return "View is not in visible: \(view.shortDescription)" + return "View is not visible: \(view.shortDescription)" case .viewIsNotHittable(let view): - return "View is not in hittable: \(view.shortDescription)" + return "View is not hittable: \(view.shortDescription)" case .pointIsNotHittable(let point): - return "Point is not in hittable: \(point)" + return "Point is not hittable: \(point)" case .unableToFindView(let identifier): return "Unable to find view: \"\(identifier)\"" case .invalidViewType(let identifier, let type, let expected): diff --git a/Sources/Hammer/Utilties/UIKit+Extensions.swift b/Sources/Hammer/Utilties/UIKit+Extensions.swift index 20acdf3..2a1da24 100644 --- a/Sources/Hammer/Utilties/UIKit+Extensions.swift +++ b/Sources/Hammer/Utilties/UIKit+Extensions.swift @@ -76,3 +76,10 @@ extension UIViewController { } } } + +extension UIView { + /// Returns the view at the top level of the view hierarchy. Could be a UIWindow. + var topLevelView: UIView { + return self.superview?.topLevelView ?? self + } +}