Jsdom: Browserverlauf pushState/onpopstate/window.location nicht gut verwaltet

Erstellt am 17. Juli 2016  ·  4Kommentare  ·  Quelle: jsdom/jsdom

Hallo,

Ich würde sagen, dass die Geschichtsverwaltung nicht vollständig ist.
Dieser Test auf meiner Seite schlägt mit jsdom Version 9.4.1 fehl:

    describe('jsdom history management', () => {
        before(() => {
        // Init DOM with a fake document
        // <base> and uri (initial uri) allow to do pushState in jsdom
            jsdom.env({
                html: `
                 <html>
                     <head>
                         <base href="http://localhost:8080/"></base>
                     </head>
                  </html>
                `,
                url: 'http://localhost:8080/',
                done(err, window) {
                    global.window = window;
                    global.document = window.document;
                    window.console = global.console;
                }
            });
        });

        it('location not updated', () => {
            window.history.pushState({}, 'route1', '/route1');
            assert(window.location.pathname === '/route1'); // this test is OK
            window.history.back();
            assert(window.location.pathname === '/'); // this test fails pathname still with value '/route1'
        });

        it('onpopstate not called', () => {
            window.onpopstate = () => { };
            const spy_onpopstate = sinon.spy(window, 'onpopstate');
            window.history.pushState({}, 'route1', '/route1');
            window.history.back();
            window.history.forward();
            assert(spy_onpopstate.called);// this test fails as well
        });
    });

Hilfreichster Kommentar

Eine Problemumgehung für alle, die diesen Beitrag finden und Tests zum Laufen bringen möchten, besteht darin, Sinon spy zu verwenden und die Methoden history.pushState oder history.replaceState zu verspotten.

Alle 4 Kommentare

Jawohl. jsdom unterstützt im Allgemeinen noch keine Navigation, da dazu ein völlig neues Fensterobjekt erstellt werden muss. Dies ist ein schwerwiegendes langfristiges Problem, über dessen Lösung wir noch nicht nachgedacht haben.

Eine Problemumgehung für alle, die diesen Beitrag finden und Tests zum Laufen bringen möchten, besteht darin, Sinon spy zu verwenden und die Methoden history.pushState oder history.replaceState zu verspotten.

@ Crobinson42 nicht sicher, ob ich dich verstehe, aber würde das Spotten auch mit dem window.onpopstate helfen?

Hier ist die Problemumgehung, die ich verwende (TypeScript):

function firePopstateOnRoute(window: DOMWindow): void {
  const { history } = window;
  const originalBack = history.back;
  const originalForwards = history.forward;

  (history as unknown as {__proto__: History})['__proto__'].back = function patchedBack(this: History, ...args: Parameters<History['back']>): void {
    originalBack.apply(this, args);

    window.dispatchEvent(new PopStateEvent('popstate'));
  };

  (history as unknown as {__proto__: History}).__proto__.forward = function patchedForward(this: History, ...args: Parameters<History['forward']>): void {
    originalForwards.apply(this, args);

    window.dispatchEvent(new PopStateEvent('popstate'));
  };
}

export function mockBrowser(): void {
  const jsdom = new JSDOM('');
  const { window } = jsdom;

  firePopstateOnRoute(window);
}
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen