diff --git a/package.json b/package.json index 18ead7ebc..affc7c973 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "ms": "^2.1.1", "request": "^2.85.0", "tough-cookie": "^2.3.4", + "whatwg-url": "^7.0.0", "ws": "^6.1.2" }, "devDependencies": { diff --git a/src/document.js b/src/document.js index 523b915db..273e50857 100644 --- a/src/document.js +++ b/src/document.js @@ -16,6 +16,7 @@ const WebSocket = require('ws'); const Window = require('jsdom/lib/jsdom/browser/Window'); const XMLHttpRequest = require('./xhr'); const { idlUtils } = require('./dom/impl'); +const whatwgURL = require('whatwg-url'); // File access, not implemented yet class File { @@ -51,38 +52,6 @@ class Screen { } -// DOM implementation of URL class -class DOMURL { - - constructor(url, base) { - if (url == null) - throw new TypeError('Failed to construct \'URL\': Invalid URL'); - if (base) - url = URL.resolve(base, url); - const parsed = URL.parse(url || 'about:blank'); - const origin = parsed.protocol && parsed.hostname && `${parsed.protocol}//${parsed.hostname}`; - Object.defineProperties(this, { - hash: { value: parsed.hash, enumerable: true }, - host: { value: parsed.host, enumerable: true }, - hostname: { value: parsed.hostname, enumerable: true }, - href: { value: URL.format(parsed), enumerable: true }, - origin: { value: origin, enumerable: true }, - password: { value: parsed.password, enumerable: true }, - pathname: { value: parsed.pathname, enumerable: true }, - port: { value: parsed.port, enumerable: true }, - protocol: { value: parsed.protocol, enumerable: true }, - search: { value: parsed.search, enumerable: true }, - username: { value: parsed.username, enumerable: true } - }); - } - - toString() { - return this.href; - } - -} - - function setupWindow(window, args) { const { document } = window; const { browser, history } = args; @@ -171,7 +140,7 @@ function setupWindow(window, args) { // Constructor for XHLHttpRequest window.XMLHttpRequest = XMLHttpRequest.bind(null, window); - window.URL = DOMURL; + window.URL = whatwgURL.URL; // Web sockets window._allWebSockets = []; diff --git a/src/history.js b/src/history.js index 86f100a6e..40847c827 100644 --- a/src/history.js +++ b/src/history.js @@ -140,6 +140,13 @@ class Location { const url = Object.assign(URL.parse(this._url), { search: value }); this.assign(URL.format(url)); } + + get searchParams() { + const url = URL.parse(this._url); + + if (url.search == null) return null; + return new URL.URLSearchParams(url.search); + } } diff --git a/test/document_test.js b/test/document_test.js index b6320b5a1..30947d53f 100644 --- a/test/document_test.js +++ b/test/document_test.js @@ -28,6 +28,39 @@ describe('Document', function() { }); }); + describe('location/DOMURL', function() { + before(function() { + brains.get('/somepath', function(req, res) { + res.send(''); + }); + + return browser.visit('/somepath?foo=bar'); + }); + + describe('port', function() { + it('should be a string', function() { + const location = browser.location; + + // Browsers type this as ?string. + assert.equal(location.port, ''); + }) + }); + describe('searchParams', function() { + it('should be present', function() { + const searchParams = browser.location.searchParams; + + assert.strictEqual(searchParams.get('foo'), 'bar'); + }); + + describe('when no query is specified', function() { + it('is undefined', function() { + browser.visit('/somepath'); + assert.equal(browser.location.searchParams, null); + }); + }); + }); + }); + describe('activeElement', function() { before(function() {