Jsdom: рддреНрд░реБрдЯрд┐: рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛: рдиреЗрд╡рд┐рдЧреЗрд╢рди

рдХреЛ рдирд┐рд░реНрдорд┐рдд 12 рдЬрдире░ 2018  ┬╖  49рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: jsdom/jsdom

рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдЕрдкрдЧреНрд░реЗрдб рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж jest (рдЬреЛ рдкреГрд╖реНрдарднреВрдорд┐ рдореЗрдВ jsdom рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ) рд╕рдВрд╕реНрдХрд░рдг 21.2.0 рд╕реЗ 22.0.6 рддрдХ рдореБрдЭреЗ рддреНрд░реБрдЯрд┐ рдорд┐рд▓рдиреА рд╢реБрд░реВ рд╣реЛ рдЧрдИ рд╣реИ: "Error: Not implemented:" navigation

рдореЗрд░рд╛ рдХреЛрдб window.location рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдореИрдВ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ:

beforeEach(() => {
                window.location.href = `/ms/submission/?mybib`;
                window.location.search = '?mybib';
});

рдХреНрдпрд╛ jsdom рдХреЗ рдирдП рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ window.location.search рдорд╛рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ?

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

рдореБрдЭреЗ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ рдкреЛрд╕реНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВ
рдореИрдВ рдмрд╕ window.location = url; рдФрд░ window.location.href = url; рдХреЗ рдЙрдкрдпреЛрдЧреЛрдВ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реВрдВ

window.location.assign(url);

рдФрд░ рдлрд┐рд░ рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдореИрдВрдиреЗ рдХрд┐рдпрд╛:

sinon.stub(window.location, 'assign');
expect(window.location.assign).to.have.been.calledWith(url);

рдПрдХ рдЖрдХрд░реНрд╖рдг рдХреА рддрд░рд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ - рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рдФрд░ рдХреА рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ

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

рдореБрдЭреЗ рдпрд╣ рддреНрд░реБрдЯрд┐ рднреА рдорд┐рд▓ рд░рд╣реА рд╣реИ

Error: Not implemented: navigation (except hash changes)
    at module.exports (...\node_modules\jsdom\lib\jsdom\browser\not-implemented.js:9:17)
    at navigateFetch (...\node_modules\jsdom\lib\jsdom\living\window\navigation.js:74:3)

jsdom рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП window.location.href рдпрд╛ рдЗрд╕реА рддрд░рд╣ рдХреА рд╕реЗрдЯрд┐рдВрдЧ рдпрд╣ рд╕рдВрджреЗрд╢ рджреЗрдЧреАред рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЬреЗрд╕реНрдЯ рдкрд╣рд▓реЗ рдЗрди рд╕рдВрджреЗрд╢реЛрдВ рдХреЛ рджрдмрд╛ рд░рд╣рд╛ рдерд╛, рдпрд╛ рдХреНрдпрд╛ред

рдпрд╣ рд╢рд╛рдпрдж рдХреБрдЫ рдРрд╕рд╛ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдареАрдХ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдпрджрд┐ рдЖрдк рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЙрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдЪрд▓рд╛ рд░рд╣реЗ рдереЗ, рддреЛ рдкрд░реАрдХреНрд╖рдг рдзрд╛рд╡рдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЙрдбрд╝ рдЬрд╛рдПрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рдЖрдк рдкреГрд╖реНрда рдХреЛ рдПрдХ рдирдП рдпреВрдЖрд░рдПрд▓ рдкрд░ рдиреЗрд╡рд┐рдЧреЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЖрдк рдХрднреА рднреА рдХреЛрдИ рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рджреЗрдЦреЗрдВрдЧреЗ рдкрд░рд┐рдгрд╛рдоред Jsdom рдореЗрдВ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рд╣рдо рдХреЗрд╡рд▓ рдХрдВрд╕реЛрд▓ рдХреЛ рдПрдХ рд╕рдВрджреЗрд╢ рдЖрдЙрдЯрдкреБрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рдЖрдк рдЪрд╛рд╣реЗрдВ рддреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ рдЖрдк рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдФрд░ рдЕрдзрд┐рдХ рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдмреЗрд╣рддрд░ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдареАрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд╡реИрд╕реЗ рднреА, рдореИрдВ рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдкрд░ рдФрд░ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЦреБрд▓рд╛ рдЫреЛрдбрд╝ рджреВрдВрдЧрд╛ред

рдЖрдк рдЬреЛ рдХрд╣ рд░рд╣реЗ рд╣реИрдВ рдЙрд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдЬреЗрд╕реНрдЯ 22 рдЕрдкрдбреЗрдЯ JSDOM 9 рд╕реЗ 11 IIRC рдкрд░ рдЪрд▓рд╛ рдЧрдпрд╛, рдЗрд╕рд▓рд┐рдП 9.x рдореЗрдВ рд╡рд╛рдкрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд╛рдлреА рднрд┐рдиреНрди рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореИрдВ рдЬреЗрдПрд╕рдбреАрдУрдПрдо рдореЗрдВ рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреЗ рдЭрдВрдбреЗ рдХреЗ рд╕рд╛рде рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд░реВрдВрдЧрд╛ рддрд╛рдХрд┐ рдЗрд╕реЗ рдПрдХ рдЕрд▓рдЧ рдкреЗрдЬ рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдиреЛ-рдСрдк рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХреЗ (рдПрдЪрдЯреАрдПрдордПрд▓ 5 рдкреБрд╢рд╕реНрдЯреЗрдЯ рдХреЗ рд╕рдорд╛рди рднрд╛рд╡рдирд╛ рдореЗрдВред) рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдЖрдорддреМрд░ рдкрд░ рдкрд░реАрдХреНрд╖рдг рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЬрдмрдХрд┐ рд╢рд╛рдпрдж рдПрдХ рд╡рд┐рдЪрд┐рддреНрд░ рдЕрдиреБрд░реЛрдз, рдЗрд╕реЗ рдЕрдХреНрд╕рд░ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рд╣рдореЗрдВ рдРрд╕рд╛ рдзреНрд╡рдЬ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдЖрдкрдХреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ jsdom рдореЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЪрд▓рд╛рдПред рддрдм рдЖрдкрдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рддреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдпрд╣ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдХрд┐рд╕реА рдЕрдиреНрдп рдкреГрд╖реНрда рдкрд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдмрдЬрд╛рдп рдЗрд╕рдХреЗ рдХрд┐ рдЖрдкрдХреЗ рдкрд░реАрдХреНрд╖рдг рд╣реЛ рд░рд╣реЗ рдХреНрд░рд┐рдпрд╛ рдХреЛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП) рдФрд░ рдЖрдк рдиреЛрдЯрд┐рд╕ рднреА рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ!

рдЦреИрд░ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ рд╡рд░реНрддрдорд╛рди рдкреГрд╖реНрда рд╕рдВрджрд░реНрдн рдХреЛ рдЙрддрд╛рд░рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХреБрдЫ рднреА рдЕрд▓рдЧ рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред рдореИрдВ рдЕрднреА рднреА window.location.href рдЕрдкрдбреЗрдЯ рд╣реЛрдиреЗ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реВрдВ, рдЖрджрд┐ред

@domenic рдореБрдЭреЗ рдПрдХ рд╣реА рд╕рдорд╕реНрдпрд╛ рд╣реИ рдФрд░ рдореИрдВ рд╕реЛрдЪ рд░рд╣рд╛ рдерд╛ рдХрд┐ window.location рд╕реЗрдЯ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдРрдк рдХреЗ рд╕рд╛рде JSDOM рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕рд░реНрд╡реЛрддреНрддрдо рдЕрднреНрдпрд╛рд╕ рд╣реИ рдпрд╛ рдирд╣реАрдВред рдореИрдВ рдЬреЛ рдмрддрд╛ рд╕рдХрддрд╛ рд╣реВрдВ рдЙрд╕рд╕реЗ JSDOM window.location рд╕реЗрдЯ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╕рдордп рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХрддрд╛ рд╣реИ рдФрд░ window.location.href рд╕реЗрдЯ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╕рдордп рдПрдХ рддреНрд░реБрдЯрд┐ рд▓реЙрдЧ рдХрд░рддрд╛ рд╣реИ - рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореИрдВ рдПрдордбреАрдПрди рдкрд░ рдкрдврд╝ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рджреЛрдиреЛрдВ рд╕рдорд╛рдирд╛рд░реНрдереА рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдХреНрдпрд╛ рдореБрдЭреЗ рд╕реНрдерд╛рди рдХреЛ рдХрд┐рд╕реА рдЕрдиреНрдп рддрд░реАрдХреЗ рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рд╕реНрдЯрдм рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реЛ?
рдорджрдж рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж

рдореБрдЭреЗ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ рдкреЛрд╕реНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВ
рдореИрдВ рдмрд╕ window.location = url; рдФрд░ window.location.href = url; рдХреЗ рдЙрдкрдпреЛрдЧреЛрдВ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реВрдВ

window.location.assign(url);

рдФрд░ рдлрд┐рд░ рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдореИрдВрдиреЗ рдХрд┐рдпрд╛:

sinon.stub(window.location, 'assign');
expect(window.location.assign).to.have.been.calledWith(url);

рдПрдХ рдЖрдХрд░реНрд╖рдг рдХреА рддрд░рд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ - рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рдФрд░ рдХреА рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ

рд╕рд╣рдордд рд╣реВрдВ рдХрд┐ рдпрд╣ рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдо FB рдкрд░ window.location рдордЬрд╝рд╛рдХ рдЙрдбрд╝рд╛рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ jsdom рдХреЗ History рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рд╛рде рд╡рд┐рд░реЛрдз рдХрд░рддрд╛ рд╣реИред

рдПрдХ рдЫреЛрдЯреА рдЯреАрдо рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдо рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЙрди рдмрдбрд╝реА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рд╕реЗ рдорджрдж рдХреА рд╕рд░рд╛рд╣рдирд╛ рдХрд░реЗрдВрдЧреЗ рдЬреЛ jsdom рдореЗрдВ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЛ рдареАрдХ рд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо рдкрд░ рдирд┐рд░реНрднрд░ рд╣реИрдВред

рдЕрдЧрд░ рдХрд┐рд╕реА рдХреЛ рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реИ, рддреЛ https://github.com/jsdom/jsdom/pull/1913 рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдЪреНрдЫреА рдЬрдЧрд╣ рд╣реЛ рд╕рдХрддреА рд╣реИред

рд╕рдВрднрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди рдЗрдХрд╛рдИ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ window рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрднрд░рддрд╛ рдЗрдВрдЬреЗрдХреНрд╢рди/рдирдХрд▓реА рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░рдирд╛ рд╣реИред

рдХреБрдЫ рдЗрд╕ рддрд░рд╣:

it('can test', () => {
  const mockWindow = {location: {href: null}};
  fn({window: mockWindow});
  expect(mockWindow.href).toEqual('something');
});

рдпрд╣ рдЖрджрд░реНрд╢ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЬреИрд╕рд╛ рдХрд┐ @domenic рдиреЗ рдХрд╣рд╛ рд╣реИ:

рдпрд╣ рд╢рд╛рдпрдж рдХреБрдЫ рдРрд╕рд╛ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдареАрдХ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдпрджрд┐ рдЖрдк рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЙрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдЪрд▓рд╛ рд░рд╣реЗ рдереЗ, рддреЛ рдкрд░реАрдХреНрд╖рдг рдзрд╛рд╡рдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЙрдбрд╝ рдЬрд╛рдПрдЧрд╛ рдЬрдм рдЖрдк рдкреГрд╖реНрда рдХреЛ рдПрдХ рдирдП рдпреВрдЖрд░рдПрд▓ рдкрд░ рдиреЗрд╡рд┐рдЧреЗрдЯ рдХрд░реЗрдВрдЧреЗред

рдЕрднреА рдХреЗ рд▓рд┐рдП рд╣рдо рдЗрд╕рдХреЗ рд╕рд╛рде рд░рд╣рддреЗ рд╣реИрдВ рдФрд░ рд╣рд╛рдБ рд╣рдо рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдкрдирд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛрдб рдмрджрд▓рддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рдмреБрд░рд╛ рдЕрднреНрдпрд╛рд╕ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рд╣рдо рд░рд╛рдд рдореЗрдВ рднреА рдЕрдЪреНрдЫреА рдиреАрдВрдж рд▓реЗрддреЗ рд╣реИрдВ!

рд╣реИрдкреНрдкреА рдЯреЗрд╕реНрдЯрд┐рдВрдЧ

@hontas рдХреЗ рд╕рдорд╛рдзрд╛рди рдиреЗ рдорджрдж рдХреА:

рдореИрдВрдиреЗ рдЕрдкрдиреЗ рдХреЛрдб рдореЗрдВ window.location.assign(Config.BASE_URL); рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛ред

рдФрд░ рдпрд╣рд╛рдБ рдкрд░реАрдХреНрд╖рдг рд╣реИ:

jest.spyOn(window.location, 'assign').mockImplementation( l => {
   expect(l).toEqual(Config.BASE_URL);
})

window.location.assign.mockClear();

рд╡рд╣реА рд╕рдорд╕реНрдпрд╛, рдореИрдВ рдЕрдкрдиреЗ рдХреЛрдб рдореЗрдВ window.location.search = foo; рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдореИрдВ рдЗрд╕реЗ jsdom (рдФрд░ рдЬреЗрд╕реНрдЯ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ

рдкреБрдирд╢реНрдЪ: рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд https://github.com/facebook/jest/issues/5266

Jsdom 12.2.0 рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рддреНрд░реБрдЯрд┐ рдорд┐рд▓реА:
рд▓реЗрдЦрди рддреНрд░реБрдЯрд┐: рд╕рдВрдкрддреНрддрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛: рдЕрд╕рд╛рдЗрди рдХрд░реЗрдВ
const assign = sinon.stub(document.location, 'assign')
рдЗрд╕реЗ рдХреИрд╕реЗ рдЬреЛрдбрд╝реЗрдВрдЧреЗ?

@ рдпреВрд░реА-рд╕рдЦрд╛рд░реЛрд╡

Jsdom 12.2.0 рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рддреНрд░реБрдЯрд┐ рдорд┐рд▓реА:
рд▓реЗрдЦрди рддреНрд░реБрдЯрд┐: рд╕рдВрдкрддреНрддрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛: рдЕрд╕рд╛рдЗрди рдХрд░реЗрдВ
const assign = sinon.stub(document.location, 'assign')
рдЗрд╕реЗ рдХреИрд╕реЗ рдЬреЛрдбрд╝реЗрдВрдЧреЗ?

sinon.stub(document.location, 'assign')

рд╣реЛрдиреЗ рдХреА рдЬрд░реВрд░рдд:

sinon.stub(window.location, 'assign')

рдЖрдкрдХреЛ document рдХреЛ window рд╕реЗ рдмрджрд▓рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ

рдореЗрд░реЗ рдкрд╛рд╕ рдирд┐рдореНрди рдХрд╛рд░реНрдп рд╣реИ:

export const isLocalHost = () => Boolean(
  window.location.hostname === 'localhost' ||
  // [::1] is the IPv6 localhost address.
  window.location.hostname === '[::1]' ||
  // 127.0.0.1/8 is considered localhost for IPv4.
  window.location.hostname.match(
    /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
  )
);

рдореЗрд░реЗ рд▓рд┐рдП рдпрд╣ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдореИрдВ рд╕реАрдзреЗ hostname рдЗрдВрдЬреЗрдХреНрдЯ рдХрд░рддрд╛ рд╣реВрдВ

it('#isLocalHost should return true for all the cases of localhost', () => {
    window.location.hostname = 'localhost';
    expect(isLocalHost()).toBeTruthy();

    window.location.hostname = '[::1]';
    expect(isLocalHost()).toBeTruthy();

    window.location.hostname = '127.0.0.1';
    expect(isLocalHost()).toBeTruthy();

    // Reset back the hostname to avoid issues with it
    window.location.hostname = '';
  });

рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрд╣ рддреНрд░реБрдЯрд┐ рдорд┐рд▓ рд░рд╣реА рд╣реИред

рдореБрдЭреЗ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП jsdom рдЙрдореНрдореАрдж рдирд╣реАрдВ рд╣реИ рд▓реЗрдХрд┐рди рдХрдо рд╕реЗ рдХрдо рдЪрд╛рдмрд┐рдпрд╛рдБ рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдордЬрд╝рд╛рдХ рдЙрдбрд╝рд╛рдПрдВред

рдореИрдВ рдЙрд▓рдЭрди рдореЗрдВ рд╣реВрдВ рдХрд┐ рдореБрдЭреЗ рдпрд╣ рддреНрд░реБрдЯрд┐ рдХреНрдпреЛрдВ рдорд┐рд▓ рд░рд╣реА рд╣реИ, рдореИрдВ рд╕рд┐рд░реНрдл рдореВрд▓реНрдп рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред

@nickhallph
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдкрдиреЗ рд▓рд┐рдЦрд╛ рдерд╛, рдореИрдВрдиреЗ рдЗрд╕реЗ window.location рдореЗрдВ рдмрджрд▓ рджрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдкрд░рд┐рдгрд╛рдо рд╡рд╣реА рд░рд╣рд╛
TypeError: Cannot redefine property: assign
рдХреЛрдИ рд╡рд┐рдЪрд╛рд░?

@ рдпреВрд░реА-рд╕рдЦрд╛рд░реЛрд╡ рдореЛрдЪрд╛ рдЪрд▓рд╛рдиреЗ рдХреЗ рд╕рдорд╛рди рд╕рдорд╕реНрдпрд╛ред

рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рдореИрдВ window.location.* рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд/рдЕрдкрдбреЗрдЯ/рдирдХрд▓реА рдпрд╛ рдХреБрдЫ рднреА рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реВрдВред рдЬрд┐рд╕ рддрд░рд╣ рд╕реЗ рдореИрдВ рдЗрд╕рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рджреЗрдЦрддрд╛ рд╣реВрдВ рд╡рд╣ рдореЗрд░рд╛ рдЕрдкрдирд╛ рдХрд╕реНрдЯрдо window.location рдирдХрд▓реА рдмрдирд╛ рд░рд╣рд╛ рд╣реИ рдФрд░ рдЙрд╕ рдкрд░ рдирд┐рд░реНрднрд░ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдкреВрд░реЗ рдХреЛрдбрдмреЗрд╕ рдХреЛ рдмрджрд▓ рд░рд╣рд╛ рд╣реИред

@hontas рдХреЗ рд╕рдорд╛рдзрд╛рди рдиреЗ рдорджрдж рдХреА:

рдореИрдВрдиреЗ рдЕрдкрдиреЗ рдХреЛрдб рдореЗрдВ window.location.assign(Config.BASE_URL); рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛ред

рдФрд░ рдпрд╣рд╛рдБ рдкрд░реАрдХреНрд╖рдг рд╣реИ:

jest.spyOn(window.location, 'assign').mockImplementation( l => {
   expect(l).toEqual(Config.BASE_URL);
})

window.location.assign.mockClear();

@Hontas 'рд╕рдорд╛рдзрд╛рди рдХрд╛ @zxiest рдХрд╛ рдЬреЗрд╕реНрдЯ рд╕рдВрд╕реНрдХрд░рдг рдореЗрд░реЗ рдХрд╛рдо рдирд╣реАрдВ рдЖрдпрд╛, рд▓реЗрдХрд┐рди рдЗрд╕рдиреЗ рдХрд┐рдпрд╛:

window.location.assign = jest.fn();
expect(window.location.assign).toHaveBeenCalledWith('https://correct-uri.com');
window.location.assign.mockRestore();

рдпрджрд┐ рдЖрдк location.assign рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдирд╛ рдХреЛрдб рдирд╣реАрдВ рдмрджрд▓рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ - рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ JSDom 11 рдФрд░ 13 рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдПрдХ рдореМрдХрд╛ рд╣реИ рдХрд┐ JSDom рдЗрд╕реЗ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рддреЛрдбрд╝ рд╕рдХрддрд╛ рд╣реИ ...)

delete window.location;
window.location = {}; // or stub/spy etc.

рдЖрдЦрд┐рд░реА рдЬрд╡рд╛рдм рдиреЗ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ replace рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛ рдкрдбрд╝рд╛:

delete window.location
window.location = { replace: jest.fn() }

рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЗрд╕рд╕реЗ рд╕рд╣рд╛рдпрддрд╛ рдорд┐рд▓реЗрдЧреАред

рдореБрдЭреЗ TypeError рдорд┐рд▓ рд░рд╣рд╛ рд╣реИ: рд╕рдВрдкрддреНрддрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛: sinon 7.2.3 рдФрд░ jsdom 13.2.0 рдХреЗ рд╕рд╛рде рдЕрд╕рд╛рдЗрди рдХрд░реЗрдВред рдкрддрд╛ рдирд╣реАрдВ рдХреНрдпреЛрдВ рдпрд╣ рдХреБрдЫ рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ рджреВрд╕рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ?

рдЗрд╕реА рд╕реЗ рдореЗрд░рд╛ рдХрд╛рдо рдмрдирд╛ рд╣реИ:

    global.window = Object.create(window);
    const url = 'http://localhost';
    Object.defineProperty(window, 'location', {
      value: {
        href: url,
      },
      writable: true,
    });

рд╣рдордиреЗ рдЗрд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП pushState рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛

 window.history.pushState(
        {},
        '',
        'http://localhost/something/123?order=asc'
      );

рдпрд╣ рдПрдХ рдХрдард┐рди рд╕реНрдерд┐рддрд┐ рд╣реИред JSDOM рдиреЗрд╡рд┐рдЧреЗрд╢рди (рдмреНрд░реЗрдбрдХреНрд░рдВрдм рдХреЗ рдЕрд▓рд╛рд╡рд╛) рдХрд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдФрд░ JSDOM рд╣рдореЗрдВ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЛ рдореЙрдХ-рдЖрдЙрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИред рдЕрдВрддрд┐рдо рдкрд░рд┐рдгрд╛рдо рдпрд╣ рд╣реИ рдХрд┐ рдореИрдВ рдРрд╕реЗ рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рд▓рд┐рдЦ рд╕рдХрддрд╛ рдЬреЛ рдЕрдВрддрддрдГ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ ред

рдпрджрд┐ JSDOM рдиреЗ рдиреЗрд╡рд┐рдЧреЗрдЯ рдХрд░рдирд╛ рд╕реАрдЦ рд▓рд┐рдпрд╛ рд╣реИ (рдореБрдЭреЗ рдпрд╣ рднреА рдкрддрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрд╕рдХрд╛ рдХреНрдпрд╛ рдЕрд░реНрде рд╣реИ), рддреЛ рд╢рд╛рдпрдж рдореИрдВ рдЙрдкрдпреБрдХреНрдд рдкреГрд╖реНрда рдкрд░ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬреЛрд░ рджреЗ рд╕рдХрддрд╛ рд╣реВрдВред рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдг рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рди рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдмрд╣реБрдд рд╕рд╛рдл/рддреЗрдЬ рд╣реИред Jsdom рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХрд░рддреЗ рд╕рдордп рдореИрдВрдиреЗ рдРрддрд┐рд╣рд╛рд╕рд┐рдХ рд░реВрдк рд╕реЗ рдпрд╣реА рдХрд┐рдпрд╛ рд╣реИ рдФрд░ рдЕрдм рдпрд╣ рдЯреВрдЯрд╛ рд╣реБрдЖ рд╣реИред

рдореБрдЭреЗ рдЕрдкрдиреЗ рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ рдкреЛрд╕реНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВ
рдореИрдВ рдмрд╕ window.location = url; рдФрд░ window.location.href = url; рдХреЗ рдЙрдкрдпреЛрдЧреЛрдВ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реВрдВ

window.location.assign(url);

рдФрд░ рдлрд┐рд░ рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдореИрдВрдиреЗ рдХрд┐рдпрд╛:

sinon.stub(window.location, 'assign');
expect(window.location.assign).to.have.been.calledWith(url);

рдПрдХ рдЖрдХрд░реНрд╖рдг рдХреА рддрд░рд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ - рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рдФрд░ рдХреА рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ

рдХрд┐ рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рд▓рдХреНрд╖реНрдп url рдкрд░ рдирд┐рдпрдВрддреНрд░рдг рд╣реИ, рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рдЖрдк google рдпрд╛ Instagram рд╡реЗрдмрд╕рд╛рдЗрдЯ рд▓реЛрдб рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдпрд╛ рдХреЛрдИ рд╡реЗрдмрд╕рд╛рдЗрдЯ? рдЖрдк рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдХреИрд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?

@chrisbateman рдХреЗ рдЙрддреНрддрд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдореИрдВ рдЗрд╕реЗ рдЬреЗрд╕реНрдЯ рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛ред рдЬреЛ рдХреЛрдИ рднреА рдЬреЗрд╕реНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИ, рдЙрд╕рдХреЗ рд▓рд┐рдП рдпрд╣ рдореЗрд░рд╛ рд╕рдорд╛рдзрд╛рди рд╣реИ:

describe('', () => {
    const originalLocation = window.location;

    beforeEach(() => {
        delete window.location;

        window.location = {
            href: '',
        };
    });

    afterEach(() => {
        window.location = originalLocation;
    });

    it('', () => {
        // test here
    });
});

рдореИрдВрдиреЗ рдЗрд╕ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд┐рдпрд╛ред рдореИрдВ рд╣реИрд╢ рдпреВрдЖрд░рдПрд▓ рдХреЗ рд▓рд┐рдП рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛:

    beforeEach(() => {
      delete global.window;
      global.window = {
        location: { replace: jest.fn(url => ({ href: url })) },
      };
    });
    it('should redirect hash url', () => {
      window.location.hash = '#/contrat?id=8171675304';
      global.window.location.href =
        'http://localhost:3000/#/contrat?id=8171675304';
      redirectHashUrl();

      expect(window.location.replace).toHaveBeenCalled();
    });

@chrisbateman @hamzahamidi рдзрдиреНрдпрд╡рд╛рдж, рдЙрд╕ рд╕рдорд╛рдзрд╛рди рдиреЗ рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд┐рдпрд╛ред

рд╢рд╛рдпрдж рдпрд╣ рдПрдХ рдЕрдЪреНрдЫрд╛ рдЕрднреНрдпрд╛рд╕ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреБрдЫ рдкрд░реАрдХреНрд╖рдг рд╣реИрдВ, рдЬреЛ рд╕реНрдерд╛рди/рд╣реЛрд╕реНрдЯ/рд╣реЛрд╕реНрдЯрдирд╛рдо рдФрд░ рдЕрдиреНрдп рд╕реНрдерд╛рди рдЧреБрдгреЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП рдЬреИрд╕рд╛ рд╣рдо рдЪрд╛рд╣рддреЗ рд╣реИрдВ рд▓реЛрдХреЗрд╢рди рдХрд╛ рдордЬрд╛рдХ рдмрдирд╛рдирд╛ рдФрд░ рдмрд╛рдж рдореЗрдВ рдмрд╣рд╛рд▓ рдХрд░рдирд╛ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░ рдЧрдпрд╛ред

const realLocation = window.location;

describe('bla bla', () => {
  afterEach(() => {
    window.location = realLocation;
  });

  it('test where I want to use hostname', () => {
    delete window.location;
    window.location = { 
      hostname: 'my-url-i-expect.com'
    };
    // check my function that uses hostname
  });
});

рдЗрд╕реА рд╕реЗ рдореЗрд░рд╛ рдХрд╛рдо рдмрдирд╛ рд╣реИ:

    global.window = Object.create(window);
    const url = 'http://localhost';
    Object.defineProperty(window, 'location', {
      value: {
        href: url,
      },
      writable: true,
    });

рдпрд╣ рд╕рд░реНрдХрд▓рд╕реА рдХреА рддрд░рд╣ CI рдкрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ

@hontas рдХреЗ рд╕рдорд╛рдзрд╛рди рдиреЗ рдорджрдж рдХреА:

рдореИрдВрдиреЗ рдЕрдкрдиреЗ рдХреЛрдб рдореЗрдВ window.location.assign(Config.BASE_URL); рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛ред

рдФрд░ рдпрд╣рд╛рдБ рдкрд░реАрдХреНрд╖рдг рд╣реИ:

jest.spyOn(window.location, 'assign').mockImplementation( l => {
   expect(l).toEqual(Config.BASE_URL);
})

window.location.assign.mockClear();

рдзрдиреНрдпрд╡рд╛рдж рджреЛрд╕реНрдд, рдЖрдкрдиреЗ рдореБрдЭреЗ рдПрдХ рджрд┐рди рдмрдЪрд╛ рд▓рд┐рдпрд╛ рд╣реИ! :)

рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдореИрдВ рдХреНрд╡реЗрд░реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдХрд░ рд░рд╣рд╛ рд╣реВрдБ, рдФрд░ рдХреЗ рдмрд╛рдж рд╕реЗ рдореЗрд░реА рдХрд▓реНрдкрдирд╛ рдХрд╛ рд╡рд┐рд╖рдп рдХреНрд╡реЗрд░реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реА рд╣реИ, рдореИрдВ рдЗрд╕реЗ рдмрд╛рдИрдкрд╛рд╕ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ, рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕реЗ рдмрд╛рд╣рд░ рдареВрдВрда рдЦреБрд╢ рд╣реВрдБред рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛:

    let name = "utm_content"
    window.history.pushState({}, 'Test Title', '/test.html?utm_content=abc');
    expect(ParseUrlUtils.getParam(name)).toBe("abc")

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣рд╛рдВ рдЗрд╕рд╕реЗ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ рдХрд┐ рд╡рд┐рдВрдбреЛ рдХрд╛ рд╢реАрд░реНрд╖рдХ рдХреНрдпрд╛ рд╣реИ рдФрд░ рдЗрд╕рд╕реЗ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ рдХрд┐ рдпрд╣ /test.html (рдЬреЛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдирд╣реАрдВ рд╣реИ) рд╣реИ, рдХреЗрд╡рд▓ рдпрд╣ рдорд╛рдпрдиреЗ рд░рдЦрддрд╛ рд╣реИ рдХрд┐ рдХреНрд╡реЗрд░реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХреА рдЧрдИ рд╣реИ ( рдпрд╣ рдЧреБрдЬрд░рддрд╛ рд╣реИ)

рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рдореБрджреНрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ рд╡рд┐рдзрд┐рдпреЛрдВ рдФрд░ рдЧреЗрдЯрд░реНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдореИрдВ рдЬреЛ рдХрд░рддрд╛ рд╣реВрдВ рд╡рд╣ рдореВрд▓ рд░реВрдк рд╕реЗ URL рдСрдмреНрдЬреЗрдХреНрдЯ рджреНрд╡рд╛рд░рд╛ рд╕реНрдерд╛рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИред URL рдореЗрдВ рд╕реНрдерд╛рди (рдЦреЛрдЬ, рд╣реЛрд╕реНрдЯ, рд╣реИрд╢, рдЖрджрд┐) рдХреЗ рд╕рднреА рдЧреБрдг рд╣реИрдВред

const realLocation = window.location;

describe('My test', () => {

    afterEach(() => {
        window.location = realLocation;
    });

    test('My test func', () => {

        // @ts-ignore
        delete window.location;

        // @ts-ignore
        window.location = new URL('http://google.com');

        // ...
    });
});

рдореБрдЭреЗ рдпрд╣ рддреНрд░реБрдЯрд┐ рднреА рдорд┐рд▓ рд░рд╣реА рд╣реИ

Error: Not implemented: navigation (except hash changes)
    at module.exports (...\node_modules\jsdom\lib\jsdom\browser\not-implemented.js:9:17)
    at navigateFetch (...\node_modules\jsdom\lib\jsdom\living\window\navigation.js:74:3)

@hontas рдХреЗ рд╕рдорд╛рдзрд╛рди рдиреЗ рдорджрдж рдХреА:

рдореИрдВрдиреЗ рдЕрдкрдиреЗ рдХреЛрдб рдореЗрдВ window.location.assign(Config.BASE_URL); рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛ред

рдФрд░ рдпрд╣рд╛рдБ рдкрд░реАрдХреНрд╖рдг рд╣реИ:

jest.spyOn(window.location, 'assign').mockImplementation( l => {
   expect(l).toEqual(Config.BASE_URL);
})

window.location.assign.mockClear();

рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд┐рдпрд╛, рдзрдиреНрдпрд╡рд╛рдж! рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореБрдЭреЗ рдЬреЗрд╕реНрдЯ рдЯреЗрд╕реНрдЯ() рд╕реЗ done рддрд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдкрдбрд╝рд╛, рдЕрдиреНрдпрдерд╛ рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реЛрдЧрд╛ рдХрд┐ рдЙрдореНрдореАрдж рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдкрд░реАрдХреНрд╖рдг рд╡реИрд╕реЗ рднреА рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдпрд╛ рдерд╛:

it('should', (done) => {
jest.spyOn(window.location, 'assign').mockImplementation( l => {
   expect(l).toEqual(Config.BASE_URL);
   done();
})

window.location.assign.mockClear();
}

@hontas рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ :( рд╕рдВрдкрддреНрддрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдиреЗ/рдмрджрд▓рдиреЗ рдореЗрдВ рдЕрд╕рдорд░реНрде

рдХреНрдпрд╛ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ рдХрд┐ рдХреМрди рд╕рд╛ рдкрд░реАрдХреНрд╖рдг "рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛: рдиреЗрд╡рд┐рдЧреЗрд╢рди" рд╕рдВрджреЗрд╢ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░ рд░рд╣рд╛ рд╣реИ? рдореЗрд░реЗ рдкрд╛рд╕ 43 рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рдПрдХ рд╕реВрдЯ рд╣реИ - рддреНрд░реБрдЯрд┐ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХреА рдЬрд╛ рд░рд╣реА рд╣реИ рдФрд░ рдпрд╣ рдЪрд╛рд░реЛрдВ рдУрд░ рдЙрдЫрд▓рддреА рд░рд╣рддреА рд╣реИред рдореИрдВ рдирд╣реАрдВ рдмрддрд╛ рд╕рдХрддрд╛ рдХрд┐ рдХреМрди рд╕рд╛ рдкрд░реАрдХреНрд╖рдг рдареАрдХ рдХрд░рдирд╛ рд╣реИ !!! рд╕реНрдЯреИрдХ рдЯреНрд░реЗрд╕ рдореБрдЭреЗ рдЕрдкрд░рд╛рдзреА рдХрд╛ рдХреЛрдИ рд╕рдВрдХреЗрдд рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ:

console.error
  Error: Not implemented: navigation (except hash changes)
      at module.exports (/Users/naresh/projects/mobx-state-router/node_modules/jsdom/lib/jsdom/browser/not-implemented.js:9:17)
      at navigateFetch (/Users/naresh/projects/mobx-state-router/node_modules/jsdom/lib/jsdom/living/window/navigation.js:76:3)
      at exports.navigate (/Users/naresh/projects/mobx-state-router/node_modules/jsdom/lib/jsdom/living/window/navigation.js:54:3)
      at Timeout._onTimeout (/Users/naresh/projects/mobx-state-router/node_modules/jsdom/lib/jsdom/living/nodes/HTMLHyperlinkElementUtils-impl.js:81:7)
      at listOnTimeout (internal/timers.js:531:17)
      at processTimers (internal/timers.js:475:7) undefined

    at VirtualConsole.<anonymous> (node_modules/jsdom/lib/jsdom/virtual-console.js:29:45)
    at module.exports (node_modules/jsdom/lib/jsdom/browser/not-implemented.js:12:26)
    at navigateFetch (node_modules/jsdom/lib/jsdom/living/window/navigation.js:76:3)
    at exports.navigate (node_modules/jsdom/lib/jsdom/living/window/navigation.js:54:3)
    at Timeout._onTimeout (node_modules/jsdom/lib/jsdom/living/nodes/HTMLHyperlinkElementUtils-impl.js:81:7)

@hontas рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ :( рд╕рдВрдкрддреНрддрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдиреЗ/рдмрджрд▓рдиреЗ рдореЗрдВ рдЕрд╕рдорд░реНрде

рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВ рд╕рдордЭрддрд╛ рд╣реВрдВ рдХрд┐ рдЬреЗрд╕реНрдЯ рдиреЗ рдирдП рд╕рдВрд╕реНрдХрд░рдг ("рдЬреЗрд╕реНрдЯ": "^ 26.0.1") рдореЗрдВ рдХреБрдЫ рдмрджрд▓ рджрд┐рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЕрднреА рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

// Mock
  Object.defineProperty(window, 'location', {
    value: {
      pathname: '/terminals',
      assign: jest.fn(),
    },
  });

// Then test
expect(window.location.assign).toBeCalledWith('/auth');

рдХреНрдпрд╛ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ рдХрд┐ рдХреМрди рд╕рд╛ рдкрд░реАрдХреНрд╖рдг "рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛: рдиреЗрд╡рд┐рдЧреЗрд╢рди" рд╕рдВрджреЗрд╢ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░ рд░рд╣рд╛ рд╣реИ? рдореЗрд░реЗ рдкрд╛рд╕ 43 рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рдПрдХ рд╕реВрдЯ рд╣реИ - рддреНрд░реБрдЯрд┐ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХреА рдЬрд╛ рд░рд╣реА рд╣реИ рдФрд░ рдпрд╣ рдЪрд╛рд░реЛрдВ рдУрд░ рдЙрдЫрд▓рддреА рд░рд╣рддреА рд╣реИред рдореИрдВ рдирд╣реАрдВ рдмрддрд╛ рд╕рдХрддрд╛ рдХрд┐ рдХреМрди рд╕рд╛ рдкрд░реАрдХреНрд╖рдг рдареАрдХ рдХрд░рдирд╛ рд╣реИ !!! рд╕реНрдЯреИрдХ рдЯреНрд░реЗрд╕ рдореБрдЭреЗ рдЕрдкрд░рд╛рдзреА рдХрд╛ рдХреЛрдИ рд╕рдВрдХреЗрдд рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ:

console.error
  Error: Not implemented: navigation (except hash changes)
      at module.exports (/Users/naresh/projects/mobx-state-router/node_modules/jsdom/lib/jsdom/browser/not-implemented.js:9:17)
      at navigateFetch (/Users/naresh/projects/mobx-state-router/node_modules/jsdom/lib/jsdom/living/window/navigation.js:76:3)
      at exports.navigate (/Users/naresh/projects/mobx-state-router/node_modules/jsdom/lib/jsdom/living/window/navigation.js:54:3)
      at Timeout._onTimeout (/Users/naresh/projects/mobx-state-router/node_modules/jsdom/lib/jsdom/living/nodes/HTMLHyperlinkElementUtils-impl.js:81:7)
      at listOnTimeout (internal/timers.js:531:17)
      at processTimers (internal/timers.js:475:7) undefined

    at VirtualConsole.<anonymous> (node_modules/jsdom/lib/jsdom/virtual-console.js:29:45)
    at module.exports (node_modules/jsdom/lib/jsdom/browser/not-implemented.js:12:26)
    at navigateFetch (node_modules/jsdom/lib/jsdom/living/window/navigation.js:76:3)
    at exports.navigate (node_modules/jsdom/lib/jsdom/living/window/navigation.js:54:3)
    at Timeout._onTimeout (node_modules/jsdom/lib/jsdom/living/nodes/HTMLHyperlinkElementUtils-impl.js:81:7)

рдпрд╣ рдмрддрд╛рдирд╛ рдХрдард┐рди рд╣реИ рдХрд┐ рдХрд┐рд╕ рдкрд░реАрдХреНрд╖рдг рд╕реЗ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХреА рдЧрдИ рддреНрд░реБрдЯрд┐ рдЖрддреА рд╣реИред

рдореИрдВ node_modules/jsdom/lib/jsdom/browser/not-implemented.js:12 рдкрд░ рдмреНрд░реЗрдХрдкреЙрдЗрдВрдЯ рдЬреЛрдбрд╝рддрд╛ рд╣реВрдВ, рдбреАрдмрдЧ рд╕рддреНрд░ рдЪрд▓рд╛рддрд╛ рд╣реВрдВ рдФрд░ рдмреНрд░реЗрдХрдкреЙрдЗрдВрдЯ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рддрдХ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реВрдВред рддрднреА рдореИрдВ рджреЗрдЦрддрд╛ рд╣реВрдВ рдХрд┐ рдЗрд╕ рд╕рдВрджреЗрд╢ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдХреМрди рд╕реА рдкрд░реАрдХреНрд╖рд╛ рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред
image

рдХрднреА-рдХрднреА рдЗрд╕рдореЗрдВ 2-3 рдорд┐рдирдЯ рдХрд╛ рд╕рдордп рд▓рдЧрддрд╛ рд╣реИ рдЬрдм рддрдХ рдзрд╛рд╡рдХ рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рддрдХ рдирд╣реАрдВ рдкрд╣реБрдВрдЪ рдЬрд╛рддрд╛ред

рдкреБрдирд╢реНрдЪ: рдореЗрд░реЗ рд╡рд░реНрддрдорд╛рди рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ 176 jsdom рд╕рдВрдмрдВрдзрд┐рдд рдкрд░реАрдХреНрд╖рдг рд╣реИрдВ

рдореИрдВ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЬреЗрд╕реНрдЯ 26.0.1 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдиреАрдЪреЗ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

  1. рд╡рд┐рдВрдбреЛ рд╕реНрдерд╛рди рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП window.location.assign(url) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред

  2. рд▓реЛрдХреЗрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдореЙрдХ рдХрд░реЗрдВ (рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╣рдЯрд╛рдирд╛ рдФрд░ рдкреБрдирд░реНрдирд┐рд░реНрдорд╛рдг рдирд╣реАрдВ рдХрд░рдирд╛ рдкрд╣рд▓реЗ рдЕрднреА рднреА рдЬреЗрд╕реНрдЯ рдХреЗ рд╡рд┐рдЦреНрдпрд╛рдд рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХреА рдЧрдИ рддреНрд░реБрдЯрд┐ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╣реИ рдФрд░ рдкрд╣рд▓реЗ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ, Object.defineProperty рднреА рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЕрднреА рднреА рдкрд░рд┐рдгрд╛рдо рдореЗрдВ рд╣реИ рддреНрд░реБрдЯрд┐):

delete window.location;
window.location = {
    href: '',
    hostname: '',
    pathname: '',
    protocol: '',
    assign: jest.fn()
};
  1. рдЗрд╕рдХреЗ рд╕рд╛рде рдЬреЛрд░ рджреЗрдВ:
expect(window.location.assign).toBeCalledWith(url);

рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рдордЬрд╝рд╛рдХ рд╣рдореЗрдВ рдЗрди рд╕рднреА рдирд┐рд░рдВрддрд░ рдореБрджреНрджреЛрдВ рдФрд░ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рдмрд┐рдирд╛ рдЖрд╕рд╛рдиреА рд╕реЗ рд╕реНрдерд╛рди рдХрд╛ рдордЬрд╝рд╛рдХ рдЙрдбрд╝рд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдореИрдВ рдкрд╣рд▓реЗ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЗ рд╕рд┐рд░реНрдл window.location.assign = jest.fn() рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рдерд╛, рдлрд┐рд░ рдореИрдВрдиреЗ v24 рд╕реЗ рдЕрдкрдЧреНрд░реЗрдб рдХрд┐рдпрд╛ рдФрд░ рдЕрдм рдпрд╣ред

рдХреНрдпрд╛ рдХреЛрдИ рдЕрдЪреНрдЫрд╛ рдХрд╛рд░рдг рд╣реИ рдХрд┐ рд╡рд┐рдВрдбреЛ рдПрдкреАрдЖрдИ рд▓реЙрдХ/рдЬрдореЗ рд╣реБрдП рдереЗ?
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдпрд╣ рдмрд╛рдзрд╛ рд╣реИред

рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рдХреНрдпрд╛ рд╣рдо рдЙрдиреНрд╣реЗрдВ рдлреНрд░реАрдЬ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ? рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рднреА рдЗрддрдиреЗ рд╕рдЦреНрдд рд╣реИрдВ рдЬреЛ рдЖрдкрдХреЛ рд╡рд┐рдВрдбреЛ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЛ рдмрджрд▓рдиреЗ рд╕реЗ рд░реЛрдХрддреЗ рд╣реИрдВред

рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╕реЗ рднрд┐рдиреНрди рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ jsdom рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ, рддреЛ рдХреГрдкрдпрд╛ рд╕рдорд╕реНрдпрд╛ рдЯреЗрдореНрдкрд▓реЗрдЯ (jsbin рдпрд╛ рд╕рдорд╛рди рджрд┐рдЦрд╛рдиреЗ рд╡рд╛рд▓реЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╡реНрдпрд╡рд╣рд╛рд░ рд╕рд╣рд┐рдд) рдХреЗ рдмрд╛рдж рдПрдХ рд╕рдорд╕реНрдпрд╛ рджрд░реНрдЬ рдХрд░реЗрдВред

рдХреНрдпрд╛ рдЬреЗрд╕реНрдЯ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рджреМрд░рд╛рди рдХреЛрдИ рдФрд░ рдЙрд╕реА Error: Not implemented: navigation (except hash changes) рдореЗрдВ рдЪрд▓ рд░рд╣рд╛ рд╣реИ рдЬреЛ рдПрдХ рдПрдВрдХрд░ рддрддреНрд╡ рдкрд░ href рд╕рд╛рде рдПрдХ рдХреНрд▓рд┐рдХ рдИрд╡реЗрдВрдЯ рдХреЛ рд╕рдХреНрд░рд┐рдп рдХрд░рддрд╛ рд╣реИ? рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП, рдореИрдВ рдПрдХ рдРрд╕реЗ рдлрд╝рдВрдХреНрд╢рди рдкрд░ рдЬрд╛рд╕реВрд╕реА рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЬрд┐рд╕реЗ onClick рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рджрд╛рд╡рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдВрдХрд░ рддрддреНрд╡ рдкрд░ рдХреНрд▓рд┐рдХ рдИрд╡реЗрдВрдЯ рдХреЛ рдЖрдЧ рд▓рдЧрд╛рдирд╛ рд╣реЛрдЧрд╛ред

рдКрдкрд░ рджрд┐рдП рдЧрдП рд╕рдорд╛рдзрд╛рди window.location рдХрд╛ рдордЬрд╛рдХ рдЙрдбрд╝рд╛рдиреЗ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рдореИрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ window.location.replace рдпрд╛ window.location.assign рдХреЙрд▓ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдорджрдж рдирд╣реАрдВ рдХрд░рддреЗ рдЬрд╣рд╛рдВ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдПрдВрдХрд░ рддрддреНрд╡ рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИ рдХреНрд▓рд┐рдХ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред

рд╕рдорд╛рдзрд╛рди рдкрд░ рдХреЛрдИ рд╡рд┐рдЪрд╛рд░? рдзрдиреНрдпрд╡рд╛рдж!

рдЖрдк рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЙрд╕ рдХреЛрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХреИрд╕реЗ рдХрд░реЗрдВрдЧреЗ? рдзреНрдпрд╛рди рд░рдЦреЗрдВ рдХрд┐ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рд▓рд┐рдВрдХ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рд╕реЗ рдЖрдкрдХрд╛ рдкреВрд░рд╛ рдкреГрд╖реНрда рдЙрдбрд╝ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдХрд┐рд╕реА рднреА рдкрд░реАрдХреНрд╖рд╛ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рддреЛ рдЗрд╕реЗ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдк рдЬреЛ рдХреБрдЫ рднреА рдХрд░реЗрдВрдЧреЗ, рд╡рд╣ рдХрдВрд╕реЛрд▓ рдкрд░ рдмрд╣реБрдд рдХрдо-рдирд╛рдЯрдХреАрдп рдЪреЗрддрд╛рд╡рдиреА рд╕рдВрджреЗрд╢ jsdom рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рднреА рд░реЛрдХ рджреЗрдЧрд╛ред

рдореЗрд░реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдиреЗ рдЬреЗрд╕реНрдЯ рдХреЛ 23 рд╕реЗ 26 рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдЕрдкрдЧреНрд░реЗрдб рдХрд┐рдпрд╛ред
рдореБрдЭреЗ location.search рд╕рдорд╕реНрдпрд╛ рдереАред рд╡рд╣реА рддреНрд░реБрдЯрд┐ Error: Not implemented: navigation ред
рдореЗрд░реЗ рджреНрд╡рд╛рд░рд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдП рдЧрдП рдореЙрдбреНрдпреВрд▓ рдХреЛ рдЦреЛрдЬ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛ рдХреЗ рдорд╛рди рдорд┐рд▓рддреЗ рд╣реИрдВред
рдЕрдЧрд▓рд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд┐рдпрд╛:

beforeAll(() => {
  delete window.location;
  window.location = new URL('your URL');
})

afterAll(() => {
  window.location.search = '';
})

@mattcphillips рдХреНрдпрд╛ рдЖрдкрдиреЗ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдпрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рдареАрдХ рдХрд┐рдпрд╛ рдЬрд╛рдП? рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╕рдордп рдореБрдЭреЗ рднреА рд╕рдорд╕реНрдпрд╛ рд╣реЛ рд░рд╣реА рд╣реИ

@Sabrinovsky рдирд╣реАрдВ, рдореИрдВрдиреЗ рдЕрдкрдиреЗ setupFiles рдореЗрдВ рдПрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЬреЛрдбрд╝рдирд╛ рд╕рдорд╛рдкреНрдд рдХрд░ рджрд┐рдпрд╛ рдЬреЛ рдХрд┐ jsdom рдиреЗрд╡рд┐рдЧреЗрд╢рди рд╕реЗ рдЖрдиреЗ рд╡рд╛рд▓реА рдХрдВрд╕реЛрд▓ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдирд┐рдЧрд▓ рдЬрд╛рдПрдЧрд╛ рддрд╛рдХрд┐ рд╡реЗ рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдЕрд╡реНрдпрд╡рд╕реНрдерд┐рдд рди рдХрд░реЗрдВред рдХрд┐рд╕реА рднреА рдЪреАрдЬрд╝ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рдмреИрдВрдбрдПрдб, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рд▓рдЧ рд░рд╣рд╛ рдерд╛ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдг рд╕реЗрдЯрдЕрдк рдореЗрдВ рдЗрди рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рдЙрдореНрдореАрдж рдХреА рдЬрд╛рдиреА рд╣реИред

рдпрд╣рд╛рдВ рд╡рд╣ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВ рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рд╕реЗ рдкрд╣рд▓реЗ рдЪрд▓рд╛рддрд╛ рд╣реВрдВ:

// There should be a single listener which simply prints to the
// console. We will wrap that listener in our own listener.
const listeners = window._virtualConsole.listeners('jsdomError');
const originalListener = listeners && listeners[0];

window._virtualConsole.removeAllListeners('jsdomError');

// Add a new listener to swallow JSDOM errors that orginate from clicks on anchor tags.
window._virtualConsole.addListener('jsdomError', error => {
  if (
    error.type !== 'not implemented' &&
    error.message !== 'Not implemented: navigation (except hash changes)' &&
    originalListener
  ) {
    originalListener(error);
  }

  // swallow error
});

рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд┐рдпрд╛ред

delete global.window.location
global.window.location = { href: 'https://test.com' }

рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд┐рдпрд╛

delete window.location
window.location = { assign: jest.fn() }

рдпрджрд┐ рдЖрдкрдХреЛ TypeError: Cannot assign to read only property 'assign' of object '[object Location]' , рддреЛ рдЕрдкрдиреЗ jest.setup.ts рдореЗрдВ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:

```
рдЧреНрд▓реЛрдмрд▓.рд╡рд┐рдВрдбреЛ = рдСрдмреНрдЬреЗрдХреНрдЯ.рдХреНрд░рд┐рдПрдЯ (рд╡рд┐рдВрдбреЛ);
Object.defineProperty (рд╡рд┐рдВрдбреЛ, 'рд╕реНрдерд╛рди', {
рдореВрд▓реНрдп: {
...рд╡рд┐рдВрдбреЛ.рд╕реНрдерд╛рди,
},
рд▓рд┐рдЦрдиреЗ рдпреЛрдЧреНрдп: рд╕рдЪ,
});
````

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕