From a67d1901c052fd3edcb0d44a7d9d5df7f296390e Mon Sep 17 00:00:00 2001 From: Tom Byers Date: Thu, 29 Aug 2019 10:58:27 +0100 Subject: [PATCH] Add mock for window.location --- tests/javascripts/support/helpers.js | 2 + tests/javascripts/support/helpers/globals.js | 89 ++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 tests/javascripts/support/helpers/globals.js diff --git a/tests/javascripts/support/helpers.js b/tests/javascripts/support/helpers.js index fe5adf08e..c86772626 100644 --- a/tests/javascripts/support/helpers.js +++ b/tests/javascripts/support/helpers.js @@ -1,3 +1,4 @@ +const globals = require('./helpers/globals.js'); const events = require('./helpers/events.js'); const domInterfaces = require('./helpers/dom_interfaces.js'); const html = require('./helpers/html.js'); @@ -5,6 +6,7 @@ const elements = require('./helpers/elements.js'); const rendering = require('./helpers/rendering.js'); const forms = require('./helpers/forms.js'); +exports.LocationMock = globals.LocationMock; exports.triggerEvent = events.triggerEvent; exports.clickElementWithMouse = events.clickElementWithMouse; exports.moveSelectionToRadio = events.moveSelectionToRadio; diff --git a/tests/javascripts/support/helpers/globals.js b/tests/javascripts/support/helpers/globals.js new file mode 100644 index 000000000..89fa44e08 --- /dev/null +++ b/tests/javascripts/support/helpers/globals.js @@ -0,0 +1,89 @@ +// helpers for mocking objects attached to the global space as properties, ie. window.location + +class LocationMock { + + constructor (URL) { + + this._location = window.location; + + // setting href sets all sub-properties + this.href = URL; + + // JSDOM sets window.location as non-configurable + // the only way to mock it, currently, is to replace it completely + delete window.location; + window.location = this; + + } + + get href () { + + return `${this.protocol}://${this.host}${this.pathname}${this.search}${this.hash}` + + } + + set href (value) { + + const partNames = ['protocol', 'hostname', 'port', 'pathname', 'search', 'hash']; + + const protocol = '(https:|http:)'; + const hostname = '[^\\/]+'; + const port = '(:\\d)'; + const pathname = '([^?]+)'; + const search = '([^#])'; + const hash = '(#[\\x00-\\x7F])'; // match any ASCII character + + const re = new RegExp(`^${protocol}{0,1}(?:\\/\\/){0,1}(${hostname}${port}{0,1}){0,1}${pathname}{0,1}${search}{0,1}${hash}{0,1}$`); + const match = value.match(re) + + if (match === null) { throw Error(`${value} is not a valid URL`); } + + match.forEach((part, idx) => { + + let partName; + + // 0 index is whole match, we want the groups + if (idx > 0) { + partName = partNames[idx - 1]; + + if (part !== undefined) { + this[partName] = part; + } else if (!(partName in this)) { // only get value from window.location if property not set + this[partName] = this._location[partName]; + } + } + + }); + + } + + get host () { + + return `${this.hostname}:${this.port}`; + + } + + set host (value) { + + const parts = value.split(':'); + + this.hostname = parts[0]; + this.protocol = parts[1]; + + } + + // origin is read-only + get origin () { + + return `${this.protol}://${this.hostname}`; + + } + + reset () { + + window.location = this._location; + + } +} + +exports.LocationMock = LocationMock;