title: NSInternalInconsistencyException Completion handler passed to webView:decidePolicyForNavigationAction:decisionHandle was not called
body: <p>I'm running into an issue with one of our iOS app tests. Any help to solve is much appreciated!</p>
  
  <p>Test code:</p>
  
  <pre><code>    func testOpenExternalBrowser_for_valid_urls() {
      // Given
      let vc = MockDashboardViewController()
      vc.openInternalBrowserCalled = false
      vc.openExternalBrowserCalled = false
      vc.webview = WKWebView()
      vc.webview.navigationDelegate = vc
  
      // When
      let url = URL.init(string: "https://example.com/restOfUrl")
      XCTAssertTrue(url!.absoluteString.contains("https://example.com"), "initial url string is wrong")
      vc.webview.load(URLRequest(url: url!));
      waitSeconds(duration: 2)
  
      // Then
      XCTAssertFalse(vc.openExternalBrowserCalled, "openExternalBrowserCalled value is wrong")
      XCTAssertTrue(vc.openInternalBrowserCalled, "openInternalBrowserCalled value is wrong")
  }
  </code></pre>
  
  <p>This gives me the error:</p>
  
  <blockquote>
    <p>error: -[Tests.ViewControllerTests testOpenExternalBrowser_for_valid_urls] : failed: caught
    "NSInternalInconsistencyException", "Completion handler passed to
    -[ViewController webView:decidePolicyForNavigationAction:decisionHandler:] was not
    called"</p>
  </blockquote>
  
  <p>This is the relevant WKWebKit ViewController code:</p>
  
  <pre><code>    // MARK: WKNavigationDelegate methods
  func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -&gt; Void) {
      guard let url = navigationAction.request.url, let urlScheme = url.scheme, let urlHost = url.host else {
          //if we can't convert the URL, deny the action
          decisionHandler(WKNavigationActionPolicy.cancel);
          return;
      }
  
      var isPortValid = false;
      if let urlPort = url.port {
          isPortValid = urlPort == HostDefinitions.PORT;
      } else {
          isPortValid = urlScheme == DashboardConstants.HTTPS;
      }
  
      if(isPortValid &amp;&amp; urlScheme == HostDefinitions.SCHEME &amp;&amp; urlHost.compare(HostDefinitions.HOST) == ComparisonResult.orderedSame) {
          openInternalBrowser(url: url, decisionHandler: decisionHandler)
          return;
      }
  
      decisionHandler(WKNavigationActionPolicy.cancel);
      openExternalBrowser(url: url)
  }
  
  func openInternalBrowser(url: URL, decisionHandler:@escaping (WKNavigationActionPolicy) -&gt; Void) {
      if(url.path == PathDefinitions.Login) {
          //the user has logged out or visited the login page. We will now de-auth them and direct them back to the login page
          OperationQueue.main.addOperation {
              AuthManager.logout()
              _ = self.navigationController?.popToRootViewController(animated: true);
          }
          decisionHandler(WKNavigationActionPolicy.cancel);
      } else {
          decisionHandler(WKNavigationActionPolicy.allow);
      }
  }
  
  func openExternalBrowser(url: URL) {
      AppManager.openExternalBrowser(url: url)
  }
  </code></pre>
  
  <p>Any ideas? I've tried adding a return statement and adding the decision handler to the function openExternalBrowser but neither work. The app functions properly (opening external URLs in Safari) but the test fails.</p>
  
  <p>Thank you!</p>
  
  <p><strong>Edit:</strong>
  Here's the MockDashboardViewController code:</p>
  
  <pre><code>class MockDashboardViewController: DashboardViewController {
  
      var openInternalBrowserCalled = false
      var openExternalBrowserCalled = false
  
      var presentNotificationCalled = false
  
      var webviewURLString = ""
  
      override func openInternalBrowser(url: URL, decisionHandler:@escaping (WKNavigationActionPolicy) -&gt; Void) {
          openInternalBrowserCalled = true
      }
  
      override func openExternalBrowser(url: URL) {
          openExternalBrowserCalled = true
      }
  
      override func presentNotification(notification: DashboardNotification, showAlertView: Bool) {
          presentNotificationCalled = true
      }
  }
  </code></pre>