_feature_ããªã¯ãšã¹ãããŸããããããšã_bug_ãå ±åããŸããïŒ ãã°ãå ±å
çŸåšã®åäœã¯äœã§ããïŒ
ãã¹ãã¹ã€ãŒãå ãã以äžãåŒã³åºããŸãã
Object.defineProperty(location, "hostname", {
value: "example.com",
writable: true
});
次ã®ãšã©ãŒãã¹ããŒããŸãã
TypeError: Cannot redefine property: hostname
at Function.defineProperty (<anonymous>)
æåŸ ãããåäœã¯äœã§ããïŒ
ã³ãŒãã¯äŸå€ãã¹ããŒããŠã¯ãªããã window.location.hostname === "example.com"
ã¯trueãšè©äŸ¡ãããã¹ãã§ãã
èŠãç®ããã jsdom
ã¯window.locationãåœé äžå¯èœã«èšå®ããããã«ãªããŸããã window.location
å
ã®å€ãå€æŽããå¯äžã®æ¹æ³ã¯ã reconfigure
ã䜿çšããããšã§ãããïŒïŒ2460ããšã«ïŒJestã¯ãã¹ãçšã«jsdom
ãå
¬ââéããŸããã
æ£ç¢ºãªJestæ§æãæäŸããJestãããŒããã€ãŒã³/ npmããŒãžã§ã³ãšãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã
ãžã§ã¹ãããŒãžã§ã³ïŒ22.0.1
ããŒãããŒãžã§ã³ïŒ8.6.0
糞ããŒãžã§ã³ïŒ1.2.0
OS ïŒmacOS High Sierra 10.13.2
åæ§ã®åé¡ããããŸãã ãã®ããã«ãç¬èªã®JSDOMEnvironmentãäœæããjsdomãªããžã§ã¯ããã°ããŒãã«ã«å ¬éã§ããŸãã
const JSDOMEnvironment = require('jest-environment-jsdom');
module.exports = class CustomizedJSDomEnvironment extends JSDOMEnvironment {
constructor(config) {
super(config);
this.global.jsdom = this.dom;
}
teardown() {
this.global.jsdom = null;
return super.teardown();
}
};
ãããŠãå¿ èŠã«å¿ããŠãã¹ãã±ãŒã¹ã§jsdom.reconfigureãåŒã³åºãããšãã§ããŸã
å ±æããŠãããŠããããšããããã¯è¯ãåé¿çã§ãïŒ
çŽæãªã®ã§super.teardown();
ãè¿ãå¿
èŠããããŸã
ããŒãã§ã¯ãã @ oliverzy-è©ŠããŠã¿ãŸãã ããããšãïŒ
ãããææžåããé©åãªå Žæã¯ãããŸããïŒ ããã¯ããªãé »ç¹ã«åºãŠãã質åã®ããã§ãã ããŸãããã°ããããããã¥ã¡ã³ãã«çµ±åãããŠããã°ãå°æ¥ã®åé¡ãåæžãããå¯èœæ§ããããŸããïŒ
ãã®è§£æ±ºçã¯ããŸããããŸããã§ããã
ãã¹ããã¡ã€ã«å
ã§ã¯ã global
ãJSDomã®window
ãªããžã§ã¯ãã«èšå®ãããŠããããã§ãã
ã€ãŸãããã¹ãã¹ã€ãŒãå
ã§ã¯ã global
ã¯window
ãšåãã§ããã JSDOMEnvironment
ãæ¡åŒµããã¯ã©ã¹å
ã§ã¯ã global
ã¯ããŒãã®ç°å¢ããååŸãããŸãã
çµæãšããŠããããæã£ãŠããïŒ
describe("test suite", () => {
it("should not fail", () => {
global.jsdom.reconfigure({
url: "https://www.example.com/"
});
});
});
global.jsdom
ãæªå®çŸ©ã§ããããã倱æããŸãã
ç§ã¯ãããè¡ãããšã§ãããåé¿ããŸããããç§ã¯ããã«ã€ããŠããŸã倧éšãããŠããŸããã
const JSDOMEnvironment = require("jest-environment-jsdom");
module.exports = class JSDOMEnvironmentGlobal extends JSDOMEnvironment {
constructor(config) {
super(config);
this.dom.window.jsdom = this.dom;
}
};
ãã®ç°å¢ã§ã¯ããã¹ãã¹ã€ãŒãå
ã®global.jsdom
ã¯this.dom
ãšçãããäžèšã®ãã¹ãã¹ã€ãŒãã¯æ©èœããŸãã
ç§ã«ã¯ã jsdom
ãç¬èªã®window
ãªããžã§ã¯ãã®ããããã£ã«èšå®ããããšã¯ãæçµçã«ã¯åŽ©å£ããããšã«ãªããŸã-ãããè¡ãããã®ããã¯ãªãŒã³ãªæ¹æ³ã¯ãããŸããïŒ
ãã¹ãã§ã¯ã global.jsdom
ã§ã¯ãªãjsdom
ãèšè¿°ããå¿
èŠããããŸãã
@oliverzyãã®ããã«ïŒ
describe("test suite", () => {
it("should not fail", () => {
jsdom.reconfigure({
url: "https://www.example.com/"
});
});
});
ããã¯jsdom is not defined
ã¹ããŒããŸãããç§ã¯èª€è§£ããŠããå¯èœæ§ããããŸãã
@ simon360èšå®ããŠãã ããtestEnvironment
ã@oliverzyããã³ãŒããåç
§https://facebook.github.io/jest/docs/en/configuration.html#testenvironment -string
@danielbayerleinç§ã®Jestæ§æã«ã¯ããããããŸãïŒ
"testEnvironment": "@wel-ui/jest-environment-jsdom-global"
ããã§ã @wel-ui/jest-environment-jsdom-global
ã¯ãmonorepoå
ã®ããã±ãŒãžã®ååã§ãã ãã ãã window
jsdom
ãèšå®ãããœãªã¥ãŒã·ã§ã³ã¯æåŸ
ã©ããã«æ©èœãããããç°å¢ã¯æ£ãã䜿çšãããŠããŸãã
ãšããã§ãå
ã®ãœãªã¥ãŒã·ã§ã³ãæ°ããããŒãžã§ã³ã§æ©èœããªãçç±ã誰ããç¥ã£ãŠããŸããïŒ
ããã§ãïŒ
Object.defineProperty(location, "hostname", {
value: "example.com",
writable: true
});
@modestfake JSDOM @ 9ããJSDOM @ 11ã«ã¢ããã°ã¬ãŒãããŸãããå€æ°ã®å®çŸ©æ¹æ³ãå€æŽããããšæããŸããã
@SimenBäºè§£ããŸããã jsdom reconfigure
ã¡ãœããã®èª¬æãèŠã€ãããŸããã
ãŠã£ã³ããŠã®äžçªäžã®ããããã£ã¯ãä»æ§ã§[Unforgeable]ãšããŒã¯ãããŠããŸããããã¯ãæ§æäžå¯èœãªç¬èªã®ããããã£ã§ãããããObject.definePropertyã䜿çšããŠããå Žåã§ããjsdomå ã§å®è¡ãããéåžžã®ã³ãŒãã«ãã£ãŠãªãŒããŒã©ã€ããŸãã¯ã·ã£ããŠã€ã³ã°ã§ããªãããšãæå³ããŸãã
ãã®åäœã瀺ãããã«ãæ°ãããªããžããªãè¿œå ããŸããã ããŒã«ã«ã§ã¯ããŒã³ãäœæããŠåçŸã§ãã人ã¯ããŸããïŒ
@ simon360åçŸ
@ simon360ç§ãèŠã€ããŸããã global.jsdom
å®çŸ©ãããšãã«this
ããŒã¯ãŒããèŠéããŸããïŒ
const JSDOMEnvironment = require("jest-environment-jsdom");
module.exports = class JSDOMEnvironmentGlobal extends JSDOMEnvironment {
constructor(config) {
super(config);
this.global.jsdom = this.dom;
}
teardown() {
this.global.jsdom = null;
return super.teardown();
}
};
location.search
ã©ãã§ããïŒ ããã«ã€ããŠã®èšåã¯èŠã€ãããŸããã§ããhttps://github.com/tmpvar/jsdom/blob/05a6deb6b91b4e02c53ce240116146e59f7e14d7/README.md#reconfiguring-the-jsdom-with-reconfiguresettings
@andrewBalekhaããã¯ã©ãã§ããïŒ
jsdom.reconfigure({
url: 'https://www.example.com/endpoint?queryparam1=15&queryparam2=test'
});
ããããšã@ modestfake-ã°ãããééãã§ããããªããïŒ
ããããŸãããããããŸãããJestç°å¢ãªããžã§ã¯ãã®this.global
global
ã¯ãJestãã¹ããã¡ã€ã«ã§npm
ã«jest-environment-jsdom-global
ãšããŠé
眮ããããšãã§ããŸãã
ãã ããå°æ¥çã«ã¯Jestã§ãããè¡ãããã®ããã¯ãªãŒã³ãªæ¹æ³ãããããšãé¡ã£ãŠããŸãã ããã¯ã window.location
ãå€æŽããããã®äœæ©æŠã®æ¹æ³ã§ã¯ãããŸãã-
@jest-environment
ããã«ãæ°ããdocblockããããŸããïŒ äŸãã°...
/**
* @jest-url https://www.example.com/
*/
ãŸãã¯ãJSDomãjest
ãªããžã§ã¯ãã®ç¹å¥ãªéšåã«å
¬éããããšãã§ããŸãã
jest.environment.jsdom.reconfigure({
url: "https://www.example.com/"
});
ïŒããã«ã¯ã window.top
ãå€æŽã§ãããšããè¿œå ã®å©ç¹ããããŸãïŒ
ïŒ5003ãçµ±åããŸããã docblockãšããŠè¿œå ã§ããããšã¯çã«ããªã£ãŠãããããããŸãããã確ãã§ã¯ãããŸããã @cpojerïŒ testUrl
ãéæšå¥šã«ããããšãã§ããŸããããã¯ããã®æ°ãããªãã·ã§ã³ãéããŠæäŸã§ããããã§ãã
ååãªé¢å¿ãããã°ããã®ã¬ãã®ä¿®åŸ©ããŒãžã§ã³ãããã±ãŒãžåããŠã
npm
ã«jest-environment-jsdom-global
ãšããŠé 眮ããããšãã§ããŸãã
ãããã«ãããURLãèšå®ããã ãã§ãªããå®å šãªJSDOMãç°å¢ã«å ¬éããã®ã§ãããã¯çã«ããªã£ãŠãããšæããŸãã
@andrewBalekha Object.defineProperty(location, 'search', { ...options });
ã¯ã window.location
ãšåããšã©ãŒãã¹ããŒããŸãã ããããææ¡ãããããšãã
Object.definePropertyïŒwindow.locationã 'href'ã{
setïŒnewValue => {currentUrl = newValue; }ã
}ïŒ;
以åã®ããŒãžã§ã³ã§ããããããŸãããããšã©ãŒãçºçããŸãã
æžã蟌ã¿å¯èœãè¿œå ããå ŽåïŒtrue
ã¢ã¯ã»ãµãšæžã蟌ã¿å¯èœã®äž¡æ¹ãæå®ã§ããªããšããå¥ã®äŸå€ãã¹ããŒããŸã
ç§ã¯npmã«jest-environment-jsdom-global
ãšããæ°ããããã±ãŒãžãå
¬éããŸãããããã¯ãäžéšã®äººã
ãObject.defineProperty
æ±ããŠããåé¡ã«åœ¹ç«ã€å¯èœæ§ããããŸãã
{ writable: true }
åé¿çã¯ãããŸããïŒ
äŸãã°ïŒ
Object.defineProperty(window.location, 'href', { writable: true })
...
Object.defineProperty(window.location, 'hash', { writable: true })
...
Object.defineProperty(window.location, 'search', { writable: true })
@danielbayerleinã¯ãã®ã¹ã¬ãããèªãã ã ã«ã¹ã¿ã ç°å¢ãäœæããå¿ èŠããããŸãã åã®ã¡ãã»ãŒãžã«ã¯äŸãå«ãURLãå«ãŸããŠããŸã
@modestfakeç§ã¯ãã§ã«ãã®ã¹ã¬ãããèªãã§ããã httpsïŒ //github.com/facebook/jest/issues/5124#issuecomment-352749005ã¯æ£åžžã«æ©èœããŸãã ããããç§ã«ã¯å¥ã®ãŠãŒã¹ã±ãŒã¹ããããŸãã Jest 21.xxã§ã¯ãURLãªãã§Object.defineProperty(window.location, 'href', { writable: true })
ãèšå®ããŸãã- { writable: true }
ã URLãèšå®ããå Žåããã¹ãã¯æå³ããããŸããã
@danielbayerleinæžã蟌ã¿å¯èœã«ããããå®éã«ã¯ãªãŒããŒã©ã€ãããªãããã«ããããã®ãŠãŒã¹ã±ãŒã¹ã¯äœã§ããïŒ ãã¶ããããç解ããããšã¯ç§ãåé¿çãèãåºãã®ãå©ããããšãã§ããŸã
URLãå€æŽããé¢æ°ããããŸãã
routing.js
...
export function redirectToErrorPage () {
window.location.href = '/error.html'
}
...
routing.test.js
test('redirect to the error page', () => {
...
expect(window.location.href).toBe('/error.html')
...
})
Jest 21.xxã§ã Object.defineProperty(window.location, 'href', { writable: true })
window.location.assign
ã«åãæ¿ããããšããå§ãããŸããããããã°ãé¢æ°ãã¢ãã¯ã§ããŸãã
@ simon360ã¯é åã®ããã«æ©èœããŸãïŒ ããããšãã ð€
䜿çšããŸãã
history.pushState({}, "page 2", "/bar.html");
jestèšå®ã®testURL
ãšäžç·ã«
åé¡ã¯ãã±ãŒã·ã§ã³éšåã ãã§ã¯ãããŸããã ç§ã¯ã€ã³ããŒãããããšã¯ã§ããŸããjsdom
åå¥ã«åŒã³åºãããã®jsdom.reconfigureWindow
ïŒãã®é¢æ°ã¯ããã¯ãjsdomã®ææ°ããŒãžã§ã³ã«ååšããããã«ïŒã window !== top
å Žåãç°ãªãæ¹æ³ã§å®è¡ãããã³ãŒãããã¹ãããããã«ãããè¡ã£ãŠããŸããã æ°ããããŒãžã§ã³ã®jsdomã䜿çšããææ°ããŒãžã§ã³ã®jestã§ãããå®çŸããæ¹æ³ã¯ãããããŸããã
@andyearnshaw jsdom.reconfigure
ã¡ãœããã®ãªããžã§ã¯ãã«ã¯windowTop
ã¡ã³ããŒããããŸãã
äžã§ãªã³ã¯ããJSDOMç°å¢ïŒ jest-environment-jsdom-global
ïŒã䜿çšããŠããå Žåã¯ã次ã®ããšãã§ããŸãã
jsdom.reconfigure({
windowTop: YOUR_VALUE
});
ããªãã®ãã¹ãã§æé«å€ãã¢ãã¯ã¢ãŠãããŸãã
ç§ã¯ããã䜿çšããŠããŸãããããŠããã¯çŽ æŽãããåããããŸããããããšãïŒ
2018幎1æ30æ¥ç«ææ¥ã13ïŒ40 simon360ã notifications @ github.comã¯æ¬¡ã®ããã«æžããŠããŸãã
@andyearnshaw https://github.com/andyearnshaw jsdom.reconfigure
ã¡ãœããã®ãªããžã§ã¯ãã«ã¯windowTopã¡ã³ããŒããããŸããJSDOMç°å¢ïŒjest-environment-jsdom-globalïŒã䜿çšããŠããå ŽåI
äžã«ãªã³ã¯ãããšã次ã®ããšãã§ããŸããjsdom.reconfigureïŒ{
windowTopïŒYOUR_VALUE
}ïŒ;ããªãã®ãã¹ãã§æé«å€ãã¢ãã¯ã¢ãŠãããŸãã
â
ããªããèšåãããã®ã§ãããªãã¯ãããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/facebook/jest/issues/5124#issuecomment-361595999 ããŸãã¯ãã¥ãŒã
ã¹ã¬ãã
https://github.com/notifications/unsubscribe-auth/ABvdEzCLlWtzr0udscL0C6KUxpgXHZRhks5tPxvJgaJpZM4RGN7C
ã
window.history.pushState
ãštestUrl
ããŸããããŸãã
https://github.com/facebook/jest/issues/5124#issuecomment -359411593
JeståŽã«ã¯äœãããããšããªããåé¿çãååšããããããããéããŸãïŒè°è«ãç¶ããŠãã ããïŒïŒ
jsdom v8.5.0ããv11.6.2ã«ã¢ããã°ã¬ãŒããããšãåé¡ã解決ããŸããã ãããã£ãŠãç§ã®package.json
ã¯æ¬¡ã®ãã®ãå«ãŸããŸãã
"jest": "^21.2.1",
"jest-cli": "^21.2.1",
"jsdom": "^11.6.2",
jestãšjest-cliãv22.2.2ã«ã¢ããã°ã¬ãŒããããšå£ããŸãã
@ andr-3-w package.jsonã«jsdomãããç¹å¥ãªçç±ã¯ãããŸããïŒ Jestã«ãã³ãã«ãããŠããŸãã
@SimenBã¯ã質åè¯ããã®ããã®å¿
èŠã¯ãããŸããjsdom
ç§ãã¡ã®äžã«package.json
ã ããããšãïŒ
ãããã£ãŠãjsdomãçŽæ¥äœ¿çšããã«ããããç§ãèªåã®ãã®ã®ããã«æãã€ãã解決çã§ãïŒ
Jest 21.2.1ã§åäœããŸãïŒç§ã¯ããã§ãã¹ãããŸããïŒïŒ
Jestèšå®ã«ç§»åããŸãïŒããšãã°ãpackage.jsonã䜿çšããŸãïŒã
"jest": {
"testURL": "http://localhost"
}
ããã§ãwindow.locationãªããžã§ã¯ããå€æŽã§ããããã«ãªãããã¹ãäžã«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);
});
ããŸãããã°ãããã¯èª°ããå©ããŸãã
ãããæçš¿ããã®ããããŠãã ãããããã¯jestã§ã¯æ©èœããŸãã "ïŒ" ^ 22.4.2 "
@UserNTããã§åäœããããŒãžã§ã³ã
å®å šãæãããã«ããœãªã¥ãŒã·ã§ã³ã¯ãã®ã¹ã¬ããã®éäžã§åãæ®ãããŠãããã...
@ petar-prog91ã®ãœãªã¥ãŒã·ã§ã³ã¯ãJest 21ã§æ©èœããŸãããæŽæ°ãããjsdom
Jest22ã§ã¯æ©èœããŸããã
ææ°ã®åè«äžã§å®è¡ããããã«ã䜿çšã®ãããªãã®jest-environment-jsdom-global
ïŒãããã¯ç§ã®ããã±ãŒãžã®å®å
šãªé瀺ã§ããïŒãé²åºããããã«jsdom
ãªããžã§ã¯ãã䜿ãjsdom.reconfigure
æã£ãŠããã§ãããããåãïŒãŸãã¯å°ãªããšãåæ§ã®ïŒå¹æã
https://github.com/facebook/jest/issues/5124#issuecomment-359411593ã¯ç§ã®ããã«jest22ã§ãåäœããŸã
@ simon360ããã«ã¡ã¯ã location.href
ã®ã»ãã¿ãŒãããã¯ããå¿
èŠãããå Žåã¯ã©ãããã°ããã§ããïŒ
ç§ã®ä»¥åã®ãã¹ãã«ã¯ãã®ãããªå€ãã®ãã¹ãããããä»ã§ã¯ãã¹ãŠå€±æããŠããŸã...
const setHrefMockFn = jest.fn();
beforeAll(() => {
Object.defineProperty(location, "href", {
get: () => "https://xxxxx",
set: setHrefMockFn
});
});
it("xxx", () => {
//...
expect(setHrefMockFn.mock.calls[0][0]).toBe(xxx);
});
@ simon360ã©ã€ãã©ãªã§ä»¥äžã®ãããªãã¹ããæŽæ°ããæ¹æ³ã®äŸãæããŠãã ãã
beforeAll(() => {
=======
Object.defineProperty(window.location, 'href', {
writable: true
});
});
@abhijeetNmishraããã¥ã¡ã³ããèŠãããšããã
@ simon360ã¯ããããã¥ã¡ã³ãã®ç§ã®ç解ã«åºã¥ããŠãããã¯çŽããããŸã
jsdom.reconfigure({
url: "https://www.example.com/"
});
ããã¯ããã¹ãããšã§ã¯ãªããã°ããŒãã«ã«URLããªãŒããŒã©ã€ãããŸãã å©ããŠãã ããïŒ
@abhijeetNmishraãã®åé¡ãè°è«ããã®ã«æé©ãªå Žæãã©ããã¯jest-environment-jsdom-global
ãªããžããªã§åé¡ãéããŠããã ããŸãããã ããããšãïŒ
@SimenBã«èšèŒãããŠããåé¿çïŒã jest-environment-jsdom-global
ãïŒã¯ãæããã«éåžžã«äžè¬çãªåé¡ã«å¯Ÿããéåžžã«æé©ã§ã¯ãªã解決çã®ããã«æããŸãã Jest 22ã«ã¢ããã°ã¬ãŒããã人ã¯èª°ã§ãããã®ãµãŒãããŒãã£ããã±ãŒãžã«äŸåé¢ä¿ãè¿œå ããïŒãŠãŒã¶ãŒã®èŠ³ç¹ããïŒãã¹ãã®äžéšãæžãçŽãå¿
èŠããããŸãã ããã¯ãJestã®åäœã®ååž°ã§ãã
ããã©ã«ãã®jest-environment-jsdom
çµã¿èŸŒãããšãã§ããããã«å¯Ÿãã解決çã¯ãããŸããïŒ ããªãã®æå°ã§PRãããŠå¹žãã§ãã
window.location.hrefãå€æŽããããã ãã«ããã®å€ãã®ããŒãã誰ãããžã£ã³ãããªããã°ãªããªãã®ã¯éåžžã«æ®å¿µã§ãã Jestã䜿ãå§ããã°ããã§ããã®åé¡ãèæ ®ããŠããã¹ããã¬ãŒã ã¯ãŒã¯ã®éžæãåæ€èšããããšããŠããŸãã äžã§ææ¡ãããéãããã¯ãããè¯ã解決çã¯æ¬åœã«ãããŸãããïŒ
@ydogandjievã¯ããã®åé¡ã解決ããããã®ãããžã§ã¯ãã«æ°è»œã«è²¢ç®ããŠãã ããã ããã¯ãªãŒãã³ãœãŒã¹ã§ããããšãå¿ããªãã§ãã ããããåãå ¥ããããªããããã°ãããŠããããªã©ã®ã³ã¡ã³ãã§æŽãåã£ãŠããã ãã«ã圹ç«ã¡ãŸããã
@ msholty-fdã§ããã°æäŒãããã§ãã ç§ã¯jestãšjsdomãå§ããã°ãããªã®ã§ããããã®ã©ã€ãã©ãªãååã«ç解ããŠããã®ãšã¯ã¹ããªãšã³ã¹ãæ¹åããããã®æè¯ã®ã«ãŒããäœã§ããããæ£ç¢ºã«ç¥ãããšãã§ãããã©ããã¯ããããŸããã ããã¯ãjestãŸãã¯jsdomã§æãé©åã«å¯ŸåŠããããã®ã§ããïŒ ãããã®ã©ã€ãã©ãªã®1ã€ããããæç¹ã§Object.definePropertyã¢ãããŒããå£ããå€æŽãå ããããã§ãã ããã¯jestãŸãã¯jsdomã§è¡ãããå€æŽã§ãããïŒ
ãããã£ãŠãwindow.locationãå€æŽããããã«å¿ èŠãªè¡æ°ã«åºã¥ããŠãç§ã奜ãŸãããšèãããã¹ãŠã®ãªãã·ã§ã³ããããŸãã ãããã®ã©ããçŸåšæ©èœããŸããïŒ
window.location.href = "https://www.example.com";
JSDOMããŠã£ã³ããŠã®ãã±ãŒã·ã§ã³ããããã£ãäœæãããããObject.definePropertyã®äœ¿çšã¯æ©èœããŸãã[Unforgeable] ïŒ
Object.defineProperty(window.location, "href", {
value: "https://www.example.com",
configurable: true
});
jestã¯ãç°¡åã«ã¢ã¯ã»ã¹ã§ããããã«å ¬éãããŠããªãç¬èªã®ã€ã³ã¹ã¿ã³ã¹ã䜿çšããŠããããã«èŠãããããjsdomã®ã€ã³ã¹ã¿ã³ã¹ãäœæããŠæ§æããããšã¯ã§ããŸããã
import { JSDOM } from "jsdom";
...
const dom = new JSDOM();
dom.reconfigure({ url: "https://www.example.com" });
ãªãã·ã§ã³1ãŸãã¯2ãæ©èœãããã«ã¯ãjsdomããå®éã®ãã©ãŠã¶ãŒã®ããã«åäœãããšããçŸåšã®ç®æšã«æ»ãå¿ èŠããããŸãã ãããã£ãŠãç§ãã¡ãæã£ãŠããå¯äžã®ãªãã·ã§ã³ã¯ãjestã䜿çšããjsdomã®ã€ã³ã¹ã¿ã³ã¹ãç°¡åã«åæ§æã§ããããã«ããããšã®ããã§ãã ãã®ã€ã³ã¹ã¿ã³ã¹ãã°ããŒãã«jestãªããžã§ã¯ãã«çŽæ¥å ¬éããããšã¯çã«ããªã£ãŠããŸããã ã€ãŸãã次ã®ãããªãã®ãèš±å¯ããŸãã
jest.dom.reconfigure({ url: "https://www.example.com" });
ç§ã¯ãŸã location.assign('some-url')
ãè¡ãæ¹ãlocation.href = 'some-url'
ãããåªããŠãããšæããŸãã å²ãåœãŠãããæ瀺çãªé¢æ°åŒã³åºããèŠã€ããŸãããé¢æ°ãã¢ãã¯ã§ããŸã
@SimenBã¯ãã³ãŒããlocation.href
ã_set_ããããšããŠããå Žåãã¯ãã location.assign()
æ¹ãåªããŠããŸãã ãããã location.href
ã_èªã¿åãåäœããã¹ãããŠããå Žåãç¹ã«JSDOMã®location.assign()
ã¯å®éã«ã¯äœãããªãããã location.assign()
ã¯åé¡ã解決ããŸããã
reconfigure
ã䜿çšããèåŸã«ããèãæ¹ã¯ã location.href
ãç¹å®ã®æ¹æ³ã§åœ¢æãããå Žåã«ã®ã¿æå¹ã«ãªãã³ãŒããã¹ãã¢ã¯ãã£ãåããããšã§ãã ç§ãã¡ã®å ŽåãçŸåšã®ãã¡ã€ã³ã«å¿ããŠå€æŽãããã³ãŒãããããŸãã-ã³ãŒãã¯èãã§ããã¯ããããããããå¿
èŠã§ãããããŠèãã³ãŒãã軜æžããããã®æè¯ã®æ¹æ³ã¯ãåäœããã£ããã£ããŠããããšã©ãŸãããšã確èªãããã¹ããã£ã¯ã¹ãã£ãæã€ããšã§ãæå®ã®äœçœ®ã«ã
EnzymeãšããŠã³ããããã³ã³ããŒãã³ãã§ããã䜿çšããŠãªãã€ã¬ã¯ãããã¹ãããæ¹æ³ã¯ãããŸããïŒ
Jestãã¢ããã°ã¬ãŒãããåã«ã以äžã®ãã¹ãã«åæ ŒããŸããã
`` `
itïŒ 'æ£ããã«ãŒããžã®ã«ãŒã'ãïŒïŒ=> {
Object.defineProperty(window.location, 'href', {
writable: true,
value: 'https://mysuperawesomesite.com/',
});
const component = mount(
<App {...props} />
);
const link = component.find('.class');
link.simulate('click');
expect(window.location.href).toEqual('https://mysuperawesomesite.com/new');
}ïŒ;
After upgrading Jest and implementing [jest-environment-jsdom-global](https://www.npmjs.com/package/jest-environment-jsdom-global), I tried the following to no avail:
```
it('routes to correct route', () => {
jsdom.reconfigure({
url: 'https://mysuperawesomesite.com/',
});
const component = mount(
<App {...props} />
);
const link = component.find('.class');
link.simulate('click');
expect(window.location.href).toEqual('https://mysuperawesomesite.com/new');
});
ïŒwindow.location.hrefã¯ãŸã ' https://mysuperawesomesite.com/ 'ã«çãããïŒ 'https://mysuperawesomesite.com/new'ïŒã«å€æŽãããŸããã§ããã
ãã®ã¡ãœããã䜿çšããå ŽåãèŠçŽ ã®ã¯ãªãã¯ã€ãã³ãã¯ãªãã€ã¬ã¯ããããŸããããªãã€ã¬ã¯ãã¯ãwindow.location.hrefãèšå®ããããšã§çºçããŸãã
ãããé©åã«ãã¹ãããæ¹æ³ããŸãã¯ä»¥åã«Object.definePropertyã䜿çšãããã¹ããæåããäžååã«æ§ç¯ãããŠãããã©ãããäžæã§ãã ãããããé¡ãããŸãã
ç·šéïŒè§£æ±ºæžã¿
window.location.href = hrefã®ä»£ããã«window.location.assignïŒurlïŒã䜿çšããããšã§ãããã解決ã§ããŸããã ããã«ãããassignã¡ãœãããã¹ã¿ãã¢ãŠãããŠãé©åã«åŒã³åºãããŠãããã©ããããã¹ãã§ããŸããã äžèšåç §ïŒ
it('routes to correct route', () => {
window.location.assign = jest.fn();
const component = mount(
<App {...props} />
);
const link = component.find('.class');
link.simulate('click');
expect(window.location.assign).toBeCalledWith('https://mysuperawesomesite.com/new');
window.location.assign.mockRestore();
});
@SimenB .assign
ãš.href
ã¯å€§ããªéãããããŸããMDNã§èªãããšãã§ããŸãã æåã®ãã®ã«ã¯ãäž»èŠãªã¯ãã¹ãã¡ã€ã³å¶éããããŸãã ç§ã®ã³ãŒãã§ã¯ãã³ãŒããå®è¡ãããŠããiframeãã芪ããŒãžããªãã€ã¬ã¯ãããããšæããŸãã ãããã¯ã¯ãã¹ãã¡ã€ã³ã§ãã ãããŠããããè¡ãå¯äžã®æ¹æ³ã¯ã href
å€æŽããããšã§ãã
çŸåšã®åé¿çãèŠåœãããããã®æ©èœã®ãã¹ããè¡ããªãããã«ããå¿
èŠãããããããã®åé¡ãå床éããŠããã ããã°å¹žãã§ãã ããã¯æããã«ã²ã©ãã§ãã
ç§ã¯@soswowãšåãè¹ã«ä¹ã£ãŠããŸãã ãã®æ©èœã埩å ããããŸã§ããã€ãã®åäœãã¹ããåé€ããã®ã§ãURLããªãŒããŒã©ã€ãããã¡ã«ããºã ãæäŸã§ããã°çŽ æŽããããšæããŸãã
çŸåšã®åé¿çãèŠåœãããããã®æ©èœã®ãã¹ããè¡ããªãããã«ããå¿ èŠãããããããã®åé¡ãå床éããŠããã ããã°å¹žãã§ãã ããã¯æããã«ã²ã©ãã§ãã
åè«ã®åŽã§ç§ãã¡ã«ã§ããããšã¯äœããããŸããã jsdomã¯ããããµããŒãããPRã倧奜ãã ãšç¢ºä¿¡ããŠããŸãã https://github.com/jsdom/jsdom/issues/2112
ãããæ©èœããç°¡åãªè§£æ±ºçã§ãã
describe('changing location', () => {
const testURL = location.href;
beforeEach(() => history.replaceState({}, 'Login', '/login'));
afterEach(() => history.replaceState({}, 'Home', '/'));
it('works', () => {
expect(location.pathname).toBe('/login');
});
});
@vastusç§ãæ瀺çã«ææããããã«ãåé¡ã¯ã¯ãã¹ãã¡ã€ã³ã«ãããŸãã å±¥æŽAPIã§ã¯ãç§ãèŠããŠããéããå¥ã®ãã¡ã€ã³ã«åãæ¿ããããšã¯ã§ããŸããã
location
ã¯jsdom window
ãªããžã§ã¯ãã§çŽæ¥ãªãŒããŒã©ã€ãã§ããªãããã1ã€ã®å¯èœãªã¢ãããŒãã¯ã掟çãªããžã§ã¯ãã§ãªãŒããŒã©ã€ãããããšã§ãã
global.window = Object.create(window);
Object.defineProperty(window, 'location', {
value: {
href: 'http://example.org/'
}
});
ç§ã¯ããã䜿ã£ãŠåé¡ã解決ããŸãïŒ
const windowLocation = JSON.stringify(window.location);
delete window.location;
Object.defineProperty(window, 'location', {
value: JSON.parse(windowLocation)
});
@ RubenVerborgh ïŒ annemarie35ã«è§Šçºããã
@vastusã®ãœãªã¥ãŒã·ã§ã³ã«åºã¥ããŠlocation.search
ããã¹ãããäŸãè¿œå ããŸãã
test('gets passed query param and returns it as a string if it exists', () => {
history.replaceState({}, 'Test', '/test?customer=123');
const customerId = getQueryParam('customer');
expect(customerId).toBe('123');
});
@RubenVerborghã¯é åã®ããã«æ©èœããŸãã
è©ŠãïŒ
window.history.pushState({}, null, '/pathname?k=v');
@sahalsaadã«äŒŒã解決çïŒ
`` `javascript
const oldWindow = window.location;
window.locationãåé€ããŸãã
window.location = {
... oldWindowã
//次ã®sinonã¹ã¿ããªã©ã®ã«ã¹ã¿ã äžæžããå«ãã
眮æïŒsinon.stubïŒïŒã
};
//éæ³ãããã
window.location = oldWindow;
`` ``
@sahalsaadããããšãïŒ ç§ã¯ããªãã®ãœãªã¥ãŒã·ã§ã³ã®ããªãšãŒã·ã§ã³ã䜿çšããŠwindow.location.searchãã¢ãã¯ããŸããïŒ
const location = {
...window.location,
search: queryString,
};
Object.defineProperty(window, 'location', {
writable: true,
value: location,
});
ããããããè¯ã解決çïŒ
import { URL } from 'whatwg-url';
const location = new URL(window.location.href);
location.assign = jest.fn()
location.replace = jest.fn()
location.reload = jest.fn()
delete window.location
window.location = location
@kdelmonteã«ãã£ãŠwindow.location.search
å€æ°ãã¢ãã¯ããå¿
èŠããããŸããã ã ããç§ã¯äœ¿çšããŸãã
window.history.pushState({}, null, '?skuId=1234')
location
ã¯jsdomwindow
ãªããžã§ã¯ãã§çŽæ¥ãªãŒããŒã©ã€ãã§ããªãããã1ã€ã®å¯èœãªã¢ãããŒãã¯ã掟çãªããžã§ã¯ãã§ãªãŒããŒã©ã€ãããããšã§ããglobal.window = Object.create(window); Object.defineProperty(window, 'location', { value: { href: 'http://example.org/' } });
ããªãã®çãã¯ç§ã®ç¶æ³ã«åœ¹ç«ã€å¯äžã®ãã®ã§ããããããšãïŒ
location
ã¯jsdomwindow
ãªããžã§ã¯ãã§çŽæ¥ãªãŒããŒã©ã€ãã§ããªãããã1ã€ã®å¯èœãªã¢ãããŒãã¯ã掟çãªããžã§ã¯ãã§ãªãŒããŒã©ã€ãããããšã§ããglobal.window = Object.create(window); Object.defineProperty(window, 'location', { value: { href: 'http://example.org/' } });
ããªãã®çãã¯ç§ã®ç¶æ³ã«åœ¹ç«ã€å¯äžã®ãã®ã§ããããããšãïŒ
ããã¯ããæ©èœããŸããð¢
location
ã¯jsdomwindow
ãªããžã§ã¯ãã§çŽæ¥ãªãŒããŒã©ã€ãã§ããªãããã1ã€ã®å¯èœãªã¢ãããŒãã¯ã掟çãªããžã§ã¯ãã§ãªãŒããŒã©ã€ãããããšã§ããglobal.window = Object.create(window); Object.defineProperty(window, 'location', { value: { href: 'http://example.org/' } });
ããªãã®çãã¯ç§ã®ç¶æ³ã«åœ¹ç«ã€å¯äžã®ãã®ã§ããããããšãïŒ
ããã¯ããæ©èœããŸããð¢
ç§ã®ããã«ãåããŠããªã
ç§ã¯ããããã£ãŠè§£æ±ºããŸããïŒ
delete window.location
window.location = {
href: 'http://example.org/,
}
Location
ããã®ãŠãŒãã£ãªãã£ãšããŠæ¬¡ã®ã¢ãã¯ã䜿çšããŠããŸã
export class MockLocation extends URL implements Location {
ancestorOrigins: any = []
toString = jest.fn().mockImplementation(() => this.toString())
assign = jest.fn(href => this.href = href)
replace = jest.fn(href => this.href = href)
reload = jest.fn()
constructor(
url: string = 'http://mock.localhost',
) {
super(url)
}
onWindow(window: Window) {
Object.defineProperty(window, 'location', {
writable: true,
value: this
});
return this
}
}
ããããç§ã®ãã¹ãã§ã¯
let location: MockLocation
beforeEach(() => {
location = new MockLocation(MOCK_PARTNER_URL).onWindow(window)
})
ç§ã¯ãã€ããã®ãããªããªãããŒãªãªããžã§ã¯ããã¹ã¿ãããŠããããšã«æ°ã¥ããæè»ãªãã«ããŒé¢æ°ãäœæããŸããã
export const safelyStubAndThenCleanup = (target, method, value) => {
const original = target[method]
beforeEach(() => {
Object.defineProperty(target, method, { configurable: true, value })
})
afterEach(() => {
Object.defineProperty(target, method, { configurable: true, value: original })
})
}
ãããŠäœ¿çšæ³ïŒ
describe('when on /pages', () => {
safelyStubAndThenCleanup(window, 'location', { pathname: '/pages' })
it('should do something neat', () => { /* ... */ })
})
ãããŠãããªãã¯ããªããæããã®ãäœã§ãã¹ã¿ãããããšãã§ããŸãïŒ pathname
ã href
ãªã©...ããã¯ããªãã«ã¯ãªãŒã³ã¢ããã®è¿œå ã®ç¡æã®å©ç¹ããããããŸãã
éèŠãªã®ã¯ã location
èªäœãå°ç¡ãã«ããããšã¯ã§ããªãã®ã§ã location
ãåœç©ãšäº€æãããã¹ããå®äºãããå
ã«æ»ãã ãã§ãã
ãããã°ã»ãã·ã§ã³ã§ãããããã«ã global.location
ã¯getterãä»ããŠå®è£
ãããŠããŸãããåçŽãªããããã£ã§ã¯ãããŸããã ãã®ããã«åå®çŸ©ããæ¹ãå®å
šã§ã¯ãªãã§ããããã
let originalLocationDescriptor;
beforeAll(() => {
originalLocationDescriptor = Object.getOwnPropertyDescriptor(global, 'location');
delete global.location;
global.location = {};
});
afterAll(() => {
Object.defineProperty(global, 'location', originalLocationDescriptor);
}):
å
ã®global.location
ã䜿çšããçç±ãæ³åããã®ã¯é£ããã§ãããããå°ãæ£ããããã§ãã
ãã¡ããããã®ã³ãŒãã¯ç§ã«ãšã£ãŠã¯åé¡ãªãæ©èœããŸãã location.pathname
ã«ã¢ã¯ã»ã¹ããã ãã§ããããã®ãªããžã§ã¯ãã¯ãå¿
èŠã«å¿ããŠjest.fn()
ã§ç°¡åã«æ¡åŒµã§ããŸãã
ããã¯ãjest26.5ã䜿çšããŠç§ã®ããã«åããŠããŸã
function stubLocation(location) {
beforeEach(() => {
jest.spyOn(window, "location", "get").mockReturnValue({
...window.location,
...location,
});
});
}
stubLocation({ pathname: "/facebook/jest/issues/5124" });
test("mocks location prop", () => {
expect(window.location.pathname).toEqual("/facebook/jest/issues/5124");
});
@vastusã®ãœãªã¥ãŒã·ã§ã³ã«åºã¥ããŠ
location.search
ããã¹ãããäŸãè¿œå ããŸããtest('gets passed query param and returns it as a string if it exists', () => { history.replaceState({}, 'Test', '/test?customer=123'); const customerId = getQueryParam('customer'); expect(customerId).toBe('123'); });
ããã¯ç§ãæ±ããŠããåé¡ã«å¯ŸããŠæ£ç¢ºã«ããŸããããŸãã
æãåèã«ãªãã³ã¡ã³ã
ç§ã¯npmã«
jest-environment-jsdom-global
ãšããæ°ããããã±ãŒãžãå ¬éããŸãããããã¯ãäžéšã®äººã ãObject.defineProperty
æ±ããŠããåé¡ã«åœ¹ç«ã€å¯èœæ§ããããŸãã