Jsdom: рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдЗрддрд┐рд╣рд╛рд╕ pushState/onpopstate/window.location рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдкреНрд░рдмрдВрдзрд┐рдд рдирд╣реАрдВ рд╣реИ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 17 рдЬреБрд▓ре░ 2016  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: jsdom/jsdom

рдирдорд╕реНрддреЗ,

рдореИрдВ рдХрд╣реВрдВрдЧрд╛ рдХрд┐ рдЗрддрд┐рд╣рд╛рд╕ рдкреНрд░рдмрдВрдзрди рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИред
рдореЗрд░реА рддрд░рдл рд╕реЗ рдпрд╣ рдкрд░реАрдХреНрд╖рдг jsdom рд╕рдВрд╕реНрдХрд░рдг 9.4.1 рдХреЗ рд╕рд╛рде рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ:

    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
        });
    });

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдХреЛрдИ рднреА рд╡реНрдпрдХреНрддрд┐ рдЬреЛ рдЗрд╕ рдкреЛрд╕реНрдЯ рдХреЛ рдвреВрдВрдврддрд╛ рд╣реИ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдп рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рдЙрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╕рдорд╛рдзрд╛рди рд╕рд┐рдиреЙрди spy рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИ рдФрд░ history.pushState рдпрд╛ history.replaceState рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдордЬрд╝рд╛рдХ рдЙрдбрд╝рд╛ рд░рд╣рд╛ рд╣реИред

рд╕рднреА 4 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рд╣рд╛рдВред jsdom рдЕрднреА рддрдХ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдореЗрдВ рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирдИ рд╡рд┐рдВрдбреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдирд╛ рд╢рд╛рдорд┐рд▓ рд╣реИред рдпрд╣ рдПрдХ рдХрдард┐рди рджреАрд░реНрдШрдХрд╛рд▓рд┐рдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдордиреЗ рд╕рдВрдмреЛрдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрдирд╛ рд╢реБрд░реВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИред

рдХреЛрдИ рднреА рд╡реНрдпрдХреНрддрд┐ рдЬреЛ рдЗрд╕ рдкреЛрд╕реНрдЯ рдХреЛ рдвреВрдВрдврддрд╛ рд╣реИ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдп рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рдЙрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╕рдорд╛рдзрд╛рди рд╕рд┐рдиреЙрди spy рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИ рдФрд░ history.pushState рдпрд╛ history.replaceState рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдордЬрд╝рд╛рдХ рдЙрдбрд╝рд╛ рд░рд╣рд╛ рд╣реИред

@ crobinson42 рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдореИрдВ рдЖрдкрдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди window.onpopstate рдХреЗ рд╕рд╛рде рднреА рдорджрдж рдХрд╛ рдордЬрд╝рд╛рдХ рдЙрдбрд╝рд╛рдПрдЧрд╛?

рдореЗрд░реЗ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдиреЗ рд╡рд╛рд▓рд╛ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдпрд╣рд╛рдВ рд╣реИ (рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ):

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);
}
рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

drewish picture drewish  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

jacekpl picture jacekpl  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

eszthoff picture eszthoff  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

khalyomede picture khalyomede  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

machineghost picture machineghost  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ