μ΅κ·Ό λ²μ 21.2.0μμ 22.0.6μΌλ‘ jest
(λ°±κ·ΈλΌμ΄λμμ jsdom μ¬μ©) μ
κ·Έλ μ΄λ ν μ€λ₯κ° λ°μνκΈ° μμνμ΅λλ€. "Error: Not implemented:" navigation
λ΄ μ½λλ window.location
μ μμ‘΄νκ³ ν
μ€νΈμμ μ¬μ©ν©λλ€.
beforeEach(() => {
window.location.href = `/ms/submission/?mybib`;
window.location.search = '?mybib';
});
μ λ²μ μ jsdomμ μ¬μ©νμ¬ window.location.search
κ°μ μ μνλ λ°©λ²μ΄ μμ΅λκΉ?
λλμ΄ μ€λ₯κ° λ°μν©λλ€
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 λλ μ΄μ μ μ¬ν μ€μ μ μ΄ λ©μμ§λ₯Ό νμν©λλ€. Jestκ° μ΄μ μ μ΄λ¬ν λ©μμ§λ₯Ό μ΅μ νλμ§, μλλ©΄ 무μμΈμ§ μ λͺ¨λ₯΄κ² μ΅λλ€.
μ΄κ²μ μλ§λ ν μ€νΈμμ μμ ν΄μΌ ν μ¬νμΌ κ²μ λλ€. μλνλ©΄ λΈλΌμ°μ μμ ν΄λΉ ν μ€νΈλ₯Ό μ€ννλ κ²½μ° νμ΄μ§λ₯Ό μ URLλ‘ νμν λ ν μ€νΈ μ€νκΈ°κ° μμ ν λ μκ°κ³ ν μ€νΈλ₯Ό λ³Ό μ μκΈ° λλ¬Έμ λλ€. κ²°κ³Ό. λμ jsdomμμλ μ½μμ λ©μμ§λ₯Ό μΆλ ₯ν©λλ€. μνλ κ²½μ° λ¬΄μνκ±°λ λ λ§μ νκ²½μμ λ μ μλνλλ‘ ν μ€νΈλ₯Ό μμ ν μ μμ΅λλ€.
μ΄μ¨λ , λλ μ¬λλ€μ μν΄ μ΄κ²μ λν λ λ§μ λ¬Έμλ₯Ό μΆκ°νκ³ μΆμ΅λλ€. κ·Έλμ μ΄ λ¬Έμ λ₯Ό μΆμ νκΈ° μν΄ μ΄ λ¬Έμ λ₯Ό μ΄μ΄ λκ² μ΅λλ€.
λΉμ μ΄ λ§νλ κ²μ μμ ν μ΄ν΄νμμμ€. μ΅κ·Ό Jest 22 μ λ°μ΄νΈλ JSDOM 9μμ 11 IIRCλ‘ μ΄λνμΌλ―λ‘ 9.xμμμ λμμ μλΉν λ€λ₯Ό μ μμ΅λλ€.
κ·Έ λͺ¨λ κ²μ μ μ³λκ³ , λλ (HTML5 pushstateμ μ μ¬ν μ μ μΌλ‘) λ€λ₯Έ νμ΄μ§λ₯Ό λ‘λνλ μΈ‘λ©΄μμ μλνμ§ μλλ‘ νκΈ° μν΄ μΌμ’ μ νλκ·Έλ₯Ό μ¬μ©νμ¬ JSDOMμ ꡬνλ νμμ λ³΄κ³ μΆμ΅λλ€. λΌμ΄λΈλ¬λ¦¬λ ν μ€νΈ λͺ©μ μΌλ‘ λ§€μ° μΌλ°μ μΌλ‘ μ¬μ©λ©λλ€. κ·Έλμ μλ§λ κΈ°λ°ν μμ²μ΄κΈ°λ νμ§λ§ μμ£Ό μ¬μ©λ©λλ€.
ν μ€νΈλ₯Ό λΈλΌμ°μ μ jsdomμμ λ€λ₯΄κ² μ€ννλ νλκ·Έλ₯Ό μΆκ°ν΄μΌ νλ€κ³ μκ°νμ§ μμ΅λλ€. κ·Έλ¬λ©΄ λΈλΌμ°μ μμ λ¬Όκ±΄μ΄ μμλ μ μμΌλ©°(μ: ν μ€νΈμμ λ°μνλ μμ μ μννλ λμ μ¬μ©μλ₯Ό λ€λ₯Έ νμ΄μ§λ‘ 리λλ μ ν μ μμ) λμΉμ±μ§ λͺ»ν μλ μμ΅λλ€!
μ΄ κ²½μ°μλ νμ¬ νμ΄μ§ 컨ν
μ€νΈλ₯Ό μΈλ‘λνμ§ μλ κ² μΈμλ μ무 κ²λ νμ§ μμ΅λλ€. λλ μ¬μ ν window.location.href
λ±μ΄ μ
λ°μ΄νΈλ κ²μΌλ‘ κΈ°λν©λλ€.
@domenic μ λ κ°μ λ¬Έμ κ° μκ³ window.location
λ₯Ό μ€μ νλ μ±μΌλ‘ JSDOMμ μ€μ νλ λͺ¨λ² μ¬λ‘κ° μλμ§ κΆκΈν©λλ€. λ΄κ° λ§ν μμλ κ²μμ JSDOMμ window.location
λ₯Ό μ€μ νλ €κ³ ν λ μ€λ₯κ° λ°μνκ³ window.location.href
λ₯Ό μ€μ νλ €κ³ ν λ μ€λ₯λ₯Ό κΈ°λ‘ν©λλ€. κ·Έλ¬λ mdnμμ λμ λμμ΄μ¬μΌ νλ€λ κ²μ μ½κ³ μμ΅λλ€. μ€ν
νκΈ° μ¬μ΄ λ€λ₯Έ λ°©λ²μΌλ‘ μμΉλ₯Ό μ
λ°μ΄νΈν΄μΌ ν©λκΉ?
λμμ£Όμ
μ κ°μ¬ν©λλ€ π
λ΄ μμ μ μ§λ¬Έμ λν λ΅λ³μ κ²μν μ μμ΅λλ€ π
λλ λ¨μν 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μ΄ λ§νλ―μ΄ :
μ΄κ²μ μλ§λ ν μ€νΈμμ μμ ν΄μΌ ν μ¬νμΌ κ²μ λλ€. μλνλ©΄ λΈλΌμ°μ μμ ν΄λΉ ν μ€νΈλ₯Ό μ€ννλ κ²½μ° νμ΄μ§λ₯Ό μ URLλ‘ νμν λ ν μ€νΈ μ€νκΈ°κ° μμ ν λ μκ° κ²μ΄κΈ° λλ¬Έμ λλ€.
μ§κΈ μ°λ¦¬λ μ΄κ²κ³Ό ν¨κ» μ΄κ³ μμ΅λλ€. μ, μ°λ¦¬λ λμ μ΅κ΄μΌλ‘ κ°μ£Όλλ ν μ€νΈλ₯Ό μν΄ κ΅¬ν μ½λλ₯Ό λ³κ²½νμ§λ§ λ°€μλ μ μκ³ μμ΅λλ€!
ν볡ν ν μ€νΈ
@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(λ° jest)μ μ¬μ©νμ¬ ν
μ€νΈνκ³ μΆμ΅λλ€. π€
μΆμ : https://github.com/facebook/jest/issues/5266 κ΄λ ¨
jsdom 12.2.0μΌλ‘ μ
λ°μ΄νΈν ν μ€λ₯κ° λ°μνμ΅λλ€.
TypeError: μμ±μ μ¬μ μν μ μμ: ν λΉ
const assign = sinon.stub(document.location, 'assign')
κ·Έκ²μ κ³ μΉλ λ°©λ²?
@yuri-sakharov
jsdom 12.2.0μΌλ‘ μ λ°μ΄νΈν ν μ€λ₯κ° λ°μνμ΅λλ€.
TypeError: μμ±μ μ¬μ μν μ μμ: ν λΉ
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
μ΄λ€ μμ΄λμ΄?
@yuri-sakharov μ€ν λͺ¨μΉ΄μ λμΌν λ¬Έμ μ λλ€.
κ²°μ½ 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();
@zxest μ @hontas ' μ루μ μ Jest λ²μ μ μ μκ² ν¨κ³Όκ° μμμ§λ§ λ€μκ³Ό κ°μ΄ νμ΅λλ€.
window.location.assign = jest.fn();
expect(window.location.assign).toHaveBeenCalledWith('https://correct-uri.com');
window.location.assign.mockRestore();
location.assign
λ₯Ό μ¬μ©νλλ‘ μ½λλ₯Ό λ³κ²½νκ³ μΆμ§ μμ κ²½μ° - μ΄κ²μ JSDom 11 λ° 13μμ μλνλ κ² κ°μ΅λλ€.
delete window.location;
window.location = {}; // or stub/spy etc.
λ§μ§λ§ λλ΅μ μ μκ² ν¨κ³Όμ μ΄μμ§λ§ replace
λ₯Ό μ μν΄μΌ νμ΅λλ€.
delete window.location
window.location = { replace: jest.fn() }
λμμ΄ λκΈ°λ₯Ό λ°λλλ€.
TypeError: Cannot redefine property: assign with 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μ νμμ λͺ¨μ(mock-out) νμ©νμ§ μμ΅λλ€. μ΅μ’ κ²°κ³Όλ κΆκ·Ήμ μΌλ‘ νμμ νΈλ¦¬κ±°νλ €κ³ μλνλ ν μ€νΈλ₯Ό μμ±ν μ μλ€λ κ² μ λλ€.
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μ λ΅λ³μ κΈ°λ°μΌλ‘ Jest νκ²½μμ μ΄ μμ μ μνν μ μμμ΅λλ€. Jestλ₯Ό μ¬μ©νλ μ¬λμ μν ν΄κ²° λ°©λ²μ λ€μκ³Ό κ°μ΅λλ€.
describe('', () => {
const originalLocation = window.location;
beforeEach(() => {
delete window.location;
window.location = {
href: '',
};
});
afterEach(() => {
window.location = originalLocation;
});
it('', () => {
// test here
});
});
μ΄ κ΅¬μ±μ μ¬μ©νμ¬ μ΄ λ¬Έμ λ₯Ό ν΄κ²°νμ΅λλ€. ν΄μ URLμ λν 리λλ μ μ ν μ€νΈνκ³ μΆμμ΅λλ€.
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, });
circleciμ κ°μ 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
(μ€μ κ° μλ)μΈ κ²λ μ€μνμ§ μμ΅λλ€. μ€μν κ²μ 쿼리 λ¬Έμμ΄μ μ¬λ°λ₯΄κ² κ°μ Έμ€λ κ²μ
λλ€( μ΄κ²μ ν΅κ³Ό)
μμ μ λ¬Έμ λ λ©μλμ κ²ν°κ° μ¬μ©λμ§ μλλ€λ κ²μ λλ€. λ΄κ°νλ μΌμ κΈ°λ³Έμ μΌλ‘ Location κ°μ²΄λ₯Ό URL κ°μ²΄λ‘ λ°κΎΈλ κ²μ λλ€. URLμλ Locationμ λͺ¨λ μμ±(κ²μ, νΈμ€νΈ, ν΄μ λ±)μ΄ μμ΅λλ€.
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();
μ΄κ²μ λλ₯Ό μν΄ μΌνμ΅λλ€. κ°μ¬ν©λλ€! κ·Έλ¬λ jest test()μμ 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 λ λλ₯Ό μν΄ μλνμ§ μμ΅λλ€ :( ν λΉ/κ΅μ²΄ μμ±μ λ€μ μΈ μ μμ΅λλ€
jestκ° μ λ²μ ("jest": "^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
μ€λ¨μ μ μΆκ°νκ³ λλ²κ·Έ μΈμ
μ μ€ννκ³ μ€λ¨μ μ λλ¬ν λκΉμ§ κΈ°λ€λ¦½λλ€. κ·ΈλμΌλ§ μ΄ λ©μμ§λ₯Ό μμ κΈ° μν΄ μ΄λ€ ν
μ€νΈλ₯Ό κ°μ ν΄μΌ νλμ§ μ μ μμ΅λλ€.
λλλ‘ λ¬λκ° λ¬Έμ κ° μλ ν μ€νΈμ λλ¬ν λκΉμ§ 2-3λΆμ΄ 걸립λλ€.
μΆμ : νμ¬ νλ‘μ νΈμλ 176κ°μ jsdom κ΄λ ¨ ν μ€νΈκ° μμ΅λλ€.
λλ νμ¬ Jest 26.0.1
νκ³ μμΌλ©° λ€μμ΄ μ μκ² ν¨κ³Όμ μ
λλ€.
window.location.assign(url)
λ₯Ό μ¬μ©νμ¬ μ°½ μμΉλ₯Ό λ³κ²½ν©λλ€.
λ€μκ³Ό κ°μ΄ μμΉ κ°μ²΄λ₯Ό μ‘°λ‘±ν©λλ€(κ°μ²΄λ₯Ό λ¨Όμ μμ νκ³ λ€μ λΉλνμ§ μμΌλ©΄ Jest λ° μ΄μ λ²μ μμ μ¬μ ν ꡬνλμ§ μμ μ€λ₯κ° λ°μν©λλ€. λν Object.defineProperty
λ μλνμ§ μκ³ μ¬μ ν κ²°κ³Όκ° μ€λ₯):
delete window.location;
window.location = {
href: '',
hostname: '',
pathname: '',
protocol: '',
assign: jest.fn()
};
expect(window.location.assign).toBeCalledWith(url);
jestλ₯Ό ν΅ν΄ μ΄λ¬ν λμμλ λ¬Έμ μ λ³κ²½ μμ΄ μ½κ² μμΉλ₯Ό μ‘°λ‘±ν μ μλ€λ©΄ μ λ§ μ’μ κ²μ
λλ€. μμ μλ window.location.assign = jest.fn()
λ§ μ¬μ©νλ€κ° λ¬Έμ μμ΄ v24μμ μ
κ·Έλ μ΄λ ν΄μ μ§κΈμ μ΄λ κ² νκ³ μμ΅λλ€.
Windows APIκ° μ κΈ°κ±°λ κ³ μ λ μ΄μ κ° μμ΅λκΉ?
νμμ΄ κ΅¬νλμ§ μμ ν΄κ²° λ°©λ²μ μλνλ μ¬λλ€μ μ₯λ²½μΈ κ² κ°μ΅λλ€.
κ·Έλ μ§ μλ€λ©΄ μ°λ¦¬λ κ·Έλ€μ μΌλ¦¬μ§ μμ μ μμ΅λκΉ? λλ λΈλΌμ°μ μ‘°μ°¨λ μ°½ κ°μ²΄λ₯Ό λ³κ²½νλ κ²μ λ§λ λ° κ·Έλ κ² μ격νλ€κ³ μκ°νμ§ μμ΅λλ€.
jsdomμ΄ λΈλΌμ°μ μ λ€λ₯΄κ² λμνλ μκ° μλ κ²½μ° λ¬Έμ ν νλ¦Ώ(jsbin λλ λΈλΌμ°μ λμμ 보μ¬μ£Όλ μ μ¬ν νλͺ© ν¬ν¨)μ λ°λΌ λ¬Έμ λ₯Ό μ μΆνμΈμ.
λ€λ₯Έ μ¬λμ΄λ‘ μ€νμ€μΈ λμΌν Error: Not implemented: navigation (except hash changes)
λλ΄μ΄ ν¨κ»νλ μ΅μ»€ μμμ νμ¬ ν΄λ¦ μ΄λ²€νΈλ₯Ό ν
μ€νΈνλ λμ href
? λ΄ ν
μ€νΈλ₯Ό μν΄ onClick
λΌλ ν¨μλ₯Ό κ°μνκ³ μ΄μ λν μ£Όμ₯μ νκ³ μμΌλ―λ‘ μ€μ λ‘ μ΅μ»€ μμμμ ν΄λ¦ μ΄λ²€νΈλ₯Ό λ°μμμΌμΌ ν©λλ€.
window.location
μ‘°λ‘±κ³Ό κ΄λ ¨λ μμ μ루μ
μ λͺ
μμ μΌλ‘ window.location.replace
λλ window.location.assign
νΈμΆνλ κ³³μμ μλνμ§λ§ νμμ΄ μ΅μ»€ μμμμ μμλλ μ΄ κ²½μ°μλ λμμ΄ λμ§ μμ΅λλ€. ν΄λ¦ μ€μ
λλ€.
μ루μ μ λν μμ΄λμ΄κ° μμ΅λκΉ? κ°μ¬ ν΄μ!
λΈλΌμ°μ μμ ν΄λΉ μ½λλ₯Ό μ΄λ»κ² ν μ€νΈνμκ² μ΅λκΉ? λΈλΌμ°μ μμ λ§ν¬λ₯Ό ν΄λ¦νλ©΄ μ 체 νμ΄μ§κ° λ μκ°κ³ λͺ¨λ ν μ€νΈ κ²°κ³Όκ° μ¬λΌμ§λλ€. λ°λΌμ μ΄λ₯Ό λ°©μ§νκΈ° μν΄ λ¬΄μμ νλ ν¨μ¬ λ κ·Ήμ μΈ κ²½κ³ λ©μμ§μΈ jsdomμ΄ μ½μμ μΆλ ₯λλ κ²μ λ°©μ§ν κ²μ λλ€.
λ΄ μν©μμ νλ‘μ νΈλ Jestλ₯Ό 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
:
```
global.window = Object.create(μ°½);
Object.defineProperty(μ°½, 'μμΉ', {
κ°: {
...μ°½.μμΉ,
},
μ°κΈ° κ°λ₯: μ¬μ€,
});
````
κ°μ₯ μ μ©ν λκΈ
λ΄ μμ μ μ§λ¬Έμ λν λ΅λ³μ κ²μν μ μμ΅λλ€ π
λλ λ¨μν
window.location = url;
λ°window.location.href = url;
μ μ¬μ©λ²μ λ€μμΌλ‘ λ체ν©λλ€.κ·Έλ° λ€μ λ΄ ν μ€νΈμμ λ€μμ μννμ΅λλ€.
맀λ ₯μ²λΌ μλν©λλ€ - λ€λ₯Έ μ¬λμκ² λμμ΄ λκΈΈ λ°λλλ€ π