File: bridge.rb

package info (click to toggle)
ruby-selenium-webdriver 3.142.7%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,592 kB
  • sloc: ruby: 6,740; javascript: 85; makefile: 3
file content (594 lines) | stat: -rwxr-xr-x 16,098 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
# frozen_string_literal: true

# Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The SFC licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

module Selenium
  module WebDriver
    module Remote
      module OSS

        #
        # Low level bridge to the remote server implementing JSON wire
        # protocol (OSS dialect), through which the rest of the API works.
        # @api private
        #

        class Bridge < Remote::Bridge

          def initialize(capabilities, session_id, **opts)
            @capabilities = capabilities
            @session_id = session_id
            super(opts)
          end

          def dialect
            :oss
          end

          def commands(command)
            COMMANDS[command]
          end

          def status
            execute :status
          end

          def get(url)
            execute :get, {}, {url: url}
          end

          def session_capabilities
            Capabilities.json_create execute(:get_capabilities)
          end

          def implicit_wait_timeout=(milliseconds)
            execute :implicitly_wait, {}, {ms: milliseconds}
          end

          def script_timeout=(milliseconds)
            execute :set_script_timeout, {}, {ms: milliseconds}
          end

          def timeout(type, milliseconds)
            execute :set_timeout, {}, {type: type, ms: milliseconds}
          end

          #
          # alerts
          #

          def accept_alert
            execute :accept_alert
          end

          def dismiss_alert
            execute :dismiss_alert
          end

          def alert=(keys)
            execute :set_alert_value, {}, {text: keys.to_s}
          end

          def alert_text
            execute :get_alert_text
          end

          def authentication(credentials)
            execute :set_authentication, {}, credentials
          end

          #
          # navigation
          #

          def go_back
            execute :go_back
          end

          def go_forward
            execute :go_forward
          end

          def url
            execute :get_current_url
          end

          def title
            execute :get_title
          end

          def page_source
            execute :get_page_source
          end

          def switch_to_window(name)
            execute :switch_to_window, {}, {name: name}
          end

          def switch_to_frame(id)
            execute :switch_to_frame, {}, {id: id}
          end

          def switch_to_parent_frame
            execute :switch_to_parent_frame
          end

          def switch_to_default_content
            switch_to_frame(nil)
          end

          def quit
            execute :quit
            http.close
          rescue *http.quit_errors
          end

          def close
            execute :close
          end

          def refresh
            execute :refresh
          end

          #
          # window handling
          #

          def window_handles
            execute :get_window_handles
          end

          def window_handle
            execute :get_current_window_handle
          end

          def resize_window(width, height, handle = :current)
            execute :set_window_size, {window_handle: handle},
                    {width: width,
                     height: height}
          end

          def maximize_window(handle = :current)
            execute :maximize_window, window_handle: handle
          end

          def window_size(handle = :current)
            data = execute :get_window_size, window_handle: handle

            Dimension.new data['width'], data['height']
          end

          def reposition_window(x, y, handle = :current)
            execute :set_window_position, {window_handle: handle},
                    {x: x, y: y}
          end

          def window_position(handle = :current)
            data = execute :get_window_position, window_handle: handle

            Point.new data['x'], data['y']
          end

          def screenshot
            execute :screenshot
          end

          #
          # HTML 5
          #

          def local_storage_item(key, value = nil)
            if value
              execute :set_local_storage_item, {}, {key: key, value: value}
            else
              execute :get_local_storage_item, key: key
            end
          end

          def remove_local_storage_item(key)
            execute :remove_local_storage_item, key: key
          end

          def local_storage_keys
            execute :get_local_storage_keys
          end

          def clear_local_storage
            execute :clear_local_storage
          end

          def local_storage_size
            execute :get_local_storage_size
          end

          def session_storage_item(key, value = nil)
            if value
              execute :set_session_storage_item, {}, {key: key, value: value}
            else
              execute :get_session_storage_item, key: key
            end
          end

          def remove_session_storage_item(key)
            execute :remove_session_storage_item, key: key
          end

          def session_storage_keys
            execute :get_session_storage_keys
          end

          def clear_session_storage
            execute :clear_session_storage
          end

          def session_storage_size
            execute :get_session_storage_size
          end

          def location
            obj = execute(:get_location) || {}
            Location.new obj['latitude'], obj['longitude'], obj['altitude']
          end

          def set_location(lat, lon, alt)
            loc = {latitude: lat, longitude: lon, altitude: alt}
            execute :set_location, {}, {location: loc}
          end

          def network_connection
            execute :get_network_connection
          end

          def network_connection=(type)
            execute :set_network_connection, {}, {parameters: {type: type}}
          end

          #
          # javascript execution
          #

          def execute_script(script, *args)
            assert_javascript_enabled

            result = execute :execute_script, {}, {script: script, args: args}
            unwrap_script_result result
          end

          def execute_async_script(script, *args)
            assert_javascript_enabled

            result = execute :execute_async_script, {}, {script: script, args: args}
            unwrap_script_result result
          end

          #
          # cookies
          #

          def manage
            @manage ||= WebDriver::Manager.new(self)
          end

          def add_cookie(cookie)
            execute :add_cookie, {}, {cookie: cookie}
          end

          def delete_cookie(name)
            execute :delete_cookie, name: name
          end

          def cookies
            execute :get_cookies
          end

          def delete_all_cookies
            execute :delete_all_cookies
          end

          #
          # actions
          #

          #
          # @return [ActionBuilder]
          # @api public
          #

          def action
            ActionBuilder.new Mouse.new(self), Keyboard.new(self)
          end

          def mouse
            WebDriver.logger.deprecate 'Driver#mouse', 'driver.action.<command>.perform'
            Mouse.new self
          end

          def keyboard
            WebDriver.logger.deprecate 'Driver#keyboard', 'driver.action.<command>.perform'
            Keyboard.new self
          end

          def click_element(element)
            execute :click_element, id: element
          end

          def click
            execute :click, {}, {button: 0}
          end

          def double_click
            execute :double_click
          end

          def context_click
            execute :click, {}, {button: 2}
          end

          def mouse_down
            execute :mouse_down
          end

          def mouse_up
            execute :mouse_up
          end

          def mouse_move_to(element, x = nil, y = nil)
            params = {element: element}

            if x && y
              params[:xoffset] = x
              params[:yoffset] = y
            end

            execute :mouse_move_to, {}, params
          end

          def send_keys_to_active_element(key)
            execute :send_keys_to_active_element, {}, {value: key}
          end

          def send_keys_to_element(element, keys)
            # TODO: rework file detectors before Selenium 4.0
            if @file_detector
              local_files = keys.first.split("\n").map { |key| @file_detector.call(Array(key)) }.compact
              if local_files.any?
                keys = local_files.map { |local_file| upload(local_file) }
                keys = keys.join("\n")
              end
            end

            execute :send_keys_to_element, {id: element}, {value: Array(keys)}
          end

          def upload(local_file)
            unless File.file?(local_file)
              WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!")
              raise Error::WebDriverError, "You are trying to work with something that isn't a file."
            end

            execute :upload_file, {}, {file: Zipper.zip_file(local_file)}
          end

          def clear_element(element)
            execute :clear_element, id: element
          end

          def submit_element(element)
            execute :submit_element, id: element
          end

          def drag_element(element, right_by, down_by)
            execute :drag_element, {id: element}, {x: right_by, y: down_by}
          end

          def touch_single_tap(element)
            execute :touch_single_tap, {}, {element: element}
          end

          def touch_double_tap(element)
            execute :touch_double_tap, {}, {element: element}
          end

          def touch_long_press(element)
            execute :touch_long_press, {}, {element: element}
          end

          def touch_down(x, y)
            execute :touch_down, {}, {x: x, y: y}
          end

          def touch_up(x, y)
            execute :touch_up, {}, {x: x, y: y}
          end

          def touch_move(x, y)
            execute :touch_move, {}, {x: x, y: y}
          end

          def touch_scroll(element, x, y)
            if element
              execute :touch_scroll, {}, {element: element,
                                          xoffset: x,
                                          yoffset: y}
            else
              execute :touch_scroll, {}, {xoffset: x, yoffset: y}
            end
          end

          def touch_flick(xspeed, yspeed)
            execute :touch_flick, {}, {xspeed: xspeed, yspeed: yspeed}
          end

          def touch_element_flick(element, right_by, down_by, speed)
            execute :touch_flick, {}, {element: element,
                                       xoffset: right_by,
                                       yoffset: down_by,
                                       speed: speed}
          end

          def screen_orientation=(orientation)
            execute :set_screen_orientation, {}, {orientation: orientation}
          end

          def screen_orientation
            execute :get_screen_orientation
          end

          #
          # logs
          #

          def available_log_types
            types = execute :get_available_log_types
            Array(types).map(&:to_sym)
          end

          def log(type)
            data = execute :get_log, {}, {type: type.to_s}

            Array(data).map do |l|
              begin
                LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
              rescue KeyError
                next
              end
            end
          end

          #
          # element properties
          #

          def element_tag_name(element)
            execute :get_element_tag_name, id: element
          end

          def element_attribute(element, name)
            execute :get_element_attribute, id: element.ref, name: name
          end

          # Backwards compatibility for w3c
          def element_property(element, name)
            execute_script 'return arguments[0][arguments[1]]', element, name
          end

          def element_value(element)
            execute :get_element_value, id: element
          end

          def element_text(element)
            execute :get_element_text, id: element
          end

          def element_location(element)
            data = execute :get_element_location, id: element

            Point.new data['x'], data['y']
          end

          def element_rect(element)
            loc = execute :get_element_location, id: element
            size = execute :get_element_size, id: element

            Rectangle.new loc['x'], loc['y'], size['width'], size['height']
          end

          def element_location_once_scrolled_into_view(element)
            data = execute :get_element_location_once_scrolled_into_view, id: element

            Point.new data['x'], data['y']
          end

          def element_size(element)
            data = execute :get_element_size, id: element

            Dimension.new data['width'], data['height']
          end

          def element_enabled?(element)
            execute :is_element_enabled, id: element
          end

          def element_selected?(element)
            execute :is_element_selected, id: element
          end

          def element_displayed?(element)
            execute :is_element_displayed, id: element.ref
          end

          def element_value_of_css_property(element, prop)
            execute :get_element_value_of_css_property, id: element, property_name: prop
          end

          #
          # finding elements
          #

          def active_element
            Element.new self, element_id_from(execute(:get_active_element))
          end

          alias_method :switch_to_active_element, :active_element

          def find_element_by(how, what, parent = nil)
            id = if parent
                   execute :find_child_element, {id: parent}, {using: how, value: what}
                 else
                   execute :find_element, {}, {using: how, value: what}
                 end

            Element.new self, element_id_from(id)
          end

          def find_elements_by(how, what, parent = nil)
            ids = if parent
                    execute :find_child_elements, {id: parent}, {using: how, value: what}
                  else
                    execute :find_elements, {}, {using: how, value: what}
                  end
            # see https://github.com/SeleniumHQ/selenium/issues/4555
            ids ||= []

            ids.map { |id| Element.new self, element_id_from(id) }
          end

          private

          def assert_javascript_enabled
            return if capabilities.javascript_enabled?

            raise Error::UnsupportedOperationError, 'underlying webdriver instance does not support javascript'
          end

          #
          # executes a command on the remote server.
          #
          # Returns the 'value' of the returned payload
          #

          def execute(*args)
            super['value']
          end

        end # Bridge
      end # OSS
    end # Remote
  end # WebDriver
end # Selenium