diff --git a/src/lib/connectors/jsdom/jsdom-async-html.ts b/src/lib/connectors/jsdom/jsdom-async-html.ts index cb6c3b1810f..45159e2f627 100644 --- a/src/lib/connectors/jsdom/jsdom-async-html.ts +++ b/src/lib/connectors/jsdom/jsdom-async-html.ts @@ -13,12 +13,17 @@ export class JSDOMAsyncHTMLDocument implements IAsyncHTMLDocument { // ------------------------------------------------------------------------------ public querySelectorAll(selector: string): Promise> { - const elements = Array.prototype.slice.call(this._document.querySelectorAll(selector)) - .map((element) => { - return new JSDOMAsyncHTMLElement(element); // eslint-disable-line no-use-before-define, typescript/no-use-before-define - }); - - return Promise.resolve(elements); + // jsdom's `querySelectorAll` can be a bit fragile (e.g.: fails if attribute name has `.` on it) + try { + const elements = Array.prototype.slice.call(this._document.querySelectorAll(selector)) + .map((element) => { + return new JSDOMAsyncHTMLElement(element); // eslint-disable-line no-use-before-define, typescript/no-use-before-define + }); + + return Promise.resolve(elements); + } catch (e) { + return Promise.resolve([]); + } } public pageHTML(): Promise { diff --git a/src/lib/utils/location-helpers.ts b/src/lib/utils/location-helpers.ts index 5a314029763..84dc1a969df 100644 --- a/src/lib/utils/location-helpers.ts +++ b/src/lib/utils/location-helpers.ts @@ -23,7 +23,11 @@ const selectorFromElement = (element: IAsyncHTMLElement): string => { for (let i = 0; i < attributes.length; i++) { const attribute: IAsyncHTMLAttribute | NamedNodeMap = attributes[i]; - selector += `[${attribute.name}="${escapeQuotes(attribute.value)}"]`; + /* jsdom breaks when attribute names have a `.` (invalid) but it is widely used, + so we ignore that selector. */ + if (!attribute.name.includes('.')) { + selector += `[${attribute.name}="${escapeQuotes(attribute.value)}"]`; + } } debug(`Selector created: ${selector}`);