lib/selenium/webdriver/devtools.rb
# 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 class DevTools autoload :ConsoleEvent, 'selenium/webdriver/devtools/console_event' autoload :ExceptionEvent, 'selenium/webdriver/devtools/exception_event' autoload :MutationEvent, 'selenium/webdriver/devtools/mutation_event' autoload :NetworkInterceptor, 'selenium/webdriver/devtools/network_interceptor' autoload :PinnedScript, 'selenium/webdriver/devtools/pinned_script' autoload :Request, 'selenium/webdriver/devtools/request' autoload :Response, 'selenium/webdriver/devtools/response' def initialize(url:) @ws = WebSocketConnection.new(url: url) @session_id = nil start_session end def close @ws.close end def callbacks @ws.callbacks end def send_cmd(method, **params) data = {method: method, params: params.compact} data[:sessionId] = @session_id if @session_id message = @ws.send_cmd(**data) raise Error::WebDriverError, error_message(message['error']) if message['error'] message end def method_missing(method, *_args) namespace = "Selenium::DevTools::V#{Selenium::DevTools.version}" methods_to_classes = "#{namespace}::METHODS_TO_CLASSES" desired_class = if Object.const_defined?(methods_to_classes) # selenium-devtools 0.113 and newer "#{namespace}::#{Object.const_get(methods_to_classes)[method]}" else # selenium-devtools 0.112 and older "#{namespace}::#{method.capitalize}" end return unless Object.const_defined?(desired_class) self.class.class_eval do define_method(method) do Object.const_get(desired_class).new(self) end end send(method) end def respond_to_missing?(method, *_args) desired_class = "Selenium::DevTools::V#{Selenium::DevTools.version}::#{method.capitalize}" Object.const_defined?(desired_class) end private def start_session targets = target.get_targets.dig('result', 'targetInfos') page_target = targets.find { |target| target['type'] == 'page' } session = target.attach_to_target(target_id: page_target['targetId'], flatten: true) @session_id = session.dig('result', 'sessionId') end def error_message(error) [error['code'], error['message'], error['data']].join(': ') end end # DevTools end # WebDriver end # Selenium