Skip to content

Instantly share code, notes, and snippets.

@tomasc
Created July 22, 2020 18:08
Show Gist options
  • Save tomasc/b2453934ffb1856d610ec215661d28fa to your computer and use it in GitHub Desktop.
Save tomasc/b2453934ffb1856d610ec215661d28fa to your computer and use it in GitHub Desktop.
```
Run options: --seed 25431
# Running:
Capybara starting Puma...
* Version 4.3.5 , codename: Mysterious Traveller
* Min threads: 0, max threads: 4
* Listening on tcp://0.0.0.0:40303
▶ 0.014318699948489666 {"method":"Target.setDiscoverTargets","params":{"discover":true},"id":1}
◀ 0.03441289998590946 {"method":"Target.targetCreated","params":{"targetInfo":{"targetId":"5415ac0f-4f33-4bee-b1ed-1d2478f6abb0","type":"browser","title":"","url":"","attached":true}}}
◀ 0.035498599987477064 {"method":"Target.targetCreated","params":{"targetInfo":{"targetId":"56A5533C95E81C49E973F17E4AAF12C9","type":"page","title":"about:blank","url":"about:blank","attached":true,"browserContextId":"803BCAC2D63A7DF7D537D01F81B09C6C"}}}
◀ 0.03660440002568066 {"method":"Target.targetCreated","params":{"targetInfo":{"targetId":"63017faa-4a66-4839-a909-55b9f9c4568d","type":"browser","title":"","url":"","attached":true}}}
◀ 0.03740929998457432 {"method":"Target.targetCreated","params":{"targetInfo":{"targetId":"ccc36cf7-694f-4661-af6b-9abeae5498ed","type":"browser","title":"","url":"","attached":false}}}
◀ 0.03801939997356385 {"id":1,"result":{}}
▶ 0.03917969996109605 {"method":"Target.createBrowserContext","params":{},"id":2}
◀ 0.04028910002671182 {"id":2,"result":{"browserContextId":"B40DAEBD0CD7B082001869695738B210"}}
▶ 0.04077850002795458 {"method":"Target.createTarget","params":{"browserContextId":"B40DAEBD0CD7B082001869695738B210","url":"about:blank"},"id":3}
◀ 0.045103800017386675 {"method":"Target.targetCreated","params":{"targetInfo":{"targetId":"DBC756CA7BC7888FD285B45ED21336FC","type":"page","title":"","url":"","attached":false,"browserContextId":"B40DAEBD0CD7B082001869695738B210"}}}
◀ 0.046841399976983666 {"id":3,"result":{"targetId":"DBC756CA7BC7888FD285B45ED21336FC"}}
▶ 0.05256490001920611 {"method":"Page.enable","params":{},"id":1001}
◀ 0.06121419998817146 {"method":"Target.targetInfoChanged","params":{"targetInfo":{"targetId":"DBC756CA7BC7888FD285B45ED21336FC","type":"page","title":"","url":"about:blank","attached":true,"browserContextId":"B40DAEBD0CD7B082001869695738B210"}}}
◀ 0.06863989995326847 {"method":"Target.targetInfoChanged","params":{"targetInfo":{"targetId":"DBC756CA7BC7888FD285B45ED21336FC","type":"page","title":"about:blank","url":"about:blank","attached":true,"browserContextId":"B40DAEBD0CD7B082001869695738B210"}}}
◀ 0.07349099998828024 {"id":1001,"result":{}}
▶ 0.07416119996923953 {"method":"Runtime.enable","params":{},"id":1002}
◀ 0.07723539997823536 {"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"origin":"://","name":"","auxData":{"isDefault":true,"type":"default","frameId":"DBC756CA7BC7888FD285B45ED21336FC"}}}}
◀ 0.07814829994458705 {"id":1002,"result":{}}
▶ 0.07928079995326698 {"method":"DOM.enable","params":{},"id":1003}
◀ 0.08101530000567436 {"method":"Runtime.executionContextCreated","params":{"context":{"id":2,"origin":"","name":"__puppeteer_utility_world__","auxData":{"isDefault":false,"type":"isolated","frameId":"DBC756CA7BC7888FD285B45ED21336FC"}}}}
◀ 0.08258419996127486 {"id":1003,"result":{}}
▶ 0.08339699998032302 {"method":"CSS.enable","params":{},"id":1004}
◀ 0.08589260000735521 {"id":1004,"result":{}}
▶ 0.08645760000217706 {"method":"Log.enable","params":{},"id":1005}
◀ 0.0879352999618277 {"id":1005,"result":{}}
▶ 0.0883581000380218 {"method":"Network.enable","params":{},"id":1006}
◀ 0.09017039998434484 {"id":1006,"result":{}}
▶ 0.0907768999459222 {"method":"Page.setDownloadBehavior","params":{"behavior":"allow","downloadPath":"./tmp/capybara"},"id":1007}
◀ 0.09805389994289726 {"id":1007,"result":{}}
▶ 0.10455110005568713 {"method":"Page.addScriptToEvaluateOnNewDocument","params":{"source":"class InvalidSelector extends Error {}\nclass TimedOutPromise extends Error {}\nclass MouseEventFailed extends Error {}\n\nconst EVENTS = {\n FOCUS: [\"blur\", \"focus\", \"focusin\", \"focusout\"],\n MOUSE: [\"click\", \"dblclick\", \"mousedown\", \"mouseenter\", \"mouseleave\",\n \"mousemove\", \"mouseover\", \"mouseout\", \"mouseup\", \"contextmenu\"],\n FORM: [\"submit\"]\n}\n\nclass Cuprite {\n constructor() {\n this._json = JSON; // In case someone overrides it like mootools\n }\n\n find(method, selector, within = document) {\n try {\n let results = [];\n\n if (method == \"xpath\") {\n let xpath = document.evaluate(selector, within, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n for (let i = 0; i \u003c xpath.snapshotLength; i++) {\n results.push(xpath.snapshotItem(i));\n }\n } else {\n results = Array.from(within.querySelectorAll(selector));\n }\n\n return results;\n } catch (error) {\n // DOMException.INVALID_EXPRESSION_ERR is undefined, using pure code\n if (error.code == DOMException.SYNTAX_ERR || error.code == 51) {\n throw new InvalidSelector;\n } else {\n throw error;\n }\n }\n }\n\n parents(node) {\n let nodes = [];\n let parent = node.parentNode;\n while (parent != document) {\n nodes.push(parent);\n parent = parent.parentNode;\n }\n return nodes;\n }\n\n visibleText(node) {\n if (this.isVisible(node)) {\n if (node.nodeName == \"TEXTAREA\") {\n return node.textContent;\n } else {\n if (node instanceof SVGElement) {\n return node.textContent;\n } else {\n return node.innerText;\n }\n }\n }\n }\n\n isVisible(node) {\n let mapName, style;\n // if node is area, check visibility of relevant image\n if (node.tagName === \"AREA\") {\n mapName = document.evaluate(\"./ancestor::map/@name\", node, null, XPathResult.STRING_TYPE, null).stringValue;\n node = document.querySelector(`img[usemap=\"#${mapName}\"]`);\n if (node == null) {\n return false;\n }\n }\n\n while (node) {\n style = window.getComputedStyle(node);\n if (style.display === \"none\" || style.visibility === \"hidden\" || parseFloat(style.opacity) === 0) {\n return false;\n }\n node = node.parentElement;\n }\n\n return true;\n }\n\n\n isDisabled(node) {\n let xpath = \"parent::optgroup[@disabled] | \\\n ancestor::select[@disabled] | \\\n parent::fieldset[@disabled] | \\\n ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]\";\n\n return node.disabled || document.evaluate(xpath, node, null, XPathResult.BOOLEAN_TYPE, null).booleanValue;\n }\n\n path(node) {\n let nodes = [node];\n let parent = node.parentNode;\n while (parent !== document) {\n nodes.unshift(parent);\n parent = parent.parentNode;\n }\n\n let selectors = nodes.map(node =\u003e {\n let prevSiblings = [];\n let xpath = document.evaluate(`./preceding-sibling::${node.tagName}`, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n\n for (let i = 0; i \u003c xpath.snapshotLength; i++) {\n prevSiblings.push(xpath.snapshotItem(i));\n }\n\n return `${node.tagName}[${(prevSiblings.length + 1)}]`;\n });\n\n return `//${selectors.join(\"/\")}`;\n }\n\n set(node, value) {\n if (node.readOnly) return;\n\n if (node.maxLength \u003e= 0) {\n value = value.substr(0, node.maxLength);\n }\n\n let valueBefore = node.value;\n\n this.trigger(node, \"focus\");\n this.setValue(node, \"\");\n\n if (node.type == \"number\" || node.type == \"date\" || node.type == \"range\") {\n this.setValue(node, value);\n this.input(node);\n } else if (node.type == \"time\") {\n this.setValue(node, new Date(value).toTimeString().split(\" \")[0]);\n this.input(node);\n } else if (node.type == \"datetime-local\") {\n value = new Date(value);\n let year = value.getFullYear();\n let month = (\"0\" + (value.getMonth() + 1)).slice(-2);\n let date = (\"0\" + value.getDate()).slice(-2);\n let hour = (\"0\" + value.getHours()).slice(-2);\n let min = (\"0\" + value.getMinutes()).slice(-2);\n let sec = (\"0\" + value.getSeconds()).slice(-2);\n this.setValue(node, `${year}-${month}-${date}T${hour}:${min}:${sec}`);\n this.input(node);\n } else {\n for (let i = 0; i \u003c value.length; i++) {\n let char = value[i];\n let keyCode = this.characterToKeyCode(char);\n // call the following functions in order, if one returns false (preventDefault),\n // stop the call chain\n [\n () =\u003e this.keyupdowned(node, \"keydown\", keyCode),\n () =\u003e this.keypressed(node, false, false, false, false, char.charCodeAt(0), char.charCodeAt(0)),\n () =\u003e {\n this.setValue(node, node.value + char)\n this.input(node)\n }\n ].some(fn =\u003e fn())\n\n this.keyupdowned(node, \"keyup\", keyCode);\n }\n }\n\n if (valueBefore !== node.value) {\n this.changed(node);\n }\n this.trigger(node, \"blur\");\n }\n\n setValue(node, value) {\n let nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, \"value\").set;\n let nativeTextareaValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, \"value\").set;\n\n if (node.tagName.toLowerCase() === 'input') {\n return nativeInputValueSetter.call(node, value);\n }\n return nativeTextareaValueSetter.call(node, value);\n }\n\n input(node) {\n let event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"input\", true, false);\n node.dispatchEvent(event);\n }\n\n /**\n * @return {boolean} false when an event handler called preventDefault()\n */\n keyupdowned(node, eventName, keyCode) {\n let event = document.createEvent(\"UIEvents\");\n event.initEvent(eventName, true, true);\n event.keyCode = keyCode;\n event.charCode = 0;\n return !node.dispatchEvent(event);\n }\n\n /**\n * @return {boolean} false when an event handler called preventDefault()\n */\n keypressed(node, altKey, ctrlKey, shiftKey, metaKey, keyCode, charCode) {\n event = document.createEvent(\"UIEvents\");\n event.initEvent(\"keypress\", true, true);\n event.window = window;\n event.altKey = altKey;\n event.ctrlKey = ctrlKey;\n event.shiftKey = shiftKey;\n event.metaKey = metaKey;\n event.keyCode = keyCode;\n event.charCode = charCode;\n return !node.dispatchEvent(event);\n }\n\n characterToKeyCode(char) {\n const specialKeys = {\n 96: 192, // `\n 45: 189, // -\n 61: 187, // =\n 91: 219, // [\n 93: 221, // ]\n 92: 220, // \\\n 59: 186, // ;\n 39: 222, // '\n 44: 188, // ,\n 46: 190, // .\n 47: 191, // /\n 127: 46, // delete\n 126: 192, // ~\n 33: 49, // !\n 64: 50, // @\n 35: 51, // #\n 36: 52, // $\n 37: 53, // %\n 94: 54, // ^\n 38: 55, // \u0026\n 42: 56, // *\n 40: 57, // (\n 41: 48, // )\n 95: 189, // _\n 43: 187, // +\n 123: 219, // {\n 125: 221, // }\n 124: 220, // |\n 58: 186, // :\n 34: 222, // \"\n 60: 188, // \u003c\n 62: 190, // \u003e\n 63: 191, // ?\n }\n\n let code = char.toUpperCase().charCodeAt(0);\n return specialKeys[code] || code;\n }\n\n scrollIntoViewport(node) {\n let areaImage = this._getAreaImage(node);\n\n if (areaImage) {\n return this.scrollIntoViewport(areaImage);\n } else {\n node.scrollIntoViewIfNeeded();\n\n if (!this._isInViewport(node)) {\n node.scrollIntoView({block: \"center\", inline: \"center\", behavior: \"instant\"});\n return this._isInViewport(node);\n }\n\n return true;\n }\n }\n\n mouseEventTest(node, name, x, y) {\n let frameOffset = this._frameOffset();\n x -= frameOffset.left;\n y -= frameOffset.top;\n\n let element = document.elementFromPoint(x, y);\n\n let el = element;\n while (el) {\n if (el == node) {\n return true;\n } else {\n el = el.parentNode;\n }\n }\n\n let selector = element \u0026\u0026 this._getSelector(element) || \"none\";\n throw new MouseEventFailed([name, selector, x, y].join(\", \"));\n }\n\n _getAreaImage(node) {\n if (\"area\" == node.tagName.toLowerCase()) {\n let map = node.parentNode;\n if (map.tagName.toLowerCase() != \"map\") {\n throw new Error(\"the area is not within a map\");\n }\n\n let mapName = map.getAttribute(\"name\");\n if (typeof mapName === \"undefined\" || mapName === null) {\n throw new Error(\"area's parent map must have a name\");\n }\n\n mapName = `#${mapName.toLowerCase()}`;\n let imageNode = this.find(\"css\", `img[usemap='${mapName}']`)[0];\n if (typeof imageNode === \"undefined\" || imageNode === null) {\n throw new Error(\"no image matches the map\");\n }\n\n return imageNode;\n }\n }\n\n _frameOffset() {\n let win = window;\n let offset = { top: 0, left: 0 };\n\n while (win.frameElement) {\n let rect = win.frameElement.getClientRects()[0];\n let style = win.getComputedStyle(win.frameElement);\n win = win.parent;\n\n offset.top += rect.top + parseInt(style.getPropertyValue(\"padding-top\"), 10)\n offset.left += rect.left + parseInt(style.getPropertyValue(\"padding-left\"), 10)\n }\n\n return offset;\n }\n\n _getSelector(el) {\n let selector = (el.tagName != 'HTML') ? this._getSelector(el.parentNode) + \" \" : \"\";\n selector += el.tagName.toLowerCase();\n if (el.id) { selector += `#${el.id}` };\n el.classList.forEach(c =\u003e selector += `.${c}`);\n return selector;\n }\n\n _isInViewport(node) {\n let rect = node.getBoundingClientRect();\n return rect.top \u003e= 0 \u0026\u0026\n rect.left \u003e= 0 \u0026\u0026\n rect.bottom \u003c= window.innerHeight \u0026\u0026\n rect.right \u003c= window.innerWidth;\n }\n\n select(node, value) {\n if (this.isDisabled(node)) {\n return false;\n } else if (value == false \u0026\u0026 !node.parentNode.multiple) {\n return false;\n } else {\n this.trigger(node.parentNode, \"focus\");\n\n node.selected = value;\n this.changed(node);\n\n this.trigger(node.parentNode, \"blur\");\n return true;\n }\n }\n\n changed(node) {\n let element;\n let event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"change\", true, false);\n\n // In the case of an OPTION tag, the change event should come\n // from the parent SELECT\n if (node.nodeName == \"OPTION\") {\n element = node.parentNode\n if (element.nodeName == \"OPTGROUP\") {\n element = element.parentNode\n }\n element\n } else {\n element = node\n }\n\n element.dispatchEvent(event)\n }\n\n trigger(node, name, options = {}) {\n let event;\n\n if (EVENTS.MOUSE.indexOf(name) != -1) {\n event = document.createEvent(\"MouseEvent\");\n event.initMouseEvent(\n name, true, true, window, 0,\n options[\"screenX\"] || 0, options[\"screenY\"] || 0,\n options[\"clientX\"] || 0, options[\"clientY\"] || 0,\n options[\"ctrlKey\"] || false,\n options[\"altKey\"] || false,\n options[\"shiftKey\"] || false,\n options[\"metaKey\"] || false,\n options[\"button\"] || 0, null\n )\n } else if (EVENTS.FOCUS.indexOf(name) != -1) {\n event = this.obtainEvent(name);\n } else if (EVENTS.FORM.indexOf(name) != -1) {\n event = this.obtainEvent(name);\n } else {\n throw \"Unknown event\";\n }\n\n node.dispatchEvent(event);\n }\n\n obtainEvent(name) {\n let event = document.createEvent(\"HTMLEvents\");\n event.initEvent(name, true, true);\n return event;\n }\n\n getAttributes(node) {\n let attrs = {};\n for (let i = 0, len = node.attributes.length; i \u003c len; i++) {\n let attr = node.attributes[i];\n attrs[attr.name] = attr.value.replace(\"\\n\", \"\\\\n\");\n }\n\n return this._json.stringify(attrs);\n }\n\n getAttribute(node, name) {\n if (name == \"checked\" || name == \"selected\") {\n return node[name];\n } else {\n return node.getAttribute(name);\n }\n }\n\n value(node) {\n if (node.tagName == \"SELECT\" \u0026\u0026 node.multiple) {\n let result = []\n\n for (let i = 0, len = node.children.length; i \u003c len; i++) {\n let option = node.children[i];\n if (option.selected) {\n result.push(option.value);\n }\n }\n\n return result;\n } else {\n return node.value;\n }\n }\n\n deleteText(node) {\n let range = document.createRange();\n range.selectNodeContents(node);\n window.getSelection().removeAllRanges();\n window.getSelection().addRange(range);\n window.getSelection().deleteFromDocument();\n }\n\n containsSelection(node) {\n let selectedNode = document.getSelection().focusNode;\n\n if (!selectedNode) {\n return false;\n }\n\n if (selectedNode.nodeType == 3) {\n selectedNode = selectedNode.parentNode;\n }\n\n return node.contains(selectedNode);\n }\n\n // This command is purely for testing error handling\n browserError() {\n throw new Error(\"zomg\");\n }\n}\n\nwindow._cuprite = new Cuprite;\n"},"id":1008}
◀ 0.10861909994855523 {"id":1008,"result":{"identifier":"1"}}
▶ 0.1106916000135243 {"method":"Runtime.evaluate","params":{"expression":"class InvalidSelector extends Error {}\nclass TimedOutPromise extends Error {}\nclass MouseEventFailed extends Error {}\n\nconst EVENTS = {\n FOCUS: [\"blur\", \"focus\", \"focusin\", \"focusout\"],\n MOUSE: [\"click\", \"dblclick\", \"mousedown\", \"mouseenter\", \"mouseleave\",\n \"mousemove\", \"mouseover\", \"mouseout\", \"mouseup\", \"contextmenu\"],\n FORM: [\"submit\"]\n}\n\nclass Cuprite {\n constructor() {\n this._json = JSON; // In case someone overrides it like mootools\n }\n\n find(method, selector, within = document) {\n try {\n let results = [];\n\n if (method == \"xpath\") {\n let xpath = document.evaluate(selector, within, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n for (let i = 0; i \u003c xpath.snapshotLength; i++) {\n results.push(xpath.snapshotItem(i));\n }\n } else {\n results = Array.from(within.querySelectorAll(selector));\n }\n\n return results;\n } catch (error) {\n // DOMException.INVALID_EXPRESSION_ERR is undefined, using pure code\n if (error.code == DOMException.SYNTAX_ERR || error.code == 51) {\n throw new InvalidSelector;\n } else {\n throw error;\n }\n }\n }\n\n parents(node) {\n let nodes = [];\n let parent = node.parentNode;\n while (parent != document) {\n nodes.push(parent);\n parent = parent.parentNode;\n }\n return nodes;\n }\n\n visibleText(node) {\n if (this.isVisible(node)) {\n if (node.nodeName == \"TEXTAREA\") {\n return node.textContent;\n } else {\n if (node instanceof SVGElement) {\n return node.textContent;\n } else {\n return node.innerText;\n }\n }\n }\n }\n\n isVisible(node) {\n let mapName, style;\n // if node is area, check visibility of relevant image\n if (node.tagName === \"AREA\") {\n mapName = document.evaluate(\"./ancestor::map/@name\", node, null, XPathResult.STRING_TYPE, null).stringValue;\n node = document.querySelector(`img[usemap=\"#${mapName}\"]`);\n if (node == null) {\n return false;\n }\n }\n\n while (node) {\n style = window.getComputedStyle(node);\n if (style.display === \"none\" || style.visibility === \"hidden\" || parseFloat(style.opacity) === 0) {\n return false;\n }\n node = node.parentElement;\n }\n\n return true;\n }\n\n\n isDisabled(node) {\n let xpath = \"parent::optgroup[@disabled] | \\\n ancestor::select[@disabled] | \\\n parent::fieldset[@disabled] | \\\n ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]\";\n\n return node.disabled || document.evaluate(xpath, node, null, XPathResult.BOOLEAN_TYPE, null).booleanValue;\n }\n\n path(node) {\n let nodes = [node];\n let parent = node.parentNode;\n while (parent !== document) {\n nodes.unshift(parent);\n parent = parent.parentNode;\n }\n\n let selectors = nodes.map(node =\u003e {\n let prevSiblings = [];\n let xpath = document.evaluate(`./preceding-sibling::${node.tagName}`, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n\n for (let i = 0; i \u003c xpath.snapshotLength; i++) {\n prevSiblings.push(xpath.snapshotItem(i));\n }\n\n return `${node.tagName}[${(prevSiblings.length + 1)}]`;\n });\n\n return `//${selectors.join(\"/\")}`;\n }\n\n set(node, value) {\n if (node.readOnly) return;\n\n if (node.maxLength \u003e= 0) {\n value = value.substr(0, node.maxLength);\n }\n\n let valueBefore = node.value;\n\n this.trigger(node, \"focus\");\n this.setValue(node, \"\");\n\n if (node.type == \"number\" || node.type == \"date\" || node.type == \"range\") {\n this.setValue(node, value);\n this.input(node);\n } else if (node.type == \"time\") {\n this.setValue(node, new Date(value).toTimeString().split(\" \")[0]);\n this.input(node);\n } else if (node.type == \"datetime-local\") {\n value = new Date(value);\n let year = value.getFullYear();\n let month = (\"0\" + (value.getMonth() + 1)).slice(-2);\n let date = (\"0\" + value.getDate()).slice(-2);\n let hour = (\"0\" + value.getHours()).slice(-2);\n let min = (\"0\" + value.getMinutes()).slice(-2);\n let sec = (\"0\" + value.getSeconds()).slice(-2);\n this.setValue(node, `${year}-${month}-${date}T${hour}:${min}:${sec}`);\n this.input(node);\n } else {\n for (let i = 0; i \u003c value.length; i++) {\n let char = value[i];\n let keyCode = this.characterToKeyCode(char);\n // call the following functions in order, if one returns false (preventDefault),\n // stop the call chain\n [\n () =\u003e this.keyupdowned(node, \"keydown\", keyCode),\n () =\u003e this.keypressed(node, false, false, false, false, char.charCodeAt(0), char.charCodeAt(0)),\n () =\u003e {\n this.setValue(node, node.value + char)\n this.input(node)\n }\n ].some(fn =\u003e fn())\n\n this.keyupdowned(node, \"keyup\", keyCode);\n }\n }\n\n if (valueBefore !== node.value) {\n this.changed(node);\n }\n this.trigger(node, \"blur\");\n }\n\n setValue(node, value) {\n let nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, \"value\").set;\n let nativeTextareaValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, \"value\").set;\n\n if (node.tagName.toLowerCase() === 'input') {\n return nativeInputValueSetter.call(node, value);\n }\n return nativeTextareaValueSetter.call(node, value);\n }\n\n input(node) {\n let event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"input\", true, false);\n node.dispatchEvent(event);\n }\n\n /**\n * @return {boolean} false when an event handler called preventDefault()\n */\n keyupdowned(node, eventName, keyCode) {\n let event = document.createEvent(\"UIEvents\");\n event.initEvent(eventName, true, true);\n event.keyCode = keyCode;\n event.charCode = 0;\n return !node.dispatchEvent(event);\n }\n\n /**\n * @return {boolean} false when an event handler called preventDefault()\n */\n keypressed(node, altKey, ctrlKey, shiftKey, metaKey, keyCode, charCode) {\n event = document.createEvent(\"UIEvents\");\n event.initEvent(\"keypress\", true, true);\n event.window = window;\n event.altKey = altKey;\n event.ctrlKey = ctrlKey;\n event.shiftKey = shiftKey;\n event.metaKey = metaKey;\n event.keyCode = keyCode;\n event.charCode = charCode;\n return !node.dispatchEvent(event);\n }\n\n characterToKeyCode(char) {\n const specialKeys = {\n 96: 192, // `\n 45: 189, // -\n 61: 187, // =\n 91: 219, // [\n 93: 221, // ]\n 92: 220, // \\\n 59: 186, // ;\n 39: 222, // '\n 44: 188, // ,\n 46: 190, // .\n 47: 191, // /\n 127: 46, // delete\n 126: 192, // ~\n 33: 49, // !\n 64: 50, // @\n 35: 51, // #\n 36: 52, // $\n 37: 53, // %\n 94: 54, // ^\n 38: 55, // \u0026\n 42: 56, // *\n 40: 57, // (\n 41: 48, // )\n 95: 189, // _\n 43: 187, // +\n 123: 219, // {\n 125: 221, // }\n 124: 220, // |\n 58: 186, // :\n 34: 222, // \"\n 60: 188, // \u003c\n 62: 190, // \u003e\n 63: 191, // ?\n }\n\n let code = char.toUpperCase().charCodeAt(0);\n return specialKeys[code] || code;\n }\n\n scrollIntoViewport(node) {\n let areaImage = this._getAreaImage(node);\n\n if (areaImage) {\n return this.scrollIntoViewport(areaImage);\n } else {\n node.scrollIntoViewIfNeeded();\n\n if (!this._isInViewport(node)) {\n node.scrollIntoView({block: \"center\", inline: \"center\", behavior: \"instant\"});\n return this._isInViewport(node);\n }\n\n return true;\n }\n }\n\n mouseEventTest(node, name, x, y) {\n let frameOffset = this._frameOffset();\n x -= frameOffset.left;\n y -= frameOffset.top;\n\n let element = document.elementFromPoint(x, y);\n\n let el = element;\n while (el) {\n if (el == node) {\n return true;\n } else {\n el = el.parentNode;\n }\n }\n\n let selector = element \u0026\u0026 this._getSelector(element) || \"none\";\n throw new MouseEventFailed([name, selector, x, y].join(\", \"));\n }\n\n _getAreaImage(node) {\n if (\"area\" == node.tagName.toLowerCase()) {\n let map = node.parentNode;\n if (map.tagName.toLowerCase() != \"map\") {\n throw new Error(\"the area is not within a map\");\n }\n\n let mapName = map.getAttribute(\"name\");\n if (typeof mapName === \"undefined\" || mapName === null) {\n throw new Error(\"area's parent map must have a name\");\n }\n\n mapName = `#${mapName.toLowerCase()}`;\n let imageNode = this.find(\"css\", `img[usemap='${mapName}']`)[0];\n if (typeof imageNode === \"undefined\" || imageNode === null) {\n throw new Error(\"no image matches the map\");\n }\n\n return imageNode;\n }\n }\n\n _frameOffset() {\n let win = window;\n let offset = { top: 0, left: 0 };\n\n while (win.frameElement) {\n let rect = win.frameElement.getClientRects()[0];\n let style = win.getComputedStyle(win.frameElement);\n win = win.parent;\n\n offset.top += rect.top + parseInt(style.getPropertyValue(\"padding-top\"), 10)\n offset.left += rect.left + parseInt(style.getPropertyValue(\"padding-left\"), 10)\n }\n\n return offset;\n }\n\n _getSelector(el) {\n let selector = (el.tagName != 'HTML') ? this._getSelector(el.parentNode) + \" \" : \"\";\n selector += el.tagName.toLowerCase();\n if (el.id) { selector += `#${el.id}` };\n el.classList.forEach(c =\u003e selector += `.${c}`);\n return selector;\n }\n\n _isInViewport(node) {\n let rect = node.getBoundingClientRect();\n return rect.top \u003e= 0 \u0026\u0026\n rect.left \u003e= 0 \u0026\u0026\n rect.bottom \u003c= window.innerHeight \u0026\u0026\n rect.right \u003c= window.innerWidth;\n }\n\n select(node, value) {\n if (this.isDisabled(node)) {\n return false;\n } else if (value == false \u0026\u0026 !node.parentNode.multiple) {\n return false;\n } else {\n this.trigger(node.parentNode, \"focus\");\n\n node.selected = value;\n this.changed(node);\n\n this.trigger(node.parentNode, \"blur\");\n return true;\n }\n }\n\n changed(node) {\n let element;\n let event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"change\", true, false);\n\n // In the case of an OPTION tag, the change event should come\n // from the parent SELECT\n if (node.nodeName == \"OPTION\") {\n element = node.parentNode\n if (element.nodeName == \"OPTGROUP\") {\n element = element.parentNode\n }\n element\n } else {\n element = node\n }\n\n element.dispatchEvent(event)\n }\n\n trigger(node, name, options = {}) {\n let event;\n\n if (EVENTS.MOUSE.indexOf(name) != -1) {\n event = document.createEvent(\"MouseEvent\");\n event.initMouseEvent(\n name, true, true, window, 0,\n options[\"screenX\"] || 0, options[\"screenY\"] || 0,\n options[\"clientX\"] || 0, options[\"clientY\"] || 0,\n options[\"ctrlKey\"] || false,\n options[\"altKey\"] || false,\n options[\"shiftKey\"] || false,\n options[\"metaKey\"] || false,\n options[\"button\"] || 0, null\n )\n } else if (EVENTS.FOCUS.indexOf(name) != -1) {\n event = this.obtainEvent(name);\n } else if (EVENTS.FORM.indexOf(name) != -1) {\n event = this.obtainEvent(name);\n } else {\n throw \"Unknown event\";\n }\n\n node.dispatchEvent(event);\n }\n\n obtainEvent(name) {\n let event = document.createEvent(\"HTMLEvents\");\n event.initEvent(name, true, true);\n return event;\n }\n\n getAttributes(node) {\n let attrs = {};\n for (let i = 0, len = node.attributes.length; i \u003c len; i++) {\n let attr = node.attributes[i];\n attrs[attr.name] = attr.value.replace(\"\\n\", \"\\\\n\");\n }\n\n return this._json.stringify(attrs);\n }\n\n getAttribute(node, name) {\n if (name == \"checked\" || name == \"selected\") {\n return node[name];\n } else {\n return node.getAttribute(name);\n }\n }\n\n value(node) {\n if (node.tagName == \"SELECT\" \u0026\u0026 node.multiple) {\n let result = []\n\n for (let i = 0, len = node.children.length; i \u003c len; i++) {\n let option = node.children[i];\n if (option.selected) {\n result.push(option.value);\n }\n }\n\n return result;\n } else {\n return node.value;\n }\n }\n\n deleteText(node) {\n let range = document.createRange();\n range.selectNodeContents(node);\n window.getSelection().removeAllRanges();\n window.getSelection().addRange(range);\n window.getSelection().deleteFromDocument();\n }\n\n containsSelection(node) {\n let selectedNode = document.getSelection().focusNode;\n\n if (!selectedNode) {\n return false;\n }\n\n if (selectedNode.nodeType == 3) {\n selectedNode = selectedNode.parentNode;\n }\n\n return node.contains(selectedNode);\n }\n\n // This command is purely for testing error handling\n browserError() {\n throw new Error(\"zomg\");\n }\n}\n\nwindow._cuprite = new Cuprite;\n","contextId":1,"returnByValue":true},"id":1009}
◀ 0.1147351999534294 {"id":1009,"result":{"result":{"type":"object","value":{"_json":{}}}}}
▶ 0.11517280002590269 {"method":"Browser.getWindowForTarget","params":{"targetId":"DBC756CA7BC7888FD285B45ED21336FC"},"id":4}
◀ 0.11627360002603382 {"id":4,"result":{"windowId":2,"bounds":{"left":0,"top":0,"width":800,"height":600,"windowState":"normal"}}}
▶ 0.11677750002127141 {"method":"Browser.setWindowBounds","params":{"windowId":2,"bounds":{"windowState":"normal"}},"id":5}
◀ 0.1177394000114873 {"id":5,"result":{}}
▶ 0.11854020005557686 {"method":"Browser.setWindowBounds","params":{"windowId":2,"bounds":{"width":1200,"height":800,"windowState":"normal"}},"id":6}
◀ 0.11955679999664426 {"id":6,"result":{}}
▶ 0.12026869994588196 {"method":"Emulation.setDeviceMetricsOverride","params":{"width":1200,"height":800,"deviceScaleFactor":1,"mobile":false,"fitWindow":false},"id":1010}
◀ 0.12299359997268766 {"method":"CSS.mediaQueryResultChanged","params":{}}
◀ 0.12305189995095134 {"method":"Page.frameResized","params":{}}
◀ 0.12336530000902712 {"id":1010,"result":{}}
▶ 0.12516020005568862 {"method":"Page.getNavigationHistory","params":{},"id":1011}
◀ 0.1281410000519827 {"id":1011,"result":{"currentIndex":0,"entries":[{"id":3,"url":"about:blank","userTypedURL":"about:blank","title":"","transitionType":"typed"}]}}
▶ 0.12863870000001043 {"method":"Page.navigate","params":{"url":"http://10.1.0.97:40303/jae-mante-vm"},"id":1012}
◀ 0.13111830002162606 {"method":"Network.requestWillBeSent","params":{"requestId":"391C683EAE60057513739FFC8913653C","loaderId":"391C683EAE60057513739FFC8913653C","documentURL":"http://10.1.0.97:40303/jae-mante-vm","request":{"url":"http://10.1.0.97:40303/jae-mante-vm","method":"GET","headers":{"Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/81.0.4044.92 Safari/537.36"},"mixedContentType":"none","initialPriority":"VeryHigh","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":990814.805281,"wallTime":1595441268.685256,"initiator":{"type":"other"},"type":"Document","frameId":"DBC756CA7BC7888FD285B45ED21336FC","hasUserGesture":false}}
◀ 0.13497440004721284 {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"391C683EAE60057513739FFC8913653C","blockedCookies":[],"headers":{"Host":"10.1.0.97:40303","Connection":"keep-alive","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/81.0.4044.92 Safari/537.36","Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","Accept-Encoding":"gzip, deflate"}}}
▶ 5.133946600020863 {"method":"Page.captureScreenshot","params":{"format":"png"},"id":1013}
◀ 5.237732699955814 {"id":1013,"result":{"data":"iVBORw0KGgoAAAANSUhEUgAABLAAAAMgCAYAAAAz4JsCAAAAAXNSR0IArs4c6QAAFf1JREFUeJzt2DEBACAMwDDAv+fhgJceiYLe3TMzCwAAAACizu8AAAAAAHgxsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEi710EKPFzQ9BwAAAAASUVORK5CYII="}}
[Screenshot]: /app/test/modulor_dummy_app/tmp/screenshots/failures_test_0001_anonymous.png
▶ 5.240800700034015 {"method":"Target.disposeBrowserContext","params":{"browserContextId":"B40DAEBD0CD7B082001869695738B210"},"id":7}
◀ 5.244058000040241 {"id":1012,"result":{"frameId":"DBC756CA7BC7888FD285B45ED21336FC","loaderId":"391C683EAE60057513739FFC8913653C"}}
◀ 5.244300300022587 {"method":"Network.loadingFailed","params":{"requestId":"391C683EAE60057513739FFC8913653C","timestamp":990819.9173,"type":"Document","errorText":"net::ERR_ABORTED","canceled":true}}
◀ 5.244690499966964 {"method":"Inspector.targetReloadedAfterCrash","params":{}}
◀ 5.2485690000467 {"method":"Target.targetInfoChanged","params":{"targetInfo":{"targetId":"DBC756CA7BC7888FD285B45ED21336FC","type":"page","title":"about:blank","url":"about:blank","attached":false,"browserContextId":"B40DAEBD0CD7B082001869695738B210"}}}
◀ 5.250695400056429 {"method":"Target.targetDestroyed","params":{"targetId":"DBC756CA7BC7888FD285B45ED21336FC"}}
◀ 5.24884779995773 {"method":"Inspector.detached","params":{"reason":"target_closed"}}
◀ 5.257888799998909 {"id":7,"result":{}}
▶ 5.25868900003843 {"method":"Target.createBrowserContext","params":{},"id":8}
◀ 5.2641663999529555 {"id":8,"result":{"browserContextId":"4AF33D32096EC2E4EE24F26BBF5229C4"}}
▶ 5.265069999964908 {"method":"Target.createTarget","params":{"browserContextId":"4AF33D32096EC2E4EE24F26BBF5229C4","url":"about:blank"},"id":9}
◀ 5.270287999999709 {"method":"Target.targetCreated","params":{"targetInfo":{"targetId":"7372F7938B6675ABE7D8CE91CED9A2D6","type":"page","title":"","url":"","attached":false,"browserContextId":"4AF33D32096EC2E4EE24F26BBF5229C4"}}}
◀ 5.277402000036091 {"id":9,"result":{"targetId":"7372F7938B6675ABE7D8CE91CED9A2D6"}}
▶ 5.285839200019836 {"method":"Page.enable","params":{},"id":1001}
◀ 5.3000164000550285 {"method":"Target.targetInfoChanged","params":{"targetInfo":{"targetId":"7372F7938B6675ABE7D8CE91CED9A2D6","type":"page","title":"","url":"about:blank","attached":true,"browserContextId":"4AF33D32096EC2E4EE24F26BBF5229C4"}}}
◀ 5.335408900049515 {"method":"Target.targetInfoChanged","params":{"targetInfo":{"targetId":"7372F7938B6675ABE7D8CE91CED9A2D6","type":"page","title":"about:blank","url":"about:blank","attached":true,"browserContextId":"4AF33D32096EC2E4EE24F26BBF5229C4"}}}
◀ 5.3454733999678865 {"id":1001,"result":{}}
▶ 5.346553200040944 {"method":"Runtime.enable","params":{},"id":1002}
◀ 5.352977599948645 {"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"origin":"://","name":"","auxData":{"isDefault":true,"type":"default","frameId":"7372F7938B6675ABE7D8CE91CED9A2D6"}}}}
◀ 5.35305639996659 {"id":1002,"result":{}}
▶ 5.354057200020179 {"method":"DOM.enable","params":{},"id":1003}
◀ 5.359068099991418 {"id":1003,"result":{}}
▶ 5.359964399947785 {"method":"CSS.enable","params":{},"id":1004}
◀ 5.3626263999613 {"method":"Runtime.executionContextCreated","params":{"context":{"id":2,"origin":"","name":"__puppeteer_utility_world__","auxData":{"isDefault":false,"type":"isolated","frameId":"7372F7938B6675ABE7D8CE91CED9A2D6"}}}}
◀ 5.365029199980199 {"id":1004,"result":{}}
▶ 5.365818900056183 {"method":"Log.enable","params":{},"id":1005}
◀ 5.368174899951555 {"id":1005,"result":{}}
▶ 5.368931100005284 {"method":"Network.enable","params":{},"id":1006}
◀ 5.370115499943495 {"id":1006,"result":{}}
▶ 5.370785600040108 {"method":"Page.setDownloadBehavior","params":{"behavior":"allow","downloadPath":"./tmp/capybara"},"id":1007}
◀ 5.37175519997254 {"id":1007,"result":{}}
▶ 5.374233599985018 {"method":"Page.addScriptToEvaluateOnNewDocument","params":{"source":"class InvalidSelector extends Error {}\nclass TimedOutPromise extends Error {}\nclass MouseEventFailed extends Error {}\n\nconst EVENTS = {\n FOCUS: [\"blur\", \"focus\", \"focusin\", \"focusout\"],\n MOUSE: [\"click\", \"dblclick\", \"mousedown\", \"mouseenter\", \"mouseleave\",\n \"mousemove\", \"mouseover\", \"mouseout\", \"mouseup\", \"contextmenu\"],\n FORM: [\"submit\"]\n}\n\nclass Cuprite {\n constructor() {\n this._json = JSON; // In case someone overrides it like mootools\n }\n\n find(method, selector, within = document) {\n try {\n let results = [];\n\n if (method == \"xpath\") {\n let xpath = document.evaluate(selector, within, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n for (let i = 0; i \u003c xpath.snapshotLength; i++) {\n results.push(xpath.snapshotItem(i));\n }\n } else {\n results = Array.from(within.querySelectorAll(selector));\n }\n\n return results;\n } catch (error) {\n // DOMException.INVALID_EXPRESSION_ERR is undefined, using pure code\n if (error.code == DOMException.SYNTAX_ERR || error.code == 51) {\n throw new InvalidSelector;\n } else {\n throw error;\n }\n }\n }\n\n parents(node) {\n let nodes = [];\n let parent = node.parentNode;\n while (parent != document) {\n nodes.push(parent);\n parent = parent.parentNode;\n }\n return nodes;\n }\n\n visibleText(node) {\n if (this.isVisible(node)) {\n if (node.nodeName == \"TEXTAREA\") {\n return node.textContent;\n } else {\n if (node instanceof SVGElement) {\n return node.textContent;\n } else {\n return node.innerText;\n }\n }\n }\n }\n\n isVisible(node) {\n let mapName, style;\n // if node is area, check visibility of relevant image\n if (node.tagName === \"AREA\") {\n mapName = document.evaluate(\"./ancestor::map/@name\", node, null, XPathResult.STRING_TYPE, null).stringValue;\n node = document.querySelector(`img[usemap=\"#${mapName}\"]`);\n if (node == null) {\n return false;\n }\n }\n\n while (node) {\n style = window.getComputedStyle(node);\n if (style.display === \"none\" || style.visibility === \"hidden\" || parseFloat(style.opacity) === 0) {\n return false;\n }\n node = node.parentElement;\n }\n\n return true;\n }\n\n\n isDisabled(node) {\n let xpath = \"parent::optgroup[@disabled] | \\\n ancestor::select[@disabled] | \\\n parent::fieldset[@disabled] | \\\n ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]\";\n\n return node.disabled || document.evaluate(xpath, node, null, XPathResult.BOOLEAN_TYPE, null).booleanValue;\n }\n\n path(node) {\n let nodes = [node];\n let parent = node.parentNode;\n while (parent !== document) {\n nodes.unshift(parent);\n parent = parent.parentNode;\n }\n\n let selectors = nodes.map(node =\u003e {\n let prevSiblings = [];\n let xpath = document.evaluate(`./preceding-sibling::${node.tagName}`, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n\n for (let i = 0; i \u003c xpath.snapshotLength; i++) {\n prevSiblings.push(xpath.snapshotItem(i));\n }\n\n return `${node.tagName}[${(prevSiblings.length + 1)}]`;\n });\n\n return `//${selectors.join(\"/\")}`;\n }\n\n set(node, value) {\n if (node.readOnly) return;\n\n if (node.maxLength \u003e= 0) {\n value = value.substr(0, node.maxLength);\n }\n\n let valueBefore = node.value;\n\n this.trigger(node, \"focus\");\n this.setValue(node, \"\");\n\n if (node.type == \"number\" || node.type == \"date\" || node.type == \"range\") {\n this.setValue(node, value);\n this.input(node);\n } else if (node.type == \"time\") {\n this.setValue(node, new Date(value).toTimeString().split(\" \")[0]);\n this.input(node);\n } else if (node.type == \"datetime-local\") {\n value = new Date(value);\n let year = value.getFullYear();\n let month = (\"0\" + (value.getMonth() + 1)).slice(-2);\n let date = (\"0\" + value.getDate()).slice(-2);\n let hour = (\"0\" + value.getHours()).slice(-2);\n let min = (\"0\" + value.getMinutes()).slice(-2);\n let sec = (\"0\" + value.getSeconds()).slice(-2);\n this.setValue(node, `${year}-${month}-${date}T${hour}:${min}:${sec}`);\n this.input(node);\n } else {\n for (let i = 0; i \u003c value.length; i++) {\n let char = value[i];\n let keyCode = this.characterToKeyCode(char);\n // call the following functions in order, if one returns false (preventDefault),\n // stop the call chain\n [\n () =\u003e this.keyupdowned(node, \"keydown\", keyCode),\n () =\u003e this.keypressed(node, false, false, false, false, char.charCodeAt(0), char.charCodeAt(0)),\n () =\u003e {\n this.setValue(node, node.value + char)\n this.input(node)\n }\n ].some(fn =\u003e fn())\n\n this.keyupdowned(node, \"keyup\", keyCode);\n }\n }\n\n if (valueBefore !== node.value) {\n this.changed(node);\n }\n this.trigger(node, \"blur\");\n }\n\n setValue(node, value) {\n let nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, \"value\").set;\n let nativeTextareaValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, \"value\").set;\n\n if (node.tagName.toLowerCase() === 'input') {\n return nativeInputValueSetter.call(node, value);\n }\n return nativeTextareaValueSetter.call(node, value);\n }\n\n input(node) {\n let event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"input\", true, false);\n node.dispatchEvent(event);\n }\n\n /**\n * @return {boolean} false when an event handler called preventDefault()\n */\n keyupdowned(node, eventName, keyCode) {\n let event = document.createEvent(\"UIEvents\");\n event.initEvent(eventName, true, true);\n event.keyCode = keyCode;\n event.charCode = 0;\n return !node.dispatchEvent(event);\n }\n\n /**\n * @return {boolean} false when an event handler called preventDefault()\n */\n keypressed(node, altKey, ctrlKey, shiftKey, metaKey, keyCode, charCode) {\n event = document.createEvent(\"UIEvents\");\n event.initEvent(\"keypress\", true, true);\n event.window = window;\n event.altKey = altKey;\n event.ctrlKey = ctrlKey;\n event.shiftKey = shiftKey;\n event.metaKey = metaKey;\n event.keyCode = keyCode;\n event.charCode = charCode;\n return !node.dispatchEvent(event);\n }\n\n characterToKeyCode(char) {\n const specialKeys = {\n 96: 192, // `\n 45: 189, // -\n 61: 187, // =\n 91: 219, // [\n 93: 221, // ]\n 92: 220, // \\\n 59: 186, // ;\n 39: 222, // '\n 44: 188, // ,\n 46: 190, // .\n 47: 191, // /\n 127: 46, // delete\n 126: 192, // ~\n 33: 49, // !\n 64: 50, // @\n 35: 51, // #\n 36: 52, // $\n 37: 53, // %\n 94: 54, // ^\n 38: 55, // \u0026\n 42: 56, // *\n 40: 57, // (\n 41: 48, // )\n 95: 189, // _\n 43: 187, // +\n 123: 219, // {\n 125: 221, // }\n 124: 220, // |\n 58: 186, // :\n 34: 222, // \"\n 60: 188, // \u003c\n 62: 190, // \u003e\n 63: 191, // ?\n }\n\n let code = char.toUpperCase().charCodeAt(0);\n return specialKeys[code] || code;\n }\n\n scrollIntoViewport(node) {\n let areaImage = this._getAreaImage(node);\n\n if (areaImage) {\n return this.scrollIntoViewport(areaImage);\n } else {\n node.scrollIntoViewIfNeeded();\n\n if (!this._isInViewport(node)) {\n node.scrollIntoView({block: \"center\", inline: \"center\", behavior: \"instant\"});\n return this._isInViewport(node);\n }\n\n return true;\n }\n }\n\n mouseEventTest(node, name, x, y) {\n let frameOffset = this._frameOffset();\n x -= frameOffset.left;\n y -= frameOffset.top;\n\n let element = document.elementFromPoint(x, y);\n\n let el = element;\n while (el) {\n if (el == node) {\n return true;\n } else {\n el = el.parentNode;\n }\n }\n\n let selector = element \u0026\u0026 this._getSelector(element) || \"none\";\n throw new MouseEventFailed([name, selector, x, y].join(\", \"));\n }\n\n _getAreaImage(node) {\n if (\"area\" == node.tagName.toLowerCase()) {\n let map = node.parentNode;\n if (map.tagName.toLowerCase() != \"map\") {\n throw new Error(\"the area is not within a map\");\n }\n\n let mapName = map.getAttribute(\"name\");\n if (typeof mapName === \"undefined\" || mapName === null) {\n throw new Error(\"area's parent map must have a name\");\n }\n\n mapName = `#${mapName.toLowerCase()}`;\n let imageNode = this.find(\"css\", `img[usemap='${mapName}']`)[0];\n if (typeof imageNode === \"undefined\" || imageNode === null) {\n throw new Error(\"no image matches the map\");\n }\n\n return imageNode;\n }\n }\n\n _frameOffset() {\n let win = window;\n let offset = { top: 0, left: 0 };\n\n while (win.frameElement) {\n let rect = win.frameElement.getClientRects()[0];\n let style = win.getComputedStyle(win.frameElement);\n win = win.parent;\n\n offset.top += rect.top + parseInt(style.getPropertyValue(\"padding-top\"), 10)\n offset.left += rect.left + parseInt(style.getPropertyValue(\"padding-left\"), 10)\n }\n\n return offset;\n }\n\n _getSelector(el) {\n let selector = (el.tagName != 'HTML') ? this._getSelector(el.parentNode) + \" \" : \"\";\n selector += el.tagName.toLowerCase();\n if (el.id) { selector += `#${el.id}` };\n el.classList.forEach(c =\u003e selector += `.${c}`);\n return selector;\n }\n\n _isInViewport(node) {\n let rect = node.getBoundingClientRect();\n return rect.top \u003e= 0 \u0026\u0026\n rect.left \u003e= 0 \u0026\u0026\n rect.bottom \u003c= window.innerHeight \u0026\u0026\n rect.right \u003c= window.innerWidth;\n }\n\n select(node, value) {\n if (this.isDisabled(node)) {\n return false;\n } else if (value == false \u0026\u0026 !node.parentNode.multiple) {\n return false;\n } else {\n this.trigger(node.parentNode, \"focus\");\n\n node.selected = value;\n this.changed(node);\n\n this.trigger(node.parentNode, \"blur\");\n return true;\n }\n }\n\n changed(node) {\n let element;\n let event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"change\", true, false);\n\n // In the case of an OPTION tag, the change event should come\n // from the parent SELECT\n if (node.nodeName == \"OPTION\") {\n element = node.parentNode\n if (element.nodeName == \"OPTGROUP\") {\n element = element.parentNode\n }\n element\n } else {\n element = node\n }\n\n element.dispatchEvent(event)\n }\n\n trigger(node, name, options = {}) {\n let event;\n\n if (EVENTS.MOUSE.indexOf(name) != -1) {\n event = document.createEvent(\"MouseEvent\");\n event.initMouseEvent(\n name, true, true, window, 0,\n options[\"screenX\"] || 0, options[\"screenY\"] || 0,\n options[\"clientX\"] || 0, options[\"clientY\"] || 0,\n options[\"ctrlKey\"] || false,\n options[\"altKey\"] || false,\n options[\"shiftKey\"] || false,\n options[\"metaKey\"] || false,\n options[\"button\"] || 0, null\n )\n } else if (EVENTS.FOCUS.indexOf(name) != -1) {\n event = this.obtainEvent(name);\n } else if (EVENTS.FORM.indexOf(name) != -1) {\n event = this.obtainEvent(name);\n } else {\n throw \"Unknown event\";\n }\n\n node.dispatchEvent(event);\n }\n\n obtainEvent(name) {\n let event = document.createEvent(\"HTMLEvents\");\n event.initEvent(name, true, true);\n return event;\n }\n\n getAttributes(node) {\n let attrs = {};\n for (let i = 0, len = node.attributes.length; i \u003c len; i++) {\n let attr = node.attributes[i];\n attrs[attr.name] = attr.value.replace(\"\\n\", \"\\\\n\");\n }\n\n return this._json.stringify(attrs);\n }\n\n getAttribute(node, name) {\n if (name == \"checked\" || name == \"selected\") {\n return node[name];\n } else {\n return node.getAttribute(name);\n }\n }\n\n value(node) {\n if (node.tagName == \"SELECT\" \u0026\u0026 node.multiple) {\n let result = []\n\n for (let i = 0, len = node.children.length; i \u003c len; i++) {\n let option = node.children[i];\n if (option.selected) {\n result.push(option.value);\n }\n }\n\n return result;\n } else {\n return node.value;\n }\n }\n\n deleteText(node) {\n let range = document.createRange();\n range.selectNodeContents(node);\n window.getSelection().removeAllRanges();\n window.getSelection().addRange(range);\n window.getSelection().deleteFromDocument();\n }\n\n containsSelection(node) {\n let selectedNode = document.getSelection().focusNode;\n\n if (!selectedNode) {\n return false;\n }\n\n if (selectedNode.nodeType == 3) {\n selectedNode = selectedNode.parentNode;\n }\n\n return node.contains(selectedNode);\n }\n\n // This command is purely for testing error handling\n browserError() {\n throw new Error(\"zomg\");\n }\n}\n\nwindow._cuprite = new Cuprite;\n"},"id":1008}
◀ 5.378786499961279 {"id":1008,"result":{"identifier":"1"}}
▶ 5.381255600019358 {"method":"Runtime.evaluate","params":{"expression":"class InvalidSelector extends Error {}\nclass TimedOutPromise extends Error {}\nclass MouseEventFailed extends Error {}\n\nconst EVENTS = {\n FOCUS: [\"blur\", \"focus\", \"focusin\", \"focusout\"],\n MOUSE: [\"click\", \"dblclick\", \"mousedown\", \"mouseenter\", \"mouseleave\",\n \"mousemove\", \"mouseover\", \"mouseout\", \"mouseup\", \"contextmenu\"],\n FORM: [\"submit\"]\n}\n\nclass Cuprite {\n constructor() {\n this._json = JSON; // In case someone overrides it like mootools\n }\n\n find(method, selector, within = document) {\n try {\n let results = [];\n\n if (method == \"xpath\") {\n let xpath = document.evaluate(selector, within, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n for (let i = 0; i \u003c xpath.snapshotLength; i++) {\n results.push(xpath.snapshotItem(i));\n }\n } else {\n results = Array.from(within.querySelectorAll(selector));\n }\n\n return results;\n } catch (error) {\n // DOMException.INVALID_EXPRESSION_ERR is undefined, using pure code\n if (error.code == DOMException.SYNTAX_ERR || error.code == 51) {\n throw new InvalidSelector;\n } else {\n throw error;\n }\n }\n }\n\n parents(node) {\n let nodes = [];\n let parent = node.parentNode;\n while (parent != document) {\n nodes.push(parent);\n parent = parent.parentNode;\n }\n return nodes;\n }\n\n visibleText(node) {\n if (this.isVisible(node)) {\n if (node.nodeName == \"TEXTAREA\") {\n return node.textContent;\n } else {\n if (node instanceof SVGElement) {\n return node.textContent;\n } else {\n return node.innerText;\n }\n }\n }\n }\n\n isVisible(node) {\n let mapName, style;\n // if node is area, check visibility of relevant image\n if (node.tagName === \"AREA\") {\n mapName = document.evaluate(\"./ancestor::map/@name\", node, null, XPathResult.STRING_TYPE, null).stringValue;\n node = document.querySelector(`img[usemap=\"#${mapName}\"]`);\n if (node == null) {\n return false;\n }\n }\n\n while (node) {\n style = window.getComputedStyle(node);\n if (style.display === \"none\" || style.visibility === \"hidden\" || parseFloat(style.opacity) === 0) {\n return false;\n }\n node = node.parentElement;\n }\n\n return true;\n }\n\n\n isDisabled(node) {\n let xpath = \"parent::optgroup[@disabled] | \\\n ancestor::select[@disabled] | \\\n parent::fieldset[@disabled] | \\\n ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]\";\n\n return node.disabled || document.evaluate(xpath, node, null, XPathResult.BOOLEAN_TYPE, null).booleanValue;\n }\n\n path(node) {\n let nodes = [node];\n let parent = node.parentNode;\n while (parent !== document) {\n nodes.unshift(parent);\n parent = parent.parentNode;\n }\n\n let selectors = nodes.map(node =\u003e {\n let prevSiblings = [];\n let xpath = document.evaluate(`./preceding-sibling::${node.tagName}`, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n\n for (let i = 0; i \u003c xpath.snapshotLength; i++) {\n prevSiblings.push(xpath.snapshotItem(i));\n }\n\n return `${node.tagName}[${(prevSiblings.length + 1)}]`;\n });\n\n return `//${selectors.join(\"/\")}`;\n }\n\n set(node, value) {\n if (node.readOnly) return;\n\n if (node.maxLength \u003e= 0) {\n value = value.substr(0, node.maxLength);\n }\n\n let valueBefore = node.value;\n\n this.trigger(node, \"focus\");\n this.setValue(node, \"\");\n\n if (node.type == \"number\" || node.type == \"date\" || node.type == \"range\") {\n this.setValue(node, value);\n this.input(node);\n } else if (node.type == \"time\") {\n this.setValue(node, new Date(value).toTimeString().split(\" \")[0]);\n this.input(node);\n } else if (node.type == \"datetime-local\") {\n value = new Date(value);\n let year = value.getFullYear();\n let month = (\"0\" + (value.getMonth() + 1)).slice(-2);\n let date = (\"0\" + value.getDate()).slice(-2);\n let hour = (\"0\" + value.getHours()).slice(-2);\n let min = (\"0\" + value.getMinutes()).slice(-2);\n let sec = (\"0\" + value.getSeconds()).slice(-2);\n this.setValue(node, `${year}-${month}-${date}T${hour}:${min}:${sec}`);\n this.input(node);\n } else {\n for (let i = 0; i \u003c value.length; i++) {\n let char = value[i];\n let keyCode = this.characterToKeyCode(char);\n // call the following functions in order, if one returns false (preventDefault),\n // stop the call chain\n [\n () =\u003e this.keyupdowned(node, \"keydown\", keyCode),\n () =\u003e this.keypressed(node, false, false, false, false, char.charCodeAt(0), char.charCodeAt(0)),\n () =\u003e {\n this.setValue(node, node.value + char)\n this.input(node)\n }\n ].some(fn =\u003e fn())\n\n this.keyupdowned(node, \"keyup\", keyCode);\n }\n }\n\n if (valueBefore !== node.value) {\n this.changed(node);\n }\n this.trigger(node, \"blur\");\n }\n\n setValue(node, value) {\n let nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, \"value\").set;\n let nativeTextareaValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, \"value\").set;\n\n if (node.tagName.toLowerCase() === 'input') {\n return nativeInputValueSetter.call(node, value);\n }\n return nativeTextareaValueSetter.call(node, value);\n }\n\n input(node) {\n let event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"input\", true, false);\n node.dispatchEvent(event);\n }\n\n /**\n * @return {boolean} false when an event handler called preventDefault()\n */\n keyupdowned(node, eventName, keyCode) {\n let event = document.createEvent(\"UIEvents\");\n event.initEvent(eventName, true, true);\n event.keyCode = keyCode;\n event.charCode = 0;\n return !node.dispatchEvent(event);\n }\n\n /**\n * @return {boolean} false when an event handler called preventDefault()\n */\n keypressed(node, altKey, ctrlKey, shiftKey, metaKey, keyCode, charCode) {\n event = document.createEvent(\"UIEvents\");\n event.initEvent(\"keypress\", true, true);\n event.window = window;\n event.altKey = altKey;\n event.ctrlKey = ctrlKey;\n event.shiftKey = shiftKey;\n event.metaKey = metaKey;\n event.keyCode = keyCode;\n event.charCode = charCode;\n return !node.dispatchEvent(event);\n }\n\n characterToKeyCode(char) {\n const specialKeys = {\n 96: 192, // `\n 45: 189, // -\n 61: 187, // =\n 91: 219, // [\n 93: 221, // ]\n 92: 220, // \\\n 59: 186, // ;\n 39: 222, // '\n 44: 188, // ,\n 46: 190, // .\n 47: 191, // /\n 127: 46, // delete\n 126: 192, // ~\n 33: 49, // !\n 64: 50, // @\n 35: 51, // #\n 36: 52, // $\n 37: 53, // %\n 94: 54, // ^\n 38: 55, // \u0026\n 42: 56, // *\n 40: 57, // (\n 41: 48, // )\n 95: 189, // _\n 43: 187, // +\n 123: 219, // {\n 125: 221, // }\n 124: 220, // |\n 58: 186, // :\n 34: 222, // \"\n 60: 188, // \u003c\n 62: 190, // \u003e\n 63: 191, // ?\n }\n\n let code = char.toUpperCase().charCodeAt(0);\n return specialKeys[code] || code;\n }\n\n scrollIntoViewport(node) {\n let areaImage = this._getAreaImage(node);\n\n if (areaImage) {\n return this.scrollIntoViewport(areaImage);\n } else {\n node.scrollIntoViewIfNeeded();\n\n if (!this._isInViewport(node)) {\n node.scrollIntoView({block: \"center\", inline: \"center\", behavior: \"instant\"});\n return this._isInViewport(node);\n }\n\n return true;\n }\n }\n\n mouseEventTest(node, name, x, y) {\n let frameOffset = this._frameOffset();\n x -= frameOffset.left;\n y -= frameOffset.top;\n\n let element = document.elementFromPoint(x, y);\n\n let el = element;\n while (el) {\n if (el == node) {\n return true;\n } else {\n el = el.parentNode;\n }\n }\n\n let selector = element \u0026\u0026 this._getSelector(element) || \"none\";\n throw new MouseEventFailed([name, selector, x, y].join(\", \"));\n }\n\n _getAreaImage(node) {\n if (\"area\" == node.tagName.toLowerCase()) {\n let map = node.parentNode;\n if (map.tagName.toLowerCase() != \"map\") {\n throw new Error(\"the area is not within a map\");\n }\n\n let mapName = map.getAttribute(\"name\");\n if (typeof mapName === \"undefined\" || mapName === null) {\n throw new Error(\"area's parent map must have a name\");\n }\n\n mapName = `#${mapName.toLowerCase()}`;\n let imageNode = this.find(\"css\", `img[usemap='${mapName}']`)[0];\n if (typeof imageNode === \"undefined\" || imageNode === null) {\n throw new Error(\"no image matches the map\");\n }\n\n return imageNode;\n }\n }\n\n _frameOffset() {\n let win = window;\n let offset = { top: 0, left: 0 };\n\n while (win.frameElement) {\n let rect = win.frameElement.getClientRects()[0];\n let style = win.getComputedStyle(win.frameElement);\n win = win.parent;\n\n offset.top += rect.top + parseInt(style.getPropertyValue(\"padding-top\"), 10)\n offset.left += rect.left + parseInt(style.getPropertyValue(\"padding-left\"), 10)\n }\n\n return offset;\n }\n\n _getSelector(el) {\n let selector = (el.tagName != 'HTML') ? this._getSelector(el.parentNode) + \" \" : \"\";\n selector += el.tagName.toLowerCase();\n if (el.id) { selector += `#${el.id}` };\n el.classList.forEach(c =\u003e selector += `.${c}`);\n return selector;\n }\n\n _isInViewport(node) {\n let rect = node.getBoundingClientRect();\n return rect.top \u003e= 0 \u0026\u0026\n rect.left \u003e= 0 \u0026\u0026\n rect.bottom \u003c= window.innerHeight \u0026\u0026\n rect.right \u003c= window.innerWidth;\n }\n\n select(node, value) {\n if (this.isDisabled(node)) {\n return false;\n } else if (value == false \u0026\u0026 !node.parentNode.multiple) {\n return false;\n } else {\n this.trigger(node.parentNode, \"focus\");\n\n node.selected = value;\n this.changed(node);\n\n this.trigger(node.parentNode, \"blur\");\n return true;\n }\n }\n\n changed(node) {\n let element;\n let event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"change\", true, false);\n\n // In the case of an OPTION tag, the change event should come\n // from the parent SELECT\n if (node.nodeName == \"OPTION\") {\n element = node.parentNode\n if (element.nodeName == \"OPTGROUP\") {\n element = element.parentNode\n }\n element\n } else {\n element = node\n }\n\n element.dispatchEvent(event)\n }\n\n trigger(node, name, options = {}) {\n let event;\n\n if (EVENTS.MOUSE.indexOf(name) != -1) {\n event = document.createEvent(\"MouseEvent\");\n event.initMouseEvent(\n name, true, true, window, 0,\n options[\"screenX\"] || 0, options[\"screenY\"] || 0,\n options[\"clientX\"] || 0, options[\"clientY\"] || 0,\n options[\"ctrlKey\"] || false,\n options[\"altKey\"] || false,\n options[\"shiftKey\"] || false,\n options[\"metaKey\"] || false,\n options[\"button\"] || 0, null\n )\n } else if (EVENTS.FOCUS.indexOf(name) != -1) {\n event = this.obtainEvent(name);\n } else if (EVENTS.FORM.indexOf(name) != -1) {\n event = this.obtainEvent(name);\n } else {\n throw \"Unknown event\";\n }\n\n node.dispatchEvent(event);\n }\n\n obtainEvent(name) {\n let event = document.createEvent(\"HTMLEvents\");\n event.initEvent(name, true, true);\n return event;\n }\n\n getAttributes(node) {\n let attrs = {};\n for (let i = 0, len = node.attributes.length; i \u003c len; i++) {\n let attr = node.attributes[i];\n attrs[attr.name] = attr.value.replace(\"\\n\", \"\\\\n\");\n }\n\n return this._json.stringify(attrs);\n }\n\n getAttribute(node, name) {\n if (name == \"checked\" || name == \"selected\") {\n return node[name];\n } else {\n return node.getAttribute(name);\n }\n }\n\n value(node) {\n if (node.tagName == \"SELECT\" \u0026\u0026 node.multiple) {\n let result = []\n\n for (let i = 0, len = node.children.length; i \u003c len; i++) {\n let option = node.children[i];\n if (option.selected) {\n result.push(option.value);\n }\n }\n\n return result;\n } else {\n return node.value;\n }\n }\n\n deleteText(node) {\n let range = document.createRange();\n range.selectNodeContents(node);\n window.getSelection().removeAllRanges();\n window.getSelection().addRange(range);\n window.getSelection().deleteFromDocument();\n }\n\n containsSelection(node) {\n let selectedNode = document.getSelection().focusNode;\n\n if (!selectedNode) {\n return false;\n }\n\n if (selectedNode.nodeType == 3) {\n selectedNode = selectedNode.parentNode;\n }\n\n return node.contains(selectedNode);\n }\n\n // This command is purely for testing error handling\n browserError() {\n throw new Error(\"zomg\");\n }\n}\n\nwindow._cuprite = new Cuprite;\n","contextId":1,"returnByValue":true},"id":1009}
◀ 5.384692099993117 {"id":1009,"result":{"result":{"type":"object","value":{"_json":{}}}}}
▶ 5.385283199953847 {"method":"Browser.getWindowForTarget","params":{"targetId":"7372F7938B6675ABE7D8CE91CED9A2D6"},"id":10}
◀ 5.386232599965297 {"id":10,"result":{"windowId":3,"bounds":{"left":0,"top":0,"width":800,"height":600,"windowState":"normal"}}}
▶ 5.387256099958904 {"method":"Browser.setWindowBounds","params":{"windowId":3,"bounds":{"windowState":"normal"}},"id":11}
◀ 5.388202599948272 {"id":11,"result":{}}
▶ 5.388954899972305 {"method":"Browser.setWindowBounds","params":{"windowId":3,"bounds":{"width":1200,"height":800,"windowState":"normal"}},"id":12}
◀ 5.389748699963093 {"id":12,"result":{}}
▶ 5.390639599994756 {"method":"Emulation.setDeviceMetricsOverride","params":{"width":1200,"height":800,"deviceScaleFactor":1,"mobile":false,"fitWindow":false},"id":1010}
◀ 5.398415799951181 {"method":"CSS.mediaQueryResultChanged","params":{}}
◀ 5.399102400057018 {"method":"Page.frameResized","params":{}}
◀ 5.399736799998209 {"id":1010,"result":{}}
▶ 5.400552200037055 {"method":"Page.getNavigationHistory","params":{},"id":1011}
◀ 5.401409700047225 {"id":1011,"result":{"currentIndex":0,"entries":[{"id":6,"url":"about:blank","userTypedURL":"about:blank","title":"","transitionType":"typed"}]}}
E
Error:
Modulor::RoleListModule::RolesSystemTest::create#test_0001_anonymous:
Ferrum::StatusError: Request to http://10.1.0.97:40303/jae-mante-vm reached server, but there are still pending connections: http://10.1.0.97:40303/jae-mante-vm
/app/modulor-dev/lib/modulor/dev/test_support/application_system_test_case.rb:35:in `sign_in'
/app/web-modules/modulor-role_list_module/test/system/modulor/role_list_module/roles_test.rb:14:in `block in <class:RolesSystemTest>'
bin/test /app/web-modules/modulor-role_list_module/test/system/modulor/role_list_module/roles_test.rb:37
Finished in 6.123222s, 0.1633 runs/s, 0.0000 assertions/s.
1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment