diff options
Diffstat (limited to 'spec/frontend/__helpers__/set_window_location_helper.js')
-rw-r--r-- | spec/frontend/__helpers__/set_window_location_helper.js | 75 |
1 files changed, 44 insertions, 31 deletions
diff --git a/spec/frontend/__helpers__/set_window_location_helper.js b/spec/frontend/__helpers__/set_window_location_helper.js index a94e73762c9..573a089f111 100644 --- a/spec/frontend/__helpers__/set_window_location_helper.js +++ b/spec/frontend/__helpers__/set_window_location_helper.js @@ -1,40 +1,53 @@ /** - * setWindowLocation allows for setting `window.location` - * (doing so directly is causing an error in jsdom) + * setWindowLocation allows for setting `window.location` within Jest. * - * Example usage: - * assert(window.location.hash === undefined); - * setWindowLocation('http://example.com#foo') - * assert(window.location.hash === '#foo'); + * The jsdom environment at the time of writing does not support changing the + * current location (see + * https://github.com/jsdom/jsdom/blob/16.4.0/lib/jsdom/living/window/navigation.js#L76), + * hence this helper. * - * More information: - * https://github.com/facebook/jest/issues/890 + * This helper mutates the current `window.location` very similarly to how + * a direct assignment to `window.location.href` would in a browser (but + * without the navigation/reload behaviour). For instance: * - * @param url + * - Set the full href by passing an absolute URL, e.g.: + * + * setWindowLocation('https://gdk.test'); + * // window.location.href is now 'https://gdk.test' + * + * - Set the path, search and/or hash components by passing a relative URL: + * + * setWindowLocation('/foo/bar'); + * // window.location.href is now 'http://test.host/foo/bar' + * + * setWindowLocation('?foo=bar'); + * // window.location.href is now 'http://test.host/?foo=bar' + * + * setWindowLocation('#foo'); + * // window.location.href is now 'http://test.host/#foo' + * + * setWindowLocation('/a/b/foo.html?bar=1#qux'); + * // window.location.href is now 'http://test.host/a/b/foo.html?bar=1#qux + * + * Both approaches also automatically update the rest of the properties on + * `window.locaton`. For instance: + * + * setWindowLocation('http://test.host/a/b/foo.html?bar=1#qux'); + * // window.location.origin is now 'http://test.host' + * // window.location.pathname is now '/a/b/foo.html' + * // window.location.search is now '?bar=1' + * // window.location.searchParams is now { bar: 1 } + * // window.location.hash is now '#qux' + * + * @param {string} url A string representing an absolute or relative URL. + * @returns {undefined} */ export default function setWindowLocation(url) { - const parsedUrl = new URL(url); + if (typeof url !== 'string') { + throw new TypeError(`Expected string; got ${url} (${typeof url})`); + } - const newLocationValue = [ - 'hash', - 'host', - 'hostname', - 'href', - 'origin', - 'pathname', - 'port', - 'protocol', - 'search', - ].reduce( - (location, prop) => ({ - ...location, - [prop]: parsedUrl[prop], - }), - {}, - ); + const newUrl = new URL(url, window.location.href); - Object.defineProperty(window, 'location', { - value: newLocationValue, - writable: true, - }); + global.jsdom.reconfigure({ url: newUrl.href }); } |