рд╣рд╛рдп @cpojer ,
рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ jsdom@8
рдореБрджреНрджреЗ рд╕реЗ рдЕрдзрд┐рдХ рд╣реИ ... tmpvar/jsdom#1388 рджреЗрдЦреЗрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рдпрд╣рд╛рдВ рднреА рдкрд┐рди рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдЗрд╕рд▓рд┐рдП рдЬреЗрд╕реНрдЯ рдЬреЛ рднреА рд╕рдорд╛рдзрд╛рди jsdom рдХреЗ рд╕рд╛рде рдЖрддрд╛ рд╣реИ рдЙрд╕реЗ рдЙрдард╛рддрд╛ рд╣реИред
рдкрд╣рд▓реЗ [email protected]/[email protected]
рдХреЗ рд╕рд╛рде рдЖрдк рдЗрд╕ рддрд░рд╣ рдПрдХ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦ рд╕рдХрддреЗ рдереЗ:
jest.autoMockOff()
jest.setMock('../lib/window', window)
jest.mock('cookies-js')
jest.mock('query-string')
jest.mock('superagent')
describe(['@utils/auth - When an AJAX response returns:'
].join('')
, function () {
beforeEach(function () {
window.location.href = 'http://quux.default.com'
var queryString = require('query-string')
queryString.__setMockParseReturns([{
'access_token': '1234foo',
'expires_in': '9999'
}])
})
it(['should set a redirect token and goto platform ',
'when the AJAX request returns 401.'
].join('')
, function () {
var superagent = require('superagent')
superagent.__setMockAjaxResponses([
[null, { 'status': 401 }]
])
var href = window.location.href
var auth = require('../index.js')
auth.login(function (res) {})
var Cookies = require('cookies-js')
var config = require.requireActual('../config')
expect(decodeURIComponent(window.location.href)).toBe([
config.loginUrl,
config.loginServiceLogin,
'?client_id=',
config.clientId,
'&response_type=token',
'&redirect_uri=',
config.clientRedirectUri
].join(''))
expect(Cookies.__getMockCookieData()[config.clientId + '_state_locationAfterLogin']).toBe(escape(href))
})
рдФрд░ рд╡рд╣ рдкрд░реАрдХреНрд╖рд╛ рдкрд╛рд╕ рд╣реЛ рдЬрд╛рдПрдЧреАред рдЪреВрдВрдХрд┐ jsdom@8
рдпрд╣ рдЕрдм рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИ рдФрд░ рдпреЗ рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ jsdom рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреА рдХреНрд╖рдорддрд╛ рдХреЛ рджреЗрдЦ рд░рд╣рд╛ рд╣реИ, рдмрд╕ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рдЬреЗрд╕реНрдЯ рдЙрдкрд▓рдмреНрдз рд╣реЛрдиреЗ рдкрд░ рдЙрд╕ рдХреНрд╖рдорддрд╛ рдХреЛ рдЙрдард╛рдПрдЧрд╛ред
рдЖрдк рд╕рд╣реА рд╣реИрдВ, рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ jsdom рдореБрджреНрджрд╛ рд╣реИред рдлреЗрд╕рдмреБрдХ рдкрд░, рд╣рдордиреЗ рдЗрд╕рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛ рдХрд┐рдпрд╛ рд╣реИ, рд╡рд╣ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣реИ:
Object.defineProperty(window.location, 'href', {
writable: true,
value: 'some url'
});
рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдБрдХрд┐ рд╣рдо рдЕрднреА рднреА рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ jsdom 7 рдкрд░ рд╣реИрдВред
рдореИрдВ рдЗрд╕реЗ рдмрдВрдж рдХрд░ рджреВрдВрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ Object.defineProperty
рдЪреАрдЬреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдареАрдХ рд╣реИред рдЕрдЧрд░ рд╡рд╣ рдЖрдкрдХреЗ рд▓рд┐рдП jsdom 8 рдореЗрдВ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдореБрдЭреЗ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓рдиреЗ рдореЗрдВ рдЦреБрд╢реА рд╣реЛ рд░рд╣реА рд╣реИред
рдмрдврд╝рд┐рдпрд╛, рдзрдиреНрдпрд╡рд╛рдж рдореИрдВ рдЗрд╕реЗ рдЖрдЬрдорд╛рдЙрдВрдЧрд╛ред
@cpojer , рдореБрдЭреЗ рдпрд╣ рдкрддрд╛ рдирд╣реАрдВ рд▓рдЧ рд░рд╣рд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдХреНрдпрд╛ рдХреНрд▓рд┐рдХ рдХрд░рдирд╛ рд╣реИ ...
рдХреНрдпрд╛ jest
рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдХреЛрдИ рднреА рд╡реНрдпрдХреНрддрд┐ jsdom.changeUrl(window, url)
рдкрд░ рдХреЙрд▓ рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ https://github.com/tmpvar/jsdom#change -the-url-of-an- рдореМрдЬреВрджрд╛-jsdom- [email protected]
рдореЗрдВ рд╡рд┐рдВрдбреЛ-рдЗрдВрд╕реНрдЯреЗрдВрд╕?
рдкреБрд░рд╛рдиреЗ рдЯрд┐рдХрдЯ рд▓реЗрдХрд┐рди рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЕрднреА рднреА рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд╣рдордиреЗ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп window.location.assign()
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рд╣рдо assign
рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдордЬрд╛рдХ рдЙрдбрд╝рд╛ рд╕рдХрддреЗ рд╣реИрдВред
it('will redirect with a bad route', () => {
window.location.assign = jest.fn();
const redirection = shallow(<Redirection />, {
context: {
router: {
location: {
pathname: '/wubbalubbadubdub',
},
},
},
});
expect(window.location.assign).toBeCalledWith(`${CONFIG.APP_LEGACY_ROOT}`);
});
рдзрдиреНрдпрд╡рд╛рдж @ th3fallen ред рдпрд╣ рдЕрдЪреНрдЫрд╛ рд╣реИ!
рдмреАрдЯреАрдбрдмреНрд▓реНрдпреВ @cpojer рдореИрдВ 1 рдордИ рдХреЛ рдПрдлрдмреА рд╕реЗ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реВрдВ ....; рдкреА
рдЕрдЪреНрдЫрд╛!
рдореИрдВ рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдореЛрдЪрд╛+рдЪрд╛рдИ+рд╕рд┐рдиреЙрди.рдЬреЗрдПрд╕ рд╕реЗ рдЬреЗрд╕реНрдЯ рдореЗрдВ рдорд╛рдЗрдЧреНрд░реЗрдЯ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдпрд╣ рдкрддрд╛ рдирд╣реАрдВ рд▓рдЧрд╛ рд╕рдХрддрд╛ рдХрд┐ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рд╕реНрдерд╛рди рдХреИрд╕реЗ рдмрджрд▓рд╛ рдЬрд╛рдПред
рдЬреЗрд╕реНрдЯ 19.x JSDom 9.12 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдЬреЛ Object.defineProperty
рдЯреНрд░рд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реНрдерд╛рди рдмрджрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИред рд╕рд╛рде рд╣реА, рдореИрдВ tmpvar/jsdom#1700 рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд╛рд░рдгреЛрдВ рдХреЗ рдХрд╛рд░рдг jsdom.changeURL()
рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ред
@cpojer рдЬреЗрд╕реНрдЯ рдореЗрдВ jsdom.changeURL()
рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдкреНрд░реЙрдХреНрд╕реА рд╡рд┐рдзрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛?
@okovpashko рд╣рдо рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЗ рд▓рд┐рдП jsdom рдХреЛ рдмреЗрдирдХрд╛рдм рдХрд░рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВ: https://github.com/facebook/jest/issues/2460
Object.defineProperty
рд╣рдорд╛рд░реЗ рд▓рд┐рдП FB рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
@thymikee рдореИрдВрдиреЗ рдЙрд╕ рдореБрджреНрджреЗ рдХреЛ рджреЗрдЦрд╛ рд▓реЗрдХрд┐рди рд╕реЛрдЪрд╛ рдХрд┐ рдкреНрд░рд╕реНрддрд╛рд╡ рдЦрд╛рд░рд┐рдЬ рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
@cpojer рдореИрдВрдиреЗ рдЖрдкрдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЛ рдЧрд▓рдд рддрд░реАрдХреЗ рд╕реЗ рдкрдврд╝рд╛ рдФрд░ рдЗрд╕реЗ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдЕрдиреНрдп рд▓реЛрдЧреЛрдВ рдХреЗ рд╕рд╛рде рдорд┐рд╢реНрд░рд┐рдд рдХрд┐рдпрд╛, рдЬрд╣рд╛рдВ рд▓реЛрдЧреЛрдВ рдиреЗ Object.defineProperty(window, 'location', {value: 'url'});
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛ред рдЖрдкрдХреЛ рдзрдиреНрдпрд╡рд╛рдж!
рдореБрдЭреЗ рди рдХреЗрд╡рд▓ href рдмрджрд▓рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рд╕рд░рд▓ рд╡рд┐рдзрд┐ рд▓рд┐рдЦреА, рдЬреЛ рдЗрд╕ рдзрд╛рдЧреЗ рдХреЛ рдкрдврд╝рдиреЗ рд╡рд╛рд▓реЗ рдХрд┐рд╕реА рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддреА рд╣реИ:
const setURL = (url) => {
const parser = document.createElement('a');
parser.href = url;
['href', 'protocol', 'host', 'hostname', 'origin', 'port', 'pathname', 'search', 'hash'].forEach(prop => {
Object.defineProperty(window.location, prop, {
value: parser[prop],
writable: true,
});
});
};
рдЗрд╕ рд╕реВрддреНрд░ рдХреЛ рдЖрдЧреЗ рдЦреАрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд╖рдорд╛ рдпрд╛рдЪрдирд╛, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рд╕реБрдЭрд╛рд╡ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдкреБрд╢ рдлрдВрдХреНрд╢рди рдХрд╛ рдордЬрд╛рдХ рдЙрдбрд╝рд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рд╣реИ ...
reactRouterReduxMock.push = (url) => {
Object.defineProperty(window.location, 'href', {
writable: true,
value: url
})
})
рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЕрднреА рднреА рдПрдХ jsdom рддреНрд░реБрдЯрд┐ рдорд┐рд▓ рд░рд╣реА рд╣реИ рдХрд┐ рдореБрдЭреЗ рдЧреЛрд▓ рдирд╣реАрдВ рд▓рдЧ рд░рд╣рд╛ рд╣реИ:
TypeError: Cannot read property '_location' of null
at Window.location (/Users/user/projects/app/client/node_modules/jsdom/lib/jsdom/browser/Window.js:148:79)
at value (/Users/user/projects/app/client/test/integration-tests/initialSetup.js:122:32) //this is the defineProperty line above
рдореБрдЭреЗ рдПрд╣рд╕рд╛рд╕ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ jsdom рддреНрд░реБрдЯрд┐ рд╣реИ, рд▓реЗрдХрд┐рди рдЬрд┐рди рд▓реЛрдЧреЛрдВ рдиреЗ рдЗрд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рд╣реИ рдЙрдирдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рдХреЛрдИ рдФрд░ рд╕реЗрдЯрдЕрдк рд╕рдВрджрд░реНрдн рд╣реИ рдЬрд┐рд╕реЗ рдЖрдк рд╕рд╛рдЭрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдореБрдЭреЗ рдЗрд╕рдХреЗ рдЖрд╕рдкрд╛рд╕ рдЬрд╛рдиреЗ рджреЗ рд╕рдХрддрд╛ рд╣реИ?
рдзрдиреНрдпрд╡рд╛рдж
@ рдореИрдЯ-рдбрд╛рд▓реНрдЯрди https://github.com/facebook/jest/issues/890#issuecomment -295939071 рдореЗрдВ рдореЗрд░реЗ рд╕реБрдЭрд╛рд╡ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ рдореЗрд░реЗ рд▓рд┐рдП рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ
@ рдореИрдЯ-рдбрд╛рд▓реНрдЯрди рдЖрдкрдХрд╛ рдпреВрдЖрд░рдПрд▓ рдХреНрдпрд╛ рд╣реИ? рдХреНрдпрд╛ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЕрдкрдиреЗ jest-config.json
рдореЗрдВ testURL рд╕реЗрдЯ рд╣реИ рдпрд╛ рдпрд╣ about:blank
рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╛рд░рдВрдн рд╣реЛрддрд╛ рд╣реИ?
@ianlyons рд╣рд╛рдБ рдореИрдВрдиреЗ package.json рдореЗрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП "https://test.com/"
рдХрд╛ рдорд╛рди рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рд╣реИ, рдФрд░ рдХреЛрдИ рднреА рдкрде blank
рдХреЗ рд░реВрдк рдореЗрдВ рджрд┐рдЦрд╛рдИ рдирд╣реАрдВ рджреЗ рд░рд╣рд╛ рд╣реИред
@ th3fallen рдЕрдЧрд░ рдореИрдВ рдЖрдкрдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд╕рдордЭрддрд╛ рд╣реВрдВ, рддреЛ рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдпрд╣ рдореЗрд░реЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдХреНрдпрд╛ рдЖрдк рдпреВрдЖрд░рдПрд▓ рдХреЛ рд╕рдВрджрд░реНрдн рдорд╛рди рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд╕ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдЬреЛ рдЕрд╕рд╛рдЗрди рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИ? рдореИрдВ рдПрдХ рдкреНрд░рд╛рдердорд┐рдХ рдПрдХреАрдХрд░рдг рдкрд░реАрдХреНрд╖рдг рдХреЛ рдПрдХ рд╕рд╛рде рд░рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдпрд╣ рдЬрд╛рдВрдЪрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рд░рд╛рдЙрдЯрд░ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдбреЗрдЯрд╛ рд▓реЛрдб рдкрд░ рдХреИрд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИред рдореИрдВрдиреЗ рдПрдкреАрдЖрдИ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдордЬрд╝рд╛рдХ рдЙрдбрд╝рд╛рдпрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдРрдк рддрд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдпреВрдЖрд░рдПрд▓ рдкрд░рд┐рд╡рд░реНрддрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдпрд╛рдиреА рдореИрдВ рдЗрд╕реЗ рдмрд╛рд╣рд░реА рд░реВрдк рд╕реЗ рдЯреНрд░рд┐рдЧрд░ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛)ред
Object.defineProperty
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, window.location.search
рдкрд░ рдирд┐рд░реНрднрд░ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЪрд╛рд▓ рдЪрд▓ рд░рд╣рд╛ рд╣реИред рдХрд╣рд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ рдХрд┐ рдпрд╣ window.location.search
рдмрджрд▓ рджреЗрддрд╛ рд╣реИ рдЗрд╕рд▓рд┐рдП рдЕрдиреНрдп рдкрд░реАрдХреНрд╖рдг рдкреНрд░рднрд╛рд╡рд┐рдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдХреНрдпрд╛ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ window.location.search
рдкрд░ Object.defineProperty
#$ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд┐рдП рдЧрдП рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ "рдкреВрд░реНрд╡рд╡рдд" рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ, рдЬреИрд╕реЗ рдХрд┐ рдЬреЗрд╕реНрдЯ рдореЙрдХ рдлрд╝рдВрдХреНрд╢рдВрд╕ рдореЗрдВ mockReset
рдлрд╝рдВрдХреНрд╢рди рд╣реЛрддрд╛ рд╣реИ?
@ msholty-fd рдЖрдк рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рдЖрдЬрдорд╛ рд╕рдХрддреЗ рд╣реИрдВ:
const origLocation = document.location.href;
let location = origLocation;
beforeAll(() => {
const parser = document.createElement('a');
['href', 'protocol', 'host', 'hostname', 'origin', 'port', 'pathname', 'search', 'hash'].forEach(prop => {
Object.defineProperty(window.location, prop, {
get: function() {
parser.href = location;
return parser[prop];
}
});
});
});
afterEach(() => {
location = origLocation;
});
test('location 1', () => {
location = "https://www.google.com/";
console.log(document.location.href); // https://www.google.com/
});
test('location 2', () => {
console.log(document.location.href); // about:blank
});
рдЗрд╕рдиреЗ рдЬреЗрд╕реНрдЯ 22.0.1 . рдореЗрдВ рдХрд╛рдо рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛
Object.defineProperty(window.location, 'href', {
writable: true,
value: 'some url'
});
рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢:
TypeError: Cannot redefine property: href
at Function.defineProperty (<anonymous>)
рд╣рдореНрдо, рд╣рдореЗрдВ рдХрд┐рд╕реА рддрд░рд╣ рд▓реЛрдЧреЛрдВ рдХреЛ reconfigure
рдкрд░ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреА рдкрдбрд╝ рд╕рдХрддреА рд╣реИред https://github.com/tmpvar/jsdom/blob/05a6deb6b91b4e02c53ce240116146e59f7e14d7/README.md#reconfigure -the-jsdom-with-reconfiguresettings
рдЗрд╕рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдПрдХ рдирдпрд╛ рдореБрджреНрджрд╛ рдЦреЛрд▓рд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдмрдВрдж рдерд╛: #5124
@SimenB рдореБрдЭреЗ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЬреЗрд╕реНрдЯ рдХреЛ рдЗрд╕реЗ рдареАрдХ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред JSDOM рдХреЛ window.location.assign()
рдХреЛ рдЗрдЪреНрдЫрд┐рдд рдХрд╛рд░реНрдп рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреА рдЪрд╛рд╣рд┐рдП рдФрд░ window.location.href
рдЖрджрд┐ рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдкреБрди: рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдореБрдЭреЗ TypeError: Could not parse "/upgrades/userlogin?hardwareSku=sku1351000490stgvha" as a URL
рдорд┐рд▓рд╛ рдХреНрдпреЛрдВрдХрд┐ jsdom рдХрд╛ рдЖрдзрд╛рд░ url рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ about:blank
рд╣реИ
рдореИрдВрдиреЗ jsdom
рдХреЛ рдЖрдзрд╛рд░ рдпреВрдЖрд░рдПрд▓ рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛, рдмрд┐рдирд╛ рд╕рдлрд▓рддрд╛ рдХреЗ 4 рдШрдВрдЯреЗ рдмрд┐рддрд╛рдП (рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИ, рдмрд╕ рдбреЛрдо рдореЗрдВ <base href='your_base_url' />
рдбрд╛рд▓реЗрдВ; рд▓реЗрдХрд┐рди , рдбреЛрдо jest
рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ
Object.defineProperty
рд╕рдорд╛рдзрд╛рди рдХреЗрд╡рд▓ jsdom
рдХреЗ рдкреБрд░рд╛рдиреЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ (рдЖрдкрдХреЛ ' jsdom
рдХреЗ рдмрд╛рдж рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рд╕рдВрдкрддреНрддрд┐ рддреНрд░реБрдЯрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ);
рдпрджрд┐ рдЖрдк jsdom
ver > 10 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ @th3fallen рдиреЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рд╣реИ рддреЛ рдпрд╣ рд╕рд╣реА рд╕рдорд╛рдзрд╛рди рд╣реИред
рдЙрдкрдпреЛрдЧ window.location.assign
рдЬрд╛рдиреЗ рдХрд╛ рд╕рд╣реА рддрд░реАрдХрд╛ рд╣реИ
рдпрджрд┐ рдЖрдк about:blank
рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХреБрдЫ рдЕрдиреНрдп url рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк testURL
config рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЖрдкрдХреЗ рдЙрддреНрддрд░ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж @SimenB ред
рдирд╣реАрдВ, рдореИрдВ рдмрд╛рдд рдХрд░ рд░рд╣рд╛ рдерд╛ base url
рдирд╣реАрдВ url
ред рдореЗрд░реЗ рдкрд╛рд╕ рдХреЛрдб рд╣реИ рдЬреЛ window.location.href="/login"
рдХрд░реЗрдЧрд╛ рдФрд░ jest
рдЪрд▓рд╛рддреЗ рд╕рдордп, jsdom
рд╢рд┐рдХрд╛рдпрдд рдлреЗрдВрдХ рдЕрдкрд╡рд╛рдж /login
рд╡реИрдз рдпреВрдЖрд░рдПрд▓ рдирд╣реАрдВ рд╣реИ
TypeError: Could not parse "/login" as a URL
рдореИрдВрдиреЗ jsdom
рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдХреА рдЬрд╛рдВрдЪ рдХреА рдФрд░ рдорд╣рд╕реВрд╕ рдХрд┐рдпрд╛ рдХрд┐ рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдореЗрд░реЗ рдкрд╛рд╕ рдЖрдзрд╛рд░ рдпреВрдЖрд░рдПрд▓ рд╕реЗрдЯрдЕрдк рдирд╣реАрдВ рд╣реИ (рдпрд╣ рдЖрдзрд╛рд░ рдкрддреЗ рдХреЗ рдмрд┐рдирд╛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдпреВрдЖрд░рдПрд▓ рдмрд╛рд░ рдореЗрдВ "/ рд▓реЙрдЧрд┐рди" рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИ)ред
рдХреЗ рд╕рд╛рде jsdom
, рдЖрдо рддреМрд░ рдкрд░ рд╣рдо рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрдзрд╛рд░ рдпреВрдЖрд░рдПрд▓ рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
global.jsdom = new JSDOM('<html><head> <base href="base_url" /></head></html>')
рд▓реЗрдХрд┐рди рдХреНрдпреЛрдВрдХрд┐ jest
рд╕реЗрдЯ рдЕрдк jsdom
, рдпрд╣ рд╣рдорд╛рд░реЗ рдирд┐рдпрдВрддреНрд░рдг рд╕реЗ рдмрд╛рд╣рд░ рд╣реИред
--- рдЕрджреНрдпрддрди: рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ jsdom
рдХреЛ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЬреЛрдбрд╝ рд╕рдХрддрд╛ рд╣реВрдВ рдФрд░ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ jsdom
рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВред
рдореБрдЭреЗ рддрдм рдПрдХ рд╕рдорд╛рдзрд╛рди рдорд┐рд▓рд╛ рдЬреЛ window.location.href=
рдХреЛ window.location.assign
$ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ рд╣реИ рдФрд░ assign
рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдирдХрд▓реА рд╣реЛрдирд╛ рд╣реИ рдФрд░ рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ
@bochen2014 рдЗрд╕ рдореБрджреНрджреЗ рдореЗрдВ jsdom рдХреЗ рдирдП рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рд╣реИ: #5124
рдЯреАрдПрд▓; рдбреЙ: рдЖрдк window.location.assign()
рдХрд╛ рдордЬрд╛рдХ рдЙрдбрд╝рд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ рдЖрдк jest-environment-jsdom-global
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдЖрдкрдХреЛ рдЙрдбрд╝рд╛рди рдореЗрдВ jsdom рдХреЛ рдлрд┐рд░ рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред
рдзрдиреНрдпрд╡рд╛рдж @ рд╕рд╛рдЗрдорди360
рд╡рд╣реА рдореИрдВрдиреЗ рдХрд┐рдпрд╛ ;-)
рдореИрдВрдиреЗ рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреНрд░рд╛рд░рдВрднрд┐рдХ urls
рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП jsdom.reconfigure
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛, рдФрд░ рдЬрдм рднреА рдореБрдЭреЗ рдХреЛрдб рдореЗрдВ рдпреВрдЖрд░рдПрд▓ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ (рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ), рддреЛ рдореИрдВ window.location.assign
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ рдФрд░ рдЗрд╕рдХрд╛ рдордЬрд╛рдХ рдЙрдбрд╝рд╛рддрд╛ рд╣реВрдВред рдЬреЛ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд┐рдпрд╛ред
рд╕рд┐рд░реНрдл рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЖрдкрдХреЗ jsdom рдХреЗ рд▓рд┐рдП рдпреВрдЖрд░рдПрд▓ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реА рдореБрджреНрджреЗ рдореЗрдВ рднрд╛рдЧ рд╕рдХрддреЗ рд╣реИрдВ/рдЪрд▓реЗрдВрдЧреЗ
// jest.config.js
module.exorts={
testURL: 'http://localhost:3000',
// or :
testEnvironmentOptions: {
url: "http://localhost:3000/",
referrer: "https://example.com/",
}
}
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣ рдЖрдкрдХреЗ рд╕рднреА рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП url рд╕реЗрдЯ рдХрд░реЗрдЧрд╛;
рдпрджрд┐ рдЖрдк рдХреБрдЫ рд╡рд┐рд╢реЗрд╖ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдПрдХ рдЕрд▓рдЧ рдпреВрдЖрд░рдПрд▓ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ jsdom.reconfigure
рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ;
рдЕрдЧрд░ рдЖрдкрдХреЛ рдпреВрдирд┐рдЯ рдЯреЗрд╕реНрдЯ рдХреЛрдб (рдпрд╛рдиреА рдкреНрд░реЛрдбрдХреНрд╢рди рдХреЛрдб) рдХреЗ рдмрд╛рд╣рд░ рдлреНрд▓рд╛рдИ рдкрд░ рдпреВрдЖрд░рдПрд▓ рдмрджрд▓рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ, рддреЛ рдЖрдкрдХреЛ window.location.assign
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдЗрд╕реЗ рдирдХрд▓реА рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛ред
рдЗрд╕реЗ рдЕрдиреНрдп рдЯрд┐рдХрдЯ рдкрд░ рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕реЗ рдпрд╣рд╛рдВ рдкреЛрд╕реНрдЯ рдХрд░реВрдВрдЧрд╛:
рдЬреЗрд╕реНрдЯ 21.2.1 рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди рдорд┐рд▓рд╛
рдареАрдХ рд╣реИ, рдЕрдм рддрдХ рдЗрд╕рдХрд╛ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рд╕рдорд╛рдзрд╛рди рд╣реИ:
рдЕрдкрдиреА рдЬреЗрд╕реНрдЯ рд╕реЗрдЯрд┐рдВрдЧ рдореЗрдВ рдЬрд╛рдПрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдореИрдВ package.json рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реВрдВрдЧрд╛):
"jest": {
"testURL": "http://localhost"
}
рдЕрдм рдЖрдкрдХреЗ рдкрд╛рд╕ рд╡рд┐рдВрдбреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рддрдХ рдкрд╣реБрдВрдЪ рд╣реЛрдЧреА рдФрд░ рдлрд┐рд░ рдЖрдк рдкрд░реАрдХреНрд╖рдг рдХреЗ рджреМрд░рд╛рди рдЕрдкрдиреА рдкрд╕рдВрдж рдХреЗ рдЕрдиреБрд╕рд╛рд░ URL рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
it('Should set href url to testURL', () => {
// Here I set href to my needs, opinionated stuff bellow
const newUrl = 'http://localhost/editor.html/content/raiweb/it/news/2018/02/altered-carbon-best-cyberpunk-tv-series-ever.html';
Object.defineProperty(window.location, 'href', {
writable: true,
value: newUrl
});
console.log(window.location.href);
});
it('Should set pathname url to testURL', () => {
// Here I set href to my needs, opinionated stuff bellow
const newUrl = '/editor.html/content/raiweb/it/news/2018/02/altered-carbon-best-cyberpunk-tv-series-ever.html';
Object.defineProperty(window.location, 'pathname', {
writable: true,
value: newUrl
});
console.log(window.location.pathname);
});
рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рдХреА рдорджрдж рдХрд░рддрд╛ рд╣реИред
@ petar-prog91 рдЬреЛ рдорджрджрдЧрд╛рд░ рдерд╛ред рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рдЯрд╛рдЗрдкреЛ рд╣реИ - рдпрд╣ testURL
рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рди рдХрд┐ TestURL
@BarthesSimpson рдиреЛрдЯрд┐рд╕ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдЕрджреНрдпрддрди рдЯрд┐рдкреНрдкрдгреАред
рдЗрд╕реЗ рдкреЛрд╕реНрдЯ рдХрд░рдирд╛ рдмрдВрдж рдХрд░реЛ, рдпрд╣ рдордЬрд╛рдХ рдкрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛": "^22.4.2"
рдирдорд╕реНрддреЗ,
рдореИрдВрдиреЗ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдЗрд╕рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рд╣реИ, рдореИрдВ рд╡реИрд╢реНрд╡рд┐рдХ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╣рдЯрд╛ рджреЗрддрд╛ рд╣реВрдВ рдФрд░ jsdom рдХреЗ рд╕рд╛рде рдПрдХ рдирдпрд╛ рдмрдирд╛ рджреЗрддрд╛ рд╣реВрдВ ...:
describe('componentDidMount', () => {
delete global.window
const window = (new JSDOM(``, {url: 'https://example.org/'})).window
global.window = window
describe('When window is defined', () => {
const spy = jest.spyOn(Utils, 'extractTokenFromUrl')
it('should call extract token function with window location', () => {
mount(<Header />)
expect(spy).toHaveBeenCalledWith('https://example.org/')
})
})
})
@UserNT рдкреБрд╖реНрдЯрд┐ рдХрд░реЗрдВ - рдпрд╣ TypeError: Cannot redefine property: href
рджреЗрддрд╛ рд╣реИ
@ annemarie35 рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ - ReferenceError: JSDOM is not defined
рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдЗрд╕рд╕реЗ рдХрд┐рд╕реА рдХреЛ рдорджрдж рдорд┐рд▓реЗрдЧреА рдпрд╛ рдирд╣реАрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдпрд╣реА рдХрд░ рд░рд╣рд╛ рд╣реВрдВред
const redirectTo = (url: string): void => {
if (process.env.NODE_ENV === "test") {
global.jsdom.reconfigure({ url: `${getBaseUrl()}${url}` });
} else {
window.location.replace(url);
}
};
рдПрдХ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦреЗрдВ рдФрд░ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдЙрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рддреЛ рдкрд░реАрдХреНрд╖рдг env рдореЗрдВ, рдпрд╣ url рднрд╛рдЧ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП jsdom.reconfigure url рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░реЗрдЧрд╛ред
рдореИрдВ рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд░рддрд╛ рд╣реВрдВ
export const clientFetchData = (
history: Object,
routes: Object,
store: Object
) => {
const callback = location =>
match({ routes, location }, (error, redirectLocation, renderProps) => {
if (error) {
redirectTo("/500.html");
} else if (redirectLocation) {
redirectTo(redirectLocation.pathname + redirectLocation.search);
} else if (renderProps) {
if (!isEmpty(window.prerenderData)) {
// Delete initial data so that subsequent data fetches can occur
window.prerenderData = undefined;
} else {
// Fetch mandatory data dependencies for 2nd route change onwards
trigger(
FETCH_DATA_HOOK,
renderProps.components,
getDefaultParams(store, renderProps)
);
}
trigger(
UPDATE_HEADER_HOOK,
renderProps.components,
getDefaultParams(store, renderProps)
);
} else {
redirectTo("/404.html");
}
});
history.listen(callback);
callback(history.getCurrentLocation());
};
рдЙрд╕рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЗ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ, рдпрд╣ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ
describe("# match route", () => {
it("should navigate to error page", () => {
fetchData.clientFetchData(history, components, store);
reactRouter.match.mock.calls[0][1](true);
expect(window.location.href).toEqual(`${SERVER_URL}/500.html`);
});
it("should redirect to /hello-world.html page", () => {
fetchData.clientFetchData(history, components, store);
reactRouter.match.mock.calls[0][1](undefined, {
pathname: "/hello-world.html",
search: ""
});
expect(window.location.href).toEqual(`${SERVER_URL}/hello-world.html`);
});
...
рдореИрдВрдиреЗ рдРрд╕рд╛ рдХрд░рдирд╛ рд╕рдорд╛рдкреНрдд рдХрд░ рджрд┐рдпрд╛ рдЬреЛ рдХрд╛рдо рдХрд░рддрд╛ рдерд╛:
global.window = new jsdom.JSDOM('', {
url: 'http://www.test.com/test?foo=1&bar=2&fizz=3'
}).window;
рдореЗрд░реЗ рдкрд╛рд╕ рдпрд╣ рдореЗрд░реА рдЬреЗрдПрд╕рдбреАрдУрдПрдо рд╕реЗрдЯрдЕрдк рдлрд╝рд╛рдЗрд▓ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рд╣реИ:
const { JSDOM } = require('jsdom');
const jsdom = new JSDOM('<!doctype html><html><body><div id="root"></div></body></html>', {
url: "http://test.com"
});
const { window } = jsdom;
function copyProps(src, target) {
const props = Object.getOwnPropertyNames(src)
.filter(prop => typeof target[prop] === 'undefined')
.map(prop => Object.getOwnPropertyDescriptor(src, prop));
Object.defineProperties(target, props);
}
global.document = window.document;
global.window = window;
global.navigator = {
userAgent: 'node.js',
};
global.HTMLElement = window.HTMLElement;
рдЬреЗрд╕реНрдЯ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдореЗрдВ "testURL": " http://localhost/ " рд╕реЗрдЯ рдХрд░рдХреЗ рдЗрд╕реЗ рдареАрдХ рдХрд┐рдпрд╛ (рдореИрдВ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ)ред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдпрд╣ " about:blank " рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдпрд╣ JSDOM рддреНрд░реБрдЯрд┐ рдЙрддреНрдкрдиреНрди рдХрд░ рд░рд╣рд╛ рдерд╛ (рдЖрдк "about:blank" url рдХреЛ рдХрд┐рд╕реА рдЕрдиреНрдп рдЪреАрдЬрд╝ рдореЗрдВ рдирд╣реАрдВ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ)ред
рд╕рд╛рдзрди:
http://jestjs.io/docs/en/configuration#testurl -string
https://github.com/jsdom/jsdom/issues/1372
рдореБрдЭреЗ рдпрд╣ рдкреЛрд╕реНрдЯ рдмрд╣реБрдд рдорджрджрдЧрд╛рд░ рд▓рдЧреА: https://www.ryandoll.com/post/2018/3/29/jest-and-url-mocking
"рдЕрдкрдиреЗ рдЬреЗрд╕реНрдЯ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдореЗрдВ, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реЗрдЯ рдХрд░рдирд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ:
"testURL": "https://www.somthing.com/test.html"
рдлрд┐рд░ рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдкрд╣рд▓реЗ () рдЕрдиреБрднрд╛рдЧ рдореЗрдВ, рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЖрд╡рд╢реНрдпрдХрддрд╛рдиреБрд╕рд╛рд░ рдкрде рдмрджрд▓реЗрдВ
рдЗрддрд┐рд╣рд╛рд╕ред рдкреБрд╢рд╕реНрдЯреЗрдЯ ()ред
window.history.pushState({}, 'Test Title', '/test.html?query=true');
рд╡реЛрдЗрд▓рд╛! рдЕрдм рдЖрдк рдХрд┐рд╕реА рднреА рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдЕрдкрдирд╛ рд░рд╛рд╕реНрддрд╛ рдмрджрд▓рддреЗ рд╣реИрдВ, рдмрд┐рдирд╛ рдХрд┐рд╕реА jsdom рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд┐рдП, рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдзрд╛рдЧреЗ рдореЗрдВ рдЕрдиреНрдп рд╕реБрдЭрд╛рд╡ рджреЗрддреЗ рд╣реИрдВред рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдореБрдЭреЗ рдпрд╣ рд╕рдорд╛рдзрд╛рди рдХрд┐рд╕ рдзрд╛рдЧреЗ рдкрд░ рдорд┐рд▓рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЙрд╕ рджреЗрд╡ рдХреЛ рдмрдзрд╛рдИ рдЬрд┐рд╕рдиреЗ рдЗрд╕реЗ рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ рд╣реИ!"
@ рдорд╛рдЗрдХ-рдЯреНрд░рд╛рди рдпреВ рд░реЙрдХ! рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛, рдЗрддрдирд╛ рдЖрд╕рд╛рдиред рдореБрдЭреЗ testURL рд╕реЗрдЯрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рдереАред
@ рдорд╛рдЗрдХ-рдЯреНрд░рд╛рди рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ! рдзрдиреНрдпрд╡рд╛рдж! рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореБрдЭреЗ testURL
рдпрд╛ beforeEach
рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рдереАред рдореИрдВрдиреЗ рдЕрднреА рдХрд┐рдпрд╛:
window.history.pushState({}, 'Test Title', '/test.html?query=true');
рдФрд░ рдЕрдм рдореБрдЭреЗ Object.defineProperty
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ
@jcmcneal рдзрдиреНрдпрд╡рд╛рдж рдЬрд┐рд╕рдиреЗ рдореЗрд░реЗ рд▓рд┐рдП рдпрд╣ рдХрд┐рдпрд╛! (рдордЬрд╛рдХ 23.0.0)
рдпрджрд┐ рдЖрдкрдХрд╛ рд▓рдХреНрд╖реНрдп window
рд╡рд╕реНрддреБ рдХрд╛ рдЙрдкрд╣рд╛рд╕ рдХрд░рдирд╛ рд╣реИ, рддреЛ рдпрд╣рд╛рдВ рдореЗрд░рд╛ (рдЗрддрдирд╛ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ) рд╕рдорд╛рдзрд╛рди рд╣реИ:
рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рдПрдВ (рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╕рд╣реА рд╢рдмреНрдж рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдмрд┐рдВрджреБ рдорд┐рд▓ рдЬрд╛рдПрдЧрд╛) рд╡рд░реНрдЧ:
// window.js
export const { location } = window;
рдЕрдкрдиреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХреЛрдб рдореЗрдВ, рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде window
рд╕реНрд╡реИрдк рдХрд░реЗрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП win
// myFile.js
import * as win from './window';
export function doSomethingThatRedirectsPage() {
win.location.href = 'google.com';
}
рдлрд┐рд░, рдЕрдкрдиреЗ рдордЬрд╝рд╛рдХ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ, рдЖрдк рдмрд╕ рдЙрдирдХрд╛ рдордЬрд╝рд╛рдХ рдЙрдбрд╝рд╛рддреЗ рд╣реИрдВ рддрд╛рдХрд┐ jsdom рд╢рд┐рдХрд╛рдпрдд рди рдХрд░реЗред рдЖрдк рдЙрди рдкрд░ рджрд╛рд╡рд╛ рднреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
// myFile.test.js
import * as myFile from './myFile';
import * as win from './window';
it('should redirect', () => {
win.location = { href: 'original-url' };
expect(win.location.href).toBe('original-url');
myFile.doSomethingThatRedirectsPage();
expect(win.location.href).toBe('google.com');
});
@ рдорд╛рдЗрдХ-рдЯреНрд░рд╛рди, @jcmcneal рдзрдиреНрдпрд╡рд╛рдж! рд╕рднреА рдкрд╣рд▓реВ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ!
рд╡рд░реНрдЧ SSOtestComponent React.Component рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рддрд╛ рд╣реИ {
componentDidMount() {
let isSuccess = this.props.location.pathname === '/sso/test/success' ? true : false
window.opener.postMessage({ type: "sso_test", isSuccess,...this.props.location.query}, window.location.origin)
}
onSsoAuthenticate() {
}
componentWillUnmount() {
}
render() {
return (<Loader />);
}
}
рдореЙрдбреНрдпреВрд▓.рдПрдХреНрд╕рдкреЛрд░реНрдЯреНрд╕ = рдПрд╕рдПрд╕рдУрдЯреЗрд╕реНрдЯ рдХреЙрдореНрдкреЛрдиреЗрдВрдЯ;
рдореИрдВ enjyme рдФрд░ рдЬреЗрд╕реНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдпреВрдирд┐рдЯ рдЯреЗрд╕реНрдЯ рдХреЗрд╕ рд▓рд┐рдЦ рд░рд╣рд╛ рд╣реВрдВ, рд╕реНрдерд┐рддрд┐ рд╡рд┐рдВрдбреЛ рдХреИрд╕реЗ рд▓рд┐рдЦреЗрдВрдЧреЗред рд╕реНрдерд╛рди ... рдХреГрдкрдпрд╛ рдЙрддреНрддрд░ рджреЗрдВ
рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд┐рдпрд╛
const location = JSON.stringify(window.location);
delete window.location;
Object.defineProperty(window, 'location', {
value: JSON.parse(location)
});
Object.defineProperty(global.location, 'href', {
value: 'http://localhost/newURL',
configurable: true
});
рдЬрд╕реНрдЯ рд╕рдВрд╕реНрдХрд░рдг 23.6.0 . рдкрд░
рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд┐рдпрд╛ред
delete global.window.location
global.window.location = { href: 'https://test-domain.com.br', ...anyOptions }
@FelipeBohnertPaetzold рдзрдиреНрдпрд╡рд╛рдж
рдзрдиреНрдпрд╡рд╛рдж @FelipeBohnertPaetzoldред рдореИрдВ рдЕрдкрдиреЗ рдХреЛрдб рдореЗрдВ location.host
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рдерд╛, рдЗрд╕рд▓рд┐рдП рдкрд╛рдпрд╛ рдХрд┐ рдореБрдЭреЗ рдПрдХ рдкреВрд░реНрдг рд╕реНрдерд╛рди рд╡рд╕реНрддреБ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкреНрд░рддреНрдпреЗрдХ рд╕реНрдерд╛рди рд╕рдВрдкрддреНрддрд┐ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдиреЗ рдореЗрд░реЗ рд▓рд┐рдП рдмреЗрд╣рддрд░ рдХрд╛рдо рдХрд┐рдпрд╛:
delete global.window.location;
global.window.location = new URL("https://www.ediblecode.com/");
рдзреНрдпрд╛рди рджреЗрдВ, рдпрд╣ рдиреЛрдб 6.13+ рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ ( рдпреВрдЖрд░рдПрд▓ рдХреНрд▓рд╛рд╕ рдбреЙрдХреНрд╕ рджреЗрдЦреЗрдВ) рдФрд░ рдореИрдВ рдЬреЗрд╕реНрдЯ 24 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рдерд╛ред
рдпрд╣ рднреА рдзреНрдпрд╛рди рджреЗрдВ, рдпрд╣ рд╕рд╛рдкреЗрдХреНрд╖ URL рдХреЗ рд╕рд╛рде рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, https://url.spec.whatwg.org/#example -url-parsing рджреЗрдЦреЗрдВред
рдпрд╣ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрд░реЗ рд▓рд┐рдП рдЬреЗрд╕реНрдЯ 24.0.0 рдФрд░ рдиреЛрдб 10.15.0 рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ:
import { mockWindow } from './testUtils';
mockWindow(window, 'http://localhost');
describe('setup tests', () => {
describe('window.location', () => {
const saveLocation = window.location;
afterAll(() => {
delete window.location;
window.location = saveLocation;
});
it('location.assign assigns a location', () => {
window.location.assign('http://foo.com');
expect(window.location.href).toBe('http://foo.com/');
(window.location.assign as jest.Mock<void, [string]>).mockClear();
});
it('location.replace replaces a location', () => {
window.location.replace('http://bar.com');
expect(window.location.href).toBe('http://bar.com/');
(window.location.replace as jest.Mock<void, [string]>).mockClear();
});
it('location.reload is a spy', () => {
window.location.reload();
expect(window.location.reload).toHaveBeenCalledTimes(1);
(window.location.reload as jest.Mock).mockClear();
});
});
});
interface MockedLocation extends Location {
assign: jest.Mock<void, [string]>;
reload: jest.Mock;
replace: jest.Mock<void, [string]>;
}
interface MockedWindow extends Window {
location: MockedLocation;
}
export function mockWindow(win: Window = window, href = win.location.href) {
const locationMocks: Partial<MockedLocation> = {
assign: jest.fn().mockImplementation(replaceLocation),
reload: jest.fn(),
replace: jest.fn().mockImplementation(replaceLocation),
};
return replaceLocation(href);
function replaceLocation(url: string) {
delete win.location;
// tslint:disable-next-line:no-any
win.location = Object.assign(new URL(url), locationMocks) as any;
return win as MockedWindow;
}
}
import { mockWindow } from './testUtils';
describe('test utils', () => {
describe('mockWindow', () => {
const saveLocation = window.location;
afterAll(() => {
delete window.location;
window.location = saveLocation;
});
it('location.assign assigns a location', () => {
const { assign } = mockWindow().location;
assign('http://foo.com');
expect(window.location.href).toBe('http://foo.com/');
assign.mockClear();
});
it('location.replace replaces a location', () => {
const { replace } = mockWindow().location;
replace('http://bar.com');
expect(window.location.href).toBe('http://bar.com/');
replace.mockClear();
});
it('location.reload is a spy', () => {
const { reload } = mockWindow().location;
reload();
expect(window.location.reload).toHaveBeenCalledTimes(1);
reload.mockClear();
});
});
});
@jedmao
рдЕрд░реЗ, рдпрд╛рд░) рдмрдврд╝рд┐рдпрд╛ рдЙрдкрдпреЛрдЧ!
рдореЗрд░реЗ рд▓рд┐рдП src/setupTests.test.ts
рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рдереЛрдбрд╝рд╛ рдмреЗрдорд╛рдиреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдиреЗ src/testUtils.test.ts рдореЗрдВ mockWindow
рдЙрдкрдпреЛрдЧ рдХрд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рд╣реИред рддреЛ, src/setupTests.ts
рдХреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдпрд╣ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ, рдХрд┐ рдЖрдк рд╕рд╣реА рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде mockWindow
рдХрд╣рддреЗ рд╣реИрдВред
рдЖрдкрдХреЛ рдзрдиреНрдпрд╡рд╛рдж)
@tzvipm @jup-iter рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдореИрдВрдиреЗ рдЕрднреА рдЬрд╛рд░реА рдХрд┐рдпрд╛ @jedmao/storage
рдФрд░ @jedmao/location
, рдЬреЛ рджреЛрдиреЛрдВ рдЬреЗрд╕реНрдЯ рдХреЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрдЬреНрдЮреЗрдпрд╡рд╛рджреА рд╣реИрдВред рдЖрдкрдХреЛ spyOn
рдмрд┐рдирд╛ рдХреЛрдИ рдЕрддрд┐рд░рд┐рдХреНрдд рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦреЗ рдЙрдкрдпреБрдХреНрдд рддрд░реАрдХреЛрдВ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐ npm рдкреИрдХреЗрдЬ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред
рдпрджрд┐ рдЖрдкрдХреЛ Vue рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдпрд╣ рддреНрд░реБрдЯрд┐ рд╣реЛ рд░рд╣реА рд╣реИ, рддреЛ рдмрд╕ this.$router.go({...}) рдХреЗ рдмрдЬрд╛рдп this.$router.go({...})
this.$router.push({...})
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдХреЛрдб рдХреЛ рд▓рд╛рдЗрди 1 рдкрд░ рд░рдЦреЗрдВ:
delete global.window.location;
global.window.location = "";
рдПрдХ рдХреНрд▓рд┐рдХ рдИрд╡реЗрдВрдЯ рдЬреЛ рд╡рд┐рдВрдбреЛ рдХреЛ рдмрджрд▓ рд░рд╣рд╛ рд╣реИред рд╕реНрдерд╛рди рдЕрдм рдХреИрдкреНрдЪрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
"рдЬрд╕реНрдЯ": "^ 23.6.0"
рдпрд╣ рд╕рд╣реА рд╣реИ:
delete window.location;
window.location = Object.assign({}, window.location);
const url = Object.assign({}, new URL('http://google.com'));
Object.keys(url).forEach(prop => (window.location[prop] = url[prop]));
рдпрд╛ рдлрд┐рд░ рдмреЗрд╣рддрд░...
delete (global as any).window;
(global as any).window = new JSDOM(undefined, { url: 'http://google.com' }).window;
рдЖрдк рд╕рд╣реА рд╣реИрдВ, рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ jsdom рдореБрджреНрджрд╛ рд╣реИред рдлреЗрд╕рдмреБрдХ рдкрд░, рд╣рдордиреЗ рдЗрд╕рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛ рдХрд┐рдпрд╛ рд╣реИ, рд╡рд╣ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣реИ:
Object.defineProperty(window.location, 'href', { writable: true, value: 'some url' });
рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдБрдХрд┐ рд╣рдо рдЕрднреА рднреА рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ jsdom 7 рдкрд░ рд╣реИрдВред
рдореИрдВ рдЗрд╕реЗ рдмрдВрдж рдХрд░ рджреВрдВрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐
Object.defineProperty
рдЪреАрдЬреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдареАрдХ рд╣реИред рдЕрдЧрд░ рд╡рд╣ рдЖрдкрдХреЗ рд▓рд┐рдП jsdom 8 рдореЗрдВ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдореБрдЭреЗ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓рдиреЗ рдореЗрдВ рдЦреБрд╢реА рд╣реЛ рд░рд╣реА рд╣реИред
рд╣рд╛рдБ, рдореЗрд░реЗ рдкрд╛рд╕ location.search
рдФрд░ location.hash
рдХреЗ рд╕рд╛рде рдХреБрдЫ рдлрд╝рдВрдХреНрд╢рди рдбреАрд▓ рд╣реИрдВ, рдФрд░ рдЬреИрд╕рд╛ рдХрд┐ рдЖрдкрдиреЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рд╣реИ, рдореИрдВ рдЗрд╕реЗ defineProperty
рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛!
рдЬрдм рдореИрдВрдиреЗ jest
рд╕рд╛рдЗрд▓реЗрдВрдЯ рдореЛрдб рдХреЛ рдмрдВрдж рдХрд┐рдпрд╛, рддреЛ рдореБрдЭреЗ рдпрд╣ рдорд┐рд▓рд╛: Error: Not implemented: navigation (except hash changes)
console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Not implemented: navigation (except hash changes)
at module.exports (/home/ghlandy/projects/wdph-utils/node_modules/jsdom/lib/jsdom/browser/not-implemented.js:9:17)
at navigateFetch (/home/ghlandy/projects/wdph-utils/node_modules/jsdom/lib/jsdom/living/window/navigation.js:74:3)
at exports.navigate (/home/ghlandy/projects/wdph-utils/node_modules/jsdom/lib/jsdom/living/window/navigation.js:52:3)
at LocationImpl._locationObjectNavigate (/home/ghlandy/projects/wdph-utils/node_modules/jsdom/lib/jsdom/living/window/Location-impl.js:29:5)
at LocationImpl.assign (/home/ghlandy/projects/wdph-utils/node_modules/jsdom/lib/jsdom/living/window/Location-impl.js:213:10)
at Location.assign (/home/ghlandy/projects/wdph-utils/node_modules/jsdom/lib/jsdom/living/generated/Location.js:93:25)
at Object.assign (/home/ghlandy/projects/wdph-utils/src/__tests__/url.test.js:6:14)
at Object.asyncJestLifecycle (/home/ghlandy/projects/wdph-utils/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:53:37)
at resolve (/home/ghlandy/projects/wdph-utils/node_modules/jest-jasmine2/build/queueRunner.js:43:12)
at new Promise (<anonymous>) undefined
рдФрд░ рдЕрдм рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдореИрдВ рдЕрдкрдиреЗ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХреИрд╕реЗ рдХрд░реВрдВред
рдХрд┐рд╕реА рдХреЗ рдкрд╛рд╕ рдкрд░реАрдХреНрд╖рдг рдХреЛ рдмрджрд▓рдиреЗ рдХрд╛ рдХреЛрдИ рднреА рддрд░реАрдХрд╛ рд╣реИ url
рдЖрдк рд╕рд╣реА рд╣реИрдВ, рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ jsdom рдореБрджреНрджрд╛ рд╣реИред рдлреЗрд╕рдмреБрдХ рдкрд░, рд╣рдордиреЗ рдЗрд╕рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛ рдХрд┐рдпрд╛ рд╣реИ, рд╡рд╣ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣реИ:
Object.defineProperty(window.location, 'href', { writable: true, value: 'some url' });
рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдБрдХрд┐ рд╣рдо рдЕрднреА рднреА рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ jsdom 7 рдкрд░ рд╣реИрдВред
рдореИрдВ рдЗрд╕реЗ рдмрдВрдж рдХрд░ рджреВрдВрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐Object.defineProperty
рдЪреАрдЬреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдареАрдХ рд╣реИред рдЕрдЧрд░ рд╡рд╣ рдЖрдкрдХреЗ рд▓рд┐рдП jsdom 8 рдореЗрдВ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдореБрдЭреЗ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓рдиреЗ рдореЗрдВ рдЦреБрд╢реА рд╣реЛ рд░рд╣реА рд╣реИредрд╣рд╛рдБ, рдореЗрд░реЗ рдкрд╛рд╕
location.search
рдФрд░location.hash
рдХреЗ рд╕рд╛рде рдХреБрдЫ рдлрд╝рдВрдХреНрд╢рди рдбреАрд▓ рд╣реИрдВ, рдФрд░ рдЬреИрд╕рд╛ рдХрд┐ рдЖрдкрдиреЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рд╣реИ, рдореИрдВ рдЗрд╕реЗdefineProperty
рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛!рдЬрдм рдореИрдВрдиреЗ
jest
рд╕рд╛рдЗрд▓реЗрдВрдЯ рдореЛрдб рдХреЛ рдмрдВрдж рдХрд┐рдпрд╛, рддреЛ рдореБрдЭреЗ рдпрд╣ рдорд┐рд▓рд╛:Error: Not implemented: navigation (except hash changes)
console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29 Error: Not implemented: navigation (except hash changes) at module.exports (/home/ghlandy/projects/wdph-utils/node_modules/jsdom/lib/jsdom/browser/not-implemented.js:9:17) at navigateFetch (/home/ghlandy/projects/wdph-utils/node_modules/jsdom/lib/jsdom/living/window/navigation.js:74:3) at exports.navigate (/home/ghlandy/projects/wdph-utils/node_modules/jsdom/lib/jsdom/living/window/navigation.js:52:3) at LocationImpl._locationObjectNavigate (/home/ghlandy/projects/wdph-utils/node_modules/jsdom/lib/jsdom/living/window/Location-impl.js:29:5) at LocationImpl.assign (/home/ghlandy/projects/wdph-utils/node_modules/jsdom/lib/jsdom/living/window/Location-impl.js:213:10) at Location.assign (/home/ghlandy/projects/wdph-utils/node_modules/jsdom/lib/jsdom/living/generated/Location.js:93:25) at Object.assign (/home/ghlandy/projects/wdph-utils/src/__tests__/url.test.js:6:14) at Object.asyncJestLifecycle (/home/ghlandy/projects/wdph-utils/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:53:37) at resolve (/home/ghlandy/projects/wdph-utils/node_modules/jest-jasmine2/build/queueRunner.js:43:12) at new Promise (<anonymous>) undefined
рдФрд░ рдЕрдм рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдореИрдВ рдЕрдкрдиреЗ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХреИрд╕реЗ рдХрд░реВрдВред
рдХрд┐рд╕реА рдХреЗ рдкрд╛рд╕ рдкрд░реАрдХреНрд╖рдг рдХреЛ рдмрджрд▓рдиреЗ рдХрд╛ рдХреЛрдИ рднреА рддрд░реАрдХрд╛ рд╣реИ
url
рдФрд░ рдореЗрд░реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдПрдХ рдлрд╝реАрд▓реНрдб рд╣реИ testURL
рдореЗрдВ jest.config.js
рдлрд╝рд╛рдЗрд▓ рдХрд╛рдо рдХрд░ рд╕рдХрддреА рд╣реИред рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рдореИрдВ рдкреНрд░рддреНрдпреЗрдХ рдкрд░реАрдХреНрд╖рдг рд╕реЗ рдкрд╣рд▓реЗ testURL рдмрджрд▓рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред
рдореБрдЭреЗ рдпрд╣ рдкреЛрд╕реНрдЯ рдмрд╣реБрдд рдорджрджрдЧрд╛рд░ рд▓рдЧреА: https://www.ryandoll.com/post/2018/3/29/jest-and-url-mocking
"рдЕрдкрдиреЗ рдЬреЗрд╕реНрдЯ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдореЗрдВ, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реЗрдЯ рдХрд░рдирд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ:
"testURL": "https://www.somthing.com/test.html"
рдлрд┐рд░ рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдкрд╣рд▓реЗ () рдЕрдиреБрднрд╛рдЧ рдореЗрдВ, рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЖрд╡рд╢реНрдпрдХрддрд╛рдиреБрд╕рд╛рд░ рдкрде рдмрджрд▓реЗрдВ
рдЗрддрд┐рд╣рд╛рд╕ред рдкреБрд╢рд╕реНрдЯреЗрдЯ ()редwindow.history.pushState({}, 'Test Title', '/test.html?query=true');
рд╡реЛрдЗрд▓рд╛! рдЕрдм рдЖрдк рдХрд┐рд╕реА рднреА рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдЕрдкрдирд╛ рд░рд╛рд╕реНрддрд╛ рдмрджрд▓рддреЗ рд╣реИрдВ, рдмрд┐рдирд╛ рдХрд┐рд╕реА jsdom рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд┐рдП, рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдзрд╛рдЧреЗ рдореЗрдВ рдЕрдиреНрдп рд╕реБрдЭрд╛рд╡ рджреЗрддреЗ рд╣реИрдВред рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдореБрдЭреЗ рдпрд╣ рд╕рдорд╛рдзрд╛рди рдХрд┐рд╕ рдзрд╛рдЧреЗ рдкрд░ рдорд┐рд▓рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЙрд╕ рджреЗрд╡ рдХреЛ рдмрдзрд╛рдИ рдЬрд┐рд╕рдиреЗ рдЗрд╕реЗ рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ рд╣реИ!"
рдмреЗрд╣рддрд░реАрди рдЙрдкрд╛рдп!!! рдЖрдкрдХрд╛ рдмрд╣реБрдд рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рдж! @ рдорд╛рдЗрдХ-рдЯреНрд░рд╛рди
рдореИрдВ рдЗрд╕ рддрд░рд╣ рдПрдХ рдЫреЛрдЯрд╛ рдФрд░ рдЖрдХреНрд░рд╛рдордХ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рдЪрд╛рд╣рддрд╛ рдерд╛!
рдЗрд╕реЗ рдЬреВрди 2019 рддрдХ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдпрд╣ рдХрд░рдирд╛ рдерд╛:
delete global.window.location;
global.window = Object.create(window);
global.window.location = {
port: '123',
protocol: 'http:',
hostname: 'localhost',
};
рдореИрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ ....
window.history.pushState({}, '', `${url}/`);
рд╢рд╛рдпрдж рдореЗрд░реЗ JSDOMTestWrapper рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдХрд┐рд╕реА рдХреА рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ
/** <strong i="6">@type</strong> {Window} */
this.testWindowObject = Object.create(window);
const wnd = this.testWindowObject;
this.testWindowObject.history = {
state: null,
prev: { /** <strong i="7">@todo</strong> immutable stack with the go(step) method emulation */
state: null,
pathname: null,
search: null,
},
go(step) {
logger.special('history go called', step);
logger.warn('history go has not supported yet');
},
back() {
this.state = this.prev.state;
wnd.location.pathname = this.prev.pathname;
wnd.location.search = this.prev.search;
const eventData = this.state ? { url: this.state.displayURL, newState: this.state, type: 'push' } : null;
wnd.sm.eventsService.triggerEvent(ROUTER_EVENTS.ROUTE_PUSH, eventData);
wnd.sm.urlService.simpleRouteTo(`${ wnd.location.pathname || '' }${ wnd.location.search || '' }`);
logger.special('history back emulated');
},
pushState(state, title, url) {
this.prev.state = Object.assign({}, this.state);
this.prev.pathname = '' + wnd.location.pathname;
this.prev.search = '' + wnd.location.search;
this.state = state;
if (title) wnd.document.title = title;
const [p, s] = url.split('?');
wnd.location.pathname = p;
wnd.location.search = s ? `?${ s }` : '';
logger.special('push state emulated', { state, title, url });
},
replaceState(state, title, url) {
this.prev.state = Object.assign({}, this.state);
this.prev.pathname = '' + wnd.location.pathname;
this.prev.search = '' + wnd.location.search;
this.state = state;
if (title) wnd.document.title = title;
const [p, s] = url.split('?');
wnd.location.pathname = p;
wnd.location.search = s ? `?${ s }` : '';
logger.special('replace state emulated', { state, title, url });
logger.special('test: urlService.getPathName()', wnd.sm.urlService.getPathName());
},
};
this.testWindowObject.innerWidth = WND_WIDTH;
this.testWindowObject.innerHeight = WND_HEIGHT;
this.testWindowObject.fetch = fetchFn;
this.testWindowObject.localStorage = lstMock;
this.testWindowObject.scrollTo = (x, y) => {
/** not implemented yet https://github.com/jsdom/jsdom/issues/1422 */
if (typeof x !== 'number' && (x.left || x.top)) {
y = x.top;
x = x.left;
}
// logger.info(`window.scrollTo(${ x }, ${ y })`);
};
if (fetchFn === JSDOMTestWrapper.FETCH_FN.DEV_MOCK) {
global.Request = RequestMock;
this.testWindowObject.Request = RequestMock;
}
if (href) {
this.testWindowObject.location = Object.assign({}, this.testWindowObject.location, urlapi.parse(href));
}
else {
this.testWindowObject.location = Object.assign({}, this.testWindowObject.location);
}
(function(ELEMENT) {
ELEMENT.matches = ELEMENT.matches || ELEMENT.mozMatchesSelector || ELEMENT.msMatchesSelector || ELEMENT.oMatchesSelector || ELEMENT.webkitMatchesSelector;
ELEMENT.closest = ELEMENT.closest || function closest(selector) {
if (!this) return null;
if (this.matches(selector)) return this;
if (!this.parentElement) {return null}
else return this.parentElement.closest(selector)
};
ELEMENT.getBoundingClientRect = ELEMENT.getBoundingClientRect || (() =>
({ bottom: WND_HEIGHT, height: WND_HEIGHT, left: 0, right: WND_WIDTH, top: 0, width: WND_WIDTH, x: 0, y: 0 }));
}(Element.prototype));
this.testWindowObject.getBoundingClientRect = () =>
({ bottom: WND_HEIGHT, height: WND_HEIGHT, left: 0, right: WND_WIDTH, top: 0, width: WND_WIDTH, x: 0, y: 0 });
this.testWindowObject.__resizeListeners__ = [];
this.testWindowObject.__resizeTriggers__ = {};
this.testWindowObject._detectElementResize = {
removeResizeListener: () => {},
};
this.testWindowObject.matchMedia = jest.fn().mockImplementation(query => {
return {
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
};
});
this.rftpr = () => {};
this.mode = mode;
this.renderFirstTimePromise = new Promise((resolve) => {
this.rftpr = resolve;
});
this.marpr = () => {};
this.mobileAppReadyPromise = new Promise((resolve) => {
this.marpr = resolve;
});
if (mode === JSDOMTestWrapper.MODE.MOBILE_APP) {
this.testWindowObject.navigator = Object.assign({}, this.testWindowObject.navigator, {
language: storeKey,
appVersion: '5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Mobile Safari/537.36',
userAgent: 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Mobile Safari/537.36',
vendor: 'Google Inc.',
});
global.intercom = {
registerUnidentifiedUser: jest.fn(),
registerForPush: jest.fn(),
};
}
const XApp = mode ? MobileApp : App;
const app = <XApp window={ this.testWindowObject } rftResolve={ this.rftpr } storeKey={ storeKey } apiHost={ apiVersion } forceMobileDetection={ mode } />;
render(app, this.testWindowObject.document.body);
if (mode === JSDOMTestWrapper.MODE.MOBILE_APP) {
setTimeout(() => {
this.testWindowObject.sm.deviceService.appRestorePathHasInit = this.marpr;
this.testWindowObject.sm.deviceService.fireEvent(this.testWindowObject.document, 'deviceready');
}, 200);
}
рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг 27 рд╕рд┐рддрдВрдмрд░, 2019 рддрдХ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ: https://stackoverflow.com/a/54034379/1344144
global.window = Object.create(window);
const url = "http://dummy.com";
Object.defineProperty(window, "location", {
value: {
href: url
},
writable: true
});
рдПрдХ рдФрд░ рд╕рдорд╛рдзрд╛рди рдореЗрд░реЗ рд▓рд┐рдП рд╡рд░реНрддрдорд╛рди рдореЗрдВ jsdom
рд▓рд┐рдЦреЗ рдмрд┐рдирд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:
testURL
рдХреЛ jest.config.js
рдореЗрдВ рд╕реЗрдЯ рдХрд┐рдпрд╛ рд╣реИ, рдЪрд╛рд╣реЗ рдХреЛрдИ рднреА рдореВрд▓реНрдп рд╣реЛ:// jest.config.js
'testURL': 'https://someurl.com'
рдЖрдкрдХреА рдкрд░реАрдХреНрд╖рдг рдлрд╝рд╛рдЗрд▓ рдореЗрдВ:
window.history.pushState({}, 'Mocked page title', 'www.yoururl.com');
рд╕реЗ рд╕реАрдЦрд╛: https://www.ryandoll.com/post/2018/3/29/jest-and-url-mockingред рд░рдпрд╛рди рдХреЛ рдзрдиреНрдпрд╡рд╛рдж!
рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛:
рд▓реЗрдЦрди рддреНрд░реБрдЯрд┐: рд╕рдЦреНрдд рдореЛрдб рдореЗрдВ рдХреЗрд╡рд▓ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЧреБрдгреЛрдВ рдХреЛ рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рд╣реИ
it("should save hash when history is not found", () => {
const historyBkp = global.window.history;
delete global.window.history;
global.window.history = false;
externalLoader.savePageURL(urlTraining);
expect(window.location.hash).to.be.equal(`#page=${urlTraining}`);
global.window.history = historyBkp;
window.location.hash = "";
});
рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛:
рд▓реЗрдЦрди рддреНрд░реБрдЯрд┐: рд╕рдЦреНрдд рдореЛрдб рдореЗрдВ рдХреЗрд╡рд▓ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЧреБрдгреЛрдВ рдХреЛ рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рд╣реИ
it("should save hash when history is not found", () => { const historyBkp = global.window.history; delete global.window.history; global.window.history = false; externalLoader.savePageURL(urlTraining); expect(window.location.hash).to.be.equal(`#page=${urlTraining}`); global.window.history = historyBkp; window.location.hash = ""; });
рдЗрд╕реЗ рд╡реИрд╢реНрд╡рд┐рдХ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЬреЛрдбрд╝реЗрдВред
рд╡реИрд╢реНрд╡рд┐рдХ.рд╡рд┐рдВрдбреЛ.рд╕реНрдерд╛рди рд╣рдЯрд╛рдПрдВ;
рд╡реИрд╢реНрд╡рд┐рдХ.рд╡рд┐рдВрдбреЛ.рд╕реНрдерд╛рди = "";
рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг 27 рд╕рд┐рддрдВрдмрд░, 2019 рддрдХ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ: https://stackoverflow.com/a/54034379/1344144
global.window = Object.create(window); const url = "http://dummy.com"; Object.defineProperty(window, "location", { value: { href: url }, writable: true });
рдореИрдВ рд╕реНрдерд╛рди рдХреЗ рд╕рд╛рде рдХреБрдЫ рдЗрд╕реА рддрд░рд╣ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рдЕрд╕рд╛рдЗрди рдХрд░реЗрдВ, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЕрдм рдФрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИред
рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдЬреЗрд╕реНрдЯ 24.9.0 . рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ
window.history.replaceState({}, 'Test Title', '/test?userName=James&userNumber=007');
рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдЬреЗрд╕реНрдЯ 24.9.0 . рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ
window.history.replaceState({}, 'Test Title', '/test?userName=James&userNumber=007');
рдЗрд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдХреЛрдб async рдмрдирд╛рдирд╛ рдкрдбрд╝рд╛ рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдПрдХ рд╡рд╛рджреЗ рдХреЗ рдЕрдВрджрд░ рдХреЛрдб рдЪрд▓рд╛ рд░рд╣рд╛ рдерд╛ред
рддреЛ рдЕрдм рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ
vuex рдПрдХреНрд╢рди рдореЗрдВ рдЪреЗрдВрдЬ рд▓реЛрдХреЗрд╢рди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХреИрд╕реЗ рдХрд░реЗрдВ?
async setForm({ rootState, state, commit, dispatch }, formData) {
....
switch (answ.result.type) {
....
case 'redirect':
console.log(answ.data.url);
window.location = answ.data.url;
console.log({ location: window.location.href });
break;
default:
break;
it('setForm - success, redirect', async done => {
expect(window.location.href).toBe('https://www.google.ru/');
рдореБрдЭреЗ рддреНрд░реБрдЯрд┐ рд╣реИ:
expect(received).toBe(expected) // Object.is equality
Expected: "https://www.google.ru/"
Received: "http://localhost/"
рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд┐рдпрд╛
const location = JSON.stringify(window.location); delete window.location; Object.defineProperty(window, 'location', { value: JSON.parse(location) }); Object.defineProperty(global.location, 'href', { value: 'http://localhost/newURL', configurable: true });
рдЬрд╕реНрдЯ рд╕рдВрд╕реНрдХрд░рдг 23.6.0 . рдкрд░
рд╡реИрд╢реНрд╡рд┐рдХ рдХреНрдпрд╛ рд╣реИ?
рд╡реИрд╢реНрд╡рд┐рдХ рдкрд░рд┐рднрд╛рд╖рд╛ рдХрд╣рд╛рдВ рд╣реИ?
рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд┐рдпрд╛ред
delete global.window.location global.window.location = { href: 'https://test-domain.com.br', ...anyOptions }
рдпрд╣ рд╕рднреА рдореВрд▓ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЗ рд╕рд╛рде рдПрдХ рд╕реНрдерд╛рди рдмрдирд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдирдХрд▓реА рд╣реИ:
beforeAll(() => {
const location = window.location
delete global.window.location
global.window.location = Object.assign({}, location)
})
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рдЖрдк рд╕рд╣реА рд╣реИрдВ, рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ jsdom рдореБрджреНрджрд╛ рд╣реИред рдлреЗрд╕рдмреБрдХ рдкрд░, рд╣рдордиреЗ рдЗрд╕рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛ рдХрд┐рдпрд╛ рд╣реИ, рд╡рд╣ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣реИ:
рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдБрдХрд┐ рд╣рдо рдЕрднреА рднреА рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ jsdom 7 рдкрд░ рд╣реИрдВред
рдореИрдВ рдЗрд╕реЗ рдмрдВрдж рдХрд░ рджреВрдВрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐
Object.defineProperty
рдЪреАрдЬреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдареАрдХ рд╣реИред рдЕрдЧрд░ рд╡рд╣ рдЖрдкрдХреЗ рд▓рд┐рдП jsdom 8 рдореЗрдВ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдореБрдЭреЗ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓рдиреЗ рдореЗрдВ рдЦреБрд╢реА рд╣реЛ рд░рд╣реА рд╣реИред