selenium-webdriver 4.35.0 → 4.47.0
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/CHANGES +111 -0
- data/Gemfile +1 -4
- data/LICENSE +1 -1
- data/NOTICE +1 -1
- data/README.md +43 -23
- data/bin/linux/selenium-manager +0 -0
- data/bin/macos/selenium-manager +0 -0
- data/bin/selenium-manager-THIRD-PARTY-NOTICES.txt +5971 -0
- data/bin/selenium-manager.cdx.json +11629 -0
- data/bin/windows/selenium-manager.exe +0 -0
- data/lib/selenium/server.rb +30 -5
- data/lib/selenium/webdriver/atoms/findElements.js +272 -54
- data/lib/selenium/webdriver/atoms/getAttribute.js +152 -6
- data/lib/selenium/webdriver/atoms/isDisplayed.js +385 -28
- data/lib/selenium/webdriver/bidi/browser.rb +71 -0
- data/lib/selenium/webdriver/bidi/browsing_context.rb +3 -2
- data/lib/selenium/webdriver/bidi/{log/filter_by.rb → error.rb} +20 -16
- data/lib/selenium/webdriver/bidi/log_handler.rb +5 -0
- data/lib/selenium/webdriver/bidi/network/cookies.rb +13 -9
- data/lib/selenium/webdriver/bidi/network/credentials.rb +4 -0
- data/lib/selenium/webdriver/bidi/network/headers.rb +4 -0
- data/lib/selenium/webdriver/bidi/network/intercepted_auth.rb +4 -0
- data/lib/selenium/webdriver/bidi/network/intercepted_item.rb +4 -0
- data/lib/selenium/webdriver/bidi/network/intercepted_request.rb +20 -4
- data/lib/selenium/webdriver/bidi/network/intercepted_response.rb +24 -6
- data/lib/selenium/webdriver/bidi/network/url_pattern.rb +4 -0
- data/lib/selenium/webdriver/bidi/network.rb +18 -9
- data/lib/selenium/webdriver/bidi/protocol/bluetooth.rb +495 -0
- data/lib/selenium/webdriver/bidi/protocol/browser.rb +250 -0
- data/lib/selenium/webdriver/bidi/protocol/browsing_context.rb +798 -0
- data/lib/selenium/webdriver/bidi/{log/base_log_entry.rb → protocol/domain.rb} +22 -11
- data/lib/selenium/webdriver/bidi/protocol/emulation.rb +448 -0
- data/lib/selenium/webdriver/bidi/protocol/error_code.rb +66 -0
- data/lib/selenium/webdriver/bidi/protocol/input.rb +354 -0
- data/lib/selenium/webdriver/bidi/protocol/log.rb +115 -0
- data/lib/selenium/webdriver/bidi/protocol/network.rb +720 -0
- data/lib/selenium/webdriver/bidi/protocol/permissions.rb +75 -0
- data/lib/selenium/webdriver/bidi/protocol/script.rb +1052 -0
- data/lib/selenium/webdriver/bidi/protocol/session.rb +286 -0
- data/lib/selenium/webdriver/bidi/protocol/speculation.rb +58 -0
- data/lib/selenium/webdriver/bidi/protocol/storage.rb +183 -0
- data/lib/selenium/webdriver/bidi/protocol/user_agent_client_hints.rb +88 -0
- data/lib/selenium/webdriver/bidi/protocol/web_extension.rb +132 -0
- data/lib/selenium/webdriver/bidi/protocol.rb +42 -0
- data/lib/selenium/webdriver/bidi/serialization/record.rb +402 -0
- data/lib/selenium/webdriver/bidi/serialization/union.rb +156 -0
- data/lib/selenium/webdriver/bidi/serialization.rb +90 -0
- data/lib/selenium/webdriver/bidi/session.rb +4 -0
- data/lib/selenium/webdriver/bidi/support/bidi_generate.rb +1420 -0
- data/lib/selenium/webdriver/bidi/support/check_generated.rb +63 -0
- data/lib/selenium/webdriver/bidi/transport.rb +57 -0
- data/lib/selenium/webdriver/bidi.rb +4 -1
- data/lib/selenium/webdriver/chrome/driver.rb +4 -3
- data/lib/selenium/webdriver/chrome/service.rb +13 -0
- data/lib/selenium/webdriver/chromium/driver.rb +0 -1
- data/lib/selenium/webdriver/chromium/options.rb +23 -1
- data/lib/selenium/webdriver/chromium/profile.rb +6 -0
- data/lib/selenium/webdriver/common/child_process.rb +2 -1
- data/lib/selenium/webdriver/common/client_config.rb +97 -0
- data/lib/selenium/webdriver/common/driver.rb +13 -7
- data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +0 -7
- data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +0 -7
- data/lib/selenium/webdriver/common/driver_extensions/{has_bidi.rb → has_session_events.rb} +19 -7
- data/lib/selenium/webdriver/common/driver_finder.rb +35 -25
- data/lib/selenium/webdriver/common/error.rb +10 -3
- data/lib/selenium/webdriver/common/local_driver.rb +29 -12
- data/lib/selenium/webdriver/common/logger.rb +28 -0
- data/lib/selenium/webdriver/common/manager.rb +2 -0
- data/lib/selenium/webdriver/common/options.rb +41 -2
- data/lib/selenium/webdriver/common/platform.rb +1 -3
- data/lib/selenium/webdriver/common/proxy.rb +1 -9
- data/lib/selenium/webdriver/common/selenium_manager.rb +2 -1
- data/lib/selenium/webdriver/common/service.rb +4 -8
- data/lib/selenium/webdriver/common/service_manager.rb +36 -4
- data/lib/selenium/webdriver/common/socket_poller.rb +1 -1
- data/lib/selenium/webdriver/common/takes_screenshot.rb +1 -1
- data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +1 -1
- data/lib/selenium/webdriver/common/wait.rb +4 -1
- data/lib/selenium/webdriver/common/websocket_connection.rb +73 -37
- data/lib/selenium/webdriver/common.rb +2 -1
- data/lib/selenium/webdriver/devtools/response.rb +3 -3
- data/lib/selenium/webdriver/devtools.rb +1 -1
- data/lib/selenium/webdriver/edge/driver.rb +4 -3
- data/lib/selenium/webdriver/edge/service.rb +14 -0
- data/lib/selenium/webdriver/firefox/driver.rb +4 -6
- data/lib/selenium/webdriver/firefox/options.rb +19 -0
- data/lib/selenium/webdriver/firefox/profile.rb +13 -6
- data/lib/selenium/webdriver/firefox/service.rb +31 -2
- data/lib/selenium/webdriver/ie/driver.rb +4 -3
- data/lib/selenium/webdriver/ie/service.rb +10 -0
- data/lib/selenium/webdriver/remote/bidi_bridge.rb +44 -10
- data/lib/selenium/webdriver/remote/bridge.rb +20 -14
- data/lib/selenium/webdriver/remote/driver.rb +15 -4
- data/lib/selenium/webdriver/remote/features.rb +26 -1
- data/lib/selenium/webdriver/remote/http/common.rb +57 -12
- data/lib/selenium/webdriver/remote/http/curb.rb +6 -8
- data/lib/selenium/webdriver/remote/http/default.rb +56 -39
- data/lib/selenium/webdriver/safari/driver.rb +4 -3
- data/lib/selenium/webdriver/safari/options.rb +23 -4
- data/lib/selenium/webdriver/safari.rb +1 -6
- data/lib/selenium/webdriver/support/block_event_listener.rb +5 -1
- data/lib/selenium/webdriver/support/color.rb +14 -14
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +5 -1
- data/lib/selenium/webdriver/support/guards/guard.rb +30 -14
- data/lib/selenium/webdriver/support/guards.rb +11 -4
- data/lib/selenium/webdriver/version.rb +1 -1
- data/lib/selenium/webdriver.rb +7 -2
- data/selenium-webdriver.gemspec +1 -1
- metadata +33 -11
- data/lib/selenium/webdriver/bidi/log/console_log_entry.rb +0 -35
- data/lib/selenium/webdriver/bidi/log/generic_log_entry.rb +0 -33
- data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +0 -33
- data/lib/selenium/webdriver/bidi/log_inspector.rb +0 -147
|
@@ -1,28 +1,385 @@
|
|
|
1
|
-
function()
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
1
|
+
(function isShownElement(elem, optIgnoreOpacity) {
|
|
2
|
+
var tagNameDescriptor = Object.getOwnPropertyDescriptor(Element.prototype, 'tagName');
|
|
3
|
+
var computedStyleCache = new Map();
|
|
4
|
+
var clientRectCache = new Map();
|
|
5
|
+
var displayedCache = new Map();
|
|
6
|
+
function toUpperCaseTag(tagName) {
|
|
7
|
+
return tagName ? tagName.toUpperCase() : undefined;
|
|
8
|
+
}
|
|
9
|
+
function isElement(node, tagName) {
|
|
10
|
+
if (!node || node.nodeType !== 1) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
var asElement = node;
|
|
14
|
+
var rawTagName = tagNameDescriptor && typeof tagNameDescriptor.get === 'function'
|
|
15
|
+
? tagNameDescriptor.get.call(asElement)
|
|
16
|
+
: asElement.tagName;
|
|
17
|
+
var upperTagName = typeof rawTagName === 'string' ? rawTagName.toUpperCase() : '';
|
|
18
|
+
var normalizedTagName = toUpperCaseTag(tagName);
|
|
19
|
+
if (upperTagName === 'FORM') {
|
|
20
|
+
return !normalizedTagName || normalizedTagName === 'FORM';
|
|
21
|
+
}
|
|
22
|
+
return !!upperTagName && (!normalizedTagName || upperTagName === normalizedTagName);
|
|
23
|
+
}
|
|
24
|
+
function getParentElement(node) {
|
|
25
|
+
var current = node.parentNode;
|
|
26
|
+
while (current &&
|
|
27
|
+
current.nodeType !== Node.ELEMENT_NODE &&
|
|
28
|
+
current.nodeType !== Node.DOCUMENT_NODE &&
|
|
29
|
+
current.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
|
|
30
|
+
current = current.parentNode;
|
|
31
|
+
}
|
|
32
|
+
return current && current.nodeType === 1 ? current : null;
|
|
33
|
+
}
|
|
34
|
+
function getEffectiveStyle(elem, propertyName) {
|
|
35
|
+
var computed = computedStyleCache.get(elem);
|
|
36
|
+
if (computed === undefined) {
|
|
37
|
+
var win = elem.ownerDocument.defaultView;
|
|
38
|
+
computed = win ? (win.getComputedStyle(elem) || null) : null;
|
|
39
|
+
computedStyleCache.set(elem, computed);
|
|
40
|
+
}
|
|
41
|
+
if (!computed) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
var value = computed.getPropertyValue(propertyName);
|
|
45
|
+
return value || null;
|
|
46
|
+
}
|
|
47
|
+
function getOpacity(elem) {
|
|
48
|
+
var opacityStyle = getEffectiveStyle(elem, 'opacity');
|
|
49
|
+
var opacity = opacityStyle ? Number(opacityStyle) : 1;
|
|
50
|
+
var parent = getParentElement(elem);
|
|
51
|
+
return parent ? opacity * getOpacity(parent) : opacity;
|
|
52
|
+
}
|
|
53
|
+
function getParentNodeInComposedDom(node) {
|
|
54
|
+
var parent = node.parentNode;
|
|
55
|
+
var slottable = node;
|
|
56
|
+
var parentWithShadow = parent;
|
|
57
|
+
if (parentWithShadow && parentWithShadow.shadowRoot && slottable.assignedSlot !== undefined) {
|
|
58
|
+
return slottable.assignedSlot ? slottable.assignedSlot.parentNode : null;
|
|
59
|
+
}
|
|
60
|
+
return parent;
|
|
61
|
+
}
|
|
62
|
+
function createRect(left, top, width, height) {
|
|
63
|
+
return {
|
|
64
|
+
left: left,
|
|
65
|
+
top: top,
|
|
66
|
+
right: left + width,
|
|
67
|
+
bottom: top + height,
|
|
68
|
+
width: width,
|
|
69
|
+
height: height,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function getClientRect(elem) {
|
|
73
|
+
var cachedRect = clientRectCache.get(elem);
|
|
74
|
+
if (cachedRect) {
|
|
75
|
+
return cachedRect;
|
|
76
|
+
}
|
|
77
|
+
var rect;
|
|
78
|
+
var imageMap = maybeFindImageMap(elem);
|
|
79
|
+
if (imageMap) {
|
|
80
|
+
rect = imageMap.rect;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
var elemTagName = typeof elem.tagName === 'string' ? elem.tagName : '';
|
|
84
|
+
if (elemTagName.toUpperCase() === 'HTML') {
|
|
85
|
+
var doc = elem.ownerDocument;
|
|
86
|
+
var sizeElem = doc.compatMode === 'CSS1Compat' ? doc.documentElement : (doc.body || doc.documentElement);
|
|
87
|
+
rect = createRect(0, 0, sizeElem.clientWidth, sizeElem.clientHeight);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
try {
|
|
91
|
+
var nativeRect = elem.getBoundingClientRect();
|
|
92
|
+
rect = {
|
|
93
|
+
left: nativeRect.left,
|
|
94
|
+
top: nativeRect.top,
|
|
95
|
+
right: nativeRect.right,
|
|
96
|
+
bottom: nativeRect.bottom,
|
|
97
|
+
width: nativeRect.right - nativeRect.left,
|
|
98
|
+
height: nativeRect.bottom - nativeRect.top,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
catch (_error) {
|
|
102
|
+
rect = createRect(0, 0, 0, 0);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
clientRectCache.set(elem, rect);
|
|
107
|
+
return rect;
|
|
108
|
+
}
|
|
109
|
+
function getAreaRelativeRect(area) {
|
|
110
|
+
var shape = area.shape.toLowerCase();
|
|
111
|
+
var coords = area.coords.split(',').map(function (value) {
|
|
112
|
+
return Number(value.trim());
|
|
113
|
+
});
|
|
114
|
+
if (shape === 'rect' && coords.length === 4) {
|
|
115
|
+
return createRect(coords[0], coords[1], coords[2] - coords[0], coords[3] - coords[1]);
|
|
116
|
+
}
|
|
117
|
+
if (shape === 'circle' && coords.length === 3) {
|
|
118
|
+
return createRect(coords[0] - coords[2], coords[1] - coords[2], coords[2] * 2, coords[2] * 2);
|
|
119
|
+
}
|
|
120
|
+
if (shape === 'poly' && coords.length > 2) {
|
|
121
|
+
var minX = coords[0];
|
|
122
|
+
var minY = coords[1];
|
|
123
|
+
var maxX = minX;
|
|
124
|
+
var maxY = minY;
|
|
125
|
+
for (var index = 2; index + 1 < coords.length; index += 2) {
|
|
126
|
+
minX = Math.min(minX, coords[index]);
|
|
127
|
+
maxX = Math.max(maxX, coords[index]);
|
|
128
|
+
minY = Math.min(minY, coords[index + 1]);
|
|
129
|
+
maxY = Math.max(maxY, coords[index + 1]);
|
|
130
|
+
}
|
|
131
|
+
return createRect(minX, minY, maxX - minX, maxY - minY);
|
|
132
|
+
}
|
|
133
|
+
return createRect(0, 0, 0, 0);
|
|
134
|
+
}
|
|
135
|
+
function findImageUsingMap(mapName, doc) {
|
|
136
|
+
return doc.querySelector('[usemap="#' + mapName.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"]');
|
|
137
|
+
}
|
|
138
|
+
function maybeFindImageMap(elem) {
|
|
139
|
+
var isMap = isElement(elem, 'MAP');
|
|
140
|
+
if (!isMap && !isElement(elem, 'AREA')) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
var map = isMap ? elem : isElement(elem.parentNode, 'MAP') ? elem.parentNode : null;
|
|
144
|
+
var image = null;
|
|
145
|
+
var rect = createRect(0, 0, 0, 0);
|
|
146
|
+
if (isElement(map, 'MAP') && map.name) {
|
|
147
|
+
image = findImageUsingMap(map.name, map.ownerDocument);
|
|
148
|
+
if (image) {
|
|
149
|
+
rect = getClientRect(image);
|
|
150
|
+
if (!isMap && isElement(elem, 'AREA') && elem.shape.toLowerCase() !== 'default') {
|
|
151
|
+
var relativeRect = getAreaRelativeRect(elem);
|
|
152
|
+
var relativeX = Math.min(Math.max(relativeRect.left, 0), rect.width);
|
|
153
|
+
var relativeY = Math.min(Math.max(relativeRect.top, 0), rect.height);
|
|
154
|
+
var width = Math.min(relativeRect.width, rect.width - relativeX);
|
|
155
|
+
var height = Math.min(relativeRect.height, rect.height - relativeY);
|
|
156
|
+
rect = createRect(relativeX + rect.left, relativeY + rect.top, width, height);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return { image: image, rect: rect };
|
|
161
|
+
}
|
|
162
|
+
function getClientRegion(elem) {
|
|
163
|
+
return getClientRect(elem);
|
|
164
|
+
}
|
|
165
|
+
function getOverflowState(elem) {
|
|
166
|
+
var region = getClientRegion(elem);
|
|
167
|
+
var ownerDoc = elem.ownerDocument;
|
|
168
|
+
var htmlElem = ownerDoc.documentElement;
|
|
169
|
+
var bodyElem = ownerDoc.body;
|
|
170
|
+
var htmlOverflowStyle = getEffectiveStyle(htmlElem, 'overflow') || 'visible';
|
|
171
|
+
var treatAsFixedPosition = false;
|
|
172
|
+
function canBeOverflowed(container, position) {
|
|
173
|
+
if (container === htmlElem) {
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
var display = getEffectiveStyle(container, 'display') || '';
|
|
177
|
+
if (display.indexOf('inline') === 0 || display === 'contents') {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
if (position === 'absolute' && getEffectiveStyle(container, 'position') === 'static') {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
function getOverflowParent(current) {
|
|
186
|
+
var position = getEffectiveStyle(current, 'position');
|
|
187
|
+
if (position === 'fixed') {
|
|
188
|
+
treatAsFixedPosition = true;
|
|
189
|
+
return current === htmlElem ? null : htmlElem;
|
|
190
|
+
}
|
|
191
|
+
var parent = getParentElement(current);
|
|
192
|
+
while (parent && !canBeOverflowed(parent, position)) {
|
|
193
|
+
parent = getParentElement(parent);
|
|
194
|
+
}
|
|
195
|
+
return parent;
|
|
196
|
+
}
|
|
197
|
+
function getOverflowStyles(current) {
|
|
198
|
+
var overflowElem = current;
|
|
199
|
+
if (htmlOverflowStyle === 'visible') {
|
|
200
|
+
if (current === htmlElem && bodyElem) {
|
|
201
|
+
overflowElem = bodyElem;
|
|
202
|
+
}
|
|
203
|
+
else if (current === bodyElem) {
|
|
204
|
+
return { x: 'visible', y: 'visible' };
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
var overflow = {
|
|
208
|
+
x: getEffectiveStyle(overflowElem, 'overflow-x') || 'visible',
|
|
209
|
+
y: getEffectiveStyle(overflowElem, 'overflow-y') || 'visible',
|
|
210
|
+
};
|
|
211
|
+
if (current === htmlElem) {
|
|
212
|
+
overflow.x = overflow.x === 'visible' ? 'auto' : overflow.x;
|
|
213
|
+
overflow.y = overflow.y === 'visible' ? 'auto' : overflow.y;
|
|
214
|
+
}
|
|
215
|
+
return overflow;
|
|
216
|
+
}
|
|
217
|
+
function getScroll(current) {
|
|
218
|
+
if (current === htmlElem) {
|
|
219
|
+
return {
|
|
220
|
+
x: ownerDoc.defaultView ? ownerDoc.defaultView.pageXOffset : 0,
|
|
221
|
+
y: ownerDoc.defaultView ? ownerDoc.defaultView.pageYOffset : 0,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
return { x: current.scrollLeft, y: current.scrollTop };
|
|
225
|
+
}
|
|
226
|
+
for (var container = getOverflowParent(elem); container; container = getOverflowParent(container)) {
|
|
227
|
+
var containerOverflow = getOverflowStyles(container);
|
|
228
|
+
if (containerOverflow.x === 'visible' && containerOverflow.y === 'visible') {
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
var containerRect = getClientRect(container);
|
|
232
|
+
if (containerRect.width === 0 || containerRect.height === 0) {
|
|
233
|
+
return 'hidden';
|
|
234
|
+
}
|
|
235
|
+
var underflowsX = region.right < containerRect.left;
|
|
236
|
+
var underflowsY = region.bottom < containerRect.top;
|
|
237
|
+
if ((underflowsX && containerOverflow.x === 'hidden') || (underflowsY && containerOverflow.y === 'hidden')) {
|
|
238
|
+
return 'hidden';
|
|
239
|
+
}
|
|
240
|
+
if ((underflowsX && containerOverflow.x !== 'visible') || (underflowsY && containerOverflow.y !== 'visible')) {
|
|
241
|
+
var containerScroll = getScroll(container);
|
|
242
|
+
var unscrollableX = region.right < containerRect.left - containerScroll.x;
|
|
243
|
+
var unscrollableY = region.bottom < containerRect.top - containerScroll.y;
|
|
244
|
+
if ((unscrollableX && containerOverflow.x !== 'visible') || (unscrollableY && containerOverflow.y !== 'visible')) {
|
|
245
|
+
return 'hidden';
|
|
246
|
+
}
|
|
247
|
+
var containerUnderflowState = getOverflowState(container);
|
|
248
|
+
return containerUnderflowState === 'hidden' ? 'hidden' : 'scroll';
|
|
249
|
+
}
|
|
250
|
+
var overflowsX = region.left >= containerRect.left + containerRect.width;
|
|
251
|
+
var overflowsY = region.top >= containerRect.top + containerRect.height;
|
|
252
|
+
if ((overflowsX && containerOverflow.x === 'hidden') || (overflowsY && containerOverflow.y === 'hidden')) {
|
|
253
|
+
return 'hidden';
|
|
254
|
+
}
|
|
255
|
+
if ((overflowsX && containerOverflow.x !== 'visible') || (overflowsY && containerOverflow.y !== 'visible')) {
|
|
256
|
+
if (treatAsFixedPosition) {
|
|
257
|
+
var docScroll = getScroll(container);
|
|
258
|
+
if (region.left >= htmlElem.scrollWidth - docScroll.x || region.right >= htmlElem.scrollHeight - docScroll.y) {
|
|
259
|
+
return 'hidden';
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
var containerOverflowState = getOverflowState(container);
|
|
263
|
+
return containerOverflowState === 'hidden' ? 'hidden' : 'scroll';
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return 'none';
|
|
267
|
+
}
|
|
268
|
+
function isShownInternal(elem, ignoreOpacity, displayedFn) {
|
|
269
|
+
if (!isElement(elem)) {
|
|
270
|
+
throw new Error('Argument to isShown must be of type Element');
|
|
271
|
+
}
|
|
272
|
+
if (isElement(elem, 'BODY')) {
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
if (isElement(elem, 'OPTION') || isElement(elem, 'OPTGROUP')) {
|
|
276
|
+
var select = elem.closest('select');
|
|
277
|
+
return !!select && isShownInternal(select, true, displayedFn);
|
|
278
|
+
}
|
|
279
|
+
var imageMap = maybeFindImageMap(elem);
|
|
280
|
+
if (imageMap) {
|
|
281
|
+
return !!imageMap.image && imageMap.rect.width > 0 && imageMap.rect.height > 0 &&
|
|
282
|
+
isShownInternal(imageMap.image, ignoreOpacity, displayedFn);
|
|
283
|
+
}
|
|
284
|
+
if (isElement(elem, 'INPUT') && elem.type.toLowerCase() === 'hidden') {
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
if (isElement(elem, 'NOSCRIPT')) {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
var visibility = getEffectiveStyle(elem, 'visibility');
|
|
291
|
+
if (visibility === 'collapse' || visibility === 'hidden') {
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
if (!displayedFn(elem)) {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
if (!ignoreOpacity && getOpacity(elem) === 0) {
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
function positiveSize(element) {
|
|
301
|
+
var rect = getClientRect(element);
|
|
302
|
+
if (rect.height > 0 && rect.width > 0) {
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
if (isElement(element, 'PATH') && (rect.height > 0 || rect.width > 0)) {
|
|
306
|
+
var strokeWidth = getEffectiveStyle(element, 'stroke-width');
|
|
307
|
+
return !!strokeWidth && parseInt(strokeWidth, 10) > 0;
|
|
308
|
+
}
|
|
309
|
+
var elementVisibility = getEffectiveStyle(element, 'visibility');
|
|
310
|
+
if (elementVisibility === 'collapse' || elementVisibility === 'hidden') {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
if (!displayedFn(element)) {
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
if (getEffectiveStyle(element, 'overflow') === 'hidden') {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
for (var index = 0; index < element.childNodes.length; index += 1) {
|
|
320
|
+
var child = element.childNodes[index];
|
|
321
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
322
|
+
var text = child.nodeValue || '';
|
|
323
|
+
if (/^[\s]*$/.test(text) && /[\n\r\t]/.test(text)) {
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
if (isElement(child) && positiveSize(child)) {
|
|
329
|
+
return true;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
if (!positiveSize(elem)) {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
function hiddenByOverflow(element) {
|
|
338
|
+
if (getOverflowState(element) !== 'hidden') {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
for (var index = 0; index < element.childNodes.length; index += 1) {
|
|
342
|
+
var child = element.childNodes[index];
|
|
343
|
+
if (isElement(child) && !hiddenByOverflow(child) && positiveSize(child)) {
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
return !hiddenByOverflow(elem);
|
|
350
|
+
}
|
|
351
|
+
function displayed(node) {
|
|
352
|
+
var cached = displayedCache.get(node);
|
|
353
|
+
if (cached !== undefined) {
|
|
354
|
+
return cached;
|
|
355
|
+
}
|
|
356
|
+
if (isElement(node)) {
|
|
357
|
+
var display = getEffectiveStyle(node, 'display');
|
|
358
|
+
var contentVisibility = getEffectiveStyle(node, 'content-visibility');
|
|
359
|
+
if (display === 'none' || contentVisibility === 'hidden') {
|
|
360
|
+
displayedCache.set(node, false);
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
var parent = getParentNodeInComposedDom(node);
|
|
365
|
+
if (typeof ShadowRoot === 'function' && parent instanceof ShadowRoot) {
|
|
366
|
+
if (parent.host.shadowRoot && parent.host.shadowRoot !== parent) {
|
|
367
|
+
displayedCache.set(node, false);
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
parent = parent.host;
|
|
371
|
+
}
|
|
372
|
+
if (parent && (parent.nodeType === Node.DOCUMENT_NODE || parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE)) {
|
|
373
|
+
displayedCache.set(node, true);
|
|
374
|
+
return true;
|
|
375
|
+
}
|
|
376
|
+
if (isElement(parent, 'DETAILS') && !parent.open && !isElement(node, 'SUMMARY')) {
|
|
377
|
+
displayedCache.set(node, false);
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
var result = !!parent && displayed(parent);
|
|
381
|
+
displayedCache.set(node, result);
|
|
382
|
+
return result;
|
|
383
|
+
}
|
|
384
|
+
return isShownInternal(elem, !!optIgnoreOpacity, displayed);
|
|
385
|
+
})
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Licensed to the Software Freedom Conservancy (SFC) under one
|
|
4
|
+
# or more contributor license agreements. See the NOTICE file
|
|
5
|
+
# distributed with this work for additional information
|
|
6
|
+
# regarding copyright ownership. The SFC licenses this file
|
|
7
|
+
# to you under the Apache License, Version 2.0 (the
|
|
8
|
+
# "License"); you may not use this file except in compliance
|
|
9
|
+
# with the License. You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing,
|
|
14
|
+
# software distributed under the License is distributed on an
|
|
15
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
16
|
+
# KIND, either express or implied. See the License for the
|
|
17
|
+
# specific language governing permissions and limitations
|
|
18
|
+
# under the License.
|
|
19
|
+
|
|
20
|
+
module Selenium
|
|
21
|
+
module WebDriver
|
|
22
|
+
class BiDi
|
|
23
|
+
#
|
|
24
|
+
# BiDi Implementation of the Browser Module
|
|
25
|
+
# Continue to use functionality from existing `driver.manager.window` method
|
|
26
|
+
#
|
|
27
|
+
# @api private
|
|
28
|
+
#
|
|
29
|
+
|
|
30
|
+
class Browser
|
|
31
|
+
Window = Struct.new(:handle, :active, :height, :width, :x, :y, :state) do
|
|
32
|
+
def active?
|
|
33
|
+
active
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
def initialize(bidi)
|
|
37
|
+
@bidi = bidi
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def create_user_context
|
|
41
|
+
@bidi.send_cmd('browser.createUserContext')
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def user_contexts
|
|
45
|
+
@bidi.send_cmd('browser.getUserContexts')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def remove_user_context(user_context)
|
|
49
|
+
@bidi.send_cmd('browser.removeUserContext', userContext: user_context)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def windows
|
|
53
|
+
response = @bidi.send_cmd('browser.getClientWindows')
|
|
54
|
+
|
|
55
|
+
response['clientWindows'].map do |win_data|
|
|
56
|
+
attributes = {
|
|
57
|
+
handle: win_data['clientWindow'],
|
|
58
|
+
active: win_data['active'],
|
|
59
|
+
height: win_data['height'],
|
|
60
|
+
width: win_data['width'],
|
|
61
|
+
x: win_data['x'],
|
|
62
|
+
y: win_data['y'],
|
|
63
|
+
state: win_data['state']
|
|
64
|
+
}
|
|
65
|
+
Window.new(**attributes)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end # Browser
|
|
69
|
+
end # BiDi
|
|
70
|
+
end # WebDriver
|
|
71
|
+
end # Selenium
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
class BiDi
|
|
23
|
-
# Implements the
|
|
23
|
+
# Implements the BrowsingContext Module of the WebDriver-BiDi specification
|
|
24
|
+
# Continue to use functionality from existing `driver.navigate` method
|
|
24
25
|
#
|
|
25
26
|
# @api private
|
|
26
27
|
#
|
|
@@ -109,7 +110,7 @@ module Selenium
|
|
|
109
110
|
context_id ||= @bridge.window_handle
|
|
110
111
|
@bidi.send_cmd('browsingContext.activate', context: context_id)
|
|
111
112
|
end
|
|
112
|
-
end
|
|
113
|
+
end # BrowsingContext
|
|
113
114
|
end # BiDi
|
|
114
115
|
end # WebDriver
|
|
115
116
|
end # Selenium
|
|
@@ -17,24 +17,28 @@
|
|
|
17
17
|
# specific language governing permissions and limitations
|
|
18
18
|
# under the License.
|
|
19
19
|
|
|
20
|
+
require 'selenium/webdriver/common/error'
|
|
21
|
+
require 'selenium/webdriver/bidi/protocol/error_code'
|
|
22
|
+
|
|
20
23
|
module Selenium
|
|
21
24
|
module WebDriver
|
|
22
|
-
|
|
23
|
-
class
|
|
24
|
-
|
|
25
|
+
module Error
|
|
26
|
+
# Register each BiDi-only code as a WebDriverError subclass; shared codes keep their classic class.
|
|
27
|
+
BiDi::Protocol::ErrorCode::CLASS_NAMES.each_value do |name|
|
|
28
|
+
const_set(name, Class.new(WebDriverError)) unless const_defined?(name, false)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"Valid log levels are 'debug', 'error', 'info' and 'warning'. Received: #{level}"
|
|
32
|
+
class BiDi
|
|
33
|
+
module Protocol
|
|
34
|
+
module ErrorCode
|
|
35
|
+
# The exception class for a wire error code, or WebDriverError for an unknown one.
|
|
36
|
+
def self.for(code)
|
|
37
|
+
name = code && CLASS_NAMES[code]
|
|
38
|
+
name ? Error.const_get(name) : Error::WebDriverError
|
|
34
39
|
end
|
|
35
|
-
FilterBy.new(level)
|
|
36
40
|
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -20,6 +20,11 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
class BiDi
|
|
23
|
+
# Implements the Log of the WebDriver-BiDi specification
|
|
24
|
+
# This functionality should be accessed through `driver.script` method
|
|
25
|
+
#
|
|
26
|
+
# @api private
|
|
27
|
+
#
|
|
23
28
|
class LogHandler
|
|
24
29
|
ConsoleLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type, :source, :method, :args)
|
|
25
30
|
JavaScriptLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type, :source)
|
|
@@ -20,17 +20,21 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
class BiDi
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
merge!(cookies)
|
|
27
|
-
end
|
|
23
|
+
#
|
|
24
|
+
# @api private
|
|
25
|
+
#
|
|
28
26
|
|
|
27
|
+
class Cookies < Hash
|
|
29
28
|
def as_json
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
map do |name, val|
|
|
30
|
+
{
|
|
31
|
+
name: name.to_s,
|
|
32
|
+
value: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
value: val.to_s
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
end
|
|
34
38
|
end
|
|
35
39
|
end
|
|
36
40
|
end # BiDi
|