capybara-simulated 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +25 -10
- data/lib/capybara/simulated/version.rb +1 -1
- data/vendor/js/csim.bundle.js +4198 -13653
- data/vendor/js/entry.mjs +20 -5
- data/vendor/js/runtime.js +10 -112
- metadata +1 -1
data/vendor/js/entry.mjs
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
|
-
// Bundle entry: brings happy-dom
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// Bundle entry: brings happy-dom + wgxpath into one IIFE that exposes them
|
|
2
|
+
// on a single `__csim_bundle` global. happy-dom does not implement
|
|
3
|
+
// `document.evaluate`, so wgxpath layers it onto `Document.prototype`.
|
|
4
4
|
import {Window} from 'happy-dom';
|
|
5
5
|
import {URL, URLSearchParams} from 'whatwg-url';
|
|
6
|
-
import
|
|
6
|
+
import wgxpath from 'wicked-good-xpath';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
// happy-dom 20's `document` is an `HTMLDocument` instance and the proto
|
|
9
|
+
// chain doesn't include `Document.prototype` (where wgxpath plants
|
|
10
|
+
// `evaluate` / `createExpression` / `createNSResolver`). Mirror the three
|
|
11
|
+
// methods onto `HTMLDocument.prototype` so `document.evaluate` works.
|
|
12
|
+
function installXPath(win) {
|
|
13
|
+
wgxpath.install(win, /* opt_force */ true);
|
|
14
|
+
if (win.HTMLDocument && win.Document) {
|
|
15
|
+
for (const m of ['evaluate', 'createExpression', 'createNSResolver']) {
|
|
16
|
+
if (win.Document.prototype[m] && !win.HTMLDocument.prototype[m]) {
|
|
17
|
+
win.HTMLDocument.prototype[m] = win.Document.prototype[m];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export {Window, URL, URLSearchParams, installXPath};
|
data/vendor/js/runtime.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
(function () {
|
|
7
7
|
const {Window, URL: WhatwgURL, URLSearchParams: WhatwgURLSearchParams,
|
|
8
|
-
|
|
8
|
+
installXPath} = globalThis.__csim_bundle;
|
|
9
9
|
if (!globalThis.URL) globalThis.URL = WhatwgURL;
|
|
10
10
|
if (!globalThis.URLSearchParams) globalThis.URLSearchParams = WhatwgURLSearchParams;
|
|
11
11
|
|
|
@@ -170,6 +170,7 @@
|
|
|
170
170
|
installValidationMessages(win);
|
|
171
171
|
installMutationObserverPin(win);
|
|
172
172
|
installAttrNodeValue(win);
|
|
173
|
+
installXPath(win);
|
|
173
174
|
}
|
|
174
175
|
|
|
175
176
|
// happy-dom 20's `Attr` class implements `value` / `textContent` / `name`
|
|
@@ -963,7 +964,6 @@
|
|
|
963
964
|
patchWindowGlobals(win);
|
|
964
965
|
installFetchShim(win);
|
|
965
966
|
installCustomElementUpgrade(win);
|
|
966
|
-
installDocumentEvaluate(win.document);
|
|
967
967
|
installHistoryTracking(win);
|
|
968
968
|
currentWindow = win;
|
|
969
969
|
currentDocument = win.document;
|
|
@@ -1257,11 +1257,14 @@
|
|
|
1257
1257
|
const fast = tryFastXPath(xpath, root);
|
|
1258
1258
|
if (fast) return fast.map(track);
|
|
1259
1259
|
try {
|
|
1260
|
-
const
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1260
|
+
const result = currentDocument.evaluate(
|
|
1261
|
+
xpath, root, null,
|
|
1262
|
+
/* UNORDERED_NODE_ITERATOR_TYPE */ 4, null
|
|
1263
|
+
);
|
|
1264
|
+
const ids = [];
|
|
1265
|
+
let n;
|
|
1266
|
+
while ((n = result.iterateNext())) ids.push(track(n));
|
|
1267
|
+
return ids;
|
|
1265
1268
|
} catch (e) {
|
|
1266
1269
|
return findViaXPathFallback(xpath, root);
|
|
1267
1270
|
}
|
|
@@ -1955,111 +1958,6 @@
|
|
|
1955
1958
|
wrap('replaceState');
|
|
1956
1959
|
}
|
|
1957
1960
|
|
|
1958
|
-
// happy-dom does not implement `document.evaluate`. Capybara internals
|
|
1959
|
-
// and user scripts both reach for it occasionally. Polyfill it on top of
|
|
1960
|
-
// fontoxpath so callers see W3C XPathResult semantics.
|
|
1961
|
-
function installDocumentEvaluate(doc) {
|
|
1962
|
-
if (typeof doc.evaluate === 'function') return;
|
|
1963
|
-
const ANY_TYPE = 0;
|
|
1964
|
-
const NUMBER_TYPE = 1;
|
|
1965
|
-
const STRING_TYPE = 2;
|
|
1966
|
-
const BOOLEAN_TYPE = 3;
|
|
1967
|
-
const UNORDERED_NODE_ITERATOR_TYPE = 4;
|
|
1968
|
-
const ORDERED_NODE_ITERATOR_TYPE = 5;
|
|
1969
|
-
const UNORDERED_NODE_SNAPSHOT_TYPE = 6;
|
|
1970
|
-
const ORDERED_NODE_SNAPSHOT_TYPE = 7;
|
|
1971
|
-
const ANY_UNORDERED_NODE_TYPE = 8;
|
|
1972
|
-
const FIRST_ORDERED_NODE_TYPE = 9;
|
|
1973
|
-
|
|
1974
|
-
function makeResult(type, items) {
|
|
1975
|
-
return {
|
|
1976
|
-
resultType: type,
|
|
1977
|
-
snapshotLength: items.length,
|
|
1978
|
-
snapshotItem: (i) => items[i] || null,
|
|
1979
|
-
get singleNodeValue() { return items[0] || null; },
|
|
1980
|
-
iterateNext: (() => { let i = 0; return () => items[i++] || null; })()
|
|
1981
|
-
};
|
|
1982
|
-
}
|
|
1983
|
-
|
|
1984
|
-
doc.evaluate = function (xpath, contextNode, _resolver, type, _result) {
|
|
1985
|
-
const root = contextNode || doc.documentElement || doc;
|
|
1986
|
-
let nodes = [];
|
|
1987
|
-
try {
|
|
1988
|
-
nodes = evaluateXPathToNodes(xpath, root, xpathDomFacade, null, {
|
|
1989
|
-
namespaceResolver: () => 'http://www.w3.org/1999/xhtml'
|
|
1990
|
-
});
|
|
1991
|
-
} catch (_) {
|
|
1992
|
-
nodes = [];
|
|
1993
|
-
}
|
|
1994
|
-
switch (type) {
|
|
1995
|
-
case FIRST_ORDERED_NODE_TYPE:
|
|
1996
|
-
case ANY_UNORDERED_NODE_TYPE:
|
|
1997
|
-
return makeResult(type, nodes.slice(0, 1));
|
|
1998
|
-
case NUMBER_TYPE:
|
|
1999
|
-
case STRING_TYPE:
|
|
2000
|
-
case BOOLEAN_TYPE:
|
|
2001
|
-
// We do not support primitive XPath results; callers fall back.
|
|
2002
|
-
return makeResult(type, []);
|
|
2003
|
-
default:
|
|
2004
|
-
return makeResult(type || ORDERED_NODE_SNAPSHOT_TYPE, nodes);
|
|
2005
|
-
}
|
|
2006
|
-
};
|
|
2007
|
-
}
|
|
2008
|
-
|
|
2009
|
-
// Custom DOM facade for fontoxpath that uses childNodes-based traversal
|
|
2010
|
-
// so happy-dom quirks around sibling links don't break root-anchored
|
|
2011
|
-
// queries. Mirrors the helper we built for linkedom.
|
|
2012
|
-
// fontoxpath calls into this facade tens of thousands of times per
|
|
2013
|
-
// traversal, so each method needs to delegate to happy-dom's native
|
|
2014
|
-
// pointers rather than reconstructing them. Earlier revisions of
|
|
2015
|
-
// getNextSibling / getPreviousSibling rebuilt childNodes via
|
|
2016
|
-
// Array.from(parent.childNodes) and then indexOf'd the node — quadratic
|
|
2017
|
-
// in tree size, and the dominant cost on any non-trivial page.
|
|
2018
|
-
const xpathDomFacade = {
|
|
2019
|
-
getAllAttributes(node) {
|
|
2020
|
-
if (!node || node.nodeType !== 1 || !node.attributes) return [];
|
|
2021
|
-
return Array.from(node.attributes);
|
|
2022
|
-
},
|
|
2023
|
-
getAttribute(node, name) {
|
|
2024
|
-
return node && node.getAttribute ? node.getAttribute(name) : null;
|
|
2025
|
-
},
|
|
2026
|
-
getChildNodes(node) {
|
|
2027
|
-
if (!node) return [];
|
|
2028
|
-
if (node.childNodes) return Array.from(node.childNodes);
|
|
2029
|
-
if (node.nodeType === 9 && node.documentElement) return [node.documentElement];
|
|
2030
|
-
return [];
|
|
2031
|
-
},
|
|
2032
|
-
getData(node) {
|
|
2033
|
-
if (!node) return '';
|
|
2034
|
-
if (node.nodeType === 2) return node.value || '';
|
|
2035
|
-
return node.data || '';
|
|
2036
|
-
},
|
|
2037
|
-
// happy-dom 20 has a quirk on `<template>`: `template.childNodes` is
|
|
2038
|
-
// empty (the parsed content lives in `template.content`) but
|
|
2039
|
-
// `template.firstChild` / `template.lastChild` still return the first
|
|
2040
|
-
// text node of `template.content`. Walking into that ghost child
|
|
2041
|
-
// makes fontoxpath traverse content as if it were a regular descendant,
|
|
2042
|
-
// which scrambles every predicate downstream. Verify against
|
|
2043
|
-
// childNodes.length before trusting firstChild / lastChild.
|
|
2044
|
-
getFirstChild(node) {
|
|
2045
|
-
const fc = node?.firstChild ?? null;
|
|
2046
|
-
if (!fc) return null;
|
|
2047
|
-
const cs = node.childNodes;
|
|
2048
|
-
if (cs && cs.length === 0) return null;
|
|
2049
|
-
return fc;
|
|
2050
|
-
},
|
|
2051
|
-
getLastChild(node) {
|
|
2052
|
-
const lc = node?.lastChild ?? null;
|
|
2053
|
-
if (!lc) return null;
|
|
2054
|
-
const cs = node.childNodes;
|
|
2055
|
-
if (cs && cs.length === 0) return null;
|
|
2056
|
-
return lc;
|
|
2057
|
-
},
|
|
2058
|
-
getNextSibling(node) { return node?.nextSibling ?? null; },
|
|
2059
|
-
getPreviousSibling(node) { return node?.previousSibling ?? null; },
|
|
2060
|
-
getParentNode(node) { return node?.parentNode ?? null; }
|
|
2061
|
-
};
|
|
2062
|
-
|
|
2063
1961
|
// Capybara's xpath gem produces a small set of stable XPath shapes for
|
|
2064
1962
|
// its built-in selectors (link, button, link_or_button, select, option,
|
|
2065
1963
|
// field, fillable_field, …). Even after the facade fix fontoxpath spends
|