title: How to fix Error: Not implemented: navigation (except hash changes)
body: <p>I am implementing unit test for a file that contain <code>window.location.href</code> and I need to check it.</p>
  
  <p>My jest version is <code>22.0.4</code>. Everything is fine when I run my test on node version >=10</p>
  
  <p>But I get this error when I run it on <code>v8.9.3</code></p>
  
  <pre><code>console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
        Error: Not implemented: navigation (except hash changes)
  </code></pre>
  
  <p>I have no idea about it. I have searched on many page to find out the solution or any hint about this to figure out what happened here.</p>
  
  <p>[UPDATE] - I took a look deep to source code and I think this error is from jsdom.</p>
  
  <pre><code>at module.exports (webapp/node_modules/jsdom/lib/jsdom/browser/not-implemented.js:9:17)
  at navigateFetch (webapp/node_modules/jsdom/lib/jsdom/living/window/navigation.js:74:3)
  </code></pre>
  
  <h2>navigation.js file</h2>
  
  <pre><code>exports.evaluateJavaScriptURL = (window, urlRecord) =&gt; {
    const urlString = whatwgURL.serializeURL(urlRecord);
    const scriptSource = whatwgURL.percentDecode(Buffer.from(urlString)).toString();
    if (window._runScripts === "dangerously") {
      try {
        return window.eval(scriptSource);
      } catch (e) {
        reportException(window, e, urlString);
      }
    }
    return undefined;
  };
  exports.navigate = (window, newURL, flags) =&gt; {
    // This is NOT a spec-compliant implementation of navigation in any way. It implements a few selective steps that
    // are nice for jsdom users, regarding hash changes and JavaScript URLs. Full navigation support is being worked on
    // and will likely require some additional hooks to be implemented.
  
    const document = idlUtils.implForWrapper(window._document);
    const currentURL = document._URL;
  
    if (!flags.reloadTriggered &amp;&amp; urlEquals(currentURL, newURL, { excludeFragments: true })) {
      if (newURL.fragment !== currentURL.fragment) {
        navigateToFragment(window, newURL, flags);
      }
      return;
    }
  
    // NOT IMPLEMENTED: Prompt to unload the active document of browsingContext.
  
    // NOT IMPLEMENTED: form submission algorithm
    // const navigationType = 'other';
  
    // NOT IMPLEMENTED: if resource is a response...
    if (newURL.scheme === "javascript") {
      window.setTimeout(() =&gt; {
        const result = exports.evaluateJavaScriptURL(window, newURL);
        if (typeof result === "string") {
          notImplemented("string results from 'javascript:' URLs", window);
        }
      }, 0);
      return;
    }
    navigateFetch(window);
  };
  </code></pre>
  
  <h2>not-implemented.js</h2>
  
  <pre><code>module.exports = function (nameForErrorMessage, window) {
    if (!window) {
      // Do nothing for window-less documents.
      return;
    }
  
    const error = new Error(`Not implemented: ${nameForErrorMessage}`);
    error.type = "not implemented";
  
    window._virtualConsole.emit("jsdomError", error);
  };
  </code></pre>
  
  <p>I see some weird logics in these file.</p>
  
  <ol>
  <li><code>const scriptSource = whatwgURL.percentDecode(Buffer.from(urlString)).toString();</code></li>
  <li>then check string and return error</li>
  </ol>